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:
parent
b42e706455
commit
2fd16d0f90
@ -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
|
||||||
|
@ -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 ()
|
||||||
|
14
gcc/testsuite/g++.dg/cpp0x/scoped_enum3.C
Normal file
14
gcc/testsuite/g++.dg/cpp0x/scoped_enum3.C
Normal 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;
|
||||||
|
}
|
20
gcc/testsuite/g++.dg/cpp0x/scoped_enum4.C
Normal file
20
gcc/testsuite/g++.dg/cpp0x/scoped_enum4.C
Normal 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;
|
||||||
|
}
|
||||||
|
};
|
@ -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" }
|
||||||
|
Loading…
Reference in New Issue
Block a user