From 4155777d7394cb929f2ad5d86045415bff5c85ff Mon Sep 17 00:00:00 2001 From: Nathan Sidwell Date: Fri, 2 Nov 2018 11:12:43 +0000 Subject: [PATCH] [C++ PATCH] refactor duplicate_decls https://gcc.gnu.org/ml/gcc-patches/2018-11/msg00085.html gcc/cp/ * decl.c (duplicate_decls): Refactor checks. gcc/testsuite/ * g++.dg/lookup/crash6.C: Adjust error * g++.dg/parse/crash38.C: Likewise. From-SVN: r265744 --- gcc/cp/ChangeLog | 4 + gcc/cp/decl.c | 134 ++++++++++++--------------- gcc/testsuite/ChangeLog | 5 + gcc/testsuite/g++.dg/lookup/crash6.C | 2 +- gcc/testsuite/g++.dg/parse/crash38.C | 6 +- 5 files changed, 70 insertions(+), 81 deletions(-) diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index b27ae1ad703..bb77e0b42ab 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,3 +1,7 @@ +2018-11-02 Nathan Sidwell + + * decl.c (duplicate_decls): Refactor checks. + 2018-11-01 Marek Polacek Implement P0846R0, ADL and function templates. diff --git a/gcc/cp/decl.c b/gcc/cp/decl.c index f0033dd5458..cf934159395 100644 --- a/gcc/cp/decl.c +++ b/gcc/cp/decl.c @@ -1370,47 +1370,6 @@ duplicate_decls (tree newdecl, tree olddecl, bool newdecl_is_friend) || TREE_TYPE (olddecl) == error_mark_node) return error_mark_node; - if (DECL_NAME (newdecl) - && DECL_NAME (olddecl) - && UDLIT_OPER_P (DECL_NAME (newdecl)) - && UDLIT_OPER_P (DECL_NAME (olddecl))) - { - if (TREE_CODE (newdecl) == TEMPLATE_DECL - && TREE_CODE (olddecl) != TEMPLATE_DECL - && check_raw_literal_operator (olddecl)) - error_at (newdecl_loc, - "literal operator template %qD conflicts with" - " raw literal operator %qD", newdecl, olddecl); - else if (TREE_CODE (newdecl) != TEMPLATE_DECL - && TREE_CODE (olddecl) == TEMPLATE_DECL - && check_raw_literal_operator (newdecl)) - error_at (newdecl_loc, - "raw literal operator %qD conflicts with" - " literal operator template %qD", newdecl, olddecl); - } - - /* True to merge attributes between the declarations, false to - set OLDDECL's attributes to those of NEWDECL (for template - explicit specializations that specify their own attributes - independent of those specified for the primary template). */ - const bool merge_attr = (TREE_CODE (newdecl) != FUNCTION_DECL - || !DECL_TEMPLATE_SPECIALIZATION (newdecl) - || DECL_TEMPLATE_SPECIALIZATION (olddecl)); - - if (DECL_P (olddecl) - && TREE_CODE (newdecl) == FUNCTION_DECL - && TREE_CODE (olddecl) == FUNCTION_DECL - && merge_attr - && diagnose_mismatched_attributes (olddecl, newdecl)) - { - if (DECL_INITIAL (olddecl)) - inform (olddecl_loc, - "previous definition of %qD was here", olddecl); - else - inform (olddecl_loc, - "previous declaration of %qD was here", olddecl); - } - /* Check for redeclaration and other discrepancies. */ if (TREE_CODE (olddecl) == FUNCTION_DECL && DECL_ARTIFICIAL (olddecl)) @@ -1634,38 +1593,45 @@ next_arg:; /* C++ Standard, 3.3, clause 4: "[Note: a namespace name or a class template name must be unique in its declarative region (7.3.2, clause 14). ]" */ - if (TREE_CODE (olddecl) != NAMESPACE_DECL - && TREE_CODE (newdecl) != NAMESPACE_DECL - && (TREE_CODE (olddecl) != TEMPLATE_DECL - || TREE_CODE (DECL_TEMPLATE_RESULT (olddecl)) != TYPE_DECL) - && (TREE_CODE (newdecl) != TEMPLATE_DECL - || TREE_CODE (DECL_TEMPLATE_RESULT (newdecl)) != TYPE_DECL)) - { - if ((TREE_CODE (olddecl) == TYPE_DECL && DECL_ARTIFICIAL (olddecl) - && TREE_CODE (newdecl) != TYPE_DECL) - || (TREE_CODE (newdecl) == TYPE_DECL && DECL_ARTIFICIAL (newdecl) - && TREE_CODE (olddecl) != TYPE_DECL)) - { - /* We do nothing special here, because C++ does such nasty - things with TYPE_DECLs. Instead, just let the TYPE_DECL - get shadowed, and know that if we need to find a TYPE_DECL - for a given name, we can look in the IDENTIFIER_TYPE_VALUE - slot of the identifier. */ - return NULL_TREE; - } - - if ((TREE_CODE (newdecl) == FUNCTION_DECL - && DECL_FUNCTION_TEMPLATE_P (olddecl)) - || (TREE_CODE (olddecl) == FUNCTION_DECL - && DECL_FUNCTION_TEMPLATE_P (newdecl))) - return NULL_TREE; + if (TREE_CODE (olddecl) == NAMESPACE_DECL + || TREE_CODE (newdecl) == NAMESPACE_DECL) + /* Namespace conflicts with not namespace. */; + else if (DECL_TYPE_TEMPLATE_P (olddecl) + || DECL_TYPE_TEMPLATE_P (newdecl)) + /* Class template conflicts. */; + else if ((TREE_CODE (newdecl) == FUNCTION_DECL + && DECL_FUNCTION_TEMPLATE_P (olddecl)) + || (TREE_CODE (olddecl) == FUNCTION_DECL + && DECL_FUNCTION_TEMPLATE_P (newdecl))) + { + /* One is a function and the other is a template + function. */ + if (!UDLIT_OPER_P (DECL_NAME (newdecl))) + return NULL_TREE; + + /* There can only be one! */ + if (TREE_CODE (newdecl) == TEMPLATE_DECL + && check_raw_literal_operator (olddecl)) + error_at (newdecl_loc, + "literal operator %q#D conflicts with" + " raw literal operator", newdecl); + else if (check_raw_literal_operator (newdecl)) + error_at (newdecl_loc, + "raw literal operator %q#D conflicts with" + " literal operator template", newdecl); + else + return NULL_TREE; + + inform (olddecl_loc, "previous declaration %q#D", olddecl); + return error_mark_node; } + else if (DECL_IMPLICIT_TYPEDEF_P (olddecl) + || DECL_IMPLICIT_TYPEDEF_P (newdecl)) + /* One is an implicit typedef, that's ok. */ + return NULL_TREE; - error ("%q#D redeclared as different kind of symbol", newdecl); - if (TREE_CODE (olddecl) == TREE_LIST) - olddecl = TREE_VALUE (olddecl); - inform (olddecl_loc, - "previous declaration %q#D", olddecl); + error ("%q#D redeclared as different kind of entity", newdecl); + inform (olddecl_loc, "previous declaration %q#D", olddecl); return error_mark_node; } @@ -1700,8 +1666,8 @@ next_arg:; return type. */ && same_type_p (TREE_TYPE (TREE_TYPE (newdecl)), TREE_TYPE (TREE_TYPE (olddecl))) - // Template functions can also be disambiguated by - // constraints. + /* Template functions can also be disambiguated by + constraints. */ && equivalently_constrained (olddecl, newdecl)) { error_at (newdecl_loc, "ambiguating new declaration %q#D", @@ -1938,16 +1904,30 @@ next_arg:; || DECL_IMPLICIT_TYPEDEF_P (newdecl))) return NULL_TREE; + if (!validate_constexpr_redeclaration (olddecl, newdecl)) + return error_mark_node; + + /* We have committed to returning OLDDECL at this point. */ + /* If new decl is `static' and an `extern' was seen previously, warn about it. */ warn_extern_redeclared_static (newdecl, olddecl); - if (!validate_constexpr_redeclaration (olddecl, newdecl)) - return error_mark_node; + /* True to merge attributes between the declarations, false to + set OLDDECL's attributes to those of NEWDECL (for template + explicit specializations that specify their own attributes + independent of those specified for the primary template). */ + const bool merge_attr = (TREE_CODE (newdecl) != FUNCTION_DECL + || !DECL_TEMPLATE_SPECIALIZATION (newdecl) + || DECL_TEMPLATE_SPECIALIZATION (olddecl)); - /* We have committed to returning 1 at this point. */ if (TREE_CODE (newdecl) == FUNCTION_DECL) { + if (merge_attr && diagnose_mismatched_attributes (olddecl, newdecl)) + inform (olddecl_loc, DECL_INITIAL (olddecl) + ? G_("previous definition of %qD here") + : G_("previous declaration of %qD here"), olddecl); + /* Now that functions must hold information normally held by field decls, there is extra work to do so that declaration information does not get destroyed during @@ -2027,7 +2007,7 @@ next_arg:; else DECL_ATTRIBUTES (olddecl) = DECL_ATTRIBUTES (newdecl); - if (DECL_DECLARES_FUNCTION_P (olddecl) && DECL_DECLARES_FUNCTION_P (newdecl)) + if (DECL_DECLARES_FUNCTION_P (olddecl)) { olddecl_friend = DECL_FRIEND_P (olddecl); olddecl_hidden_friend = DECL_HIDDEN_FRIEND_P (olddecl); diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 0824f9ab72b..74fa20c45e3 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,8 @@ +2018-11-02 Nathan Sidwell + + * g++.dg/lookup/crash6.C: Adjust error + * g++.dg/parse/crash38.C: Likewise. + 2018-11-02 Andreas Schwab * gcc.c-torture/execute/20010904-2.c: Fix last change. diff --git a/gcc/testsuite/g++.dg/lookup/crash6.C b/gcc/testsuite/g++.dg/lookup/crash6.C index b8481be4d34..b824edda3db 100644 --- a/gcc/testsuite/g++.dg/lookup/crash6.C +++ b/gcc/testsuite/g++.dg/lookup/crash6.C @@ -5,4 +5,4 @@ // PR c++/18652: ICE redeclaring variable as template. int A; // { dg-message "previous declaration" } -template struct A; // { dg-error "different kind of symbol" } +template struct A; // { dg-error "different kind of" } diff --git a/gcc/testsuite/g++.dg/parse/crash38.C b/gcc/testsuite/g++.dg/parse/crash38.C index 7a0c2655681..5747f9fb21b 100644 --- a/gcc/testsuite/g++.dg/parse/crash38.C +++ b/gcc/testsuite/g++.dg/parse/crash38.C @@ -2,10 +2,10 @@ /* This would not ICE. */ namespace M { } /* { dg-message "previous declaration" } */ -struct M; /* { dg-error "redeclared as different kind of symbol" } */ +struct M; /* { dg-error "redeclared as different kind of" } */ M *p; /* { dg-error "does not name a type" } */ /* This would ICE when processing 'p'. */ namespace N { } /* { dg-message "previous declaration" } */ -struct N; /* { dg-error "redeclared as different kind of symbol" } */ -struct N* p; /* { dg-error "redeclared as different kind of symbol|invalid type" } */ +struct N; /* { dg-error "redeclared as different kind of" } */ +struct N* p; /* { dg-error "redeclared as different kind of" } */ -- 2.30.2