This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
C++ PATCH for c++/50084 (ICE with decltype and unnamed local class)
- From: Jason Merrill <jason at redhat dot com>
- To: gcc-patches List <gcc-patches at gcc dot gnu dot org>
- Date: Tue, 30 Aug 2011 17:32:07 -0400
- Subject: C++ PATCH for c++/50084 (ICE with decltype and unnamed local class)
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.
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());
+}