From patchwork Fri Feb 5 04:21:31 2016 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Patrick Palka X-Patchwork-Id: 579372 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 EC77B14056B for ; Fri, 5 Feb 2016 15:22:00 +1100 (AEDT) Authentication-Results: ozlabs.org; dkim=pass (1024-bit key; unprotected) header.d=gcc.gnu.org header.i=@gcc.gnu.org header.b=AgjtUZ1I; dkim-atps=neutral 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=OWlZM5iOwavB 3NeuMyylPWk/uvm9CukAAY88uHJW7WeEK20ExO6/DD9hK4lmYB4xe7E9w2ayagCE BI1qwfaibRdtB/tRaNNYAwWPfhmCZXCfwkpcbLT+P/pLVMzZmQxWKSqEw+tGE+64 UqDstv/nbx2S/wFlxG3tJ+2tbUPTCvI= 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=U7Ha9xigYTj6RuYdSm /wuERUkBo=; b=AgjtUZ1IAe9eclJiI/GSBB/WisVQejA4rA6ipQrRlllcDkgPmC zcgCo6bUJt4ejJuLJ9eCay+XrVv/bAC6GuaAwXFtXchN2EBdDsVrFE9zTBuV2Lqw gvkrI+qWr32PkW++KHWKtRLx60TNhDs7epKdIWjtOpAAXVaUmfFwoBclc= Received: (qmail 7649 invoked by alias); 5 Feb 2016 04:21:52 -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 7633 invoked by uid 89); 5 Feb 2016 04:21:50 -0000 Authentication-Results: sourceware.org; auth=none X-Virus-Found: No X-Spam-SWARE-Status: No, score=-2.6 required=5.0 tests=AWL, BAYES_00, RCVD_IN_DNSWL_LOW autolearn=ham version=3.3.2 spammy=injected, Alternatively, sk:constru, diagnoses X-HELO: mail-qg0-f52.google.com Received: from mail-qg0-f52.google.com (HELO mail-qg0-f52.google.com) (209.85.192.52) by sourceware.org (qpsmtpd/0.93/v0.84-503-g423c35a) with (AES128-GCM-SHA256 encrypted) ESMTPS; Fri, 05 Feb 2016 04:21:49 +0000 Received: by mail-qg0-f52.google.com with SMTP id b35so59273375qge.0 for ; Thu, 04 Feb 2016 20:21:49 -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=Bzy5JFyD5Po750FfVDzCn2XP7b9oEBU7my8bos/sDP8=; b=eHlomO1NcI9fOhAbSDeYcn+3YJU8KEb+EnjbNAWKQGPjeoND7+YmxtDBY4Qr8fwFoY pQCsN47bvm2pZGIySQpYNva6bVJ47iv9uIzOFA8NNv5n4P0+NkPIMCtHw0bimDiuaAGG 95y5A5HY6bH/qMxhUvKwGVLZeM3IbYhf2vDQgTxqeyoW+TY/ThYy/wGtxKxNriJFSLwP W2zQuPn9NeoQLe0AQv/4GEsjj9ZMvizW6RN8axQaJx1Fi7BN9ifd0A8/HD6ScPXCUu08 y/I+3/88x2qTZE1SEAePS5MsXCzfJZd0oHsclH0/qsyx3O/XmvBOD9D8zFamKb6EXrmC JjsQ== X-Gm-Message-State: AG10YOSiIaQ4EihKORfQk7+WjWvG9EfQlkHCUXy484CPfcRuW0ztY51weAXjUasdT2Un8A== X-Received: by 10.140.225.199 with SMTP id v190mr14767502qhb.18.1454646107098; Thu, 04 Feb 2016 20:21:47 -0800 (PST) Received: from localhost.localdomain (ool-4353abbc.dyn.optonline.net. [67.83.171.188]) by smtp.gmail.com with ESMTPSA id e105sm6736737qgd.22.2016.02.04.20.21.45 (version=TLS1_2 cipher=ECDHE-RSA-AES128-SHA bits=128/128); Thu, 04 Feb 2016 20:21:45 -0800 (PST) From: Patrick Palka To: gcc-patches@gcc.gnu.org Cc: jason@redhat.com, Patrick Palka Subject: [PATCH] Fix PR c++/68948 (wrong code generation due to invalid constructor call) Date: Thu, 4 Feb 2016 23:21:31 -0500 Message-Id: <1454646091-8065-1-git-send-email-patrick@parcs.ath.cx> The compiler correctly detects and diagnoses invalid constructor calls such as C::C () in a non-template context but it fails to do so while processing a class template. [ Section 3.4.3.1 of the standard is what makes these forms of constructor calls illegal -- see https://gcc.gnu.org/bugzilla/show_bug.cgi?id=68948#c9 ] In a non-template context this diagnosis would take place in build_new_method_call, called from finish_call_expr, but while processing a class template we may exit early out of finish_call_expr and never call build_new_method_call. Thus we never diagnose this invalid constructor call during template processing. So then during instantiation of the enclosing template we call tsubst_baselink on this constructor call, during which the call to lookup_fnfields returns NULL (because it finds the injected class type C not the constructor C). Because the lookup failed, tsubst_baselink returns error_mark_node and this node persists all the way through to gimplification where it silently gets discarded. This patch fixes this problem by diagnosing these invalid constructor calls in tsubst_baselink. Alternatively, we can rewire finish_call_expr avoid exiting early while processing a template if the call in question is a constructor call. I'm not sure which approach is better. This approach seems more conservative, since it's just attaching an error message to an existing error path. gcc/cp/ChangeLog: PR c++/68948 * pt.c (tsubst_baselink): Diagnose an invalid constructor call if lookup_fnfields returns NULL_TREE and name we're looking up has the form A::A. gcc/testsuite/ChangeLog: PR c++/68948 * g++.dg/template/pr68948.C: New test. --- gcc/cp/pt.c | 10 +++++++- gcc/testsuite/g++.dg/template/pr68948.C | 41 +++++++++++++++++++++++++++++++++ 2 files changed, 50 insertions(+), 1 deletion(-) create mode 100644 gcc/testsuite/g++.dg/template/pr68948.C diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c index 4d405cf..91d0ef2 100644 --- a/gcc/cp/pt.c +++ b/gcc/cp/pt.c @@ -13583,7 +13583,15 @@ tsubst_baselink (tree baselink, tree object_type, name = mangle_conv_op_name_for_type (optype); baselink = lookup_fnfields (qualifying_scope, name, /*protect=*/1); if (!baselink) - return error_mark_node; + { + if (constructor_name_p (name, qualifying_scope)) + { + if (complain & tf_error) + error ("cannot call constructor %<%T::%D%> directly", + qualifying_scope, name); + } + return error_mark_node; + } /* If lookup found a single function, mark it as used at this point. (If it lookup found multiple functions the one selected diff --git a/gcc/testsuite/g++.dg/template/pr68948.C b/gcc/testsuite/g++.dg/template/pr68948.C new file mode 100644 index 0000000..ccbfb19 --- /dev/null +++ b/gcc/testsuite/g++.dg/template/pr68948.C @@ -0,0 +1,41 @@ +// PR c++/68948 + +struct B { B (); B (int); }; + +struct Time : B { }; + +/* Here, A and B are unrelated types. */ + +template +struct A +{ + void TestBody () + { + B::B (); // { dg-error "cannot call constructor" } + B::B::B (); // { dg-error "cannot call constructor" } + B::B (0); // { dg-error "cannot call constructor" } + } +}; + +/* Here, C is (indirectly) derived from B. */ + +template +struct C : Time +{ + void TestBody () + { + B::B (); // { dg-error "cannot call constructor" } + B::B::B (); // { dg-error "cannot call constructor" } + B::B (0); // { dg-error "cannot call constructor" } + Time::B (0); + } +}; + +int +main (void) +{ + A a; + C c; + a.TestBody (); + c.TestBody (); +}