On 6/26/20 3:26 PM, Marek Polacek wrote:
This patch wraps up PR94553.  Variable template names have no C
compatibility implications so they should be unique in their
declarative region.  It occurred to me that this applies to concepts
as well.  This is not specified in [basic.scope.declarative]/4.2
but that seems like a bug in the standard.

I couldn't use variable_template_p because that uses PRIMARY_TEMPLATE_P
which uses DECL_PRIMARY_TEMPLATE and that might not have been set up yet
(push_template_decl hasn't yet been called).  PRIMARY_TEMPLATE_P is
important to distinguish between a variable template and a variable in a
function template.  But I think we don't have to worry about that in
duplicate_decls: a template declaration cannot appear at block scope,
and additional checks in duplicate_decls suggest that it won't ever
see a TEMPLATE_DECL for a variable in a function template.  So
checking that the DECL_TEMPLATE_RESULT is a VAR_DECL seems to be fine.
I could have added a default argument to variable_template_p too to
avoid checking PRIMARY_TEMPLATE_P but it didn't seem worth the effort.

Bootstrapped/regtested on x86_64-pc-linux-gnu, ok for trunk?

OK.

gcc/cp/ChangeLog:

        PR c++/94553
        * decl.c (duplicate_decls): Make sure a concept or a variable
        template is unique in its declarative region.

gcc/testsuite/ChangeLog:

        PR c++/94553
        * g++.dg/cpp1y/pr68578.C: Adjust dg-error.
        * g++.dg/cpp1y/var-templ66.C: New test.
        * g++.dg/cpp2a/concepts-redecl1.C: New test.
---
  gcc/cp/decl.c                                 | 12 +++++++++++-
  gcc/testsuite/g++.dg/cpp1y/pr68578.C          |  2 +-
  gcc/testsuite/g++.dg/cpp1y/var-templ66.C      |  7 +++++++
  gcc/testsuite/g++.dg/cpp2a/concepts-redecl1.C |  7 +++++++
  4 files changed, 26 insertions(+), 2 deletions(-)
  create mode 100644 gcc/testsuite/g++.dg/cpp1y/var-templ66.C
  create mode 100644 gcc/testsuite/g++.dg/cpp2a/concepts-redecl1.C

diff --git a/gcc/cp/decl.c b/gcc/cp/decl.c
index 3afad5ca805..45c871af741 100644
--- a/gcc/cp/decl.c
+++ b/gcc/cp/decl.c
@@ -1679,6 +1679,16 @@ duplicate_decls (tree newdecl, tree olddecl, bool 
newdecl_is_friend)
        else if (DECL_TYPE_TEMPLATE_P (olddecl)
               || DECL_TYPE_TEMPLATE_P (newdecl))
        /* Class template conflicts.  */;
+      else if ((TREE_CODE (olddecl) == TEMPLATE_DECL
+               && DECL_TEMPLATE_RESULT (olddecl)
+               && TREE_CODE (DECL_TEMPLATE_RESULT (olddecl)) == VAR_DECL)
+              || (TREE_CODE (newdecl) == TEMPLATE_DECL
+                  && DECL_TEMPLATE_RESULT (newdecl)
+                  && TREE_CODE (DECL_TEMPLATE_RESULT (newdecl)) == VAR_DECL))
+       /* Variable template conflicts.  */;
+      else if (concept_definition_p (olddecl)
+              || concept_definition_p (newdecl))
+       /* Concept conflicts.  */;
        else if ((TREE_CODE (newdecl) == FUNCTION_DECL
                && DECL_FUNCTION_TEMPLATE_P (olddecl))
               || (TREE_CODE (olddecl) == FUNCTION_DECL
@@ -1701,7 +1711,7 @@ duplicate_decls (tree newdecl, tree olddecl, bool 
newdecl_is_friend)
                      " literal operator template", newdecl);
          else
            return NULL_TREE;
-       
+
          inform (olddecl_loc, "previous declaration %q#D", olddecl);
          return error_mark_node;
        }
diff --git a/gcc/testsuite/g++.dg/cpp1y/pr68578.C 
b/gcc/testsuite/g++.dg/cpp1y/pr68578.C
index 18edd83cd7f..9b3898176f1 100644
--- a/gcc/testsuite/g++.dg/cpp1y/pr68578.C
+++ b/gcc/testsuite/g++.dg/cpp1y/pr68578.C
@@ -1,4 +1,4 @@
  // { dg-do compile { target c++14 } }
-template <typename> struct bar foo; template <> struct foo<>: // { dg-error "class template" }
+template <typename> struct bar foo; template <> struct foo<>:  // { dg-error "class 
template|redeclared" }
  // { dg-error "-:expected" "" { target *-*-* } .+1 }
diff --git a/gcc/testsuite/g++.dg/cpp1y/var-templ66.C 
b/gcc/testsuite/g++.dg/cpp1y/var-templ66.C
new file mode 100644
index 00000000000..65cd3d9d31b
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp1y/var-templ66.C
@@ -0,0 +1,7 @@
+// PR c++/94553
+// { dg-do compile { target c++14 } }
+
+struct C { };
+template<typename> int C; // { dg-error "different kind of entity" }
+template<typename> int D;
+struct D { }; // { dg-error "different kind of entity" }
diff --git a/gcc/testsuite/g++.dg/cpp2a/concepts-redecl1.C 
b/gcc/testsuite/g++.dg/cpp2a/concepts-redecl1.C
new file mode 100644
index 00000000000..33cd778a318
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp2a/concepts-redecl1.C
@@ -0,0 +1,7 @@
+// PR c++/94553
+// { dg-do compile { target c++20 } }
+
+struct E { };
+template<typename> concept E = false; // { dg-error "different kind of entity" 
}
+template<typename> concept F = false;
+struct F { }; // { dg-error "different kind of entity" }

base-commit: b3d77404c060c0d65d8d4c97254995737d0fc032


Reply via email to