Patchwork C++ PATCH for c++/50084 (ICE with decltype and unnamed local class)

login
register
mail settings
Submitter Jason Merrill
Date Aug. 30, 2011, 9:32 p.m.
Message ID <4E5D56D7.8000509@redhat.com>
Download mbox | patch
Permalink /patch/112386/
State New
Headers show

Comments

Jason Merrill - Aug. 30, 2011, 9:32 p.m.
In this testcase the compiler was incorrectly treating the typedef as 
giving a name to the class for linkage purposes, and then getting 
confused by that.  While looking at this I noticed that nothing was 
actually looking at the user_defined_type_p bitfield, so I repurposed it.

Tested x86_64-pc-linux-gnu, applying to trunk.

Patch

commit bd3f1ed177f5ce0961f6482a3ea8a3dd1f9df336
Author: Jason Merrill <jason@redhat.com>
Date:   Tue Aug 30 16:46:14 2011 -0400

    	PR c++/50084
    	* cp-tree.h (cp_decl_specifier_seq): Rename user_defined_type_p
    	to type_definition_p.
    	* parser.c (cp_parser_set_decl_spec_type): Likewise.
    	* decl.c (grokdeclarator): Check it.

diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h
index d125642..d18599b 100644
--- a/gcc/cp/cp-tree.h
+++ b/gcc/cp/cp-tree.h
@@ -4551,8 +4551,8 @@  typedef struct cp_decl_specifier_seq {
   /* The storage class specified -- or sc_none if no storage class was
      explicitly specified.  */
   cp_storage_class storage_class;
-  /* True iff TYPE_SPEC indicates a user-defined type.  */
-  BOOL_BITFIELD user_defined_type_p : 1;
+  /* True iff TYPE_SPEC defines a class or enum.  */
+  BOOL_BITFIELD type_definition_p : 1;
   /* True iff multiple types were (erroneously) specified for this
      decl-specifier-seq.  */
   BOOL_BITFIELD multiple_types_p : 1;
diff --git a/gcc/cp/decl.c b/gcc/cp/decl.c
index 9090b11..39a0b0e 100644
--- a/gcc/cp/decl.c
+++ b/gcc/cp/decl.c
@@ -9643,6 +9643,7 @@  grokdeclarator (const cp_declarator *declarator,
 	  && TYPE_NAME (type)
 	  && TREE_CODE (TYPE_NAME (type)) == TYPE_DECL
 	  && TYPE_ANONYMOUS_P (type)
+	  && declspecs->type_definition_p
 	  && cp_type_quals (type) == TYPE_UNQUALIFIED)
 	{
 	  tree t;
diff --git a/gcc/cp/parser.c b/gcc/cp/parser.c
index c862a7d..7d766d1 100644
--- a/gcc/cp/parser.c
+++ b/gcc/cp/parser.c
@@ -12577,7 +12577,7 @@  cp_parser_type_specifier (cp_parser* parser,
 	    cp_parser_set_decl_spec_type (decl_specs,
 					  type_spec,
 					  token->location,
-					  /*user_defined_p=*/true);
+					  /*type_definition_p=*/true);
 	  return type_spec;
 	}
       else
@@ -12606,7 +12606,7 @@  cp_parser_type_specifier (cp_parser* parser,
 	    cp_parser_set_decl_spec_type (decl_specs,
 					  type_spec,
 					  token->location,
-					  /*user_defined_p=*/true);
+					  /*type_definition_p=*/true);
 	  return type_spec;
 	}
 
@@ -12628,7 +12628,7 @@  cp_parser_type_specifier (cp_parser* parser,
 	cp_parser_set_decl_spec_type (decl_specs,
 				      type_spec,
 				      token->location,
-				      /*user_defined_p=*/true);
+				      /*type_definition_p=*/false);
       return type_spec;
 
     case RID_CONST:
@@ -12821,7 +12821,7 @@  cp_parser_simple_type_specifier (cp_parser* parser,
       if (decl_specs)
 	cp_parser_set_decl_spec_type (decl_specs, type,
 				      token->location,
-				      /*user_defined_p=*/true);
+				      /*type_definition_p=*/false);
 
       return type;
 
