This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

PATCH RFA: -Wc++-compat warning about typedefs and struct fields


In C++, this code is invalid:

typedef int myint;
struct s { myint myint; };

It is invalid because when parsing the type of the field "myint", a
lookup of the type name "myint" is done first within the struct.  That
lookup will return the field, and of course a field is not a type.

Similarly, in C++ this code is invalid:

typedef int myint;
struct s1 { int myint; struct s2 { myint f2; } f1; };

Again, the lookup of the type name "myint" when parsing the field "f2"
will find the field "myint" in s1, not the type.

This patch implements these warnings in the C frontend.  I gathered the
existing struct_types vector into a struct, and replace the in_struct
static variable with struct_parse_info.  The extra storage is relatively
minor, and is only used when -Wc++-compat is specified.  This patch
requires approval from the C frontend maintainers.

I also fixed the only instance where this causes trouble in the gcc code
base: dse.c has a field named "bitmap" of type "bitmap".

Bootstrapped and tested on x86_64-unknown-linux-gnu.  OK for mainline?

Ian


gcc/ChangeLog:

2009-06-18  Ian Lance Taylor  <iant@google.com>

	* dse.c (struct store_info): Rename bitmap field to bmap.  Change
	all uses.

	* c-decl.c (in_struct, struct_types): Remove.
	(struct c_binding): Add in_struct field.
	(c_binding_ptr): Define type, along with VEC.
	(struct c_struct_parse_info): Define.
	(struct_parse_info): New static variable.
	(bind): Initialize in_struct field.
	(start_struct): Remove enclosing_in_struct and
	enclosing_struct_types parameters.  Add
	enclosing_struct_parse_info parameter.  Change all callers.  Set
	struct_parse_info rather than in_struct and struct_types.
	(grokfield): If -Wc++-compat and there is a symbol binding for the
	field name, set the in_struct flag and push it on the
	struct_parse_info->fields vector.
	(warn_cxx_compat_finish_struct): New static function.
	(finish_struct): Remove enclosing_in_struct and
	enclosing_struct_types parameters.  Add
	enclosing_struct_parse_info parameter.  Change all callers.  Don't
	set C_TYPE_DEFINED_IN_STRUCT here.  Call
	warn_cxx_compat_finish_struct.  Free struct_parse_info and set to
	parameter.  Only push on struct_types if warn_cxx_compat.
	(finish_enum): Only push on struct_types if warn_cxx_compat.
	(declspecs_add_type): Add loc parameter.  Change all callers.
	Change all error calls to error_at.  Pass loc, not input_location,
	to pedwarn calls.  Warn if -Wc++-compat and a typedef name is
	defined in a struct.  If -Wc++-compat and parsing a struct, record
	that a typedef name was used.
	* c-parser.c (c_parser_declspecs): Get location to pass to
	declspecs_add_type.
	(c_parser_struct_or_union_specifier): Update calls to start_struct
	and finish_struct.
	* c-tree.h (struct c_struct_parse_info): Declare.
	(finish_struct, start_struct): Update declarations.
	(declspecs_add_type): Update declaration.

gcc/objc/ChangeLog:

2009-06-18  Ian Lance Taylor  <iant@google.com>

	* objc-act.c (objc_in_struct, objc_struct_types): Remove.
	(objc_struct_info): New static variable.
	(objc_start_struct): Pass &objc_struct_info, not &objc_in_struct
	and &objc_struct_types, to start_struct.
	(objc_finish_struct): Likewise for finish_struct.

gcc/objcp/ChangeLog:

2009-06-18  Ian Lance Taylor  <iant@google.com>

	* objcp-decl.h (start_struct): Remove in_struct and struct_types
	parameters.  Add struct_info parameter.
	(finish_struct): Likewise.

gcc/testsuite/ChangeLog:

2009-06-18  Ian Lance Taylor  <iant@google.com>

	* gcc.dg/Wcxx-compat-15.c: New testcase.


Index: c-decl.c
===================================================================
--- c-decl.c	(revision 148620)
+++ c-decl.c	(working copy)
@@ -126,15 +126,6 @@ static GTY(()) struct stmt_tree_s c_stmt
 tree c_break_label;
 tree c_cont_label;
 
-/* True if we are currently parsing the fields of a struct or
-   union.  */
-
-static bool in_struct;
-
-/* A list of types defined in the current struct or union.  */
-
-static VEC(tree,heap) *struct_types;
-
 /* Linked list of TRANSLATION_UNIT_DECLS for the translation units
    included in this invocation.  Note that the current translation
    unit is not included in this list.  */
@@ -223,7 +214,7 @@ struct GTY((chain_next ("%h.prev"))) c_b
   BOOL_BITFIELD invisible : 1;  /* normal lookup should ignore this binding */
   BOOL_BITFIELD nested : 1;     /* do not set DECL_CONTEXT when popping */
   BOOL_BITFIELD inner_comp : 1; /* incomplete array completed in inner scope */
-  /* one free bit */
+  BOOL_BITFIELD in_struct : 1;	/* currently defined as struct field */
   location_t locus;		/* location for nested bindings */
 };
 #define B_IN_SCOPE(b1, b2) ((b1)->depth == (b2)->depth)
@@ -513,6 +504,34 @@ static bool keep_next_level_flag;
 
 static bool next_is_function_body;
 
+/* A VEC of pointers to c_binding structures.  */
+
+typedef struct c_binding *c_binding_ptr;
+DEF_VEC_P(c_binding_ptr);
+DEF_VEC_ALLOC_P(c_binding_ptr,heap);
+
+/* Information that we keep for a struct or union while it is being
+   parsed.  */
+
+struct c_struct_parse_info
+{
+  /* If warn_cxx_compat, a list of types defined within this
+     struct.  */
+  VEC(tree,heap) *struct_types;
+  /* If warn_cxx_compat, a list of field names which have bindings,
+     and which are defined in this struct, but which are not defined
+     in any enclosing struct.  This is used to clear the in_struct
+     field of the c_bindings structure.  */
+  VEC(c_binding_ptr,heap) *fields;
+  /* If warn_cxx_compat, a list of typedef names used when defining
+     fields in this struct.  */
+  VEC(tree,heap) *typedefs_seen;
+};
+
+/* Information for the struct or union currently being parsed, or
+   NULL if not parsing a struct or union.  */
+static struct c_struct_parse_info *struct_parse_info;
+
 /* Forward declarations.  */
 static tree lookup_name_in_scope (tree, struct c_scope *);
 static tree c_make_fname_decl (location_t, tree, int);
