public inbox for gcc-patches@gcc.gnu.org
 help / color / mirror / Atom feed
* [PATCH] Fix PR c++/60994 gcc does not recognize hidden/shadowed enumeration as valid nested-name-specifier
@ 2014-04-29 10:04 Momchil Velikov
  2014-05-08 20:49 ` Momchil Velikov
  0 siblings, 1 reply; 5+ messages in thread
From: Momchil Velikov @ 2014-04-29 10:04 UTC (permalink / raw)
  To: gcc-patches

[-- Attachment #1: Type: text/plain, Size: 969 bytes --]

Hello,

gcc version 4.10.0 20140428 (experimental) (GCC)

Compiling (with c++ -c -std=c++11 b.cc) the following program

enum struct A
{
  n = 3
};

int
foo()
{
  int A;
  return A::n;
}

results in the error:

b.cc: In function 'int foo()':
b.cc:10:10: error: 'A' is not a class, namespace, or enumeration
   return A::n;
          ^
According to the C++11 Standard, [basic.lookup.qual] #1

"If a :: scope resolution operator in a nested-name-specifier is not
preceded by a decltype-specifier, lookup of the name preceding that ::
considers only namespaces, types, and templates whose specializations
are types."

GCC ought not to resolve "A" to the local variable, but to the
enumeration type. This is very similar to the example in the standard

struct A
{
  static int n;
};

int
foo()
{
  int A;
  return A::n;
}

which is compiled correctly by GCC, though.


Please, review this proposed fix. Bootstrapped/regtested for C/C++ on
x86_64-unknown-linux-gnu.

~chill

[-- Attachment #2: scoped-enum-nested-name-specifier.diff --]
[-- Type: text/plain, Size: 1752 bytes --]

diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog
index a5f3829..36c07a6 100644
--- a/gcc/cp/ChangeLog
+++ b/gcc/cp/ChangeLog
@@ -1,3 +1,9 @@
+2014-04-29  Momchil Velikov  <momchil.velikov@gmail.com>
+
+	PR c++/60994
+	* parser.c (cp_parser_class_name): Allow enumeral type as a
+	nested-name-specifier
+
 2014-04-28  Paolo Carlini  <paolo.carlini@oracle.com>
 
 	PR c++/59120
diff --git a/gcc/cp/parser.c b/gcc/cp/parser.c
index 962cace..460535e 100644
--- a/gcc/cp/parser.c
+++ b/gcc/cp/parser.c
@@ -19218,7 +19218,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))
+                || 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/ChangeLog b/gcc/testsuite/ChangeLog
index b2f07c6..0d9468e 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -1,3 +1,8 @@
+2014-04-29  Momchil Velikov  <momchil.velikov@gmail.com>
+
+	PR c++/60994
+	* g++.dg/cpp0x/scoped_enum3.C: New testcase.
+
 2014-04-28  Martin Jambor  <mjambor@suse.cz>
 
         * gcc.dg/tree-ssa/sra-14.c: New test.
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..ba527cb
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/scoped_enum3.C
@@ -0,0 +1,12 @@
+// { dg-do compile { target c++11 } }
+enum struct A
+{
+  n = 3
+};
+
+int
+foo()
+{
+  int A;
+  return A::n; // { dg-error "cannot convert 'A' to 'int' in return" }
+}

^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: [PATCH] Fix PR c++/60994 gcc does not recognize hidden/shadowed enumeration as valid nested-name-specifier
  2014-04-29 10:04 [PATCH] Fix PR c++/60994 gcc does not recognize hidden/shadowed enumeration as valid nested-name-specifier Momchil Velikov
@ 2014-05-08 20:49 ` Momchil Velikov
  2014-05-08 22:08   ` Paolo Carlini
  2014-05-10  0:56   ` Jason Merrill
  0 siblings, 2 replies; 5+ messages in thread
From: Momchil Velikov @ 2014-05-08 20:49 UTC (permalink / raw)
  To: gcc-patches; +Cc: Jason Merrill

