From: Marek Polacek Date: Fri, 26 Jun 2020 16:40:59 +0000 (-0400) Subject: c++: Check uniqueness of concepts/variable templates [PR94553] X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=54980635c537f3130481da2d8b1109c775db8bb0;p=gcc.git 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. --- 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 struct bar foo; template <> struct foo<>: // { dg-error "class template" } +template 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 int C; // { dg-error "different kind of entity" } +template 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 concept E = false; // { dg-error "different kind of entity" } +template concept F = false; +struct F { }; // { dg-error "different kind of entity" }