@@ -588,6 +607,7 @@ bind (tree name, tree decl, struct c_sco
   b->invisible = invisible;
   b->nested = nested;
   b->inner_comp = 0;
+  b->in_struct = 0;
   b->locus = locus;
 
   b->u.type = NULL;
@@ -6276,16 +6296,14 @@ xref_tag (enum tree_code code, tree name
    LOC is the location of the struct's definition.
    CODE says which kind of tag NAME ought to be.
 
-   This stores the current value of the file static IN_STRUCT in
-   *ENCLOSING_IN_STRUCT, and sets IN_STRUCT to true.  Similarly, this
-   sets STRUCT_TYPES in *ENCLOSING_STRUCT_TYPES, and sets STRUCT_TYPES
-   to an empty vector.  The old values are restored in
-   finish_struct.  */
+   This stores the current value of the file static STRUCT_PARSE_INFO
+   in *ENCLOSING_STRUCT_PARSE_INFO, and points STRUCT_PARSE_INFO at a
+   new c_struct_parse_info structure.  The old value of
+   STRUCT_PARSE_INFO is restored in finish_struct.  */
 
 tree
 start_struct (location_t loc, enum tree_code code, tree name,
-    	      bool *enclosing_in_struct,
-	      VEC(tree,heap) **enclosing_struct_types)
+	      struct c_struct_parse_info **enclosing_struct_parse_info)
 {
   /* If there is already a tag defined at this scope
      (as a forward reference), just return it.  */
@@ -6333,10 +6351,11 @@ start_struct (location_t loc, enum tree_
   C_TYPE_BEING_DEFINED (ref) = 1;
   TYPE_PACKED (ref) = flag_pack_struct;
 
-  *enclosing_in_struct = in_struct;
-  *enclosing_struct_types = struct_types;
-  in_struct = true;
-  struct_types = VEC_alloc(tree, heap, 0);
+  *enclosing_struct_parse_info = struct_parse_info;
+  struct_parse_info = XNEW (struct c_struct_parse_info);
+  struct_parse_info->struct_types = VEC_alloc (tree, heap, 0);
+  struct_parse_info->fields = VEC_alloc (c_binding_ptr, heap, 0);
+  struct_parse_info->typedefs_seen = VEC_alloc (tree, heap, 0);
 
   /* FIXME: This will issue a warning for a use of a type defined
      within a statement expr used within sizeof, et. al.  This is not
@@ -6424,6 +6443,25 @@ grokfield (location_t loc,
   finish_decl (value, loc, NULL_TREE, NULL_TREE, NULL_TREE);
   DECL_INITIAL (value) = width;
 
+  if (warn_cxx_compat && DECL_NAME (value) != NULL_TREE)
+    {
+      /* If we currently have a binding for this field, set the
+	 in_struct field in the binding, so that we warn about lookups
+	 which find it.  */
+      struct c_binding *b = I_SYMBOL_BINDING (DECL_NAME (value));
+      if (b != NULL)
+	{
+	  /* If the in_struct field is not yet set, push it on a list
+	     to be cleared when this struct is finished.  */
+	  if (!b->in_struct)
+	    {
+	      VEC_safe_push (c_binding_ptr, heap,
+			     struct_parse_info->fields, b);
+	      b->in_struct = 1;
+	    }
+	}
+    }
+
   return value;
 }
 
@@ -6484,25 +6522,80 @@ detect_field_duplicates (tree fieldlist)
     }
 }
 
