re PR c++/60994 (gcc does not recognize hidden/shadowed enumeration as valid nested-name-specifier)

PR c++/60994
	* parser.c (cp_parser_class_name): Add enum_ok parameter.
	(cp_parser_qualifying_entity): Use it instead of cp_parser_type_name.
	(cp_parser_diagnose_invalid_type_name): Don't assume a template is
	a class template.

Co-Authored-By: Jason Merrill <jason@redhat.com>

From-SVN: r222094
This commit is contained in:
Momchil Velikov 2015-04-14 15:29:21 +00:00 committed by Jason Merrill
parent b42e706455
commit 2fd16d0f90
5 changed files with 66 additions and 37 deletions

View File

@ -1,3 +1,12 @@
2015-04-14 Momchil Velikov <momchil.velikov@gmail.com>
Jason Merrill <jason@redhat.com>
PR c++/60994
* parser.c (cp_parser_class_name): Add enum_ok parameter.
(cp_parser_qualifying_entity): Use it instead of cp_parser_type_name.
(cp_parser_diagnose_invalid_type_name): Don't assume a template is
a class template.
2015-04-12 Jakub Jelinek <jakub@redhat.com> 2015-04-12 Jakub Jelinek <jakub@redhat.com>
PR c++/65736 PR c++/65736

View File

