aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorMark Mitchell <mark@codesourcery.com>2004-12-15 00:42:33 +0000
committerMark Mitchell <mmitchel@gcc.gnu.org>2004-12-15 00:42:33 +0000
commit0c88d886685d51b8579f29f079d81433ae1e9d31 (patch)
treef4dae82d23279fb3656e496ae669d665c8bd8f38 /gcc
parenta150cb057b5c6c835a95f0bf905dc929a24d4bf2 (diff)
downloadgcc-0c88d886685d51b8579f29f079d81433ae1e9d31.zip
gcc-0c88d886685d51b8579f29f079d81433ae1e9d31.tar.gz
gcc-0c88d886685d51b8579f29f079d81433ae1e9d31.tar.bz2
re PR c++/18738 (typename not allowed with non-dependent qualified name)
PR c++/18738 * decl.c (make_typename_type): Do not handle namespace-scoped names here. (tag_name): Handle typename_type. (check_elaborated_type_specifier): Handle typenames. * parser.c (cp_parser_diagnose_invalid_type_name): Improve comment. (cp_parser_elaborated_type_specifier): Use cp_parser_diagnose_invalid_type_name. PR c++/18738 * g++.dg/template/typename8.C: New test. * g++.dg/parse/friend2.C: Tweak error message. From-SVN: r92172
Diffstat (limited to 'gcc')
-rw-r--r--gcc/cp/ChangeLog12
-rw-r--r--gcc/cp/decl.c25
-rw-r--r--gcc/cp/parser.c15
-rw-r--r--gcc/testsuite/ChangeLog6
-rw-r--r--gcc/testsuite/g++.dg/parse/friend2.C2
-rw-r--r--gcc/testsuite/g++.dg/template/typename8.C10
6 files changed, 48 insertions, 22 deletions
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog
index ef54628..120f9b9 100644
--- a/gcc/cp/ChangeLog
+++ b/gcc/cp/ChangeLog
@@ -1,3 +1,15 @@
+2004-12-14 Mark Mitchell <mark@codesourcery.com>
+
+ PR c++/18738
+ * decl.c (make_typename_type): Do not handle namespace-scoped
+ names here.
+ (tag_name): Handle typename_type.
+ (check_elaborated_type_specifier): Handle typenames.
+ * parser.c (cp_parser_diagnose_invalid_type_name): Improve
+ comment.
+ (cp_parser_elaborated_type_specifier): Use
+ cp_parser_diagnose_invalid_type_name.
+
2004-12-14 Andrew Pinski <pinskia@physics.uc.edu>
PR c++/18965
diff --git a/gcc/cp/decl.c b/gcc/cp/decl.c
index 410f686..d711899 100644
--- a/gcc/cp/decl.c
+++ b/gcc/cp/decl.c
@@ -2669,15 +2669,7 @@ make_typename_type (tree context, tree name, enum tag_types tag_type,
return error_mark_node;
}
gcc_assert (TREE_CODE (name) == IDENTIFIER_NODE);
-
- if (TREE_CODE (context) == NAMESPACE_DECL)
- {
- /* We can get here from typename_sub0 in the explicit_template_type
- expansion. Just fail. */
- if (complain & tf_error)
- error ("no class template named %q#T in %q#T", name, context);
- return error_mark_node;
- }
+ gcc_assert (TYPE_P (context));
if (!dependent_type_p (context)
|| currently_open_class (context))
@@ -9048,6 +9040,8 @@ grok_op_properties (tree decl, int friendp, bool complain)
return ok;
}
+/* Return a string giving the keyword associate with CODE. */
+
static const char *
tag_name (enum tag_types code)
{
@@ -9058,9 +9052,11 @@ tag_name (enum tag_types code)
case class_type:
return "class";
case union_type:
- return "union ";
+ return "union";
case enum_type:
return "enum";
+ case typename_type:
+ return "typename";
default:
gcc_unreachable ();
}
@@ -9106,7 +9102,8 @@ check_elaborated_type_specifier (enum tag_types tag_code,
In other words, the only legitimate declaration to use in the
elaborated type specifier is the implicit typedef created when
the type is declared. */
- else if (!DECL_IMPLICIT_TYPEDEF_P (decl))
+ else if (!DECL_IMPLICIT_TYPEDEF_P (decl)
+ && tag_code != typename_type)
{
error ("using typedef-name %qD after %qs", decl, tag_name (tag_code));
cp_error_at ("%qD has a previous declaration here", decl);
@@ -9114,14 +9111,16 @@ check_elaborated_type_specifier (enum tag_types tag_code,
}
else if (TREE_CODE (type) != RECORD_TYPE
&& TREE_CODE (type) != UNION_TYPE
- && tag_code != enum_type)
+ && tag_code != enum_type
+ && tag_code != typename_type)
{
error ("%qT referred to as %qs", type, tag_name (tag_code));
cp_error_at ("%qT has a previous declaration here", type);
return error_mark_node;
}
else if (TREE_CODE (type) != ENUMERAL_TYPE
- && tag_code == enum_type)
+ && tag_code == enum_type
+ && tag_code != typename_type)
{
error ("%qT referred to as enum", type);
cp_error_at ("%qT has a previous declaration here", type);
diff --git a/gcc/cp/parser.c b/gcc/cp/parser.c
index 9d3696f..13578f0 100644
--- a/gcc/cp/parser.c
+++ b/gcc/cp/parser.c
@@ -1939,9 +1939,8 @@ cp_parser_non_integral_constant_expression (cp_parser *parser,
return false;
}
-/* Emit a diagnostic for an invalid type name. Consider also if it is
- qualified or not and the result of a lookup, to provide a better
- message. */
+/* Emit a diagnostic for an invalid type name. SCOPE is the
+ qualifying scope (or NULL, if none) for ID. */
static void
cp_parser_diagnose_invalid_type_name (cp_parser *parser, tree scope, tree id)
@@ -9647,7 +9646,8 @@ cp_parser_elaborated_type_specifier (cp_parser* parser,
}
/* For a `typename', we needn't call xref_tag. */
- if (tag_type == typename_type)
+ if (tag_type == typename_type
+ && TREE_CODE (parser->scope) != NAMESPACE_DECL)
return cp_parser_make_typename_type (parser, parser->scope,
identifier);
/* Look up a qualified name in the usual way. */
@@ -9655,9 +9655,6 @@ cp_parser_elaborated_type_specifier (cp_parser* parser,
{
tree decl;
- /* In an elaborated-type-specifier, names are assumed to name
- types, so we set IS_TYPE to TRUE when calling
- cp_parser_lookup_name. */
decl = cp_parser_lookup_name (parser, identifier,
tag_type,
/*is_template=*/false,
@@ -9692,7 +9689,9 @@ cp_parser_elaborated_type_specifier (cp_parser* parser,
if (TREE_CODE (decl) != TYPE_DECL)
{
- error ("expected type-name");
+ cp_parser_diagnose_invalid_type_name (parser,
+ parser->scope,
+ identifier);
return error_mark_node;
}
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index f58377f..ec5facc 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -1,3 +1,9 @@
+2004-12-14 Mark Mitchell <mark@codesourcery.com>
+
+ PR c++/18738
+ * g++.dg/template/typename8.C: New test.
+ * g++.dg/parse/friend2.C: Tweak error message.
+
2004-12-14 Andrew Pinski <pinskia@physics.uc.edu>
* gcc.c-torture/20041214-1.c: New test.
diff --git a/gcc/testsuite/g++.dg/parse/friend2.C b/gcc/testsuite/g++.dg/parse/friend2.C
index 2e88845..1a2ad8b 100644
--- a/gcc/testsuite/g++.dg/parse/friend2.C
+++ b/gcc/testsuite/g++.dg/parse/friend2.C
@@ -10,7 +10,7 @@ namespace NS {
}
template <class T> class X {
- friend class NS::C; // { dg-error "expected|friend" }
+ friend class NS::C; // { dg-error "template|friend" }
};
X<int> c;
diff --git a/gcc/testsuite/g++.dg/template/typename8.C b/gcc/testsuite/g++.dg/template/typename8.C
new file mode 100644
index 0000000..85f585d
--- /dev/null
+++ b/gcc/testsuite/g++.dg/template/typename8.C
@@ -0,0 +1,10 @@
+// PR c++/18738
+
+namespace foo {
+ typedef int my_type;
+}
+
+template<typename T>
+struct A {
+ typename foo::my_type bar();
+};