From patchwork Sun Mar 2 00:26:55 2014 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Patrick Palka X-Patchwork-Id: 325505 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org 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 8DDF72C00BD for ; Sun, 2 Mar 2014 11:27:17 +1100 (EST) DomainKey-Signature: a=rsa-sha1; c=nofws; d=gcc.gnu.org; h=list-id :list-unsubscribe:list-archive:list-post:list-help:sender:from :to:cc:subject:date:message-id; q=dns; s=default; b=hooycwjup0Ix 98cNVnuHq5zggTj32vJ77rOuX39C7glK9kRte1zyyHREVdOH9Y1BEMZx2k+UCI4W /rgSB3AgdXtbFzafAXOC883nMFf4pJB4rvxqGADe1pHd3UmqzSJG946W48XgYh/H lkLvk58gtS4nwLNIwYFvpx7ibRtS9Zk= DKIM-Signature: v=1; a=rsa-sha1; c=relaxed; d=gcc.gnu.org; h=list-id :list-unsubscribe:list-archive:list-post:list-help:sender:from :to:cc:subject:date:message-id; s=default; bh=nIFWOAkD1sIusgqezn Sjkn+8CdI=; b=LdwtCtysqYdgxgeKHRpuVOrVuqfvPJqboO6H0ZnRgik8KPFAa3 yDOiBRfBzJTBGmHS8L8PtkW8v/BpbJk4viPnGwYCQsgE3ivS60MHjCeGxr1HIoTj NeKaAaKng7nah6frISyv9NjJgHIHypaRmQJSA8WAaq0/FrKY2b0N1DSc4= Received: (qmail 11641 invoked by alias); 2 Mar 2014 00:27:10 -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 11631 invoked by uid 89); 2 Mar 2014 00:27:09 -0000 Authentication-Results: sourceware.org; auth=none X-Virus-Found: No X-Spam-SWARE-Status: No, score=-2.2 required=5.0 tests=AWL, BAYES_00, RCVD_IN_DNSWL_LOW autolearn=ham version=3.3.2 X-HELO: mail-qc0-f172.google.com Received: from mail-qc0-f172.google.com (HELO mail-qc0-f172.google.com) (209.85.216.172) by sourceware.org (qpsmtpd/0.93/v0.84-503-g423c35a) with (AES128-SHA encrypted) ESMTPS; Sun, 02 Mar 2014 00:27:08 +0000 Received: by mail-qc0-f172.google.com with SMTP id i8so2381523qcq.17 for ; Sat, 01 Mar 2014 16:27:06 -0800 (PST) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20130820; h=x-gm-message-state:from:to:cc:subject:date:message-id; bh=vKGJ1U7lvd1M5NvuigkS9gtJP5xW3IVwK7gNfc3geTY=; b=aHRW4PEc+lSTUSpDyKfedggqyeUPrfnucd/lRAaA0AOaW8ivt6qiC/pW+A0pCeQDPR ktTZp9VTE2Pev8H3JKM2zraL67wGmoQiMcPkaw3984hnHBFpHmcL3hdkbvexEnCCsebm a6g3qZS9W2cXXjZFUOHo+OZ1frlrLPVR4wCxKPrAZKqXRvL6IbDB18QqHXXCeVMYyLTi CX0aJlor/DEMAc+wav/27rlc4mjInUpScUIfYajXHQrIplEPfgWR3Q+IpvVJ+qq3czKl jfZ2ROgxnthRe5b0qv23v27WKclYVCImlOIH5XX+AyC2TVSatgVA8lIYuik136uFpxAN k6ig== X-Gm-Message-State: ALoCoQnSU2lGGOVhOhgz75ppCDHlefoBr57SuEwF/gM2z43T115j/+A3+cFy8UiTM5XI2Vn1B2e6 X-Received: by 10.140.51.109 with SMTP id t100mr13288828qga.50.1393720026255; Sat, 01 Mar 2014 16:27:06 -0800 (PST) Received: from localhost.localdomain (ool-4353a9c4.dyn.optonline.net. [67.83.169.196]) by mx.google.com with ESMTPSA id b30sm8979858qge.21.2014.03.01.16.27.04 for (version=TLSv1.2 cipher=ECDHE-RSA-AES128-SHA bits=128/128); Sat, 01 Mar 2014 16:27:05 -0800 (PST) From: Patrick Palka To: gcc-patches@gcc.gnu.org Cc: jason@redhat.com, Patrick Palka Subject: [PATCH v2] Fix PR c++/25940 Date: Sat, 1 Mar 2014 19:26:55 -0500 Message-Id: <1393720015-23354-1-git-send-email-patrick@parcs.ath.cx> Hi, The following patch fixes two issues: the first issue is PR c++/25940 and the second is related to PR c++/13699. The first issue is that the C++ frontend fails to reject duplicate definitions of functions declared to have C language linkage. This results in the compiler emitting ASM that defines the same symbol more than once. The second issue is that upon encountering a redeclaration of an extern "C" function with a different exception specification, the C++ frontend fails to add the new declaration to the list of things declared in the current namespace (because we exit early from pushdecl_maybe_friend_1). This behavior makes the new declaration appear to be not in scope. I bootstrapped and regtested this patch on x86_64-unknown-linux-gnu. I had a few guality and cilk FAILs though I don't think they are related to this patch. I have not yet finalized my copyright assignment but I would appreciate any comments on the patch (this is my first substantive patch to GCC). Would this patch be OK for trunk once my copyright assignment is in place? Changes in v2: No longer return error_mark_node after emitting a redefinition error. Simplified the new testcase "extern-c-redecl6.C". CC'd the C++ maintainer. Regards, Patrick PR c++/25940 * name-lookup.c (pushdecl_maybe_friend_1): Emit an error when a function with C language linkage is redefined. Don't return error_mark_node after a function with C language linkage is redeclared with a different exception specification. (lookup_extern_c_fun_in_all_ns): Prefer returning an existing function definition instead of a declaration. PR c++/25940 * g++.dg/lookup/extern-c-redecl6.C: New test. * g++.dg/lookup/extern-c-redecl7.C: New test. --- gcc/cp/name-lookup.c | 23 ++++++++++++++++++----- gcc/testsuite/g++.dg/lookup/extern-c-redecl6.C | 25 +++++++++++++++++++++++++ gcc/testsuite/g++.dg/lookup/extern-c-redecl7.C | 12 ++++++++++++ 3 files changed, 55 insertions(+), 5 deletions(-) create mode 100644 gcc/testsuite/g++.dg/lookup/extern-c-redecl6.C create mode 100644 gcc/testsuite/g++.dg/lookup/extern-c-redecl7.C diff --git a/gcc/cp/name-lookup.c b/gcc/cp/name-lookup.c index ea16061..c797193 100644 --- a/gcc/cp/name-lookup.c +++ b/gcc/cp/name-lookup.c @@ -861,6 +861,14 @@ pushdecl_maybe_friend_1 (tree x, bool is_friend) tree x_exception_spec = NULL_TREE; tree previous_exception_spec = NULL_TREE; + if (DECL_INITIAL (x) && DECL_INITIAL (previous)) + { + error_at (input_location, + "redefinition of %q+#D with C language linkage", + x); + inform (input_location, + "%q+#D previously defined here", previous); + } x_exception_spec = TYPE_RAISES_EXCEPTIONS (TREE_TYPE (x)); previous_exception_spec = @@ -877,7 +885,6 @@ pushdecl_maybe_friend_1 (tree x, bool is_friend) previous); pedwarn (input_location, 0, "due to different exception specifications"); - return error_mark_node; } if (DECL_ASSEMBLER_NAME_SET_P (previous)) SET_DECL_ASSEMBLER_NAME (x, @@ -2142,8 +2149,10 @@ binding_for_name (cp_binding_level *scope, tree name) } /* Walk through the bindings associated to the name of FUNCTION, - and return the first declaration of a function with a - "C" linkage specification, a.k.a 'extern "C"'. + and return the first definition of a function with a + "C" linkage specification, a.k.a 'extern "C"'. If no previous + definition exists, return the first declaration of the function. + This function looks for the binding, regardless of which scope it has been defined in. It basically looks in all the known scopes. Note that this function does not lookup for bindings of builtin functions @@ -2152,6 +2161,7 @@ static tree lookup_extern_c_fun_in_all_ns (tree function) { tree name; + tree ret = NULL_TREE; cxx_binding *iter; gcc_assert (function && TREE_CODE (function) == FUNCTION_DECL); @@ -2172,11 +2182,14 @@ lookup_extern_c_fun_in_all_ns (tree function) && DECL_EXTERN_C_P (decl) && !DECL_ARTIFICIAL (decl)) { - return decl; + if (DECL_INITIAL (decl)) + return decl; + if (!ret) + ret = decl; } } } - return NULL; + return ret; } /* Returns a list of C-linkage decls with the name NAME. */ diff --git a/gcc/testsuite/g++.dg/lookup/extern-c-redecl6.C b/gcc/testsuite/g++.dg/lookup/extern-c-redecl6.C new file mode 100644 index 0000000..7577d3c --- /dev/null +++ b/gcc/testsuite/g++.dg/lookup/extern-c-redecl6.C @@ -0,0 +1,25 @@ +// PR c++/25940 + +namespace A { + extern "C" void foo () // { dg-message "previously defined" } + { + } +} + +namespace Y { + extern "C" void foo (); +} + +namespace B { + extern "C" void foo () // { dg-error "redefinition" } + { + } +} + +namespace Z { + extern "C" void foo (); +} + +extern "C" void foo () // { dg-error "redefinition" } +{ +} diff --git a/gcc/testsuite/g++.dg/lookup/extern-c-redecl7.C b/gcc/testsuite/g++.dg/lookup/extern-c-redecl7.C new file mode 100644 index 0000000..2210417 --- /dev/null +++ b/gcc/testsuite/g++.dg/lookup/extern-c-redecl7.C @@ -0,0 +1,12 @@ +namespace A { + extern "C" void foo () throw (); // { dg-error "previous declaration" } +} + +namespace B { + extern "C" void foo (); // { dg-error "declaration of|different exception" } +} + +void bar () +{ + B::foo (); +}