@@ -12831,7 +12831,7 @@  cp_parser_simple_type_specifier (cp_parser* parser,
       if (decl_specs)
 	cp_parser_set_decl_spec_type (decl_specs, type,
 				      token->location,
-				      /*user_defined_p=*/true);
+				      /*type_definition_p=*/false);
 
       return type;
 
@@ -12848,7 +12848,7 @@  cp_parser_simple_type_specifier (cp_parser* parser,
       if (decl_specs)
 	cp_parser_set_decl_spec_type (decl_specs, type,
 				      token->location,
-				      /*user_defined_p=*/true);
+				      /*type_definition_p=*/false);
       cp_lexer_consume_token (parser->lexer);
       return type;
     }
@@ -12865,7 +12865,7 @@  cp_parser_simple_type_specifier (cp_parser* parser,
 	cp_parser_set_decl_spec_type (decl_specs,
 				      type,
 				      token->location,
-				      /*user_defined=*/false);
+				      /*type_definition_p=*/false);
       if (decl_specs)
 	decl_specs->any_specifiers_p = true;
 
@@ -12940,7 +12940,7 @@  cp_parser_simple_type_specifier (cp_parser* parser,
       if (type && decl_specs)
 	cp_parser_set_decl_spec_type (decl_specs, type,
 				      token->location,
-				      /*user_defined=*/true);
+				      /*type_definition_p=*/false);
     }
 
   /* If we didn't get a type-name, issue an error message.  */
@@ -21004,15 +21004,14 @@  cp_parser_set_storage_class (cp_parser *parser,
     decl_specs->conflicting_specifiers_p = true;
 }
 
-/* Update the DECL_SPECS to reflect the TYPE_SPEC.  If USER_DEFINED_P
-   is true, the type is a user-defined type; otherwise it is a
-   built-in type specified by a keyword.  */
+/* Update the DECL_SPECS to reflect the TYPE_SPEC.  If TYPE_DEFINITION_P
+   is true, the type is a class or enum definition.  */
 
 static void
 cp_parser_set_decl_spec_type (cp_decl_specifier_seq *decl_specs,
 			      tree type_spec,
 			      location_t location,
-			      bool user_defined_p)
+			      bool type_definition_p)
 {
   decl_specs->any_specifiers_p = true;
 
@@ -21022,7 +21021,7 @@  cp_parser_set_decl_spec_type (cp_decl_specifier_seq *decl_specs,
      declarations so that G++ can work with system headers that are not
      C++-safe.  */
   if (decl_specs->specs[(int) ds_typedef]
-      && !user_defined_p
+      && !type_definition_p
       && (type_spec == boolean_type_node
 	  || type_spec == char16_type_node
 	  || type_spec == char32_type_node
@@ -21037,7 +21036,7 @@  cp_parser_set_decl_spec_type (cp_decl_specifier_seq *decl_specs,
       if (!decl_specs->type)
 	{
 	  decl_specs->type = type_spec;
-	  decl_specs->user_defined_type_p = false;
+	  decl_specs->type_definition_p = false;
 	  decl_specs->type_location = location;
 	}
     }
@@ -21046,7 +21045,7 @@  cp_parser_set_decl_spec_type (cp_decl_specifier_seq *decl_specs,
   else
     {
       decl_specs->type = type_spec;
-      decl_specs->user_defined_type_p = user_defined_p;
+      decl_specs->type_definition_p = type_definition_p;
       decl_specs->redefined_builtin_type = NULL_TREE;
       decl_specs->type_location = location;
     }
diff --git a/gcc/testsuite/g++.dg/cpp0x/decltype33.C b/gcc/testsuite/g++.dg/cpp0x/decltype33.C
new file mode 100644
index 0000000..d022d16
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/decltype33.C
@@ -0,0 +1,18 @@ 
+// PR c++/50084
+// { dg-options "-std=c++0x -fno-inline" }
+
+template<typename>   struct remove_reference;
+template<typename T> struct remove_reference<T&> { typedef T type; };
+
+template <class T> void f(T) { }
+
+void g()
+{
+  struct { } * v = 0;
+
+  typedef remove_reference<decltype(*v)>::type at;
+
+  // The typedef should't assign the name "at" to the struct.
+  // { dg-final { scan-assembler "_Z1fIZ1gvEUt_EvT_" } }
+  f(at());
+}