d: Fix ICE using non-local variable: internal compiler error: Segmentation fault
Moves no frame access error to own function, adding use of it for both when get_framedecl() cannot find a path to the outer function frame, and guarding get_decl_tree() from recursively calling itself. gcc/d/ChangeLog: PR d/96254 * d-codegen.cc (error_no_frame_access): New. (get_frame_for_symbol): Use fdparent name in error message. (get_framedecl): Replace call to assert with error. * d-tree.h (error_no_frame_access): Declare. * decl.cc (get_decl_tree): Detect recursion and error. gcc/testsuite/ChangeLog: PR d/96254 * gdc.dg/pr96254a.d: New test. * gdc.dg/pr96254b.d: New test.
This commit is contained in:
parent
58cfec3a6e
commit
2b1c2a4bd9
@ -2127,6 +2127,17 @@ build_vthis_function (tree basetype, tree type)
|
||||
return fntype;
|
||||
}
|
||||
|
||||
/* Raise an error at that the context pointer of the function or object SYM is
|
||||
not accessible from the current scope. */
|
||||
|
||||
tree
|
||||
error_no_frame_access (Dsymbol *sym)
|
||||
{
|
||||
error_at (input_location, "cannot get frame pointer to %qs",
|
||||
sym->toPrettyChars ());
|
||||
return null_pointer_node;
|
||||
}
|
||||
|
||||
/* If SYM is a nested function, return the static chain to be
|
||||
used when calling that function from the current function.
|
||||
|
||||
@ -2191,7 +2202,7 @@ get_frame_for_symbol (Dsymbol *sym)
|
||||
{
|
||||
error_at (make_location_t (sym->loc),
|
||||
"%qs is a nested function and cannot be accessed from %qs",
|
||||
fd->toPrettyChars (), thisfd->toPrettyChars ());
|
||||
fdparent->toPrettyChars (), thisfd->toPrettyChars ());
|
||||
return null_pointer_node;
|
||||
}
|
||||
|
||||
@ -2202,39 +2213,35 @@ get_frame_for_symbol (Dsymbol *sym)
|
||||
while (fd != dsym)
|
||||
{
|
||||
/* Check if enclosing function is a function. */
|
||||
FuncDeclaration *fd = dsym->isFuncDeclaration ();
|
||||
FuncDeclaration *fdp = dsym->isFuncDeclaration ();
|
||||
Dsymbol *parent = dsym->toParent2 ();
|
||||
|
||||
if (fd != NULL)
|
||||
if (fdp != NULL)
|
||||
{
|
||||
if (fdparent == fd->toParent2 ())
|
||||
if (fdparent == parent)
|
||||
break;
|
||||
|
||||
gcc_assert (fd->isNested () || fd->vthis);
|
||||
dsym = dsym->toParent2 ();
|
||||
gcc_assert (fdp->isNested () || fdp->vthis);
|
||||
dsym = parent;
|
||||
continue;
|
||||
}
|
||||
|
||||
/* Check if enclosed by an aggregate. That means the current
|
||||
function must be a member function of that aggregate. */
|
||||
AggregateDeclaration *ad = dsym->isAggregateDeclaration ();
|
||||
AggregateDeclaration *adp = dsym->isAggregateDeclaration ();
|
||||
|
||||
if (ad == NULL)
|
||||
goto Lnoframe;
|
||||
if (ad->isClassDeclaration () && fdparent == ad->toParent2 ())
|
||||
break;
|
||||
if (ad->isStructDeclaration () && fdparent == ad->toParent2 ())
|
||||
break;
|
||||
|
||||
if (!ad->isNested () || !ad->vthis)
|
||||
if (adp != NULL)
|
||||
{
|
||||
Lnoframe:
|
||||
error_at (make_location_t (thisfd->loc),
|
||||
"cannot get frame pointer to %qs",
|
||||
sym->toPrettyChars ());
|
||||
return null_pointer_node;
|
||||
if ((adp->isClassDeclaration () || adp->isStructDeclaration ())
|
||||
&& fdparent == parent)
|
||||
break;
|
||||
}
|
||||
|
||||
dsym = dsym->toParent2 ();
|
||||
/* No frame to outer function found. */
|
||||
if (!adp || !adp->isNested () || !adp->vthis)
|
||||
return error_no_frame_access (sym);
|
||||
|
||||
dsym = parent;
|
||||
}
|
||||
}
|
||||
|
||||
@ -2724,8 +2731,10 @@ get_framedecl (FuncDeclaration *inner, FuncDeclaration *outer)
|
||||
break;
|
||||
}
|
||||
|
||||
if (fd != outer)
|
||||
return error_no_frame_access (outer);
|
||||
|
||||
/* Go get our frame record. */
|
||||
gcc_assert (fd == outer);
|
||||
tree frame_type = FRAMEINFO_TYPE (get_frameinfo (outer));
|
||||
|
||||
if (frame_type != NULL_TREE)
|
||||
|
@ -575,6 +575,7 @@ extern tree d_build_call (TypeFunction *, tree, tree, Expressions *);
|
||||
extern tree d_assert_call (const Loc &, libcall_fn, tree = NULL_TREE);
|
||||
extern tree build_float_modulus (tree, tree, tree);
|
||||
extern tree build_vthis_function (tree, tree);
|
||||
extern tree error_no_frame_access (Dsymbol *);
|
||||
extern tree get_frame_for_symbol (Dsymbol *);
|
||||
extern tree build_vthis (AggregateDeclaration *);
|
||||
extern void build_closure (FuncDeclaration *);
|
||||
|
@ -1480,6 +1480,11 @@ get_decl_tree (Declaration *decl)
|
||||
AggregateDeclaration *ad = fd->isThis ();
|
||||
gcc_assert (ad != NULL);
|
||||
|
||||
/* The parent function is for the same `this' declaration we are
|
||||
building a chain to. Non-local declaration is inaccessible. */
|
||||
if (fd->vthis == vd)
|
||||
return error_no_frame_access (fd);
|
||||
|
||||
t = get_decl_tree (fd->vthis);
|
||||
Dsymbol *outer = fd;
|
||||
|
||||
|
28
gcc/testsuite/gdc.dg/pr96254a.d
Normal file
28
gcc/testsuite/gdc.dg/pr96254a.d
Normal file
@ -0,0 +1,28 @@
|
||||
// https://gcc.gnu.org/bugzilla/show_bug.cgi?id=96254
|
||||
// { dg-do compile }
|
||||
struct map(alias fun)
|
||||
{
|
||||
@property run()
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
struct Task(Args)
|
||||
{
|
||||
Args _args;
|
||||
}
|
||||
|
||||
template reduce(functions...)
|
||||
{
|
||||
auto reduce(Args)(Args args)
|
||||
{
|
||||
alias RTask = Task!(typeof(args));
|
||||
auto task = RTask();
|
||||
}
|
||||
}
|
||||
|
||||
void main() // { dg-error "'D main' is a nested function and cannot be accessed" }
|
||||
{
|
||||
immutable delta = 1;
|
||||
reduce!"a + b"(map!({ immutable x = delta; })());
|
||||
}
|
24
gcc/testsuite/gdc.dg/pr96254b.d
Normal file
24
gcc/testsuite/gdc.dg/pr96254b.d
Normal file
@ -0,0 +1,24 @@
|
||||
// https://gcc.gnu.org/bugzilla/show_bug.cgi?id=96254
|
||||
// { dg-do compile }
|
||||
mixin template test()
|
||||
{
|
||||
int next;
|
||||
}
|
||||
|
||||
void foo(alias l)()
|
||||
{
|
||||
l.next = 0; // { dg-error "cannot get frame pointer to 'D main'" }
|
||||
}
|
||||
|
||||
void bar(alias l, alias t)()
|
||||
{
|
||||
l.next = 0; // { dg-error "cannot get frame pointer to 'D main'" }
|
||||
}
|
||||
|
||||
void main()
|
||||
{
|
||||
mixin test l1;
|
||||
mixin test l2;
|
||||
foo!(l1);
|
||||
bar!(l1,l2);
|
||||
}
|
Loading…
Reference in New Issue
Block a user