aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
Diffstat (limited to 'gcc')
-rw-r--r--gcc/ChangeLog8
-rw-r--r--gcc/c-decl.c34
-rw-r--r--gcc/gimplify.c13
-rw-r--r--gcc/testsuite/ChangeLog5
-rw-r--r--gcc/testsuite/gcc.dg/typename-vla-1.c17
-rw-r--r--gcc/testsuite/gnat.dg/forward_vla.adb20
6 files changed, 96 insertions, 1 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index 3292139..f9596e8 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,3 +1,11 @@
+2006-10-06 Olivier Hainque <hainque@adacore.com>
+
+ * gimplify.c (gimplify_type_sizes) [POINTER_TYPE, REFERENCE_TYPE]:
+ Don't recurse on the pointed-to type.
+ * c-decl.c (grokdeclarator) [cdk_pointer]: If we are in a NORMAL or
+ DECL context, attach an artificial TYPE_DECL to anonymous pointed-to
+ types with components of variable size.
+
2006-10-06 Danny Smith <dannysmith@users.sourceforge.net>
config/i386/mingw32.h (GOMP_SELF_SPECS): Add -mthreads for openmp.
diff --git a/gcc/c-decl.c b/gcc/c-decl.c
index fd20078..6379a1e 100644
--- a/gcc/c-decl.c
+++ b/gcc/c-decl.c
@@ -4471,6 +4471,40 @@ grokdeclarator (const struct c_declarator *declarator,
type = c_build_qualified_type (type, type_quals);
size_varies = 0;
+ /* When the pointed-to type involves components of variable size,
+ care must be taken to ensure that the size evaluation code is
+ emitted early enough to dominate all the possible later uses
+ and late enough for the variables on which it depends to have
+ been assigned.
+
+ This is expected to happen automatically when the pointed-to
+ type has a name/declaration of it's own, but special attention
+ is required if the type is anonymous.
+
+ We handle the NORMAL and FIELD contexts here by attaching an
+ artificial TYPE_DECL to such pointed-to type. This forces the
+ sizes evaluation at a safe point and ensures it is not deferred
+ until e.g. within a deeper conditional context.
+
+ We expect nothing to be needed here for PARM or TYPENAME.
+ Pushing a TYPE_DECL at this point for TYPENAME would actually
+ be incorrect, as we might be in the middle of an expression
+ with side effects on the pointed-to type size "arguments" prior
+ to the pointer declaration point and the fake TYPE_DECL in the
+ enclosing context would force the size evaluation prior to the
+ side effects. */
+
+ if (!TYPE_NAME (type)
+ && (decl_context == NORMAL || decl_context == FIELD)
+ && variably_modified_type_p (type, NULL_TREE))
+ {
+ tree decl = build_decl (TYPE_DECL, NULL_TREE, type);
+ DECL_ARTIFICIAL (decl) = 1;
+ pushdecl (decl);
+ finish_decl (decl, NULL_TREE, NULL_TREE);
+ TYPE_NAME (type) = decl;
+ }
+
type = build_pointer_type (type);
/* Process type qualifiers (such as const or volatile)
diff --git a/gcc/gimplify.c b/gcc/gimplify.c
index 84c7219..faa5b48 100644
--- a/gcc/gimplify.c
+++ b/gcc/gimplify.c
@@ -6043,7 +6043,18 @@ gimplify_type_sizes (tree type, tree *list_p)
case POINTER_TYPE:
case REFERENCE_TYPE:
- gimplify_type_sizes (TREE_TYPE (type), list_p);
+ /* We used to recurse on the pointed-to type here, which turned out to
+ be incorrect because its definition might refer to variables not
+ yet initialized at this point if a forward declaration is involved.
+
+ It was actually useful for anonymous pointed-to types to ensure
+ that the sizes evaluation dominates every possible later use of the
+ values. Restricting to such types here would be safe since there
+ is no possible forward declaration around, but would introduce a
+ undesireable middle-end semantic to anonymity. We then defer to
+ front-ends the responsibilty of ensuring that the sizes are
+ evaluated both early and late enough, e.g. by attaching artifical
+ type declarations to the tree. */
break;
default:
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index 4754970..43988d7 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -1,3 +1,8 @@
+2006-10-06 Olivier Hainque <hainque@adacore.com>
+
+ * gcc.dg/typename-vla-1.c: New case.
+ * gnat.dg/forward_vla.adb: New case.
+
2006-10-06 Jakub Jelinek <jakub@redhat.com>
PR tree-optimization/29290
diff --git a/gcc/testsuite/gcc.dg/typename-vla-1.c b/gcc/testsuite/gcc.dg/typename-vla-1.c
new file mode 100644
index 0000000..1616513
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/typename-vla-1.c
@@ -0,0 +1,17 @@
+/* PR c/21536 */
+/* { dg-do run } */
+/* { dg-options "-O2 -Wuninitialized" } */
+
+extern void abort (void);
+extern void exit (int);
+
+int
+main (void)
+{
+ int a = 1;
+ if (sizeof (*(++a, (char (*)[a])0)) != 2)
+ abort ();
+ exit (0);
+}
+
+
diff --git a/gcc/testsuite/gnat.dg/forward_vla.adb b/gcc/testsuite/gnat.dg/forward_vla.adb
new file mode 100644
index 0000000..515112b
--- /dev/null
+++ b/gcc/testsuite/gnat.dg/forward_vla.adb
@@ -0,0 +1,20 @@
+-- { dg-do compile }
+-- { dg-options "-O2 -gnatp -Wuninitialized" }
+
+procedure Forward_Vla is
+
+ function N return Natural is begin return 1; end;
+
+ type Sequence;
+ type Sequence_Access is access all Sequence;
+
+ Ptr : Sequence_Access := null; -- freeze access type
+
+ Sequence_Length : Natural := N;
+ type Sequence is array (1 .. Sequence_Length) of Natural;
+
+ Seq : Sequence;
+begin
+ Seq (1) := 0;
+end;
+