re PR c++/60994 (gcc does not recognize hidden/shadowed enumeration as valid nested...
authorMomchil Velikov <momchil.velikov@gmail.com>
Tue, 14 Apr 2015 15:29:21 +0000 (15:29 +0000)
committerJason Merrill <jason@gcc.gnu.org>
Tue, 14 Apr 2015 15:29:21 +0000 (11:29 -0400)
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

gcc/cp/ChangeLog
gcc/cp/parser.c
gcc/testsuite/g++.dg/cpp0x/scoped_enum3.C [new file with mode: 0644]
gcc/testsuite/g++.dg/cpp0x/scoped_enum4.C [new file with mode: 0644]
gcc/testsuite/g++.dg/cpp1y/var-templ23.C

index e5a6ae2..2e43e4d 100644 (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>
 
        PR c++/65736
index 4d6b479..c457a29 100644 (file)
@@ -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 (file)
index 0000000..67a3d17
--- /dev/null
@@ -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 (file)
index 0000000..80798ef
--- /dev/null
@@ -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;
+  }
+};
index a5b19d2..80d8217 100644 (file)
@@ -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" }