aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorIain Buclaw <ibuclaw@gdcproject.org>2020-07-21 19:59:00 +0200
committerIain Buclaw <ibuclaw@gdcproject.org>2020-08-03 11:18:46 +0200
commit2b1c2a4bd9fb555dccde5d67d6da64547064e0e6 (patch)
tree5da49e400890cbbb33d45ca68f9c47e323bf2baf /gcc
parent58cfec3a6e756b534b33787e51c52f5fc63b53ab (diff)
downloadgcc-2b1c2a4bd9fb555dccde5d67d6da64547064e0e6.zip
gcc-2b1c2a4bd9fb555dccde5d67d6da64547064e0e6.tar.gz
gcc-2b1c2a4bd9fb555dccde5d67d6da64547064e0e6.tar.bz2
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.
Diffstat (limited to 'gcc')
-rw-r--r--gcc/d/d-codegen.cc53
-rw-r--r--gcc/d/d-tree.h1
-rw-r--r--gcc/d/decl.cc5
-rw-r--r--gcc/testsuite/gdc.dg/pr96254a.d28
-rw-r--r--gcc/testsuite/gdc.dg/pr96254b.d24
5 files changed, 89 insertions, 22 deletions
diff --git a/gcc/d/d-codegen.cc b/gcc/d/d-codegen.cc
index 2dce09d..73a6a34 100644
--- a/gcc/d/d-codegen.cc
+++ b/gcc/d/d-codegen.cc
@@ -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)
diff --git a/gcc/d/d-tree.h b/gcc/d/d-tree.h
index df317d5..2be80dd 100644
--- a/gcc/d/d-tree.h
+++ b/gcc/d/d-tree.h
@@ -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 *);
diff --git a/gcc/d/decl.cc b/gcc/d/decl.cc
index 15eb9a4..72c8a8c 100644
--- a/gcc/d/decl.cc
+++ b/gcc/d/decl.cc
@@ -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;
diff --git a/gcc/testsuite/gdc.dg/pr96254a.d b/gcc/testsuite/gdc.dg/pr96254a.d
new file mode 100644
index 0000000..e5dd124
--- /dev/null
+++ b/gcc/testsuite/gdc.dg/pr96254a.d
@@ -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; })());
+}
diff --git a/gcc/testsuite/gdc.dg/pr96254b.d b/gcc/testsuite/gdc.dg/pr96254b.d
new file mode 100644
index 0000000..02e3c48
--- /dev/null
+++ b/gcc/testsuite/gdc.dg/pr96254b.d
@@ -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);
+}