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]

Re: Improve -Wc++-compat to warn about types defined inside structs


"Joseph S. Myers" <joseph@codesourcery.com> writes:

> On Fri, 8 May 2009, Ian Lance Taylor wrote:
>
>> Thanks for pointing that out.  I extended the patch to catch types
>> defined in sizeof/typeof/alignof and in casts.  For sizeof/typeof/
>> alignof it will only issue that warning, not the warning about being
>> defined in a struct/union.
>
> Since you're including the GNU extensions of typeof and alignof I think 
> you should also check for types being defined in compound literals (C99 
> but a GNU extension to C++).  The C changes are OK with that added, and 
> with ...
>
>> One issue I noticed is that gcc itself uses a type defined in a cast, in
>> CONST_CAST in system.h.  Therefore, I changed __extension__ to disable
>> -Wc++-compat.  I didn't change the documentation, as by my reading of it
>
>  ... a testcase added for this disabling.

Done.  Committed as follows, along with the second patch in

http://gcc.gnu.org/ml/gcc-patches/2009-05/msg00299.html

Ian

gcc/ChangeLog:

2009-05-10  Ian Lance Taylor  <iant@google.com>

	* c-decl.c (in_struct, struct_types): New static variables.
	(pushtag): Add loc parameter.  Change all callers.
	(lookup_tag): Add ploc parameter.  Change all callers.
	(check_compound_literal_type): New function.
	(parser_xref_tag): Add loc parameter.  Change all callers.  If
	-Wc++-compat, warn about struct/union/enum types defined within a
	struct or union.
	(start_struct): Add enclosing_in_struct, enclosing_struct_types,
	and loc parameters.  Change all callers.  Change error calls to
	error_at, using loc.  For a redefinition, if the location of the
	original definition is known, report it.  Set in_struct and
	struct_types.  If -Wc++-compat warn if in sizeof, typeof, or
	alignof.
	(finish_struct): Add new parameters enclosing_in_struct and
	enclosing_struct_types.  Change all callers.  Set
	C_TYPE_DEFINED_IN_STRUCT for all struct/union/enum types defined
	in the struct.  If in a struct, add this struct to struct_types.
	(start_enum): Add loc parameter.  Change all callers.  Use
	error_at for errors, using loc.  For a redefinition, if the
	location of the original definition is known, report it.  If in a
	struct, add this enum type to struct_types.  If -Wc++-compat warn
	if in sizeof, typeof, or alignof.
	* c-parser.c (disable_extension_diagnostics): Disable
	-Wc++-compat.
	(enable_extension_diagnostics): Reenable -Wc++-compat if
	appropriate.
	(c_parser_enum_specifier): Get enum location for start_enum.
	(c_parser_struct_or_union_specifier): Get struct location for
	start_struct.  Save in_struct and struct_types status between
	start_struct and finish_struct.
	(c_parser_cast_expression): Get location of cast.
	(c_parser_alignof_expression): Get location of type.
	(c_parser_postfix_expression): Likewise.
	(c_parser_postfix_expression_after_paren_type): Add type_loc
	parameter.  Change all callers.  Call
	check_compound_literal_type.  Use type_loc for error about
	variable size type.
	* c-typeck.c (build_external_ref): If -Wc++-compat, warn about a
	use of an enum constant from an enum type defined in a struct or
	union.
	(c_cast_expr): Add loc parameter.  Change all callers.  If
	-Wc++-compat, warn about defining a type in a cast.
	* c-tree.h (C_TYPE_DEFINED_IN_STRUCT): Define.
	(start_enum, start_struct, finish_struct): Update declarations.
	(parser_xref_tag, c_cast_expr): Update declarations.
	(check_compound_literal_type): Declare.

gcc/objc/ChangeLog:

2009-05-10  Ian Lance Taylor  <iant@google.com>

	* objc-act.c (objc_building_struct): New static variable.
	(objc_in_struct, objc_struct_types): New static variables.
	(objc_start_struct, objc_finish_struct): New static functions.
	(generate_struct_by_value_array): Call objc_start_struct instead
	of start_struct, and call objc_finish_struct instead of
	finish_struct.
	(objc_build_struct, build_objc_symtab_template): Likewise.
	(build_module_descriptor): Likewise.
	(build_next_objc_exception_stuff): Likewise.
	(build_protocol_template): Likewise.
	(build_method_prototype_list_template): Likewise.
	(build_method_prototype_template): Likewise.
	(build_category_template, build_selector_template): Likewise.
	(build_class_template, build_super_template): Likewise.
	(build_ivar_template, build_ivar_list_template): Likewise.
	(build_method_list_template): Likewise.
	(build_method_template): Likewise.

gcc/objcp/ChangeLog:

2009-05-10  Ian Lance Taylor  <iant@google.com>

	* objcp-decl.h (start_struct): Add three new, ignored, macro
	parameters.
	(finish_struct): Add two new, ignored, macro parameters.

gcc/testsuite/ChangeLog:

2009-05-10  Ian Lance Taylor  <iant@google.com>

	* gcc.dg/Wcxx-compat-7.c: New testcase.
	* gcc.dg/Wcxx-compat-8.c: New testcase.
	* gcc.dg/c99-tag-1.c: Recognize new "originally defined here"
	notes
	* gcc.dg/pr17188-1.c: Likewise.
	* gcc.dg/pr39084.c: Likewise.


Index: c-decl.c
===================================================================
--- c-decl.c	(revision 147115)
+++ c-decl.c	(working copy)
@@ -126,6 +126,15 @@ 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.  */
@@ -1046,13 +1055,12 @@ pop_file_scope (void)
    In that case, the TYPE_SIZE will be zero.  */
 
 static void
