From patchwork Fri Nov 2 11:10:18 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Nathan Sidwell X-Patchwork-Id: 992272 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=pass (mailfrom) smtp.mailfrom=gcc.gnu.org (client-ip=209.132.180.131; helo=sourceware.org; envelope-from=gcc-patches-return-488883-incoming=patchwork.ozlabs.org@gcc.gnu.org; receiver=) Authentication-Results: ozlabs.org; dmarc=none (p=none dis=none) header.from=acm.org Authentication-Results: ozlabs.org; dkim=fail reason="signature verification failed" (2048-bit key; unprotected) header.d=gmail.com header.i=@gmail.com header.b="b+bl5dKX"; dkim-atps=neutral Received: from sourceware.org (server1.sourceware.org [209.132.180.131]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 42mfWC5ZDFzB4Vn for ; Fri, 2 Nov 2018 22:10:30 +1100 (AEDT) Received: (qmail 21502 invoked by alias); 2 Nov 2018 11:10:24 -0000 Mailing-List: contact gcc-patches-help@gcc.gnu.org; run by ezmlm Precedence: bulk List-Id: List-Unsubscribe: List-Archive: List-Post: List-Help: Sender: gcc-patches-owner@gcc.gnu.org Delivered-To: mailing list gcc-patches@gcc.gnu.org Received: (qmail 21490 invoked by uid 89); 2 Nov 2018 11:10:24 -0000 Authentication-Results: sourceware.org; auth=none X-Spam-SWARE-Status: No, score=-11.1 required=5.0 tests=BAYES_00, FREEMAIL_FROM, GIT_PATCH_2, GIT_PATCH_3, KAM_ASCII_DIVIDERS, RCVD_IN_DNSWL_NONE, SPF_PASS autolearn=ham version=3.3.2 spammy=Refactor, name_lookup, TYPE_DECL, TYPE_DECLs X-HELO: mail-yw1-f44.google.com Received: from mail-yw1-f44.google.com (HELO mail-yw1-f44.google.com) (209.85.161.44) by sourceware.org (qpsmtpd/0.93/v0.84-503-g423c35a) with ESMTP; Fri, 02 Nov 2018 11:10:22 +0000 Received: by mail-yw1-f44.google.com with SMTP id d126-v6so611033ywa.5 for ; Fri, 02 Nov 2018 04:10:22 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=sender:to:from:subject:message-id:date:user-agent:mime-version :content-language; bh=qcZxLo4mIK9AZJ7K3uFizSM42VP6dvddtuth/7asLBQ=; b=b+bl5dKX+PkbmIjYb93XqZkp3SUiLsZXfVjWx3D0jmGnBXXPPHDlQzpmKowCPel5CQ SgBWy6ymjNmZDZqyEj8hGQo7QGCvNfp+Kv6f5+9l8VOLs4JWvQOOeP5Q6NVvYvaZPjOo Rxv56HG0orV55H64KwwK4XwDmgpEdVaR4z+yBwnCykW4KHsQr69AHP2okYC2sMXpwL1A KYHjFfwrD6YEhmUDAglQGhPNRm+aChqdMf3P1s2uXEXdCRjxcKivnWPIJ2qxQivPM0Tx p7z3AcKQo9fjcyD3NNglIMjP0x1/QWuiPf5DoyOsxZ3iR/P2jY9uySDxH3WbpJ4pxX1u 49dQ== Received: from ?IPv6:2620:10d:c0a3:20fb:4c42:7706:4744:c0d9? ([2620:10d:c091:200::4:4b90]) by smtp.googlemail.com with ESMTPSA id m16-v6sm10354954ywh.18.2018.11.02.04.10.19 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Fri, 02 Nov 2018 04:10:19 -0700 (PDT) Sender: Nathan Sidwell To: GCC Patches From: Nathan Sidwell Subject: [C++ PATCH] refactor duplicate_decls Message-ID: <3fe6681d-1be8-bcb1-cf78-25a6062a9943@acm.org> Date: Fri, 2 Nov 2018 07:10:18 -0400 User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:60.0) Gecko/20100101 Thunderbird/60.2.1 MIME-Version: 1.0 duplicate_decls is one of the more complex fns in decl.c, and I need to make it more complicated. But first some refactoring, so it's a little more understandable. Generally moving warning checks later when we know we've actually got a duplicate, and splitting up some conflict checking. Applying to trunk after an x86_64-linux bootstrap. nathan 2018-11-01 Nathan Sidwell gcc/cp/ * decl.c (duplicate_decls): Refactor checks. * name-lookup.c (name_lookup::process_module_binding): Only pubic namespaces are shared. gcc/testsuite/ * g++.dg/lookup/crash6.C: Adjust error * g++.dg/parse/crash38.C: Likewise. Index: gcc/cp/decl.c =================================================================== --- gcc/cp/decl.c (revision 265743) +++ gcc/cp/decl.c (working copy) @@ -1370,47 +1370,6 @@ duplicate_decls (tree newdecl, tree oldd || 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); Index: gcc/testsuite/g++.dg/lookup/crash6.C =================================================================== --- gcc/testsuite/g++.dg/lookup/crash6.C (revision 265743) +++ gcc/testsuite/g++.dg/lookup/crash6.C (working copy) @@ -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" } Index: gcc/testsuite/g++.dg/parse/crash38.C =================================================================== --- gcc/testsuite/g++.dg/parse/crash38.C (revision 265743) +++ gcc/testsuite/g++.dg/parse/crash38.C (working copy) @@ -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" } */