@ -2193,7 +2193,7 @@ static tree finish_fully_implicit_template
/* Classes [gram.class] */ /* Classes [gram.class] */
static tree cp_parser_class_name static tree cp_parser_class_name
(cp_parser *, bool, bool, enum tag_types, bool, bool, bool); (cp_parser *, bool, bool, enum tag_types, bool, bool, bool, bool = false);
static tree cp_parser_class_specifier static tree cp_parser_class_specifier
(cp_parser *); (cp_parser *);
static tree cp_parser_class_head static tree cp_parser_class_head
@ -2957,10 +2957,13 @@ cp_parser_diagnose_invalid_type_name (cp_parser *parser, tree id,
return; return;
/* If the lookup found a template-name, it means that the user forgot /* If the lookup found a template-name, it means that the user forgot
to specify an argument list. Emit a useful error message. */ to specify an argument list. Emit a useful error message. */
if (TREE_CODE (decl) == TEMPLATE_DECL) if (DECL_TYPE_TEMPLATE_P (decl))
error_at (location, {
"invalid use of template-name %qE without an argument list", error_at (location,
decl); "invalid use of template-name %qE without an argument list",
decl);
inform (DECL_SOURCE_LOCATION (decl), "%qD declared here", decl);
}
else if (TREE_CODE (id) == BIT_NOT_EXPR) else if (TREE_CODE (id) == BIT_NOT_EXPR)
error_at (location, "invalid use of destructor %qD as a type", id); error_at (location, "invalid use of destructor %qD as a type", id);
else if (TREE_CODE (decl) == TYPE_DECL) else if (TREE_CODE (decl) == TYPE_DECL)
@ -3037,6 +3040,8 @@ cp_parser_diagnose_invalid_type_name (cp_parser *parser, tree id,
error_at (location_of (id), error_at (location_of (id),
"%qE in namespace %qE does not name a type", "%qE in namespace %qE does not name a type",
id, parser->scope); id, parser->scope);
if (DECL_P (decl))
inform (DECL_SOURCE_LOCATION (decl), "%qD declared here", decl);
} }
else if (CLASS_TYPE_P (parser->scope) else if (CLASS_TYPE_P (parser->scope)
&& constructor_name_p (id, parser->scope)) && constructor_name_p (id, parser->scope))
@ -3063,6 +3068,8 @@ cp_parser_diagnose_invalid_type_name (cp_parser *parser, tree id,
error_at (location_of (id), error_at (location_of (id),
"%qE in %q#T does not name a type", "%qE in %q#T does not name a type",
id, parser->scope); id, parser->scope);
if (DECL_P (decl))
inform (DECL_SOURCE_LOCATION (decl), "%qD declared here", decl);
} }
else else
gcc_unreachable (); gcc_unreachable ();
@ -5710,35 +5717,9 @@ cp_parser_qualifying_entity (cp_parser *parser,
type_p ? class_type : none_type, type_p ? class_type : none_type,
check_dependency_p, check_dependency_p,
/*class_head_p=*/false, /*class_head_p=*/false,
is_declaration); is_declaration,
/*enum_ok=*/cxx_dialect > cxx98);
successful_parse_p = only_class_p || cp_parser_parse_definitely (parser); successful_parse_p = only_class_p || cp_parser_parse_definitely (parser);
/* If that didn't work and we're in C++0x mode, try for a type-name. */
if (!only_class_p
&& cxx_dialect != cxx98
&& !successful_parse_p)
{
/* Restore the saved scope. */
parser->scope = saved_scope;
parser->qualifying_scope = saved_qualifying_scope;
parser->object_scope = saved_object_scope;
/* Parse tentatively. */
cp_parser_parse_tentatively (parser);
/* Parse a type-name */
scope = cp_parser_type_name (parser);
/* "If the name found does not designate a namespace or a class,
enumeration, or dependent type, the program is ill-formed."
We cover classes and dependent types above and namespaces below,
so this code is only looking for enums. */
if (!scope || TREE_CODE (scope) != TYPE_DECL
|| TREE_CODE (TREE_TYPE (scope)) != ENUMERAL_TYPE)
cp_parser_simulate_error (parser);
successful_parse_p = cp_parser_parse_definitely (parser);
}
/* If that didn't work, try for a namespace-name. */ /* If that didn't work, try for a namespace-name. */
if (!only_class_p && !successful_parse_p) if (!only_class_p && !successful_parse_p)
{ {
@ -19608,7 +19589,8 @@ cp_parser_initializer_list (cp_parser* parser, bool* non_constant_p)
is a template. TAG_TYPE indicates the explicit tag given before is a template. TAG_TYPE indicates the explicit tag given before
the type name, if any. If CHECK_DEPENDENCY_P is FALSE, names are the type name, if any. If CHECK_DEPENDENCY_P is FALSE, names are
looked up in dependent scopes. If CLASS_HEAD_P is TRUE, this class looked up in dependent scopes. If CLASS_HEAD_P is TRUE, this class
is the class being defined in a class-head. is the class being defined in a class-head. If ENUM_OK is TRUE,
enum-names are also accepted.
Returns the TYPE_DECL representing the class. */ Returns the TYPE_DECL representing the class. */
@ -19619,7 +19601,8 @@ cp_parser_class_name (cp_parser *parser,
enum tag_types tag_type, enum tag_types tag_type,
bool check_dependency_p, bool check_dependency_p,
bool class_head_p, bool class_head_p,
bool is_declaration) bool is_declaration,
bool enum_ok)
{ {
tree decl; tree decl;
tree scope; tree scope;
@ -19747,7 +19730,8 @@ cp_parser_class_name (cp_parser *parser,
} }
else if (TREE_CODE (decl) != TYPE_DECL else if (TREE_CODE (decl) != TYPE_DECL
|| TREE_TYPE (decl) == error_mark_node || TREE_TYPE (decl) == error_mark_node
|| !MAYBE_CLASS_TYPE_P (TREE_TYPE (decl)) || !(MAYBE_CLASS_TYPE_P (TREE_TYPE (decl))
|| (enum_ok && TREE_CODE (TREE_TYPE (decl)) == ENUMERAL_TYPE))
/* In Objective-C 2.0, a classname followed by '.' starts a /* In Objective-C 2.0, a classname followed by '.' starts a
dot-syntax expression, and it's not a type-name. */ dot-syntax expression, and it's not a type-name. */
|| (c_dialect_objc () || (c_dialect_objc ()

View File

@ -0,0 +1,14 @@
// PR c++/60994
// { dg-do compile { target c++11 } }
enum struct A
{
n = 3
};
A
foo()
{
int A;
return A::n;
}

View File

@ -0,0 +1,20 @@
// PR c++/60994
// { dg-do compile { target c++11 } }
struct B {
enum struct A
{
n = 3
};
};
struct C: B
{
using B::A;
A foo()
{
int A;
return A::n;
}
};

View File

@ -3,5 +3,7 @@
namespace std { namespace std {
template <typename T> int declval; template <typename T> int declval;
typename std::declval<> d; // { dg-error "not a type" } typename std::declval<> d; // { dg-error "type" }
} }
// { dg-prune-output "expected" }