aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorMarek Polacek <polacek@redhat.com>2020-06-26 12:40:59 -0400
committerMarek Polacek <polacek@redhat.com>2020-06-29 11:01:58 -0400
commit54980635c537f3130481da2d8b1109c775db8bb0 (patch)
treefa66658f274fc2274a323c83c1fc709fc3232a62 /gcc
parentb1005f553d3543bb56dc6b9b34ee35455d697ca4 (diff)
downloadgcc-54980635c537f3130481da2d8b1109c775db8bb0.zip
gcc-54980635c537f3130481da2d8b1109c775db8bb0.tar.gz
gcc-54980635c537f3130481da2d8b1109c775db8bb0.tar.bz2
c++: Check uniqueness of concepts/variable templates [PR94553]
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. 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.
Diffstat (limited to 'gcc')
-rw-r--r--gcc/cp/decl.c12
-rw-r--r--gcc/testsuite/g++.dg/cpp1y/pr68578.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp1y/var-templ66.C7
-rw-r--r--gcc/testsuite/g++.dg/cpp2a/concepts-redecl1.C7
4 files changed, 26 insertions, 2 deletions
diff --git a/gcc/cp/decl.c b/gcc/cp/decl.c
index 3afad5c..45c871a 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 18edd83..9b38981 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 0000000..65cd3d9
--- /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 0000000..33cd778
--- /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" }