/* typeinfo.cc -- D runtime type identification.
- Copyright (C) 2013-2018 Free Software Foundation, Inc.
+ Copyright (C) 2013-2020 Free Software Foundation, Inc.
GCC is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
va_end (ap);
}
-/* Helper for create_tinfo_types. Creates a typeinfo class declaration
- incase one wasn't supplied by reading `object.d'. */
+/* Reference to the `object` module, where all TypeInfo is defined. */
+
+static Module *object_module;
+
+/* Helper for create_frontend_tinfo_types. Creates a typeinfo class
+ declaration incase one wasn't supplied by reading `object.d'. */
static void
-make_frontend_typeinfo (Module *mod, Identifier *ident,
- ClassDeclaration *base = NULL)
+make_frontend_typeinfo (Identifier *ident, ClassDeclaration *base = NULL)
{
if (!base)
base = Type::dtypeinfo;
+ gcc_assert (object_module);
+
/* Create object module in order to complete the semantic. */
- if (!mod->_scope)
- mod->importAll (NULL);
+ if (!object_module->_scope)
+ object_module->importAll (NULL);
/* Assignment of global typeinfo variables is managed by the ClassDeclaration
constructor, so only need to new the declaration here. */
- Loc loc = (mod->md) ? mod->md->loc : mod->loc;
+ Loc loc = (object_module->md) ? object_module->md->loc : object_module->loc;
ClassDeclaration *tinfo = ClassDeclaration::create (loc, ident, NULL, NULL,
true);
- tinfo->parent = mod;
- tinfo->semantic (mod->_scope);
+ tinfo->parent = object_module;
+ tinfo->semantic (object_module->_scope);
tinfo->baseClass = base;
+ /* This is a compiler generated class, and shouldn't be mistaken for being
+ the type declared in the runtime library. */
+ tinfo->storage_class |= STCtemp;
}
/* Make sure the required builtin types exist for generating the TypeInfo
ptr_type_node, d_uint_type, ptr_type_node,
array_type_node, ptr_type_node, ptr_type_node, NULL);
+ object_module = mod;
+}
+
+/* Same as create_tinfo_types, but builds all front-end TypeInfo variable
+ definitions. */
+
+static void
+create_frontend_tinfo_types (void)
+{
+ /* If there's no Object class defined, then neither can TypeInfo be. */
+ if (object_module == NULL || ClassDeclaration::object == NULL)
+ return;
+
/* Create all frontend TypeInfo classes declarations. We rely on all
existing, even if only just as stubs. */
if (!Type::dtypeinfo)
- make_frontend_typeinfo (mod, Identifier::idPool ("TypeInfo"),
+ make_frontend_typeinfo (Identifier::idPool ("TypeInfo"),
ClassDeclaration::object);
if (!Type::typeinfoclass)
- make_frontend_typeinfo (mod, Identifier::idPool ("TypeInfo_Class"));
+ make_frontend_typeinfo (Identifier::idPool ("TypeInfo_Class"));
if (!Type::typeinfointerface)
- make_frontend_typeinfo (mod, Identifier::idPool ("TypeInfo_Interface"));
+ make_frontend_typeinfo (Identifier::idPool ("TypeInfo_Interface"));
if (!Type::typeinfostruct)
- make_frontend_typeinfo (mod, Identifier::idPool ("TypeInfo_Struct"));
+ make_frontend_typeinfo (Identifier::idPool ("TypeInfo_Struct"));
if (!Type::typeinfopointer)
- make_frontend_typeinfo (mod, Identifier::idPool ("TypeInfo_Pointer"));
+ make_frontend_typeinfo (Identifier::idPool ("TypeInfo_Pointer"));
if (!Type::typeinfoarray)
- make_frontend_typeinfo (mod, Identifier::idPool ("TypeInfo_Array"));
+ make_frontend_typeinfo (Identifier::idPool ("TypeInfo_Array"));
if (!Type::typeinfostaticarray)
- make_frontend_typeinfo (mod, Identifier::idPool ("TypeInfo_StaticArray"));
+ make_frontend_typeinfo (Identifier::idPool ("TypeInfo_StaticArray"));
if (!Type::typeinfoassociativearray)
- make_frontend_typeinfo (mod, Identifier::idPool ("TypeInfo_AssociativeArray"));
+ make_frontend_typeinfo (Identifier::idPool ("TypeInfo_AssociativeArray"));
if (!Type::typeinfoenum)
- make_frontend_typeinfo (mod, Identifier::idPool ("TypeInfo_Enum"));
+ make_frontend_typeinfo (Identifier::idPool ("TypeInfo_Enum"));
if (!Type::typeinfofunction)
- make_frontend_typeinfo (mod, Identifier::idPool ("TypeInfo_Function"));
+ make_frontend_typeinfo (Identifier::idPool ("TypeInfo_Function"));
if (!Type::typeinfodelegate)
- make_frontend_typeinfo (mod, Identifier::idPool ("TypeInfo_Delegate"));
+ make_frontend_typeinfo (Identifier::idPool ("TypeInfo_Delegate"));
if (!Type::typeinfotypelist)
- make_frontend_typeinfo (mod, Identifier::idPool ("TypeInfo_Tuple"));
+ make_frontend_typeinfo (Identifier::idPool ("TypeInfo_Tuple"));
if (!Type::typeinfoconst)
- make_frontend_typeinfo (mod, Identifier::idPool ("TypeInfo_Const"));
+ make_frontend_typeinfo (Identifier::idPool ("TypeInfo_Const"));
if (!Type::typeinfoinvariant)
- make_frontend_typeinfo (mod, Identifier::idPool ("TypeInfo_Invariant"),
+ make_frontend_typeinfo (Identifier::idPool ("TypeInfo_Invariant"),
Type::typeinfoconst);
if (!Type::typeinfoshared)
- make_frontend_typeinfo (mod, Identifier::idPool ("TypeInfo_Shared"),
+ make_frontend_typeinfo (Identifier::idPool ("TypeInfo_Shared"),
Type::typeinfoconst);
if (!Type::typeinfowild)
- make_frontend_typeinfo (mod, Identifier::idPool ("TypeInfo_Wild"),
+ make_frontend_typeinfo (Identifier::idPool ("TypeInfo_Wild"),
Type::typeinfoconst);
if (!Type::typeinfovector)
- make_frontend_typeinfo (mod, Identifier::idPool ("TypeInfo_Vector"));
+ make_frontend_typeinfo (Identifier::idPool ("TypeInfo_Vector"));
if (!ClassDeclaration::cpp_type_info_ptr)
- make_frontend_typeinfo (mod, Identifier::idPool ("__cpp_type_info_ptr"),
+ make_frontend_typeinfo (Identifier::idPool ("__cpp_type_info_ptr"),
ClassDeclaration::object);
}
+/* Return true if TypeInfo class TINFO is available in the runtime library. */
+
+bool
+have_typeinfo_p (ClassDeclaration *tinfo)
+{
+ /* Run-time typeinfo disabled on command line. */
+ if (!global.params.useTypeInfo)
+ return false;
+
+ /* Can't layout TypeInfo if type is not declared, or is an opaque
+ declaration in the object module. */
+ if (!tinfo || !tinfo->members)
+ return false;
+
+ /* Typeinfo is compiler-generated. */
+ if (tinfo->storage_class & STCtemp)
+ return false;
+
+ return true;
+}
+
/* Implements the visitor interface to build the TypeInfo layout of all
TypeInfoDeclaration AST classes emitted from the D Front-end.
All visit methods accept one parameter D, which holds the frontend AST
void layout_base (ClassDeclaration *cd)
{
gcc_assert (cd != NULL);
- this->layout_field (build_address (get_vtable_decl (cd)));
+
+ if (have_typeinfo_p (cd))
+ this->layout_field (build_address (get_vtable_decl (cd)));
+ else
+ this->layout_field (null_pointer_node);
+
this->layout_field (null_pointer_node);
}
this->layout_base (Type::typeinfoconst);
/* TypeInfo for the mutable type. */
- this->layout_field (build_typeinfo (tm));
+ this->layout_field (build_typeinfo (d->loc, tm));
}
/* Layout of TypeInfo_Immutable is:
this->layout_base (Type::typeinfoinvariant);
/* TypeInfo for the mutable type. */
- this->layout_field (build_typeinfo (tm));
+ this->layout_field (build_typeinfo (d->loc, tm));
}
/* Layout of TypeInfo_Shared is:
this->layout_base (Type::typeinfoshared);
/* TypeInfo for the unshared type. */
- this->layout_field (build_typeinfo (tm));
+ this->layout_field (build_typeinfo (d->loc, tm));
}
/* Layout of TypeInfo_Inout is:
this->layout_base (Type::typeinfowild);
/* TypeInfo for the mutable type. */
- this->layout_field (build_typeinfo (tm));
+ this->layout_field (build_typeinfo (d->loc, tm));
}
/* Layout of TypeInfo_Enum is:
this->layout_base (Type::typeinfoenum);
/* TypeInfo for enum members. */
- tree memtype = (ed->memtype) ? build_typeinfo (ed->memtype)
+ tree memtype = (ed->memtype) ? build_typeinfo (d->loc, ed->memtype)
: null_pointer_node;
this->layout_field (memtype);
this->layout_base (Type::typeinfopointer);
/* TypeInfo for pointer-to type. */
- this->layout_field (build_typeinfo (ti->next));
+ this->layout_field (build_typeinfo (d->loc, ti->next));
}
/* Layout of TypeInfo_Array is:
this->layout_base (Type::typeinfoarray);
/* TypeInfo for array of type. */
- this->layout_field (build_typeinfo (ti->next));
+ this->layout_field (build_typeinfo (d->loc, ti->next));
}
/* Layout of TypeInfo_StaticArray is:
this->layout_base (Type::typeinfostaticarray);
/* TypeInfo for array of type. */
- this->layout_field (build_typeinfo (ti->next));
+ this->layout_field (build_typeinfo (d->loc, ti->next));
/* Static array length. */
this->layout_field (size_int (ti->dim->toInteger ()));
this->layout_base (Type::typeinfoassociativearray);
/* TypeInfo for value of type. */
- this->layout_field (build_typeinfo (ti->next));
+ this->layout_field (build_typeinfo (d->loc, ti->next));
/* TypeInfo for index of type. */
- this->layout_field (build_typeinfo (ti->index));
+ this->layout_field (build_typeinfo (d->loc, ti->index));
}
/* Layout of TypeInfo_Vector is:
this->layout_base (Type::typeinfovector);
/* TypeInfo for equivalent static array. */
- this->layout_field (build_typeinfo (ti->basetype));
+ this->layout_field (build_typeinfo (d->loc, ti->basetype));
}
/* Layout of TypeInfo_Function is:
this->layout_base (Type::typeinfofunction);
/* TypeInfo for function return value. */
- this->layout_field (build_typeinfo (ti->next));
+ this->layout_field (build_typeinfo (d->loc, ti->next));
/* Mangled name of function declaration. */
this->layout_string (d->tinfo->deco);
this->layout_base (Type::typeinfodelegate);
/* TypeInfo for delegate return value. */
- this->layout_field (build_typeinfo (ti->next));
+ this->layout_field (build_typeinfo (d->loc, ti->next));
/* Mangled name of delegate declaration. */
this->layout_string (d->tinfo->deco);
flags |= ClassFlags::noPointers;
Lhaspointers:
- this->layout_field (size_int (flags));
+ this->layout_field (build_integer_cst (flags, d_uint_type));
/* void *deallocator; */
tree ddtor = (cd->aggDelete)
if (cd->isCOMinterface ())
flags |= ClassFlags::isCOMclass;
- this->layout_field (size_int (flags));
+ this->layout_field (build_integer_cst (flags, d_uint_type));
/* void *deallocator;
OffsetTypeInfo[] m_offTi; (not implemented)
StructFlags::Type m_flags = 0;
if (ti->hasPointers ())
m_flags |= StructFlags::hasPointers;
- this->layout_field (size_int (m_flags));
+ this->layout_field (build_integer_cst (m_flags, d_uint_type));
/* void function(void*) xdtor; */
tree dtor = (sd->dtor) ? build_address (get_symbol_decl (sd->dtor))
this->layout_field (null_pointer_node);
/* uint m_align; */
- this->layout_field (size_int (ti->alignsize ()));
+ this->layout_field (build_integer_cst (ti->alignsize (), d_uint_type));
if (global.params.is64bit)
{
/* TypeInfo m_arg1; */
- tree arg1type = (sd->arg1type) ? build_typeinfo (sd->arg1type)
+ tree arg1type = (sd->arg1type) ? build_typeinfo (d->loc, sd->arg1type)
: null_pointer_node;
this->layout_field (arg1type);
/* TypeInfo m_arg2; */
- tree arg2type = (sd->arg2type) ? build_typeinfo (sd->arg2type)
+ tree arg2type = (sd->arg2type) ? build_typeinfo (d->loc, sd->arg2type)
: null_pointer_node;
this->layout_field (arg2type);
}
{
Parameter *arg = (*ti->arguments)[i];
CONSTRUCTOR_APPEND_ELT (elms, size_int (i),
- build_typeinfo (arg->type));
+ build_typeinfo (d->loc, arg->type));
}
tree ctor = build_constructor (build_ctype (satype), elms);
tree decl = build_artificial_decl (TREE_TYPE (ctor), ctor);
tree
layout_typeinfo (TypeInfoDeclaration *d)
{
+ if (!Type::dtypeinfo)
+ create_frontend_tinfo_types ();
+
tree type = TREE_TYPE (get_typeinfo_decl (d));
TypeInfoVisitor v = TypeInfoVisitor (type);
d->accept (&v);
tree
layout_classinfo (ClassDeclaration *cd)
{
+ if (!Type::dtypeinfo)
+ create_frontend_tinfo_types ();
+
TypeInfoClassDeclaration *d = TypeInfoClassDeclaration::create (cd->type);
tree type = TREE_TYPE (get_classinfo_decl (cd));
TypeInfoVisitor v = TypeInfoVisitor (type);
/* Returns typeinfo reference for TYPE. */
tree
-build_typeinfo (Type *type)
+build_typeinfo (const Loc &loc, Type *type)
{
+ if (!global.params.useTypeInfo)
+ {
+ static int warned = 0;
+
+ if (!warned)
+ {
+ error_at (make_location_t (loc),
+ "%<object.TypeInfo%> cannot be used with %<-fno-rtti%>");
+ warned = 1;
+ }
+ }
+
gcc_assert (type->ty != Terror);
create_typeinfo (type, NULL);
return build_address (get_typeinfo_decl (type->vtinfo));
void
layout_cpp_typeinfo (ClassDeclaration *cd)
{
+ if (!Type::dtypeinfo)
+ create_frontend_tinfo_types ();
+
gcc_assert (cd->isCPPclass ());
tree decl = get_cpp_typeinfo_decl (cd);
void
create_typeinfo (Type *type, Module *mod)
{
+ if (!Type::dtypeinfo)
+ create_frontend_tinfo_types ();
+
/* Do this since not all Type's are merged. */
Type *t = type->merge2 ();
Identifier *ident;
array_type_node, array_type_node,
ptr_type_node, ptr_type_node,
ptr_type_node, ptr_type_node,
- size_type_node, ptr_type_node,
- ptr_type_node, size_type_node,
+ d_uint_type, ptr_type_node,
+ ptr_type_node, d_uint_type,
ptr_type_node, argtype, argtype, NULL);
}
t->vtinfo = TypeInfoStructDeclaration::create (t);