-pushtag (tree name, tree type)
+pushtag (tree name, tree type, location_t loc)
 {
   /* Record the identifier as the type's name if it has none.  */
   if (name && !TYPE_NAME (type))
     TYPE_NAME (type) = name;
-  bind (name, type, current_scope, /*invisible=*/false, /*nested=*/false,
-	UNKNOWN_LOCATION);
+  bind (name, type, current_scope, /*invisible=*/false, /*nested=*/false, loc);
 
   /* Create a fake NULL-named TYPE_DECL node whose TREE_TYPE will be the
      tagged type we just added to the current scope.  This fake
@@ -2685,10 +2693,13 @@ define_label (location_t location, tree 
    If THISLEVEL_ONLY is nonzero, searches only the current_scope.
    CODE says which kind of type the caller wants;
    it is RECORD_TYPE or UNION_TYPE or ENUMERAL_TYPE.
+   If PLOC is not NULL and this returns non-null, it sets *PLOC to the
+   location where the tag was defined.
    If the wrong kind of type is found, an error is reported.  */
 
 static tree
-lookup_tag (enum tree_code code, tree name, int thislevel_only)
+lookup_tag (enum tree_code code, tree name, int thislevel_only,
+	    location_t *ploc)
 {
   struct c_binding *b = I_TAG_BINDING (name);
   int thislevel = 0;
@@ -2725,6 +2736,10 @@ lookup_tag (enum tree_code code, tree na
       if (thislevel)
 	pending_xref_error ();
     }
+
+  if (ploc != NULL)
+    *ploc = b->locus;
+
   return b->decl;
 }
 
@@ -2997,12 +3012,12 @@ shadow_tag_warned (const struct c_declsp
 	  else
 	    {
 	      pending_invalid_xref = 0;
-	      t = lookup_tag (code, name, 1);
+	      t = lookup_tag (code, name, 1, NULL);
 
 	      if (t == 0)
 		{
 		  t = make_node (code);
-		  pushtag (name, t);
+		  pushtag (name, t, input_location);
 		}
 	    }
 	}
@@ -3857,6 +3872,17 @@ build_compound_literal (tree type, tree 
 
   return complit;
 }
+
+/* Check the type of a compound literal.  Here we just check that it
+   is valid for C++.  */
+
+void
+check_compound_literal_type (struct c_type_name *type_name, location_t loc)
+{
+  if (warn_cxx_compat && type_name->specs->tag_defined_p)
+    warning_at (loc, OPT_Wc___compat,
+		"defining a type in a compound literal is invalid in C++");
+}
 
 /* Determine whether TYPE is a structure with a flexible array member,
    or a union containing such a structure (possibly recursively).  */
@@ -5512,10 +5538,11 @@ get_parm_info (bool ellipsis)
    Return a c_typespec structure for the type specifier.  */
 
 struct c_typespec
-parser_xref_tag (enum tree_code code, tree name)
+parser_xref_tag (enum tree_code code, tree name, location_t loc)
 {
   struct c_typespec ret;
   tree ref;
+  location_t refloc;
 
   ret.expr = NULL_TREE;
   ret.expr_const_operands = true;
@@ -5523,7 +5550,7 @@ parser_xref_tag (enum tree_code code, tr
   /* If a cross reference is requested, look up the type
      already defined for this tag and return it.  */
 
-  ref = lookup_tag (code, name, 0);
+  ref = lookup_tag (code, name, 0, &refloc);
   /* If this is the right type of tag, return what we found.
      (This reference will be shadowed by shadow_tag later if appropriate.)
      If this is the wrong type of tag, do not return it.  If it was the
@@ -5538,6 +5565,35 @@ parser_xref_tag (enum tree_code code, tr
   ret.kind = (ref ? ctsk_tagref : ctsk_tagfirstref);
   if (ref && TREE_CODE (ref) == code)
     {
+      if (C_TYPE_DEFINED_IN_STRUCT (ref)
+	  && loc != UNKNOWN_LOCATION
+	  && warn_cxx_compat)
+	{
+	  switch (code)
+	    {
+	    case ENUMERAL_TYPE:
+	      warning_at (loc, OPT_Wc___compat,
+			  ("enum type defined in struct or union "
+			   "is not visible in C++"));
+	      inform (refloc, "enum type defined here");
+	      break;
+	    case RECORD_TYPE:
+	      warning_at (loc, OPT_Wc___compat,
+			  ("struct defined in struct or union "
+			   "is not visible in C++"));
+	      inform (refloc, "struct defined here");
+	      break;
+	    case UNION_TYPE:
+	      warning_at (loc, OPT_Wc___compat,
+			  ("union defined in struct or union "
+			   "is not visible in C++"));
+	      inform (refloc, "union defined here");
+	      break;
+	    default:
+	      gcc_unreachable();
+	    }
+	}
+
       ret.spec = ref;
       return ret;
     }
@@ -5561,7 +5617,7 @@ parser_xref_tag (enum tree_code code, tr
       TYPE_MAX_VALUE (ref) = TYPE_MAX_VALUE (unsigned_type_node);
     }
 
-  pushtag (name, ref);
+  pushtag (name, ref, loc);
 
   ret.spec = ref;
   return ret;
@@ -5574,40 +5630,53 @@ parser_xref_tag (enum tree_code code, tr
 tree
 xref_tag (enum tree_code code, tree name)
 {
-  return parser_xref_tag (code, name).spec;
+  return parser_xref_tag (code, name, UNKNOWN_LOCATION).spec;
 }
 
 /* Make sure that the tag NAME is defined *in the current scope*
    at least as a forward reference.
-   CODE says which kind of tag NAME ought to be.  */
+   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.  */
 
 tree
-start_struct (enum tree_code code, tree name)
+start_struct (enum tree_code code, tree name, bool *enclosing_in_struct,
+	      VEC(tree,heap) **enclosing_struct_types, location_t loc)
 {
   /* If there is already a tag defined at this scope
      (as a forward reference), just return it.  */
 
-  tree ref = 0;
+  tree ref = NULL_TREE;
+  location_t refloc = UNKNOWN_LOCATION;
 
-  if (name != 0)
-    ref = lookup_tag (code, name, 1);
+  if (name != NULL_TREE)
+    ref = lookup_tag (code, name, 1, &refloc);
   if (ref && TREE_CODE (ref) == code)
     {
       if (TYPE_SIZE (ref))
 	{
 	  if (code == UNION_TYPE)
-	    error ("redefinition of %<union %E%>", name);
+	    error_at (loc, "redefinition of %<union %E%>", name);
 	  else
-	    error ("redefinition of %<struct %E%>", name);
+	    error_at (loc, "redefinition of %<struct %E%>", name);
+	  if (refloc != UNKNOWN_LOCATION)
+	    inform (refloc, "originally defined here");
 	  /* Don't create structures using a name already in use.  */
 	  ref = NULL_TREE;
 	}
       else if (C_TYPE_BEING_DEFINED (ref))
 	{
 	  if (code == UNION_TYPE)
-	    error ("nested redefinition of %<union %E%>", name);
+	    error_at (loc, "nested redefinition of %<union %E%>", name);
 	  else
-	    error ("nested redefinition of %<struct %E%>", name);
+	    error_at (loc, "nested redefinition of %<struct %E%>", name);
+	  /* Don't bother to report "originally defined here" for a
+	     nested redefinition; the original definition should be
+	     obvious.  */
 	  /* Don't create structures that contain themselves.  */
 	  ref = NULL_TREE;
 	}
@@ -5618,11 +5687,28 @@ start_struct (enum tree_code code, tree 
   if (ref == NULL_TREE || TREE_CODE (ref) != code)
     {
       ref = make_node (code);
-      pushtag (name, ref);
+      pushtag (name, ref, loc);
     }
 
   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);
+
+  /* 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
+     terribly serious as C++ doesn't permit statement exprs within
+     sizeof anyhow.  */
+  if (warn_cxx_compat && (in_sizeof || in_typeof || in_alignof))
+    warning_at (loc, OPT_Wc___compat,
+		"defining type in %qs expression is invalid in C++",
+		(in_sizeof
+		 ? "sizeof"
+		 : (in_typeof ? "typeof" : "alignof")));
+
   return ref;
 }
 
@@ -5760,14 +5846,22 @@ detect_field_duplicates (tree fieldlist)
 
 /* Fill in the fields of a RECORD_TYPE or UNION_TYPE node, T.
    FIELDLIST is a chain of FIELD_DECL nodes for the fields.
-   ATTRIBUTES are attributes to be applied to the structure.  */
+   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.  */
 
 tree
-finish_struct (tree t, tree fieldlist, tree attributes)
+finish_struct (tree t, tree fieldlist, tree attributes,
+	       bool enclosing_in_struct,
+	       VEC(tree,heap) *enclosing_struct_types)
 {
   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.  */
@@ -6020,6 +6114,24 @@ finish_struct (tree t, tree fieldlist, t
   if (cur_stmt_list && variably_modified_type_p (t, NULL_TREE))
     add_stmt (build_stmt (DECL_EXPR, build_decl (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;
+
+  VEC_free (tree, heap, struct_types);
+
+  in_struct = enclosing_in_struct;
+  struct_types = enclosing_struct_types;
+
+  /* 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);
+
   return t;
 }
 
@@ -6040,32 +6152,35 @@ layout_array_type (tree t)
    may be used to declare the individual values as they are read.  */
 
 tree
-start_enum (struct c_enum_contents *the_enum, tree name)
+start_enum (struct c_enum_contents *the_enum, tree name, location_t loc)
 {
-  tree enumtype = 0;
+  tree enumtype = NULL_TREE;
+  location_t enumloc = UNKNOWN_LOCATION;
 
   /* If this is the real definition for a previous forward reference,
      fill in the contents in the same object that used to be the
      forward reference.  */
 
-  if (name != 0)
-    enumtype = lookup_tag (ENUMERAL_TYPE, name, 1);
+  if (name != NULL_TREE)
+    enumtype = lookup_tag (ENUMERAL_TYPE, name, 1, &enumloc);
 
   if (enumtype == 0 || TREE_CODE (enumtype) != ENUMERAL_TYPE)
     {
       enumtype = make_node (ENUMERAL_TYPE);
-      pushtag (name, enumtype);
+      pushtag (name, enumtype, loc);
     }
 
   if (C_TYPE_BEING_DEFINED (enumtype))
-    error ("nested redefinition of %<enum %E%>", name);
+    error_at (loc, "nested redefinition of %<enum %E%>", name);
 
   C_TYPE_BEING_DEFINED (enumtype) = 1;
 
   if (TYPE_VALUES (enumtype) != 0)
     {
       /* This enum is a named one that has been declared already.  */
-      error ("redeclaration of %<enum %E%>", name);
+      error_at (loc, "redeclaration of %<enum %E%>", name);
+      if (enumloc != UNKNOWN_LOCATION)
+	inform (enumloc, "originally defined here");
 
       /* Completely replace its old definition.
 	 The old enumerators remain defined, however.  */
@@ -6078,6 +6193,16 @@ start_enum (struct c_enum_contents *the_
   if (flag_short_enums)
     TYPE_PACKED (enumtype) = 1;
 
+  /* FIXME: This will issue a warning for a use of a type defined
+     within sizeof in a statement expr.  This is not terribly serious
+     as C++ doesn't permit statement exprs within sizeof anyhow.  */
+  if (warn_cxx_compat && (in_sizeof || in_typeof || in_alignof))
+    warning_at (loc, OPT_Wc___compat,
+		"defining type in %qs expression is invalid in C++",
+		(in_sizeof
+		 ? "sizeof"
+		 : (in_typeof ? "typeof" : "alignof")));
+
   return enumtype;
 }
 
@@ -6217,6 +6342,11 @@ finish_enum (tree enumtype, tree values,
   /* Finish debugging output for this type.  */
   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);
+
   return enumtype;
 }
 
Index: c-parser.c
===================================================================
--- c-parser.c	(revision 147115)
+++ c-parser.c	(working copy)
@@ -820,12 +820,14 @@ disable_extension_diagnostics (void)
 	     | (warn_pointer_arith << 1)
 	     | (warn_traditional << 2)
 	     | (flag_iso << 3)
-	     | (warn_long_long << 4));
+	     | (warn_long_long << 4)
+	     | (warn_cxx_compat << 5));
   cpp_opts->pedantic = pedantic = 0;
   warn_pointer_arith = 0;
   cpp_opts->warn_traditional = warn_traditional = 0;
   flag_iso = 0;
   cpp_opts->warn_long_long = warn_long_long = 0;
+  warn_cxx_compat = 0;
   return ret;
 }
 
@@ -840,6 +842,7 @@ restore_extension_diagnostics (int flags
   cpp_opts->warn_traditional = warn_traditional = (flags >> 2) & 1;
   flag_iso = (flags >> 3) & 1;
   cpp_opts->warn_long_long = warn_long_long = (flags >> 4) & 1;
+  warn_cxx_compat = (flags >> 5) & 1;
 }
 
 /* Possibly kinds of declarator to parse.  */
@@ -910,7 +913,8 @@ static struct c_expr c_parser_sizeof_exp
 static struct c_expr c_parser_alignof_expression (c_parser *);
 static struct c_expr c_parser_postfix_expression (c_parser *);
 static struct c_expr c_parser_postfix_expression_after_paren_type (c_parser *,
-								   struct c_type_name *);
+								   struct c_type_name *,
+								   location_t);
 static struct c_expr c_parser_postfix_expression_after_primary (c_parser *,
 								struct c_expr);
 static struct c_expr c_parser_expression (c_parser *);
@@ -1617,8 +1621,10 @@ c_parser_enum_specifier (c_parser *parse
   struct c_typespec ret;
   tree attrs;
   tree ident = NULL_TREE;
+  location_t enum_loc;
   location_t ident_loc = UNKNOWN_LOCATION;  /* Quiet warning.  */
   gcc_assert (c_parser_next_token_is_keyword (parser, RID_ENUM));
+  enum_loc = c_parser_peek_token (parser)->location;
   c_parser_consume_token (parser);
   attrs = c_parser_attributes (parser);
   /* Set the location in case we create a decl now.  */
@@ -1627,13 +1633,14 @@ c_parser_enum_specifier (c_parser *parse
     {
       ident = c_parser_peek_token (parser)->value;
       ident_loc = c_parser_peek_token (parser)->location;
+      enum_loc = ident_loc;
       c_parser_consume_token (parser);
     }
   if (c_parser_next_token_is (parser, CPP_OPEN_BRACE))
     {
       /* Parse an enum definition.  */
       struct c_enum_contents the_enum;
-      tree type = start_enum (&the_enum, ident);
+      tree type = start_enum (&the_enum, ident, enum_loc);
       tree postfix_attrs;
       /* We chain the enumerators in reverse order, then put them in
 	 forward order at the end.  */
@@ -1712,7 +1719,7 @@ c_parser_enum_specifier (c_parser *parse
       ret.expr_const_operands = true;
       return ret;
     }
-  ret = parser_xref_tag (ENUMERAL_TYPE, ident);
+  ret = parser_xref_tag (ENUMERAL_TYPE, ident, ident_loc);
   /* In ISO C, enumerated types can be referred to only if already
      defined.  */
   if (pedantic && !COMPLETE_TYPE_P (ret.spec))
@@ -1769,6 +1776,8 @@ c_parser_struct_or_union_specifier (c_pa
   struct c_typespec ret;
   tree attrs;
   tree ident = NULL_TREE;
+  location_t struct_loc;
+  location_t ident_loc = UNKNOWN_LOCATION;
   enum tree_code code;
   switch (c_parser_peek_token (parser)->keyword)
     {
@@ -1781,6 +1790,7 @@ c_parser_struct_or_union_specifier (c_pa
     default:
       gcc_unreachable ();
     }
+  struct_loc = c_parser_peek_token (parser)->location;
   c_parser_consume_token (parser);
   attrs = c_parser_attributes (parser);
   /* Set the location in case we create a decl now.  */
@@ -1788,13 +1798,18 @@ c_parser_struct_or_union_specifier (c_pa
   if (c_parser_next_token_is (parser, CPP_NAME))
     {
       ident = c_parser_peek_token (parser)->value;
+      ident_loc = c_parser_peek_token (parser)->location;
+      struct_loc = ident_loc;
       c_parser_consume_token (parser);
     }
   if (c_parser_next_token_is (parser, CPP_OPEN_BRACE))
     {
       /* Parse a struct or union definition.  Start the scope of the
 	 tag before parsing components.  */
-      tree type = start_struct (code, ident);
+      bool in_struct;
+      VEC(tree,heap) *struct_types;
+      tree type = start_struct (code, ident, &in_struct, &struct_types,
+				struct_loc);
       tree postfix_attrs;
       /* We chain the components in reverse order, then put them in
 	 forward order at the end.  Each struct-declaration may
@@ -1884,7 +1899,8 @@ c_parser_struct_or_union_specifier (c_pa
 	}
       postfix_attrs = c_parser_attributes (parser);
       ret.spec = finish_struct (type, nreverse (contents),
-				chainon (attrs, postfix_attrs));
+				chainon (attrs, postfix_attrs),
+				in_struct, struct_types);
       ret.kind = ctsk_tagdef;
       ret.expr = NULL_TREE;
       ret.expr_const_operands = true;
@@ -1899,7 +1915,7 @@ c_parser_struct_or_union_specifier (c_pa
       ret.expr_const_operands = true;
       return ret;
     }
-  ret = parser_xref_tag (code, ident);
+  ret = parser_xref_tag (code, ident, ident_loc);
   return ret;
 }
 
@@ -4828,10 +4844,12 @@ c_parser_cast_expression (c_parser *pars
   if (c_parser_next_token_is (parser, CPP_OPEN_PAREN)
       && c_token_starts_typename (c_parser_peek_2nd_token (parser)))
     {
+      location_t loc;
       struct c_type_name *type_name;
       struct c_expr ret;
       struct c_expr expr;
       c_parser_consume_token (parser);
+      loc = c_parser_peek_token (parser)->location;
       type_name = c_parser_type_name (parser);
       c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, "expected %<)%>");
       if (type_name == NULL)
@@ -4846,11 +4864,11 @@ c_parser_cast_expression (c_parser *pars
       used_types_insert (type_name->specs->type);
 
       if (c_parser_next_token_is (parser, CPP_OPEN_BRACE))
-	return c_parser_postfix_expression_after_paren_type (parser,
-							     type_name);
+	return c_parser_postfix_expression_after_paren_type (parser, type_name,
+							     loc);
       expr = c_parser_cast_expression (parser, NULL);
       expr = default_function_array_conversion (expr);
-      ret.value = c_cast_expr (type_name, expr.value);
+      ret.value = c_cast_expr (type_name, expr.value, loc);
       ret.original_code = ERROR_MARK;
       ret.original_type = NULL;
       return ret;
@@ -5021,7 +5039,8 @@ c_parser_sizeof_expression (c_parser *pa
       if (c_parser_next_token_is (parser, CPP_OPEN_BRACE))
 	{
 	  expr = c_parser_postfix_expression_after_paren_type (parser,
-							       type_name);
+							       type_name,
+							       expr_loc);
 	  goto sizeof_expr;
 	}
       /* sizeof ( type-name ).  */
@@ -5058,9 +5077,11 @@ c_parser_alignof_expression (c_parser *p
     {
       /* Either __alignof__ ( type-name ) or __alignof__
 	 unary-expression starting with a compound literal.  */
+      location_t loc;
       struct c_type_name *type_name;
       struct c_expr ret;
       c_parser_consume_token (parser);
+      loc = c_parser_peek_token (parser)->location;
       type_name = c_parser_type_name (parser);
       c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, "expected %<)%>");
       if (type_name == NULL)
@@ -5076,7 +5097,8 @@ c_parser_alignof_expression (c_parser *p
       if (c_parser_next_token_is (parser, CPP_OPEN_BRACE))
 	{
 	  expr = c_parser_postfix_expression_after_paren_type (parser,
-							       type_name);
+							       type_name,
+							       loc);
 	  goto alignof_expr;
 	}
       /* alignof ( type-name ).  */
@@ -5247,8 +5269,10 @@ c_parser_postfix_expression (c_parser *p
 	     than going directly to
 	     c_parser_postfix_expression_after_paren_type from
 	     elsewhere?  */
+	  location_t loc;
 	  struct c_type_name *type_name;
 	  c_parser_consume_token (parser);
+	  loc = c_parser_peek_token (parser)->location;
 	  type_name = c_parser_type_name (parser);
 	  c_parser_skip_until_found (parser, CPP_CLOSE_PAREN,
 				     "expected %<)%>");
@@ -5258,7 +5282,8 @@ c_parser_postfix_expression (c_parser *p
 	    }
 	  else
 	    expr = c_parser_postfix_expression_after_paren_type (parser,
-								 type_name);
+								 type_name,
+								 loc);
 	}
       else
 	{
@@ -5576,11 +5601,14 @@ c_parser_postfix_expression (c_parser *p
    possible to tell until after the type name whether a cast
    expression has a cast or a compound literal, or whether the operand
    of sizeof is a parenthesized type name or starts with a compound
-   literal.  */
+   literal.  TYPE_LOC is the location where TYPE_NAME starts--the
+   location of the first token after the parentheses around the type
+   name.  */
 
 static struct c_expr
 c_parser_postfix_expression_after_paren_type (c_parser *parser,
-					      struct c_type_name *type_name)
+					      struct c_type_name *type_name,
+					      location_t type_loc)
 {
   tree type;
   struct c_expr init;
@@ -5589,12 +5617,13 @@ c_parser_postfix_expression_after_paren_
   location_t start_loc;
   tree type_expr = NULL_TREE;
   bool type_expr_const = true;
+  check_compound_literal_type (type_name, type_loc);
   start_init (NULL_TREE, NULL, 0);
   type = groktypename (type_name, &type_expr, &type_expr_const);
   start_loc = c_parser_peek_token (parser)->location;
   if (type != error_mark_node && C_TYPE_VARIABLE_SIZE (type))
     {
-      error_at (start_loc, "compound literal has variable size");
+      error_at (type_loc, "compound literal has variable size");
       type = error_mark_node;
     }
   init = c_parser_braced_init (parser, type, false);
Index: c-typeck.c
===================================================================
--- c-typeck.c	(revision 147115)
+++ c-typeck.c	(working copy)
@@ -2246,6 +2246,17 @@ build_external_ref (tree id, int fun, lo
   if (TREE_CODE (ref) == CONST_DECL)
     {
       used_types_insert (TREE_TYPE (ref));
+
+      if (warn_cxx_compat
+	  && TREE_CODE (TREE_TYPE (ref)) == ENUMERAL_TYPE
+	  && C_TYPE_DEFINED_IN_STRUCT (TREE_TYPE (ref)))
+	{
+	  warning_at (loc, OPT_Wc___compat,
+		      ("enum constant defined in struct or union "
+		       "is not visible in C++"));
+	  inform (DECL_SOURCE_LOCATION (ref), "enum constant defined here");
+	}
+
       ref = DECL_INITIAL (ref);
       TREE_CONSTANT (ref) = 1;
     }
@@ -4262,7 +4273,7 @@ build_c_cast (tree type, tree expr)
 
 /* Interpret a cast of expression EXPR to type TYPE.  */
 tree
-c_cast_expr (struct c_type_name *type_name, tree expr)
+c_cast_expr (struct c_type_name *type_name, tree expr, location_t loc)
 {
   tree type;
   tree type_expr = NULL_TREE;
@@ -4283,6 +4294,15 @@ c_cast_expr (struct c_type_name *type_na
       ret = build2 (C_MAYBE_CONST_EXPR, TREE_TYPE (ret), type_expr, ret);
       C_MAYBE_CONST_EXPR_NON_CONST (ret) = !type_expr_const;
     }
+
+  if (CAN_HAVE_LOCATION_P (ret) && !EXPR_HAS_LOCATION (ret))
+    SET_EXPR_LOCATION (ret, loc);
+
+  /* C++ does not permits types to be defined in a cast.  */
+  if (warn_cxx_compat && type_name->specs->tag_defined_p)
+    warning_at (loc, OPT_Wc___compat,
+		"defining a type in a cast is invalid in C++");
+
   return ret;
 }
 
Index: c-tree.h
===================================================================
--- c-tree.h	(revision 147115)
+++ c-tree.h	(working copy)
@@ -73,6 +73,10 @@ struct GTY(()) lang_type {
 #define C_TYPE_VARIABLE_SIZE(TYPE) TYPE_LANG_FLAG_1 (TYPE)
 #define C_DECL_VARIABLE_SIZE(TYPE) DECL_LANG_FLAG_0 (TYPE)
 
+/* Record whether a type is defined inside a struct or union type.
+   This is used for -Wc++-compat. */
+#define C_TYPE_DEFINED_IN_STRUCT(TYPE) TYPE_LANG_FLAG_2 (TYPE)
+
 /* Record whether a typedef for type `int' was actually `signed int'.  */
 #define C_TYPEDEF_EXPLICITLY_SIGNED(EXP) DECL_LANG_FLAG_1 (EXP)
 
@@ -514,7 +518,7 @@ extern void c_maybe_initialize_eh (void)
 extern void finish_decl (tree, tree, tree, tree);
 extern tree finish_enum (tree, tree, tree);
 extern void finish_function (void);
-extern tree finish_struct (tree, tree, tree);
+extern tree finish_struct (tree, tree, tree, bool, VEC(tree,heap) *);
 extern struct c_arg_info *get_parm_info (bool);
 extern tree grokfield (location_t, struct c_declarator *,
 		       struct c_declspecs *, tree, tree *);
@@ -532,15 +536,16 @@ extern tree c_builtin_function (tree);
 extern tree c_builtin_function_ext_scope (tree);
 extern void shadow_tag (const struct c_declspecs *);
 extern void shadow_tag_warned (const struct c_declspecs *, int);
-extern tree start_enum (struct c_enum_contents *, tree);
+extern tree start_enum (struct c_enum_contents *, tree, location_t);
 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 (enum tree_code, tree);
+extern tree start_struct (enum tree_code, tree, bool *, VEC(tree,heap) **,
+			  location_t);
 extern void store_parm_decls (void);
 extern void store_parm_decls_from (struct c_arg_info *);
 extern tree xref_tag (enum tree_code, tree);
-extern struct c_typespec parser_xref_tag (enum tree_code, tree);
+extern struct c_typespec parser_xref_tag (enum tree_code, tree, location_t);
 extern int c_expand_decl (tree);
 extern struct c_parm *build_c_parm (struct c_declspecs *, tree,
 				    struct c_declarator *);
@@ -604,7 +609,7 @@ extern struct c_expr parser_build_binary
 					     struct c_expr);
 extern tree build_conditional_expr (tree, bool, tree, tree);
 extern tree build_compound_expr (tree, tree);
-extern tree c_cast_expr (struct c_type_name *, tree);
+extern tree c_cast_expr (struct c_type_name *, tree, location_t);
 extern tree build_c_cast (tree, tree);
 extern void store_init_value (tree, tree, tree);
 extern void error_init (const char *);
@@ -619,6 +624,7 @@ extern void set_init_index (tree, tree);
 extern void set_init_label (tree);
 extern void process_init_element (struct c_expr, bool);
 extern tree build_compound_literal (tree, tree, bool);
+extern void check_compound_literal_type (struct c_type_name *, location_t);
 extern tree c_start_case (tree);
 extern void c_finish_case (tree);
 extern tree build_asm_expr (tree, tree, tree, tree, bool);
Index: objc/objc-act.c
===================================================================
--- objc/objc-act.c	(revision 147115)
+++ objc/objc-act.c	(working copy)
@@ -415,6 +415,35 @@ FILE *gen_declaration_file;
 
 static int generating_instance_variables = 0;
 
+/* For building an objc struct.  These may not be used when this file
+   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;
+
+/* Start building a struct for objc.  */
+
+static tree
+objc_start_struct (tree name)
+{
+  gcc_assert (!objc_building_struct);
+  objc_building_struct = true;
+  return start_struct (RECORD_TYPE, name, &objc_in_struct, &objc_struct_types,
+		       UNKNOWN_LOCATION);
+}
+
+/* Finish building a struct for objc.  */
+
+static tree
+objc_finish_struct (tree type, tree fieldlist)
+{
+  gcc_assert (objc_building_struct);
+  objc_building_struct = false;
+  return finish_struct (type, fieldlist, NULL_TREE, objc_in_struct,
+			objc_struct_types);
+}
+
 /* Some platforms pass small structures through registers versus
    through an invisible pointer.  Determine at what size structure is
    the transition point between the two possibilities.  */
@@ -434,7 +463,7 @@ generate_struct_by_value_array (void)
       char buffer[5];
 
       /* Create an unnamed struct that has `i' character components */
-      type = start_struct (RECORD_TYPE, NULL_TREE);
+      type = objc_start_struct (NULL_TREE);
 
       strcpy (buffer, "c1");
       field_decl = create_field_decl (char_type_node,
@@ -448,7 +477,7 @@ generate_struct_by_value_array (void)
 					  buffer);
 	  chainon (field_decl_chain, field_decl);
 	}
-      finish_struct (type, field_decl_chain, NULL_TREE);
+      objc_finish_struct (type, field_decl_chain);
 
       aggregate_in_mem[i] = aggregate_value_p (type, 0);
       if (!aggregate_in_mem[i])
@@ -788,7 +817,7 @@ static tree
 objc_build_struct (tree klass, tree fields, tree super_name)
 {
   tree name = CLASS_NAME (klass);
-  tree s = start_struct (RECORD_TYPE, name);
+  tree s = objc_start_struct (name);
   tree super = (super_name ? xref_tag (RECORD_TYPE, super_name) : NULL_TREE);
   tree t, objc_info = NULL_TREE;
 
@@ -849,7 +878,7 @@ objc_build_struct (tree klass, tree fiel
   INIT_TYPE_OBJC_INFO (s);
   TYPE_OBJC_INTERFACE (s) = klass;
 
-  s = finish_struct (s, fields, NULL_TREE);
+  s = objc_finish_struct (s, fields);
 
   for (t = TYPE_NEXT_VARIANT (s); t;
        t = TYPE_NEXT_VARIANT (t), objc_info = TREE_CHAIN (objc_info))
@@ -2057,8 +2086,7 @@ build_objc_symtab_template (void)
 {
   tree field_decl, field_decl_chain;
 
-  objc_symtab_template
-    = start_struct (RECORD_TYPE, get_identifier (UTAG_SYMTAB));
+  objc_symtab_template = objc_start_struct (get_identifier (UTAG_SYMTAB));
 
   /* long sel_ref_cnt; */
   field_decl = create_field_decl (long_integer_type_node, "sel_ref_cnt");
@@ -2092,7 +2120,7 @@ build_objc_symtab_template (void)
       chainon (field_decl_chain, field_decl);
     }
 
-  finish_struct (objc_symtab_template, field_decl_chain, NULL_TREE);
+  objc_finish_struct (objc_symtab_template, field_decl_chain);
 }
 
 /* Create the initial value for the `defs' field of _objc_symtab.
@@ -2292,8 +2320,7 @@ build_module_descriptor (void)
   push_lang_context (lang_name_c); /* extern "C" */
 #endif
 
-  objc_module_template
-    = start_struct (RECORD_TYPE, get_identifier (UTAG_MODULE));
+  objc_module_template = objc_start_struct (get_identifier (UTAG_MODULE));
 
   /* long version; */
   field_decl = create_field_decl (long_integer_type_node, "version");
@@ -2315,7 +2342,7 @@ build_module_descriptor (void)
 			 "symtab");
   chainon (field_decl_chain, field_decl);
 
-  finish_struct (objc_module_template, field_decl_chain, NULL_TREE);
+  objc_finish_struct (objc_module_template, field_decl_chain);
 
   /* Create an instance of "_objc_module".  */
   UOBJC_MODULES_decl = start_var_decl (objc_module_template, "_OBJC_MODULES");
@@ -3993,7 +4020,7 @@ build_next_objc_exception_stuff (void)
   tree field_decl, field_decl_chain, index, temp_type;
 
   objc_exception_data_template
-    = start_struct (RECORD_TYPE, get_identifier (UTAG_EXCDATA));
+    = objc_start_struct (get_identifier (UTAG_EXCDATA));
 
   /* int buf[OBJC_JBLEN]; */
 
@@ -4009,7 +4036,7 @@ build_next_objc_exception_stuff (void)
 				  "pointers");
   chainon (field_decl_chain, field_decl);
 
-  finish_struct (objc_exception_data_template, field_decl_chain, NULL_TREE);
+  objc_finish_struct (objc_exception_data_template, field_decl_chain);
 
   /* int _setjmp(...); */
   /* If the user includes <setjmp.h>, this shall be superseded by
@@ -4156,8 +4183,7 @@ build_protocol_template (void)
 {
   tree field_decl, field_decl_chain;
 
-  objc_protocol_template = start_struct (RECORD_TYPE,
-					 get_identifier (UTAG_PROTOCOL));
+  objc_protocol_template = objc_start_struct (get_identifier (UTAG_PROTOCOL));
 
   /* struct _objc_class *isa; */
   field_decl = create_field_decl (build_pointer_type
@@ -4187,7 +4213,7 @@ build_protocol_template (void)
 				  "class_methods");
   chainon (field_decl_chain, field_decl);
 
-  finish_struct (objc_protocol_template, field_decl_chain, NULL_TREE);
+  objc_finish_struct (objc_protocol_template, field_decl_chain);
 }
 
 static tree
@@ -4237,7 +4263,7 @@ build_method_prototype_list_template (tr
 
   /* Generate an unnamed struct definition.  */
 
-  objc_ivar_list_record = start_struct (RECORD_TYPE, NULL_TREE);
+  objc_ivar_list_record = objc_start_struct (NULL_TREE);
 
   /* int method_count; */
   field_decl = create_field_decl (integer_type_node, "method_count");
@@ -4251,7 +4277,7 @@ build_method_prototype_list_template (tr
 				  "method_list");
   chainon (field_decl_chain, field_decl);
 
-  finish_struct (objc_ivar_list_record, field_decl_chain, NULL_TREE);
+  objc_finish_struct (objc_ivar_list_record, field_decl_chain);
 
   return objc_ivar_list_record;
 }
@@ -4262,8 +4288,7 @@ build_method_prototype_template (void)
   tree proto_record;
   tree field_decl, field_decl_chain;
 
-  proto_record
-    = start_struct (RECORD_TYPE, get_identifier (UTAG_METHOD_PROTOTYPE));
+  proto_record = objc_start_struct (get_identifier (UTAG_METHOD_PROTOTYPE));
 
   /* SEL _cmd; */
   field_decl = create_field_decl (objc_selector_type, "_cmd");
@@ -4273,7 +4298,7 @@ build_method_prototype_template (void)
   field_decl = create_field_decl (string_type_node, "method_types");
   chainon (field_decl_chain, field_decl);
 
-  finish_struct (proto_record, field_decl_chain, NULL_TREE);
+  objc_finish_struct (proto_record, field_decl_chain);
 
   return proto_record;
 }
@@ -4758,8 +4783,7 @@ build_category_template (void)
 {
   tree field_decl, field_decl_chain;
 
-  objc_category_template = start_struct (RECORD_TYPE,
-					 get_identifier (UTAG_CATEGORY));
+  objc_category_template = objc_start_struct (get_identifier (UTAG_CATEGORY));
 
   /* char *category_name; */
   field_decl = create_field_decl (string_type_node, "category_name");
@@ -4786,7 +4810,7 @@ build_category_template (void)
 				  "protocol_list");
   chainon (field_decl_chain, field_decl);
 
-  finish_struct (objc_category_template, field_decl_chain, NULL_TREE);
+  objc_finish_struct (objc_category_template, field_decl_chain);
 }
 
 /* struct _objc_selector {
@@ -4797,11 +4821,9 @@ build_category_template (void)
 static void
 build_selector_template (void)
 {
-
   tree field_decl, field_decl_chain;
 
-  objc_selector_template
-    = start_struct (RECORD_TYPE, get_identifier (UTAG_SELECTOR));
+  objc_selector_template = objc_start_struct (get_identifier (UTAG_SELECTOR));
 
   /* SEL sel_id; */
   field_decl = create_field_decl (objc_selector_type, "sel_id");
@@ -4811,7 +4833,7 @@ build_selector_template (void)
   field_decl = create_field_decl (string_type_node, "sel_type");
   chainon (field_decl_chain, field_decl);
 
-  finish_struct (objc_selector_template, field_decl_chain, NULL_TREE);
+  objc_finish_struct (objc_selector_template, field_decl_chain);
 }
 
 /* struct _objc_class {
@@ -4847,8 +4869,7 @@ build_class_template (void)
 {
   tree field_decl, field_decl_chain;
 
-  objc_class_template
-    = start_struct (RECORD_TYPE, get_identifier (UTAG_CLASS));
+  objc_class_template = objc_start_struct (get_identifier (UTAG_CLASS));
 
   /* struct _objc_class *isa; */
   field_decl = create_field_decl (build_pointer_type (objc_class_template),
@@ -4941,7 +4962,7 @@ build_class_template (void)
 				  "gc_object_type");
   chainon (field_decl_chain, field_decl);
 
-  finish_struct (objc_class_template, field_decl_chain, NULL_TREE);
+  objc_finish_struct (objc_class_template, field_decl_chain);
 }
 
 /* Generate appropriate forward declarations for an implementation.  */
@@ -5042,7 +5063,7 @@ build_super_template (void)
 {
   tree field_decl, field_decl_chain;
 
-  objc_super_template = start_struct (RECORD_TYPE, get_identifier (UTAG_SUPER));
+  objc_super_template = objc_start_struct (get_identifier (UTAG_SUPER));
 
   /* struct _objc_object *self; */
   field_decl = create_field_decl (objc_object_type, "self");
@@ -5053,7 +5074,7 @@ build_super_template (void)
 				  "super_class");
   chainon (field_decl_chain, field_decl);
 
-  finish_struct (objc_super_template, field_decl_chain, NULL_TREE);
+  objc_finish_struct (objc_super_template, field_decl_chain);
 }
 
 /* struct _objc_ivar {
@@ -5069,7 +5090,7 @@ build_ivar_template (void)
   tree field_decl, field_decl_chain;
 
   objc_ivar_id = get_identifier (UTAG_IVAR);
-  objc_ivar_record = start_struct (RECORD_TYPE, objc_ivar_id);
+  objc_ivar_record = objc_start_struct (objc_ivar_id);
 
   /* char *ivar_name; */
   field_decl = create_field_decl (string_type_node, "ivar_name");
@@ -5083,7 +5104,7 @@ build_ivar_template (void)
   field_decl = create_field_decl (integer_type_node, "ivar_offset");
   chainon (field_decl_chain, field_decl);
 
-  finish_struct (objc_ivar_record, field_decl_chain, NULL_TREE);
+  objc_finish_struct (objc_ivar_record, field_decl_chain);
 
   return objc_ivar_record;
 }
@@ -5099,7 +5120,7 @@ build_ivar_list_template (tree list_type
   tree objc_ivar_list_record;
   tree field_decl, field_decl_chain;
 
-  objc_ivar_list_record = start_struct (RECORD_TYPE, NULL_TREE);
+  objc_ivar_list_record = objc_start_struct (NULL_TREE);
 
   /* int ivar_count; */
   field_decl = create_field_decl (integer_type_node, "ivar_count");
@@ -5113,7 +5134,7 @@ build_ivar_list_template (tree list_type
 				  "ivar_list");
   chainon (field_decl_chain, field_decl);
 
-  finish_struct (objc_ivar_list_record, field_decl_chain, NULL_TREE);
+  objc_finish_struct (objc_ivar_list_record, field_decl_chain);
 
   return objc_ivar_list_record;
 }
@@ -5130,7 +5151,7 @@ build_method_list_template (tree list_ty
   tree objc_ivar_list_record;
   tree field_decl, field_decl_chain;
 
-  objc_ivar_list_record = start_struct (RECORD_TYPE, NULL_TREE);
+  objc_ivar_list_record = objc_start_struct (NULL_TREE);
 
   /* struct _objc__method_prototype_list *method_next; */
   field_decl = create_field_decl (objc_method_proto_list_ptr,
@@ -5149,7 +5170,7 @@ build_method_list_template (tree list_ty
 				  "method_list");
   chainon (field_decl_chain, field_decl);
 
-  finish_struct (objc_ivar_list_record, field_decl_chain, NULL_TREE);
+  objc_finish_struct (objc_ivar_list_record, field_decl_chain);
 
   return objc_ivar_list_record;
 }
@@ -5337,7 +5358,7 @@ build_method_template (void)
   tree _SLT_record;
   tree field_decl, field_decl_chain;
 
-  _SLT_record = start_struct (RECORD_TYPE, get_identifier (UTAG_METHOD));
+  _SLT_record = objc_start_struct (get_identifier (UTAG_METHOD));
 
   /* SEL _cmd; */
   field_decl = create_field_decl (objc_selector_type, "_cmd");
@@ -5352,7 +5373,7 @@ build_method_template (void)
 				  "_imp");
   chainon (field_decl_chain, field_decl);
 
-  finish_struct (_SLT_record, field_decl_chain, NULL_TREE);
+  objc_finish_struct (_SLT_record, field_decl_chain);
 
   return _SLT_record;
 }
Index: objcp/objcp-decl.h
===================================================================
--- objcp/objcp-decl.h	(revision 147115)
+++ objcp/objcp-decl.h	(working copy)
@@ -1,6 +1,6 @@
 /* Process the ObjC-specific declarations and variables for 
    the Objective-C++ compiler.
-   Copyright (C) 2005, 2007 Free Software Foundation, Inc.
+   Copyright (C) 2005, 2007, 2009 Free Software Foundation, Inc.
    Contributed by Ziemowit Laski  <zlaski@apple.com>
 
 This file is part of GCC.
@@ -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(code, name) \
+#define start_struct(code, name, in_struct, struct_types, loc) \
 	objcp_start_struct (code, name)
-#define finish_struct(t, fieldlist, attributes) \
+#define finish_struct(t, fieldlist, attributes, in_struct, struct_types) \
 	objcp_finish_struct (t, fieldlist, attributes)
 #define finish_function() \
 	objcp_finish_function ()
Index: testsuite/gcc.dg/Wcxx-compat-7.c
===================================================================
--- testsuite/gcc.dg/Wcxx-compat-7.c	(revision 0)
+++ testsuite/gcc.dg/Wcxx-compat-7.c	(revision 0)
@@ -0,0 +1,35 @@
+/* { dg-do compile } */
+/* { dg-options "-Wc++-compat" } */
+
+struct s1
+{
+  enum e1	/* { dg-message "note: enum type defined here" } */
+  {
+    A,		/* { dg-message "note: enum constant defined here" } */
+    B
+  } f1;
+  struct s2	/* { dg-message "note: struct defined here" } */
+  {
+    struct s3	/* { dg-message "note: struct defined here" } */
+    {
+      enum e1 f3;
+      struct s1 *p1;
+      struct s2 *p2;
+      struct s3 *p3;
+    } f2;
+    union u1	/* { dg-message "note: union defined here" } */
+    {
+      int f4;
+    } f5;
+    struct s3 f6;
+  } f7;
+  struct s2 f8;
+  enum e1 f9;
+};
+
+struct s1 v1;
+enum e1 v2;	/* { dg-warning "not visible in C\[+\]\[+\]" } */
+struct s2 v3;	/* { dg-warning "not visible in C\[+\]\[+\]" } */
+struct s3 v4;	/* { dg-warning "not visible in C\[+\]\[+\]" } */
+union u1 v5;	/* { dg-warning "not visible in C\[+\]\[+\]" } */
+int i = A;	/* { dg-warning "not visible in C\[+\]\[+\]" } */
Index: testsuite/gcc.dg/pr39084.c
===================================================================
--- testsuite/gcc.dg/pr39084.c	(revision 147115)
+++ testsuite/gcc.dg/pr39084.c	(working copy)
@@ -1,7 +1,7 @@
 /* { dg-do compile } */
 /* { dg-options "-O2" } */
 
-struct color { int i; };
+struct color { int i; }; /* { dg-message "note: originally defined here" } */
 static const struct color col;
 struct color * f(void)
 {
Index: testsuite/gcc.dg/Wcxx-compat-8.c
===================================================================
--- testsuite/gcc.dg/Wcxx-compat-8.c	(revision 0)
+++ testsuite/gcc.dg/Wcxx-compat-8.c	(revision 0)
@@ -0,0 +1,43 @@
+/* { dg-do compile } */
+/* { dg-options "-Wc++-compat" } */
+
+struct s1
+{
+  enum e1	/* { dg-message "note: enum type defined here" } */
+  {
+    A = sizeof (struct s2 { int i; }),	/* { dg-warning "invalid in C\[+\]\[+\]" } */
+    B
+  } f1;
+};
+struct s2 v1;	/* Don't issue another warning about s2.  */
+enum e1 v2;	/* { dg-warning "not visible in C\[+\]\[+\]" } */
+
+enum e2
+{
+  C = sizeof (struct s3 { int i; }),	/* { dg-warning "invalid in C\[+\]\[+\]" } */
+  D = __alignof__ (struct s4 { int i; }), /* { dg-warning "invalid in C\[+\]\[+\]" } */
+  E
+};
+
+struct s3 v3;
+int v4 = C;
+
+__typeof__ (struct s5 { int i; }) v5; /* { dg-warning "invalid in C\[+\]\[+\]" } */
+
+int
+f1 (struct s1 *p)
+{
+  return ((struct s6 { int j; } *) p)->j;  /* { dg-warning "invalid in C\[+\]\[+\]" } */
+}
+
+int
+f2 (struct s1 *p)
+{
+  return (__extension__ (struct s7 { int j; } *)p)->j;
+}
+
+int
+f3 ()
+{
+  return (struct s8 { int i; }) { 0 }.i;  /* { dg-warning "invalid in C\[+\]\[+\]" } */
+}
Index: testsuite/gcc.dg/c99-tag-1.c
===================================================================
--- testsuite/gcc.dg/c99-tag-1.c	(revision 147115)
+++ testsuite/gcc.dg/c99-tag-1.c	(working copy)
@@ -24,7 +24,7 @@ foo (void)
   /* A specific type shall have its content defined at most once.  But we
      may redeclare the tag in different scopes.  */
   {
-    struct s0 { int i; };
+    struct s0 { int i; }; /* { dg-message "note: originally defined here" } */
     {
       struct s0 { long l; };
     }
@@ -33,7 +33,7 @@ foo (void)
     }
     struct s0 { int i; }; /* { dg-bogus "warning" "warning in place of error" } */
     /* { dg-error "rede" "struct redef" { target *-*-* } 34 } */
-    union u0 { int i; };
+    union u0 { int i; }; /* { dg-message "note: originally defined here" } */
     {
       union u0 { long l; };
     }
@@ -42,7 +42,7 @@ foo (void)
     }
     union u0 { int i; }; /* { dg-bogus "warning" "warning in place of error" } */
     /* { dg-error "rede" "union redef" { target *-*-* } 43 } */
-    enum e0 { E0A };
+    enum e0 { E0A }; /* { dg-message "note: originally defined here" } */
     {
       enum e0 { E0B };
     }
Index: testsuite/gcc.dg/pr17188-1.c
===================================================================
--- testsuite/gcc.dg/pr17188-1.c	(revision 147115)
+++ testsuite/gcc.dg/pr17188-1.c	(working copy)
@@ -5,20 +5,20 @@
 /* { dg-do compile } */
 /* { dg-options "" } */
 
-struct s0 { };
+struct s0 { }; /* { dg-message "note: originally defined here" } */
 struct s0;
 struct s0 { }; /* { dg-error "redefinition of 'struct s0'" } */
 
-struct s1 { };
+struct s1 { }; /* { dg-message "note: originally defined here" } */
 struct s1 { }; /* { dg-error "redefinition of 'struct s1'" } */
 
-struct s2 { int a : 1; };
+struct s2 { int a : 1; }; /* { dg-message "note: originally defined here" } */
 struct s2 { int a : 1; }; /* { dg-error "redefinition of 'struct s2'" } */
 
-struct s3 { };
+struct s3 { }; /* { dg-message "note: originally defined here" } */
 struct s3 { int a : 1; }; /* { dg-error "redefinition of 'struct s3'" } */
 
-struct s4 { int a : 1; };
+struct s4 { int a : 1; }; /* { dg-message "note: originally defined here" } */
 struct s4 { }; /* { dg-error "redefinition of 'struct s4'" } */
 
 struct s5 { int a : 1; };

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