aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMomchil Velikov <momchil.velikov@gmail.com>2015-04-14 15:29:21 +0000
committerJason Merrill <jason@gcc.gnu.org>2015-04-14 11:29:21 -0400
commit2fd16d0f9007f2e9a991b80c6ae2e4c5f85272b6 (patch)
tree9c81b516ff7b99da9d474e39696137390b743930
parentb42e7064553ea0deb7081e6ee7cf2aa898f6de78 (diff)
downloadgcc-2fd16d0f9007f2e9a991b80c6ae2e4c5f85272b6.zip
gcc-2fd16d0f9007f2e9a991b80c6ae2e4c5f85272b6.tar.gz
gcc-2fd16d0f9007f2e9a991b80c6ae2e4c5f85272b6.tar.bz2
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
-rw-r--r--gcc/cp/ChangeLog9
-rw-r--r--gcc/cp/parser.c56
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/scoped_enum3.C14
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/scoped_enum4.C20
-rw-r--r--gcc/testsuite/g++.dg/cpp1y/var-templ23.C4
5 files changed, 66 insertions, 37 deletions
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog
index e5a6ae2..2e43e4d 100644
--- a/gcc/cp/ChangeLog
+++ b/gcc/cp/ChangeLog
@@ -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>
PR c++/65736
diff --git a/gcc/cp/parser.c b/gcc/cp/parser.c
index 4d6b479..c457a29 100644
--- a/gcc/cp/parser.c
+++ b/gcc/cp/parser.c
@@ -2193,7 +2193,7 @@ static tree finish_fully_implicit_template
/* Classes [gram.class] */
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
(cp_parser *);
static tree cp_parser_class_head
@@ -2957,10 +2957,13 @@ cp_parser_diagnose_invalid_type_name (cp_parser *parser, tree id,
return;
/* If the lookup found a template-name, it means that the user forgot
to specify an argument list. Emit a useful error message. */
- if (TREE_CODE (decl) == TEMPLATE_DECL)
- error_at (location,
- "invalid use of template-name %qE without an argument list",
- decl);
+ if (DECL_TYPE_TEMPLATE_P (decl))
+ {
+ error_at (location,
+ "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)
error_at (location, "invalid use of destructor %qD as a type", id);
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),
"%qE in namespace %qE does not name a type",
id, parser->scope);
+ if (DECL_P (decl))
+ inform (DECL_SOURCE_LOCATION (decl), "%qD declared here", decl);
}
else if (CLASS_TYPE_P (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),
"%qE in %q#T does not name a type",
id, parser->scope);
+ if (DECL_P (decl))
+ inform (DECL_SOURCE_LOCATION (decl), "%qD declared here", decl);
}
else
gcc_unreachable ();
@@ -5710,35 +5717,9 @@ cp_parser_qualifying_entity (cp_parser *parser,
type_p ? class_type : none_type,
check_dependency_p,
/*class_head_p=*/false,
- is_declaration);
+ is_declaration,
+ /*enum_ok=*/cxx_dialect > cxx98);
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 (!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
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
- 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. */
@@ -19619,7 +19601,8 @@ cp_parser_class_name (cp_parser *parser,
enum tag_types tag_type,
bool check_dependency_p,
bool class_head_p,
- bool is_declaration)
+ bool is_declaration,
+ bool enum_ok)
{
tree decl;
tree scope;
@@ -19747,7 +19730,8 @@ cp_parser_class_name (cp_parser *parser,
}
else if (TREE_CODE (decl) != TYPE_DECL
|| 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
dot-syntax expression, and it's not a type-name. */
|| (c_dialect_objc ()
diff --git a/gcc/testsuite/g++.dg/cpp0x/scoped_enum3.C b/gcc/testsuite/g++.dg/cpp0x/scoped_enum3.C
new file mode 100644
index 0000000..67a3d17
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/scoped_enum3.C
@@ -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;
+}
diff --git a/gcc/testsuite/g++.dg/cpp0x/scoped_enum4.C b/gcc/testsuite/g++.dg/cpp0x/scoped_enum4.C
new file mode 100644
index 0000000..80798ef
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/scoped_enum4.C
@@ -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;
+ }
+};
diff --git a/gcc/testsuite/g++.dg/cpp1y/var-templ23.C b/gcc/testsuite/g++.dg/cpp1y/var-templ23.C
index a5b19d2..80d8217 100644
--- a/gcc/testsuite/g++.dg/cpp1y/var-templ23.C
+++ b/gcc/testsuite/g++.dg/cpp1y/var-templ23.C
@@ -3,5 +3,7 @@
namespace std {
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" }