diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index 329213934531c9fa5f221b8eb2cabc16b63066f8..f9596e82c321cb1fb9999833965908c2a6421476 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 fd2007803fae6b51e60f0d3f9940966b287c88c9..6379a1e29740210e151e2fb1dfcdfd2efa0dd6db 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 84c7219ce0395fb5c6077fba0feafcca9ba897b3..faa5b48baad953c4875f40312f818915b2437f05 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 4754970e48c149b1dc764e835fcda4597c35909e..43988d7250e2c07aafb90b842542bde6964616a6 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 0000000000000000000000000000000000000000..16165131287d11342da68c0f2496393325f4ec2e
--- /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 0000000000000000000000000000000000000000..515112b83e347cf89530fdd50d733f53ff42f841
--- /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;
+