+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
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))
return ok;
}
\f
+/* Return a string giving the keyword associate with CODE. */
+
static const char *
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 ();
}
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);
}
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);
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)
}
/* 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. */
{
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,
if (TREE_CODE (decl) != TYPE_DECL)
{
- error ("expected type-name");
+ cp_parser_diagnose_invalid_type_name (parser,
+ parser->scope,
+ identifier);
return error_mark_node;
}
+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.
}
template <class T> class X {
- friend class NS::C; // { dg-error "expected|friend" }
+ friend class NS::C; // { dg-error "template|friend" }
};
X<int> c;
--- /dev/null
+// PR c++/18738
+
+namespace foo {
+ typedef int my_type;
+}
+
+template<typename T>
+struct A {
+ typename foo::my_type bar();
+};