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