+/* Finish up struct info used by -Wc++-compat.  */
+
+static void
+warn_cxx_compat_finish_struct (tree fieldlist)
+{
+  unsigned int ix;
+  tree x;
+  struct c_binding *b;
+
+  /* Set the C_TYPE_DEFINED_IN_STRUCT flag for each type defined in
+     the current struct.  We do this now at the end of the struct
+     because the flag is used to issue visibility warnings, and we
+     only want to issue those warnings if the type is referenced
+     outside of the struct declaration.  */
+  for (ix = 0; VEC_iterate (tree, struct_parse_info->struct_types, ix, x); ++ix)
+    C_TYPE_DEFINED_IN_STRUCT (x) = 1;
+
+  /* The TYPEDEFS_SEEN field of STRUCT_PARSE_INFO is a list of
+     typedefs used when declaring fields in this struct.  If the name
+     of any of the fields is also a typedef name then the struct would
+     not parse in C++, because the C++ lookup rules say that the
+     typedef name would be looked up in the context of the struct, and
+     would thus be the field rather than the typedef.  */
+  if (!VEC_empty (tree, struct_parse_info->typedefs_seen)
+      && fieldlist != NULL_TREE)
+    {
+      /* Use a pointer_map from the name of the typedef to the decl.
+	 We can use a pointer_map because identifiers are interned.  */
+      struct pointer_set_t *tset = pointer_set_create ();
+
+      for (ix = 0;
+	   VEC_iterate (tree, struct_parse_info->typedefs_seen, ix, x);
+	   ++ix)
+	pointer_set_insert (tset, DECL_NAME (x));
+
+      for (x = fieldlist; x != NULL_TREE; x = TREE_CHAIN (x))
+	{
+	  if (pointer_set_contains (tset, DECL_NAME (x)))
+	    {
+	      warning_at (DECL_SOURCE_LOCATION (x), OPT_Wc___compat,
+			  ("using %qD as both field and typedef name is "
+			   "invalid in C++"),
+			  x);
+	      /* FIXME: It would be nice to report the location where
+		 the typedef name is used.  */
+	    }
+	}
+
+      pointer_set_destroy (tset);
+    }
+
+  /* For each field which has a binding and which was not defined in
+     an enclosing struct, clear the in_struct field.  */
+  for (ix = 0;
+       VEC_iterate (c_binding_ptr, struct_parse_info->fields, ix, b);
+       ++ix)
+    b->in_struct = 0;
+}
+
 /* Fill in the fields of a RECORD_TYPE or UNION_TYPE node, T.
    LOC is the location of the RECORD_TYPE or UNION_TYPE's definition.
    FIELDLIST is a chain of FIELD_DECL nodes for the fields.
    ATTRIBUTES are attributes to be applied to the structure.
 
-   ENCLOSING_IN_STRUCT is the value of IN_STRUCT, and
-   ENCLOSING_STRUCT_TYPES is the value of STRUCT_TYPES, when the
-   struct was started.  This sets the C_TYPE_DEFINED_IN_STRUCT flag
-   for any type defined in the current struct.  */
+   ENCLOSING_STRUCT_PARSE_INFO is the value of STRUCT_PARSE_INFO when
+   the struct was started.  */
 
 tree
 finish_struct (location_t loc, tree t, tree fieldlist, tree attributes,
-	       bool enclosing_in_struct,
-	       VEC(tree,heap) *enclosing_struct_types)
+	       struct c_struct_parse_info *enclosing_struct_parse_info)
 {
   tree x;
   bool toplevel = file_scope == current_scope;
   int saw_named_field;
-  unsigned int ix;
 
   /* If this type was previously laid out as a forward reference,
      make sure we lay it out again.  */
@@ -6760,23 +6853,22 @@ finish_struct (location_t loc, tree t, t
     add_stmt (build_stmt (loc,
 			  DECL_EXPR, build_decl (loc, TYPE_DECL, NULL, t)));
 
-  /* Set the C_TYPE_DEFINED_IN_STRUCT flag for each type defined in
-     the current struct.  We do this now at the end of the struct
-     because the flag is used to issue visibility warnings when using
-     -Wc++-compat, and we only want to issue those warnings if the
-     type is referenced outside of the struct declaration.  */
-  for (ix = 0; VEC_iterate (tree, struct_types, ix, x); ++ix)
-    C_TYPE_DEFINED_IN_STRUCT (x) = 1;
+  if (warn_cxx_compat)
+    warn_cxx_compat_finish_struct (fieldlist);
 
-  VEC_free (tree, heap, struct_types);
+  VEC_free (tree, heap, struct_parse_info->struct_types);
+  VEC_free (c_binding_ptr, heap, struct_parse_info->fields);
+  VEC_free (tree, heap, struct_parse_info->typedefs_seen);
+  XDELETE (struct_parse_info);
 
-  in_struct = enclosing_in_struct;
-  struct_types = enclosing_struct_types;
+  struct_parse_info = enclosing_struct_parse_info;
 
   /* If this struct is defined inside a struct, add it to
-     STRUCT_TYPES.  */
-  if (in_struct && !in_sizeof && !in_typeof && !in_alignof)
-    VEC_safe_push (tree, heap, struct_types, t);
+     struct_types.  */
+  if (warn_cxx_compat
+      && struct_parse_info != NULL
+      && !in_sizeof && !in_typeof && !in_alignof)
+    VEC_safe_push (tree, heap, struct_parse_info->struct_types, t);
 
   return t;
 }
@@ -6990,9 +7082,11 @@ finish_enum (tree enumtype, tree values,
   rest_of_type_compilation (enumtype, toplevel);
 
   /* If this enum is defined inside a struct, add it to
-     STRUCT_TYPES.  */
-  if (in_struct && !in_sizeof && !in_typeof && !in_alignof)
-    VEC_safe_push (tree, heap, struct_types, enumtype);
+     struct_types.  */
+  if (warn_cxx_compat
+      && struct_parse_info != NULL
+      && !in_sizeof && !in_typeof && !in_alignof)
+    VEC_safe_push (tree, heap, struct_parse_info->struct_types, enumtype);
 
   return enumtype;
 }
@@ -8254,7 +8348,8 @@ declspecs_add_qual (struct c_declspecs *
    returning SPECS.  */
 
 struct c_declspecs *
-declspecs_add_type (struct c_declspecs *specs, struct c_typespec spec)
+declspecs_add_type (location_t loc, struct c_declspecs *specs,
+		    struct c_typespec spec)
 {
   tree type = spec.spec;
   specs->non_sc_seen_p = true;
@@ -8271,7 +8366,7 @@ declspecs_add_type (struct c_declspecs *
       enum rid i = C_RID_CODE (type);
       if (specs->type)
 	{
-	  error ("two or more data types in declaration specifiers");
+	  error_at (loc, "two or more data types in declaration specifiers");
 	  return specs;
 	}
       if ((int) i <= (int) RID_LAST_MODIFIER)
@@ -8283,203 +8378,257 @@ declspecs_add_type (struct c_declspecs *
 	    case RID_LONG:
 	      if (specs->long_long_p)
 		{
-		  error ("%<long long long%> is too long for GCC");
+		  error_at (loc, "%<long long long%> is too long for GCC");
 		  break;
 		}
 	      if (specs->long_p)
 		{
 		  if (specs->typespec_word == cts_double)
 		    {
-		      error ("both %<long long%> and %<double%> in "
-			     "declaration specifiers");
+		      error_at (loc,
+				("both %<long long%> and %<double%> in "
+				 "declaration specifiers"));
 		      break;
 		    }
-		  pedwarn_c90 (input_location, OPT_Wlong_long, 
+		  pedwarn_c90 (loc, OPT_Wlong_long,
 			       "ISO C90 does not support %<long long%>");
 		  specs->long_long_p = 1;
 		  break;
 		}
 	      if (specs->short_p)
-		error ("both %<long%> and %<short%> in "
-		       "declaration specifiers");
+		error_at (loc,
+			  ("both %<long%> and %<short%> in "
+			   "declaration specifiers"));
 	      else if (specs->typespec_word == cts_void)
-		error ("both %<long%> and %<void%> in "
-		       "declaration specifiers");
+		error_at (loc,
+			  ("both %<long%> and %<void%> in "
+			   "declaration specifiers"));
 	      else if (specs->typespec_word == cts_bool)
-		error ("both %<long%> and %<_Bool%> in "
-		       "declaration specifiers");
+		error_at (loc,
+			  ("both %<long%> and %<_Bool%> in "
+			   "declaration specifiers"));
 	      else if (specs->typespec_word == cts_char)
-		error ("both %<long%> and %<char%> in "
-		       "declaration specifiers");
+		error_at (loc,
+			  ("both %<long%> and %<char%> in "
+			   "declaration specifiers"));
 	      else if (specs->typespec_word == cts_float)
-		error ("both %<long%> and %<float%> in "
-		       "declaration specifiers");
+		error_at (loc,
+			  ("both %<long%> and %<float%> in "
+			   "declaration specifiers"));
 	      else if (specs->typespec_word == cts_dfloat32)
-		error ("both %<long%> and %<_Decimal32%> in "
-		       "declaration specifiers");
+		error_at (loc,
+			  ("both %<long%> and %<_Decimal32%> in "
+			   "declaration specifiers"));
 	      else if (specs->typespec_word == cts_dfloat64)
-		error ("both %<long%> and %<_Decimal64%> in "
-		       "declaration specifiers");
+		error_at (loc,
+			  ("both %<long%> and %<_Decimal64%> in "
+			   "declaration specifiers"));
 	      else if (specs->typespec_word == cts_dfloat128)
-		error ("both %<long%> and %<_Decimal128%> in "
-		       "declaration specifiers");
+		error_at (loc,
+			  ("both %<long%> and %<_Decimal128%> in "
+			   "declaration specifiers"));
 	      else
 		specs->long_p = true;
 	      break;
 	    case RID_SHORT:
 	      dupe = specs->short_p;
 	      if (specs->long_p)
-		error ("both %<long%> and %<short%> in "
-		       "declaration specifiers");
+		error_at (loc,
+			  ("both %<long%> and %<short%> in "
+			   "declaration specifiers"));
 	      else if (specs->typespec_word == cts_void)
-		error ("both %<short%> and %<void%> in "
-		       "declaration specifiers");
+		error_at (loc,
+			  ("both %<short%> and %<void%> in "
+			   "declaration specifiers"));
 	      else if (specs->typespec_word == cts_bool)
-		error ("both %<short%> and %<_Bool%> in "
-		       "declaration specifiers");
+		error_at (loc,
+			  ("both %<short%> and %<_Bool%> in "
+			   "declaration specifiers"));
 	      else if (specs->typespec_word == cts_char)
-		error ("both %<short%> and %<char%> in "
-		       "declaration specifiers");
+		error_at (loc,
+			  ("both %<short%> and %<char%> in "
+			   "declaration specifiers"));
 	      else if (specs->typespec_word == cts_float)
-		error ("both %<short%> and %<float%> in "
-		       "declaration specifiers");
+		error_at (loc,
+			  ("both %<short%> and %<float%> in "
+			   "declaration specifiers"));
 	      else if (specs->typespec_word == cts_double)
-		error ("both %<short%> and %<double%> in "
-		       "declaration specifiers");
+		error_at (loc,
+			  ("both %<short%> and %<double%> in "
+			   "declaration specifiers"));
 	      else if (specs->typespec_word == cts_dfloat32)
-                error ("both %<short%> and %<_Decimal32%> in "
-		       "declaration specifiers");
+                error_at (loc,
+			  ("both %<short%> and %<_Decimal32%> in "
+			   "declaration specifiers"));
 	      else if (specs->typespec_word == cts_dfloat64)
-		error ("both %<short%> and %<_Decimal64%> in "
-		                        "declaration specifiers");
+		error_at (loc,
+			  ("both %<short%> and %<_Decimal64%> in "
+			   "declaration specifiers"));
 	      else if (specs->typespec_word == cts_dfloat128)
-		error ("both %<short%> and %<_Decimal128%> in "
-		       "declaration specifiers");
+		error_at (loc,
+			  ("both %<short%> and %<_Decimal128%> in "
+			   "declaration specifiers"));
 	      else
 		specs->short_p = true;
 	      break;
 	    case RID_SIGNED:
 	      dupe = specs->signed_p;
 	      if (specs->unsigned_p)
-		error ("both %<signed%> and %<unsigned%> in "
-		       "declaration specifiers");
+		error_at (loc,
+			  ("both %<signed%> and %<unsigned%> in "
+			   "declaration specifiers"));
 	      else if (specs->typespec_word == cts_void)
-		error ("both %<signed%> and %<void%> in "
-		       "declaration specifiers");
+		error_at (loc,
+			  ("both %<signed%> and %<void%> in "
+			   "declaration specifiers"));
 	      else if (specs->typespec_word == cts_bool)
-		error ("both %<signed%> and %<_Bool%> in "
-		       "declaration specifiers");
+		error_at (loc,
+			  ("both %<signed%> and %<_Bool%> in "
+			   "declaration specifiers"));
 	      else if (specs->typespec_word == cts_float)
-		error ("both %<signed%> and %<float%> in "
-		       "declaration specifiers");
+		error_at (loc,
+			  ("both %<signed%> and %<float%> in "
+			   "declaration specifiers"));
 	      else if (specs->typespec_word == cts_double)
-		error ("both %<signed%> and %<double%> in "
-		       "declaration specifiers");
+		error_at (loc,
+			  ("both %<signed%> and %<double%> in "
+			   "declaration specifiers"));
 	      else if (specs->typespec_word == cts_dfloat32)
-		error ("both %<signed%> and %<_Decimal32%> in "
-		       "declaration specifiers");
+		error_at (loc,
+			  ("both %<signed%> and %<_Decimal32%> in "
+			   "declaration specifiers"));
 	      else if (specs->typespec_word == cts_dfloat64)
-		error ("both %<signed%> and %<_Decimal64%> in "
-		       "declaration specifiers");
+		error_at (loc,
+			  ("both %<signed%> and %<_Decimal64%> in "
+			   "declaration specifiers"));
 	      else if (specs->typespec_word == cts_dfloat128)
-		error ("both %<signed%> and %<_Decimal128%> in "
-		       "declaration specifiers");
+		error_at (loc,
+			  ("both %<signed%> and %<_Decimal128%> in "
+			   "declaration specifiers"));
 	      else
 		specs->signed_p = true;
 	      break;
 	    case RID_UNSIGNED:
 	      dupe = specs->unsigned_p;
 	      if (specs->signed_p)
-		error ("both %<signed%> and %<unsigned%> in "
-		       "declaration specifiers");
+		error_at (loc,
+			  ("both %<signed%> and %<unsigned%> in "
+			   "declaration specifiers"));
 	      else if (specs->typespec_word == cts_void)
-		error ("both %<unsigned%> and %<void%> in "
-		       "declaration specifiers");
+		error_at (loc,
+			  ("both %<unsigned%> and %<void%> in "
+			   "declaration specifiers"));
 	      else if (specs->typespec_word == cts_bool)
-		error ("both %<unsigned%> and %<_Bool%> in "
-		       "declaration specifiers");
+		error_at (loc,
+			  ("both %<unsigned%> and %<_Bool%> in "
+			   "declaration specifiers"));
 	      else if (specs->typespec_word == cts_float)
-		error ("both %<unsigned%> and %<float%> in "
-		       "declaration specifiers");
+		error_at (loc,
+			  ("both %<unsigned%> and %<float%> in "
+			   "declaration specifiers"));
 	      else if (specs->typespec_word == cts_double)
-		error ("both %<unsigned%> and %<double%> in "
-		       "declaration specifiers");
+		error_at (loc,
+			  ("both %<unsigned%> and %<double%> in "
+			   "declaration specifiers"));
               else if (specs->typespec_word == cts_dfloat32)
-		error ("both %<unsigned%> and %<_Decimal32%> in "
-		       "declaration specifiers");
+		error_at (loc,
+			  ("both %<unsigned%> and %<_Decimal32%> in "
+			   "declaration specifiers"));
 	      else if (specs->typespec_word == cts_dfloat64)
-		error ("both %<unsigned%> and %<_Decimal64%> in "
-		       "declaration specifiers");
+		error_at (loc,
+			  ("both %<unsigned%> and %<_Decimal64%> in "
+			   "declaration specifiers"));
 	      else if (specs->typespec_word == cts_dfloat128)
-		error ("both %<unsigned%> and %<_Decimal128%> in "
-		       "declaration specifiers");
+		error_at (loc,
+			  ("both %<unsigned%> and %<_Decimal128%> in "
+			   "declaration specifiers"));
 	      else
 		specs->unsigned_p = true;
 	      break;
 	    case RID_COMPLEX:
 	      dupe = specs->complex_p;
 	      if (!flag_isoc99 && !in_system_header)
-		pedwarn (input_location, OPT_pedantic, "ISO C90 does not support complex types");
+		pedwarn (loc, OPT_pedantic,
+			 "ISO C90 does not support complex types");
 	      if (specs->typespec_word == cts_void)
-		error ("both %<complex%> and %<void%> in "
-		       "declaration specifiers");
+		error_at (loc,
+			  ("both %<complex%> and %<void%> in "
+			   "declaration specifiers"));
 	      else if (specs->typespec_word == cts_bool)
-		error ("both %<complex%> and %<_Bool%> in "
-		       "declaration specifiers");
+		error_at (loc,
+			  ("both %<complex%> and %<_Bool%> in "
+			   "declaration specifiers"));
               else if (specs->typespec_word == cts_dfloat32)
-		error ("both %<complex%> and %<_Decimal32%> in "
-		       "declaration specifiers");
+		error_at (loc,
+			  ("both %<complex%> and %<_Decimal32%> in "
+			   "declaration specifiers"));
 	      else if (specs->typespec_word == cts_dfloat64)
-		error ("both %<complex%> and %<_Decimal64%> in "
-		       "declaration specifiers");
+		error_at (loc,
+			  ("both %<complex%> and %<_Decimal64%> in "
+			   "declaration specifiers"));
 	      else if (specs->typespec_word == cts_dfloat128)
-		error ("both %<complex%> and %<_Decimal128%> in "
-		       "declaration specifiers");
+		error_at (loc,
+			  ("both %<complex%> and %<_Decimal128%> in "
+			   "declaration specifiers"));
 	      else if (specs->typespec_word == cts_fract)
-		error ("both %<complex%> and %<_Fract%> in "
-		       "declaration specifiers");
+		error_at (loc,
+			  ("both %<complex%> and %<_Fract%> in "
+			   "declaration specifiers"));
 	      else if (specs->typespec_word == cts_accum)
-		error ("both %<complex%> and %<_Accum%> in "
-		       "declaration specifiers");
+		error_at (loc,
+			  ("both %<complex%> and %<_Accum%> in "
+			   "declaration specifiers"));
 	      else if (specs->saturating_p)
-		error ("both %<complex%> and %<_Sat%> in "
-		       "declaration specifiers");
+		error_at (loc,
+			  ("both %<complex%> and %<_Sat%> in "
+			   "declaration specifiers"));
 	      else
 		specs->complex_p = true;
 	      break;
 	    case RID_SAT:
 	      dupe = specs->saturating_p;
-	      pedwarn (input_location, OPT_pedantic, "ISO C does not support saturating types");
+	      pedwarn (loc, OPT_pedantic,
+		       "ISO C does not support saturating types");
 	      if (specs->typespec_word == cts_void)
-		error ("both %<_Sat%> and %<void%> in "
-		       "declaration specifiers");
+		error_at (loc,
+			  ("both %<_Sat%> and %<void%> in "
+			   "declaration specifiers"));
 	      else if (specs->typespec_word == cts_bool)
-		error ("both %<_Sat%> and %<_Bool%> in "
-		       "declaration specifiers");
+		error_at (loc,
+			  ("both %<_Sat%> and %<_Bool%> in "
+			   "declaration specifiers"));
 	      else if (specs->typespec_word == cts_char)
-		error ("both %<_Sat%> and %<char%> in "
-		       "declaration specifiers");
+		error_at (loc,
+			  ("both %<_Sat%> and %<char%> in "
+			   "declaration specifiers"));
 	      else if (specs->typespec_word == cts_int)
-		error ("both %<_Sat%> and %<int%> in "
-		       "declaration specifiers");
+		error_at (loc,
+			  ("both %<_Sat%> and %<int%> in "
+			   "declaration specifiers"));
 	      else if (specs->typespec_word == cts_float)
-		error ("both %<_Sat%> and %<float%> in "
-		       "declaration specifiers");
+		error_at (loc,
+			  ("both %<_Sat%> and %<float%> in "
+			   "declaration specifiers"));
 	      else if (specs->typespec_word == cts_double)
-		error ("both %<_Sat%> and %<double%> in "
-		       "declaration specifiers");
+		error_at (loc,
+			  ("both %<_Sat%> and %<double%> in "
+			   "declaration specifiers"));
               else if (specs->typespec_word == cts_dfloat32)
-		error ("both %<_Sat%> and %<_Decimal32%> in "
-		       "declaration specifiers");
+		error_at (loc,
+			  ("both %<_Sat%> and %<_Decimal32%> in "
+			   "declaration specifiers"));
 	      else if (specs->typespec_word == cts_dfloat64)
-		error ("both %<_Sat%> and %<_Decimal64%> in "
-		       "declaration specifiers");
+		error_at (loc,
+			  ("both %<_Sat%> and %<_Decimal64%> in "
+			   "declaration specifiers"));
 	      else if (specs->typespec_word == cts_dfloat128)
-		error ("both %<_Sat%> and %<_Decimal128%> in "
-		       "declaration specifiers");
+		error_at (loc,
+			  ("both %<_Sat%> and %<_Decimal128%> in "
+			   "declaration specifiers"));
 	      else if (specs->complex_p)
-		error ("both %<_Sat%> and %<complex%> in "
-		       "declaration specifiers");
+		error_at (loc,
+			  ("both %<_Sat%> and %<complex%> in "
+			   "declaration specifiers"));
 	      else
 		specs->saturating_p = true;
 	      break;
@@ -8488,7 +8637,7 @@ declspecs_add_type (struct c_declspecs *
 	    }
 
 	  if (dupe)
-	    error ("duplicate %qE", type);
+	    error_at (loc, "duplicate %qE", type);
 
 	  return specs;
 	}
@@ -8498,110 +8647,137 @@ declspecs_add_type (struct c_declspecs *
 	     "_Decimal64", "_Decimal128", "_Fract" or "_Accum".  */
 	  if (specs->typespec_word != cts_none)
 	    {
-	      error ("two or more data types in declaration specifiers");
+	      error_at (loc,
+			"two or more data types in declaration specifiers");
 	      return specs;
 	    }
 	  switch (i)
 	    {
 	    case RID_VOID:
 	      if (specs->long_p)
-		error ("both %<long%> and %<void%> in "
-		       "declaration specifiers");
+		error_at (loc,
+			  ("both %<long%> and %<void%> in "
+			   "declaration specifiers"));
 	      else if (specs->short_p)
-		error ("both %<short%> and %<void%> in "
-		       "declaration specifiers");
+		error_at (loc,
+			  ("both %<short%> and %<void%> in "
+			   "declaration specifiers"));
 	      else if (specs->signed_p)
-		error ("both %<signed%> and %<void%> in "
-		       "declaration specifiers");
+		error_at (loc,
+			  ("both %<signed%> and %<void%> in "
+			   "declaration specifiers"));
 	      else if (specs->unsigned_p)
-		error ("both %<unsigned%> and %<void%> in "
-		       "declaration specifiers");
+		error_at (loc,
+			  ("both %<unsigned%> and %<void%> in "
+			   "declaration specifiers"));
 	      else if (specs->complex_p)
-		error ("both %<complex%> and %<void%> in "
-		       "declaration specifiers");
+		error_at (loc,
+			  ("both %<complex%> and %<void%> in "
+			   "declaration specifiers"));
 	      else if (specs->saturating_p)
-		error ("both %<_Sat%> and %<void%> in "
-		       "declaration specifiers");
+		error_at (loc,
+			  ("both %<_Sat%> and %<void%> in "
+			   "declaration specifiers"));
 	      else
 		specs->typespec_word = cts_void;
 	      return specs;
 	    case RID_BOOL:
 	      if (specs->long_p)
-		error ("both %<long%> and %<_Bool%> in "
-		       "declaration specifiers");
+		error_at (loc,
+			  ("both %<long%> and %<_Bool%> in "
+			   "declaration specifiers"));
 	      else if (specs->short_p)
-		error ("both %<short%> and %<_Bool%> in "
-		       "declaration specifiers");
+		error_at (loc,
+			  ("both %<short%> and %<_Bool%> in "
+			   "declaration specifiers"));
 	      else if (specs->signed_p)
-		error ("both %<signed%> and %<_Bool%> in "
-		       "declaration specifiers");
+		error_at (loc,
+			  ("both %<signed%> and %<_Bool%> in "
+			   "declaration specifiers"));
 	      else if (specs->unsigned_p)
-		error ("both %<unsigned%> and %<_Bool%> in "
-		       "declaration specifiers");
+		error_at (loc,
+			  ("both %<unsigned%> and %<_Bool%> in "
+			   "declaration specifiers"));
 	      else if (specs->complex_p)
-		error ("both %<complex%> and %<_Bool%> in "
-		       "declaration specifiers");
+		error_at (loc,
+			  ("both %<complex%> and %<_Bool%> in "
+			   "declaration specifiers"));
 	      else if (specs->saturating_p)
-		error ("both %<_Sat%> and %<_Bool%> in "
-		       "declaration specifiers");
+		error_at (loc,
+			  ("both %<_Sat%> and %<_Bool%> in "
+			   "declaration specifiers"));
 	      else
 		specs->typespec_word = cts_bool;
 	      return specs;
 	    case RID_CHAR:
 	      if (specs->long_p)
-		error ("both %<long%> and %<char%> in "
-		       "declaration specifiers");
+		error_at (loc,
+			  ("both %<long%> and %<char%> in "
+			   "declaration specifiers"));
 	      else if (specs->short_p)
-		error ("both %<short%> and %<char%> in "
-		       "declaration specifiers");
+		error_at (loc,
+			  ("both %<short%> and %<char%> in "
+			   "declaration specifiers"));
 	      else if (specs->saturating_p)
-		error ("both %<_Sat%> and %<char%> in "
-		       "declaration specifiers");
+		error_at (loc,
+			  ("both %<_Sat%> and %<char%> in "
+			   "declaration specifiers"));
 	      else
 		specs->typespec_word = cts_char;
 	      return specs;
 	    case RID_INT:
 	      if (specs->saturating_p)
-		error ("both %<_Sat%> and %<int%> in "
-		       "declaration specifiers");
+		error_at (loc,
+			  ("both %<_Sat%> and %<int%> in "
+			   "declaration specifiers"));
 	      else
 		specs->typespec_word = cts_int;
 	      return specs;
 	    case RID_FLOAT:
 	      if (specs->long_p)
-		error ("both %<long%> and %<float%> in "
-		       "declaration specifiers");
+		error_at (loc,
+			  ("both %<long%> and %<float%> in "
+			   "declaration specifiers"));
 	      else if (specs->short_p)
-		error ("both %<short%> and %<float%> in "
-		       "declaration specifiers");
+		error_at (loc,
+			  ("both %<short%> and %<float%> in "
+			   "declaration specifiers"));
 	      else if (specs->signed_p)
-		error ("both %<signed%> and %<float%> in "
-		       "declaration specifiers");
+		error_at (loc,
+			  ("both %<signed%> and %<float%> in "
+			   "declaration specifiers"));
 	      else if (specs->unsigned_p)
-		error ("both %<unsigned%> and %<float%> in "
-		       "declaration specifiers");
+		error_at (loc,
+			  ("both %<unsigned%> and %<float%> in "
+			   "declaration specifiers"));
 	      else if (specs->saturating_p)
-		error ("both %<_Sat%> and %<float%> in "
-		       "declaration specifiers");
+		error_at (loc,
+			  ("both %<_Sat%> and %<float%> in "
+			   "declaration specifiers"));
 	      else
 		specs->typespec_word = cts_float;
 	      return specs;
 	    case RID_DOUBLE:
 	      if (specs->long_long_p)
-		error ("both %<long long%> and %<double%> in "
-		       "declaration specifiers");
+		error_at (loc,
+			  ("both %<long long%> and %<double%> in "
+			   "declaration specifiers"));
 	      else if (specs->short_p)
-		error ("both %<short%> and %<double%> in "
-		       "declaration specifiers");
+		error_at (loc,
+			  ("both %<short%> and %<double%> in "
+			   "declaration specifiers"));
 	      else if (specs->signed_p)
-		error ("both %<signed%> and %<double%> in "
-		       "declaration specifiers");
+		error_at (loc,
+			  ("both %<signed%> and %<double%> in "
+			   "declaration specifiers"));
 	      else if (specs->unsigned_p)
-		error ("both %<unsigned%> and %<double%> in "
-		       "declaration specifiers");
+		error_at (loc,
+			  ("both %<unsigned%> and %<double%> in "
+			   "declaration specifiers"));
 	      else if (specs->saturating_p)
-		error ("both %<_Sat%> and %<double%> in "
-		       "declaration specifiers");
+		error_at (loc,
+			  ("both %<_Sat%> and %<double%> in "
+			   "declaration specifiers"));
 	      else
 		specs->typespec_word = cts_double;
 	      return specs;
@@ -8617,26 +8793,40 @@ declspecs_add_type (struct c_declspecs *
 		else
 		  str = "_Decimal128";
 		if (specs->long_long_p)
-		  error ("both %<long long%> and %<%s%> in "
-			 "declaration specifiers", str);
+		  error_at (loc,
+			    ("both %<long long%> and %<%s%> in "
+			     "declaration specifiers"),
+			    str);
 		if (specs->long_p)
-		  error ("both %<long%> and %<%s%> in "
-			 "declaration specifiers", str);
+		  error_at (loc,
+			    ("both %<long%> and %<%s%> in "
+			     "declaration specifiers"),
+			    str);
 		else if (specs->short_p)
-		  error ("both %<short%> and %<%s%> in "
-			 "declaration specifiers", str);
+		  error_at (loc,
+			    ("both %<short%> and %<%s%> in "
+			     "declaration specifiers"),
+			    str);
 		else if (specs->signed_p)
-		  error ("both %<signed%> and %<%s%> in "
-			 "declaration specifiers", str);
+		  error_at (loc,
+			    ("both %<signed%> and %<%s%> in "
+			     "declaration specifiers"),
+			    str);
 		else if (specs->unsigned_p)
-		  error ("both %<unsigned%> and %<%s%> in "
-			 "declaration specifiers", str);
+		  error_at (loc,
+			    ("both %<unsigned%> and %<%s%> in "
+			     "declaration specifiers"),
+			    str);
                 else if (specs->complex_p)
-                  error ("both %<complex%> and %<%s%> in "
-                         "declaration specifiers", str);
+                  error_at (loc,
+			    ("both %<complex%> and %<%s%> in "
+			     "declaration specifiers"),
+			    str);
                 else if (specs->saturating_p)
-                  error ("both %<_Sat%> and %<%s%> in "
-                         "declaration specifiers", str);
+                  error_at (loc,
+			    ("both %<_Sat%> and %<%s%> in "
+			     "declaration specifiers"),
+			    str);
 		else if (i == RID_DFLOAT32)
 		  specs->typespec_word = cts_dfloat32;
 		else if (i == RID_DFLOAT64)
@@ -8645,8 +8835,10 @@ declspecs_add_type (struct c_declspecs *
 		  specs->typespec_word = cts_dfloat128;
 	      }
 	      if (!targetm.decimal_float_supported_p ())
-		error ("decimal floating point not supported for this target");
-	      pedwarn (input_location, OPT_pedantic, 
+		error_at (loc,
+			  ("decimal floating point not supported "
+			   "for this target"));
+	      pedwarn (loc, OPT_pedantic,
 		       "ISO C does not support decimal floating point");
 	      return specs;
 	    case RID_FRACT:
@@ -8658,16 +8850,19 @@ declspecs_add_type (struct c_declspecs *
 		else
 		  str = "_Accum";
                 if (specs->complex_p)
-                  error ("both %<complex%> and %<%s%> in "
-                         "declaration specifiers", str);
+                  error_at (loc,
+			    ("both %<complex%> and %<%s%> in "
+			     "declaration specifiers"),
+			    str);
 		else if (i == RID_FRACT)
 		    specs->typespec_word = cts_fract;
 		else
 		    specs->typespec_word = cts_accum;
 	      }
 	      if (!targetm.fixed_point_supported_p ())
-		error ("fixed-point types not supported for this target");
-	      pedwarn (input_location, OPT_pedantic, 
+		error_at (loc,
+			  "fixed-point types not supported for this target");
+	      pedwarn (loc, OPT_pedantic,
 		       "ISO C does not support fixed-point types");
 	      return specs;
 	    default:
@@ -8685,7 +8880,7 @@ declspecs_add_type (struct c_declspecs *
   if (specs->type || specs->typespec_word != cts_none
       || specs->long_p || specs->short_p || specs->signed_p
       || specs->unsigned_p || specs->complex_p)
-    error ("two or more data types in declaration specifiers");
+    error_at (loc, "two or more data types in declaration specifiers");
   else if (TREE_CODE (type) == TYPE_DECL)
     {
       if (TREE_TYPE (type) == error_mark_node)
@@ -8696,13 +8891,26 @@ declspecs_add_type (struct c_declspecs *
 	  specs->decl_attr = DECL_ATTRIBUTES (type);
 	  specs->typedef_p = true;
 	  specs->explicit_signed_p = C_TYPEDEF_EXPLICITLY_SIGNED (type);
+
+	  /* If this typedef name is defined in a struct, then a C++
+	     lookup would return a different value.  */
+	  if (warn_cxx_compat
+	      && I_SYMBOL_BINDING (DECL_NAME (type))->in_struct)
+	    warning_at (loc, OPT_Wc___compat,
+			"C++ lookup of %qD would return a field, not a type",
+			type);
+
+	  /* If we are parsing a struct, record that a struct field
+	     used a typedef.  */
+	  if (warn_cxx_compat && struct_parse_info != NULL)
+	    VEC_safe_push (tree, heap, struct_parse_info->typedefs_seen, type);
 	}
     }
   else if (TREE_CODE (type) == IDENTIFIER_NODE)
     {
       tree t = lookup_name (type);
       if (!t || TREE_CODE (t) != TYPE_DECL)
-	error ("%qE fails to be a typedef or built in type", type);
+	error_at (loc, "%qE fails to be a typedef or built in type", type);
       else if (TREE_TYPE (t) == error_mark_node)
 	;
       else
Index: c-parser.c
===================================================================
--- c-parser.c	(revision 148620)
+++ c-parser.c	(working copy)
@@ -1447,6 +1447,7 @@ c_parser_declspecs (c_parser *parser, st
     {
       struct c_typespec t;
       tree attrs;
+      location_t loc = c_parser_peek_token (parser)->location;
       if (c_parser_next_token_is (parser, CPP_NAME))
 	{
 	  tree value = c_parser_peek_token (parser)->value;
@@ -1482,7 +1483,7 @@ c_parser_declspecs (c_parser *parser, st
 	      t.expr = NULL_TREE;
 	      t.expr_const_operands = true;
 	    }
-	  declspecs_add_type (specs, t);
+	  declspecs_add_type (loc, specs, t);
 	  continue;
 	}
       if (c_parser_next_token_is (parser, CPP_LESS))
@@ -1498,7 +1499,7 @@ c_parser_declspecs (c_parser *parser, st
 	  t.spec = objc_get_protocol_qualified_type (NULL_TREE, proto);
 	  t.expr = NULL_TREE;
 	  t.expr_const_operands = true;
-	  declspecs_add_type (specs, t);
+	  declspecs_add_type (loc, specs, t);
 	  continue;
 	}
       gcc_assert (c_parser_next_token_is (parser, CPP_KEYWORD));
@@ -1547,7 +1548,7 @@ c_parser_declspecs (c_parser *parser, st
 	  t.spec = c_parser_peek_token (parser)->value;
 	  t.expr = NULL_TREE;
 	  t.expr_const_operands = true;
-	  declspecs_add_type (specs, t);
+	  declspecs_add_type (loc, specs, t);
 	  c_parser_consume_token (parser);
 	  break;
 	case RID_ENUM:
@@ -1556,7 +1557,7 @@ c_parser_declspecs (c_parser *parser, st
 	  attrs_ok = true;
 	  seen_type = true;
 	  t = c_parser_enum_specifier (parser);
-	  declspecs_add_type (specs, t);
+	  declspecs_add_type (loc, specs, t);
 	  break;
 	case RID_STRUCT:
 	case RID_UNION:
@@ -1566,7 +1567,7 @@ c_parser_declspecs (c_parser *parser, st
 	  seen_type = true;
 	  t = c_parser_struct_or_union_specifier (parser);
           invoke_plugin_callbacks (PLUGIN_FINISH_TYPE, t.spec);
-	  declspecs_add_type (specs, t);
+	  declspecs_add_type (loc, specs, t);
 	  break;
 	case RID_TYPEOF:
 	  /* ??? The old parser rejected typeof after other type
@@ -1577,7 +1578,7 @@ c_parser_declspecs (c_parser *parser, st
 	  attrs_ok = true;
 	  seen_type = true;
 	  t = c_parser_typeof_specifier (parser);
-	  declspecs_add_type (specs, t);
+	  declspecs_add_type (loc, specs, t);
 	  break;
 	case RID_CONST:
 	case RID_VOLATILE:
@@ -1815,10 +1816,8 @@ c_parser_struct_or_union_specifier (c_pa
     {
       /* Parse a struct or union definition.  Start the scope of the
 	 tag before parsing components.  */
-      bool in_struct;
-      VEC(tree,heap) *struct_types;
-      tree type = start_struct (struct_loc, code, ident,
-	  			&in_struct, &struct_types);
+      struct c_struct_parse_info *struct_info;
+      tree type = start_struct (struct_loc, code, ident, &struct_info);
       tree postfix_attrs;
       /* We chain the components in reverse order, then put them in
 	 forward order at the end.  Each struct-declaration may
@@ -1908,8 +1907,7 @@ c_parser_struct_or_union_specifier (c_pa
 	}
       postfix_attrs = c_parser_attributes (parser);
       ret.spec = finish_struct (struct_loc, type, nreverse (contents),
-				chainon (attrs, postfix_attrs),
-				in_struct, struct_types);
+				chainon (attrs, postfix_attrs), struct_info);
       ret.kind = ctsk_tagdef;
       ret.expr = NULL_TREE;
       ret.expr_const_operands = true;
Index: c-tree.h
===================================================================
--- c-tree.h	(revision 148620)
+++ c-tree.h	(working copy)
@@ -430,6 +430,7 @@ extern void gen_aux_info_record (tree, i
 
 /* in c-decl.c */
 struct c_spot_bindings;
+struct c_struct_parse_info;
 extern struct obstack parser_obstack;
 extern tree c_break_label;
 extern tree c_cont_label;
@@ -465,7 +466,8 @@ extern void c_maybe_initialize_eh (void)
 extern void finish_decl (tree, location_t, tree, tree, tree);
 extern tree finish_enum (tree, tree, tree);
 extern void finish_function (void);
-extern tree finish_struct (location_t, tree, tree, tree, bool, VEC(tree,heap) *);
+extern tree finish_struct (location_t, tree, tree, tree,
+			   struct c_struct_parse_info *);
 extern struct c_arg_info *get_parm_info (bool);
 extern tree grokfield (location_t, struct c_declarator *,
 		       struct c_declspecs *, tree, tree *);
@@ -487,7 +489,8 @@ extern tree start_enum (location_t, stru
 extern int  start_function (struct c_declspecs *, struct c_declarator *, tree);
 extern tree start_decl (struct c_declarator *, struct c_declspecs *, bool,
 			tree);
-extern tree start_struct (location_t, enum tree_code, tree, bool *, VEC(tree,heap) **);
+extern tree start_struct (location_t, enum tree_code, tree,
+			  struct c_struct_parse_info **);
 extern void store_parm_decls (void);
 extern void store_parm_decls_from (struct c_arg_info *);
 extern tree xref_tag (enum tree_code, tree);
@@ -504,7 +507,8 @@ extern struct c_declarator *make_pointer
 						     struct c_declarator *);
 extern struct c_declspecs *build_null_declspecs (void);
 extern struct c_declspecs *declspecs_add_qual (struct c_declspecs *, tree);
-extern struct c_declspecs *declspecs_add_type (struct c_declspecs *,
+extern struct c_declspecs *declspecs_add_type (location_t,
+					       struct c_declspecs *,
 					       struct c_typespec);
 extern struct c_declspecs *declspecs_add_scspec (struct c_declspecs *, tree);
 extern struct c_declspecs *declspecs_add_attrs (struct c_declspecs *, tree);
Index: objc/objc-act.c
===================================================================
--- objc/objc-act.c	(revision 148620)
+++ objc/objc-act.c	(working copy)
@@ -420,8 +420,7 @@ static int generating_instance_variables
    is compiled as part of obj-c++.  */
 
 static bool objc_building_struct;
-static bool objc_in_struct ATTRIBUTE_UNUSED;
-static VEC(tree,heap) *objc_struct_types ATTRIBUTE_UNUSED;
+static struct c_struct_parse_info *objc_struct_info ATTRIBUTE_UNUSED;
 
 /* Start building a struct for objc.  */
 
@@ -430,8 +429,7 @@ objc_start_struct (tree name)
 {
   gcc_assert (!objc_building_struct);
   objc_building_struct = true;
-  return start_struct (input_location, RECORD_TYPE, 
-		       name, &objc_in_struct, &objc_struct_types);
+  return start_struct (input_location, RECORD_TYPE, name, &objc_struct_info);
 }
 
 /* Finish building a struct for objc.  */
@@ -442,7 +440,7 @@ objc_finish_struct (tree type, tree fiel
   gcc_assert (objc_building_struct);
   objc_building_struct = false;
   return finish_struct (input_location, type, fieldlist, NULL_TREE,
-			objc_in_struct, objc_struct_types);
+			objc_struct_info);
 }
 
 /* Some platforms pass small structures through registers versus
Index: testsuite/gcc.dg/Wcxx-compat-15.c
===================================================================
--- testsuite/gcc.dg/Wcxx-compat-15.c	(revision 0)
+++ testsuite/gcc.dg/Wcxx-compat-15.c	(revision 0)
@@ -0,0 +1,33 @@
+/* { dg-do compile } */
+/* { dg-options "-Wc++-compat" } */
+
+typedef int myint1;
+typedef int myint2;
+typedef int myint3;
+struct s1
+{
+  myint1 myint1;	/* { dg-warning "invalid in C\[+\]\[+\]" } */
+  myint2 *myint2;	/* { dg-warning "invalid in C\[+\]\[+\]" } */
+  int myint3;
+  struct s2
+  {
+    myint3 f2;		/* { dg-warning "C\[+\]\[+\]" } */
+  } f1;
+};
+
+struct s3
+{
+  int myint1;
+  struct s4
+  {
+    int myint1;
+  } f1;
+  struct s5
+  {
+    int myint1;
+    struct s6
+    {
+      myint1 f4;	/* { dg-warning "C\[+\]\[+\]" } */
+    } f3;
+  } f2;
+};
Index: objcp/objcp-decl.h
===================================================================
--- objcp/objcp-decl.h	(revision 148620)
+++ objcp/objcp-decl.h	(working copy)
@@ -37,9 +37,9 @@ extern tree objcp_end_compound_stmt (tre
    invoke the original C++ functions if needed).  */
 #ifdef OBJCP_REMAP_FUNCTIONS
 
-#define start_struct(loc, code, name, in_struct, struct_types) \
+#define start_struct(loc, code, name, struct_info) \
 	objcp_start_struct (loc, code, name)
-#define finish_struct(loc, t, fieldlist, attributes, in_struct, struct_types) \
+#define finish_struct(loc, t, fieldlist, attributes, struct_info) \
 	objcp_finish_struct (loc, t, fieldlist, attributes)
 #define finish_function() \
 	objcp_finish_function ()
Index: dse.c
===================================================================
--- dse.c	(revision 148620)
+++ dse.c	(working copy)
@@ -244,7 +244,7 @@ struct store_info 
 	{
 	  /* A bitmap with one bit per byte.  Cleared bit means the position
 	     is needed.  Used if IS_LARGE is false.  */
-	  bitmap bitmap;
+	  bitmap bmap;
 
 	  /* Number of set bits (i.e. unneeded bytes) in BITMAP.  If it is
 	     equal to END - BEGIN, the whole store is unused.  */
@@ -791,7 +791,7 @@ free_store_info (insn_info_t insn_info)
     {
       store_info_t next = store_info->next;
       if (store_info->is_large)
-	BITMAP_FREE (store_info->positions_needed.large.bitmap);
+	BITMAP_FREE (store_info->positions_needed.large.bmap);
       if (store_info->cse_base)
 	pool_free (cse_store_info_pool, store_info);
       else
@@ -1213,10 +1213,10 @@ set_position_unneeded (store_info_t s_in
 {
   if (__builtin_expect (s_info->is_large, false))
     {
-      if (!bitmap_bit_p (s_info->positions_needed.large.bitmap, pos))
+      if (!bitmap_bit_p (s_info->positions_needed.large.bmap, pos))
 	{
 	  s_info->positions_needed.large.count++;
-	  bitmap_set_bit (s_info->positions_needed.large.bitmap, pos);
+	  bitmap_set_bit (s_info->positions_needed.large.bmap, pos);
 	}
     }
   else
@@ -1233,7 +1233,7 @@ set_all_positions_unneeded (store_info_t
     {
       int pos, end = s_info->end - s_info->begin;
       for (pos = 0; pos < end; pos++)
-	bitmap_set_bit (s_info->positions_needed.large.bitmap, pos);
+	bitmap_set_bit (s_info->positions_needed.large.bmap, pos);
       s_info->positions_needed.large.count = end;
     }
   else
@@ -1263,7 +1263,7 @@ all_positions_needed_p (store_info_t s_i
     {
       int end = start + width;
       while (start < end)
-	if (bitmap_bit_p (s_info->positions_needed.large.bitmap, start++))
+	if (bitmap_bit_p (s_info->positions_needed.large.bmap, start++))
 	  return false;
       return true;
     }
@@ -1605,7 +1605,7 @@ record_store (rtx body, bb_info_t bb_inf
     {
       store_info->is_large = true;
       store_info->positions_needed.large.count = 0;
-      store_info->positions_needed.large.bitmap = BITMAP_ALLOC (NULL);
+      store_info->positions_needed.large.bmap = BITMAP_ALLOC (NULL);
     }
   else
     {
@@ -2721,7 +2721,7 @@ dse_step1 (void)
 		  for (s_info = ptr->store_rec; s_info; s_info = s_info->next)
 		    if (s_info->is_large)
 		      {
-			BITMAP_FREE (s_info->positions_needed.large.bitmap);
+			BITMAP_FREE (s_info->positions_needed.large.bmap);
 			s_info->is_large = false;
 		      }
 		}

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]