d: Improve TypeInfo errors when compiling in -fno-rtti mode

The existing TypeInfo errors can be cryptic.  This alters the diagnostic
to include which expression is requiring `object.TypeInfo'.

gcc/d/ChangeLog:

	* d-tree.h (check_typeinfo_type): Add Expression* parameter.
	(build_typeinfo): Likewise.  Declare new override.
	* expr.cc (ExprVisitor): Call build_typeinfo with Expression*.
	* typeinfo.cc (check_typeinfo_type): Include expression in the
	diagnostic message.
	(build_typeinfo): New override.

gcc/testsuite/ChangeLog:

	* gdc.dg/rtti1.d: New test.

(cherry picked from commit e55eda2385)
This commit is contained in:
Iain Buclaw 2022-06-13 14:35:38 +02:00
parent 54ec210b72
commit 5f7a1a436c
4 changed files with 63 additions and 30 deletions

View File

@ -671,8 +671,9 @@ extern tree layout_classinfo (ClassDeclaration *);
extern unsigned base_vtable_offset (ClassDeclaration *, BaseClass *);
extern tree get_typeinfo_decl (TypeInfoDeclaration *);
extern tree get_classinfo_decl (ClassDeclaration *);
extern void check_typeinfo_type (const Loc &, Scope *);
extern tree build_typeinfo (const Loc &, Type *);
extern void check_typeinfo_type (const Loc &, Scope *, Expression * = NULL);
extern tree build_typeinfo (const Loc &, Type *, Expression * = NULL);
extern tree build_typeinfo (Expression *, Type *);
extern void create_typeinfo (Type *, Module *);
extern void create_tinfo_types (Module *);
extern void layout_cpp_typeinfo (ClassDeclaration *);

View File

@ -427,7 +427,7 @@ public:
tree result = build_libcall (LIBCALL_ADEQ2, e->type, 3,
d_array_convert (e->e1),
d_array_convert (e->e2),
build_typeinfo (e->loc, t1array));
build_typeinfo (e, t1array));
if (e->op == EXP::notEqual)
result = build1 (TRUTH_NOT_EXPR, build_ctype (e->type), result);
@ -450,7 +450,7 @@ public:
{
/* Use _aaEqual() for associative arrays. */
tree result = build_libcall (LIBCALL_AAEQUAL, e->type, 3,
build_typeinfo (e->loc, tb1),
build_typeinfo (e, tb1),
build_expr (e->e1),
build_expr (e->e2));
@ -484,7 +484,7 @@ public:
/* Build a call to _aaInX(). */
this->result_ = build_libcall (LIBCALL_AAINX, e->type, 3,
build_expr (e->e2),
build_typeinfo (e->loc, tkey),
build_typeinfo (e, tkey),
build_address (key));
}
@ -728,13 +728,13 @@ public:
size_int (ndims), build_address (var));
result = build_libcall (LIBCALL_ARRAYCATNTX, e->type, 2,
build_typeinfo (e->loc, e->type), arrs);
build_typeinfo (e, e->type), arrs);
}
else
{
/* Handle single concatenation (a ~ b). */
result = build_libcall (LIBCALL_ARRAYCATT, e->type, 3,
build_typeinfo (e->loc, e->type),
build_typeinfo (e, e->type),
d_array_convert (etype, e->e1),
d_array_convert (etype, e->e2));
}
@ -946,7 +946,7 @@ public:
/* So we can call postblits on const/immutable objects. */
Type *tm = etype->unSharedOf ()->mutableOf ();
tree ti = build_typeinfo (e->loc, tm);
tree ti = build_typeinfo (e, tm);
/* Generate: _d_arraysetassign (t1.ptr, &t2, t1.length, ti); */
result = build_libcall (LIBCALL_ARRAYSETASSIGN, Type::tvoid, 4,
@ -1020,7 +1020,7 @@ public:
{
/* Generate: _d_arrayassign(ti, from, to); */
this->result_ = build_libcall (LIBCALL_ARRAYASSIGN, e->type, 3,
build_typeinfo (e->loc, etype),
build_typeinfo (e, etype),
d_array_convert (e->e2),
d_array_convert (e->e1));
}
@ -1165,7 +1165,7 @@ public:
Type *arrtype = (e->type->ty == TY::Tsarray)
? etype->arrayOf () : e->type;
tree result = build_libcall (libcall, arrtype, 4,
build_typeinfo (e->loc, etype),
build_typeinfo (e, etype),
d_array_convert (e->e2),
d_array_convert (e->e1),
build_address (elembuf));
@ -1236,13 +1236,13 @@ public:
{
libcall = LIBCALL_AAGETY;
ptr = build_address (build_expr (e->e1));
tinfo = build_typeinfo (e->loc, tb1->unSharedOf ()->mutableOf ());
tinfo = build_typeinfo (e, tb1->unSharedOf ()->mutableOf ());
}
else
{
libcall = LIBCALL_AAGETRVALUEX;
ptr = build_expr (e->e1);
tinfo = build_typeinfo (e->loc, tkey);
tinfo = build_typeinfo (e, tkey);
}
/* Index the associative array. */
@ -1470,7 +1470,7 @@ public:
this->result_ = build_libcall (LIBCALL_AADELX, Type::tbool, 3,
build_expr (e->e1),
build_typeinfo (e->loc, tkey),
build_typeinfo (e, tkey),
build_address (index));
}
else
@ -2024,7 +2024,7 @@ public:
{
if (Type *tid = isType (e->obj))
{
tree ti = build_typeinfo (e->loc, tid);
tree ti = build_typeinfo (e, tid);
/* If the typeinfo is at an offset. */
if (tid->vtinfo->offset)
@ -2358,7 +2358,7 @@ public:
/* Generate: _d_newitemT() */
libcall_fn libcall = htype->isZeroInit ()
? LIBCALL_NEWITEMT : LIBCALL_NEWITEMIT;
tree arg = build_typeinfo (e->loc, e->newtype);
tree arg = build_typeinfo (e, e->newtype);
new_call = build_libcall (libcall, tb, 1, arg);
if (e->member || !e->arguments)
@ -2426,7 +2426,7 @@ public:
libcall_fn libcall = tarray->next->isZeroInit ()
? LIBCALL_NEWARRAYT : LIBCALL_NEWARRAYIT;
result = build_libcall (libcall, tb, 2,
build_typeinfo (e->loc, e->type),
build_typeinfo (e, e->type),
build_expr (arg));
}
else
@ -2458,7 +2458,7 @@ public:
libcall_fn libcall = telem->isZeroInit ()
? LIBCALL_NEWARRAYMTX : LIBCALL_NEWARRAYMITX;
tree tinfo = build_typeinfo (e->loc, e->type);
tree tinfo = build_typeinfo (e, e->type);
tree dims = d_array_value (build_ctype (Type::tsize_t->arrayOf ()),
size_int (e->arguments->length),
build_address (var));
@ -2485,7 +2485,7 @@ public:
libcall_fn libcall = tpointer->next->isZeroInit (e->loc)
? LIBCALL_NEWITEMT : LIBCALL_NEWITEMIT;
tree arg = build_typeinfo (e->loc, e->newtype);
tree arg = build_typeinfo (e, e->newtype);
result = build_libcall (libcall, tb, 1, arg);
if (e->arguments && e->arguments->length == 1)
@ -2730,7 +2730,7 @@ public:
/* Allocate space on the memory managed heap. */
tree mem = build_libcall (LIBCALL_ARRAYLITERALTX,
etype->pointerTo (), 2,
build_typeinfo (e->loc, etype->arrayOf ()),
build_typeinfo (e, etype->arrayOf ()),
size_int (e->elements->length));
mem = d_save_expr (mem);
@ -2787,7 +2787,7 @@ public:
build_address (avals));
tree mem = build_libcall (LIBCALL_ASSOCARRAYLITERALTX, Type::tvoidptr, 3,
build_typeinfo (e->loc, ta), keys, vals);
build_typeinfo (e, ta), keys, vals);
/* Return an associative array pointed to by MEM. */
tree aatype = build_ctype (ta);

View File

@ -1394,21 +1394,29 @@ get_classinfo_decl (ClassDeclaration *decl)
}
/* Performs sanity checks on the `object.TypeInfo' type, raising an error if
RTTI is disabled, or the type is missing. */
RTTI is disabled, or the type is missing. LOC is the location used for error
messages. SC is the context, and EXPR is expression where TypeInfo is
required from, if either are set. */
void
check_typeinfo_type (const Loc &loc, Scope *sc)
check_typeinfo_type (const Loc &loc, Scope *sc, Expression *expr)
{
if (!global.params.useTypeInfo)
{
static int warned = 0;
/* Even when compiling without RTTI we should still be able to evaluate
TypeInfo at compile-time, just not at run-time. */
if (!warned && (!sc || !(sc->flags & SCOPEctfe)))
if (!sc || !(sc->flags & SCOPEctfe))
{
error_at (make_location_t (loc),
"%<object.TypeInfo%> cannot be used with %<-fno-rtti%>");
static int warned = 0;
if (expr != NULL)
error_at (make_location_t (loc),
"expression %qs requires %<object.TypeInfo%> and cannot "
"be used with %<-fno-rtti%>", expr->toChars ());
else if (!warned)
error_at (make_location_t (loc),
"%<object.TypeInfo%> cannot be used with %<-fno-rtti%>");
warned = 1;
}
}
@ -1429,17 +1437,23 @@ check_typeinfo_type (const Loc &loc, Scope *sc)
}
}
/* Returns typeinfo reference for TYPE. */
/* Returns typeinfo reference for TYPE. LOC is the location used for error
messages. EXPR is the expression where TypeInfo is required, if set. */
tree
build_typeinfo (const Loc &loc, Type *type)
build_typeinfo (const Loc &loc, Type *type, Expression *expr)
{
gcc_assert (type->ty != TY::Terror);
check_typeinfo_type (loc, NULL);
check_typeinfo_type (loc, NULL, expr);
create_typeinfo (type, NULL);
return build_address (get_typeinfo_decl (type->vtinfo));
}
tree build_typeinfo (Expression *expr, Type *type)
{
return build_typeinfo (expr->loc, type, expr);
}
/* Like layout_classinfo, but generates an Object that wraps around a
pointer to C++ type_info so it can be distinguished from D TypeInfo. */

View File

@ -0,0 +1,18 @@
// { dg-do compile }
// { dg-options "-fno-rtti" }
// { dg-shouldfail "expressions depend on TypeInfo" }
int* testInExp(int key, int[int] aa)
{
return key in aa; // { dg-error "requires .object.TypeInfo. and cannot be used with .-fno-rtti." }
}
bool testAAEqual(int[string] aa1, int[string] aa2)
{
return aa1 == aa2; // { dg-error "requires .object.TypeInfo. and cannot be used with .-fno-rtti." }
}
string testConcat(string a, string b)
{
return a ~ b; // { dg-error "requires .object.TypeInfo. and cannot be used with .-fno-rtti." }
}