[-- Attachment #1: Type: text/plain, Size: 1356 bytes --]

Ping.

previous post: http://gcc.gnu.org/ml/gcc-patches/2014-04/msg01938.html

Again bootstrapped/regtested/diffed against
xg++ (GCC) 4.10.0 20140508 (experimental) [master revision
ed50168:49aa3a5:e79f58c7b12f37014efb7425399c93814cddb4c4]

On 29.04.2014 12:58, Momchil Velikov wrote:
> Hello,
>
> gcc version 4.10.0 20140428 (experimental) (GCC)
>
> Compiling (with c++ -c -std=c++11 b.cc) the following program
>
> enum struct A
> {
>    n = 3
> };
>
> int
> foo()
> {
>    int A;
>    return A::n;
> }
>
> results in the error:
>
> b.cc: In function 'int foo()':
> b.cc:10:10: error: 'A' is not a class, namespace, or enumeration
>     return A::n;
>            ^
> According to the C++11 Standard, [basic.lookup.qual] #1
>
> "If a :: scope resolution operator in a nested-name-specifier is not
> preceded by a decltype-specifier, lookup of the name preceding that ::
> considers only namespaces, types, and templates whose specializations
> are types."
>
> GCC ought not to resolve "A" to the local variable, but to the
> enumeration type. This is very similar to the example in the standard
>
> struct A
> {
>    static int n;
> };
>
> int
> foo()
> {
>    int A;
>    return A::n;
> }
>
> which is compiled correctly by GCC, though.
>
>
> Please, review this proposed fix. Bootstrapped/regtested for C/C++ on
> x86_64-unknown-linux-gnu.
>
> ~chill
>

[-- Attachment #2: scoped-enum-nested-name-specifier.diff --]
[-- Type: text/x-patch, Size: 1818 bytes --]

diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog
index 3d400bb..cd86f95 100644
--- a/gcc/cp/ChangeLog
+++ b/gcc/cp/ChangeLog
@@ -1,3 +1,9 @@
+2014-05-08  Momchil Velikov  <momchil.velikov@gmail.com>
+
+	PR c++/60994
+	* parser.c (cp_parser_class_name): Allow enumeral type as a
+	nested-name-specifier
+
 2014-05-08  Paolo Carlini  <paolo.carlini@oracle.com>
 
 	PR c++/13981
diff --git a/gcc/cp/parser.c b/gcc/cp/parser.c
index 5542dcd..e7ff57f 100644
--- a/gcc/cp/parser.c
+++ b/gcc/cp/parser.c
@@ -19220,7 +19220,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))
+                || 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/ChangeLog b/gcc/testsuite/ChangeLog
index aa92e3b..60cbe3d 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -1,3 +1,8 @@
+2014-05-08  Momchil Velikov  <momchil.velikov@gmail.com>
+
+	PR c++/60994
+	* g++.dg/cpp0x/scoped_enum3.C: New testcase.
+
 2014-05-08  Joseph Myers  <joseph@codesourcery.com>
 
 	* gcc.target/i386/avx256-unaligned-load-2.c,
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..ba527cb
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/scoped_enum3.C
@@ -0,0 +1,12 @@
+// { dg-do compile { target c++11 } }
+enum struct A
+{
+  n = 3
+};
+
+int
+foo()
+{
+  int A;
+  return A::n; // { dg-error "cannot convert 'A' to 'int' in return" }
+}

^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: [PATCH] Fix PR c++/60994 gcc does not recognize hidden/shadowed enumeration as valid nested-name-specifier
  2014-05-08 20:49 ` Momchil Velikov
@ 2014-05-08 22:08   ` Paolo Carlini
  2014-05-10  0:56   ` Jason Merrill
  1 sibling, 0 replies; 5+ messages in thread
From: Paolo Carlini @ 2014-05-08 22:08 UTC (permalink / raw)
  To: Momchil Velikov, gcc-patches; +Cc: Jason Merrill

Nit: normally, ChangeLog entries are not submitted as diffs, part of the 
patch proper, but separately (also because the ChangeLog files keep 
changing quite fast).

Paolo.

^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: [PATCH] Fix PR c++/60994 gcc does not recognize hidden/shadowed enumeration as valid nested-name-specifier
  2014-05-08 20:49 ` Momchil Velikov
  2014-05-08 22:08   ` Paolo Carlini
@ 2014-05-10  0:56   ` Jason Merrill
  2015-04-14 15:16     ` Jason Merrill
  1 sibling, 1 reply; 5+ messages in thread
From: Jason Merrill @ 2014-05-10  0:56 UTC (permalink / raw)
  To: Momchil Velikov, gcc-patches

I don't think we want cp_parser_class_name to find enums; better I think 
to change cp_parser_qualifying_entity to use something other than 
cp_parser_type_name to look for enums.

Jason

^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: [PATCH] Fix PR c++/60994 gcc does not recognize hidden/shadowed enumeration as valid nested-name-specifier
  2014-05-10  0:56   ` Jason Merrill
@ 2015-04-14 15:16     ` Jason Merrill
  0 siblings, 0 replies; 5+ messages in thread
From: Jason Merrill @ 2015-04-14 15:16 UTC (permalink / raw)
  To: Momchil Velikov, gcc-patches

[-- Attachment #1: Type: text/plain, Size: 340 bytes --]

On 05/09/2014 08:56 PM, Jason Merrill wrote:
> I don't think we want cp_parser_class_name to find enums; better I think
> to change cp_parser_qualifying_entity to use something other than
> cp_parser_type_name to look for enums.

I had a go at this myself, and it was problematic, so I ended up using a 
variation on your patch instead:




[-- Attachment #2: 60994.patch --]
[-- Type: text/x-patch, Size: 6284 bytes --]

commit 5edd0f55206e3a2662c371f75d1d53c9c6988444
Author: Jason Merrill <jason@redhat.com>
Date:   Fri Apr 3 15:48:00 2015 -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.

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" }

^ permalink raw reply	[flat|nested] 5+ messages in thread

end of thread, other threads:[~2015-04-14 15:16 UTC | newest]

Thread overview: 5+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2014-04-29 10:04 [PATCH] Fix PR c++/60994 gcc does not recognize hidden/shadowed enumeration as valid nested-name-specifier Momchil Velikov
2014-05-08 20:49 ` Momchil Velikov
2014-05-08 22:08   ` Paolo Carlini
2014-05-10  0:56   ` Jason Merrill
2015-04-14 15:16     ` Jason Merrill

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).