From patchwork Wed Feb 10 19:16:04 2016 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Patrick Palka X-Patchwork-Id: 581579 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 C5A9A140783 for ; Thu, 11 Feb 2016 06:16:26 +1100 (AEDT) Authentication-Results: ozlabs.org; dkim=pass (1024-bit key; unprotected) header.d=gcc.gnu.org header.i=@gcc.gnu.org header.b=o38joXxi; 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=PVvPZGMulEoR GvWcHs4X1e16Hgj4/p+iXN0iwlC85WO67khA4qF/alTvNw6MCo6jZnA5vBKzZqE1 u0Kw6L21HxEbxAgNvtOHLz1oyCvgRbOo2S4W4IkzKJsorE435bDZ0G3gZeMHajHc QZj1f4PF66+2a6G162RnvexocSv82J0= 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=Vwl33Ib7wT6MJxqWfF mVRZMIukI=; b=o38joXxigSRN6kqF5mKYsV+za0BrOZaV3SdI2bov2fF0ey9cJN gNa+7JJIbWTJfLj9tNeGXQYMaryhbTG7GDMFi4OT7Vk+isPk2qyD2Js+/oayYwIG JC+Gd+GigbJQ6FVkFbxsXyUwmdeNsIUNODFZG9Ihzve7NjB8/CdkWHJnk= Received: (qmail 49941 invoked by alias); 10 Feb 2016 19:16:18 -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 49929 invoked by uid 89); 10 Feb 2016 19:16:16 -0000 Authentication-Results: sourceware.org; auth=none X-Virus-Found: No X-Spam-SWARE-Status: No, score=-2.6 required=5.0 tests=BAYES_00, RCVD_IN_DNSWL_LOW autolearn=ham version=3.3.2 spammy=Trigger, EXPR, 1, 37, foo2 X-HELO: mail-qk0-f179.google.com Received: from mail-qk0-f179.google.com (HELO mail-qk0-f179.google.com) (209.85.220.179) by sourceware.org (qpsmtpd/0.93/v0.84-503-g423c35a) with (AES128-GCM-SHA256 encrypted) ESMTPS; Wed, 10 Feb 2016 19:16:15 +0000 Received: by mail-qk0-f179.google.com with SMTP id o6so10660222qkc.2 for ; Wed, 10 Feb 2016 11:16:15 -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=XiuUL5ZxZjZDzC2MPpOukkXtTxkN6ZumpMg6lzhuKvU=; b=gPDq85zIujSso1aodC8LpY+/Pw4BPlkCdfTlmnQ1HX0L6ysxl03Eo1lbZ94EmhpvKN rGWRiHab2nAkCpIDMqppdMu66HlJqpQzmOFmL9TF0W6OfAkvNcHytdPpZBCmOp60MRf1 8aACFFSG18K2Sob2r1eXo7V0G0VfRJd+0VdA8sOPkvRmhxdijevpSC5RicZj+i3Z+EYv nkP5T3ICEDkLXJFt1ul2ca8/E/eGUPdgd0FUZcIcL1OM18JilpOO8hLhlUdA239rQXBZ tBycvG1cKFHyXkcHsyoRe8KzfuBeaZI3sFHOi+/ZryZcaA5BSzGeiaUz+rq6mSwFicYc TeVw== X-Gm-Message-State: AG10YOQXBnR+Tt1TlgbSlnvrGC/slKSPtowvm4VgcJ8JbVcZoZI7iT5m9rXVerwNNJDrYw== X-Received: by 10.55.43.102 with SMTP id r99mr22201339qkh.51.1455131773513; Wed, 10 Feb 2016 11:16:13 -0800 (PST) Received: from localhost.localdomain (ool-4353abbc.dyn.optonline.net. [67.83.171.188]) by smtp.gmail.com with ESMTPSA id i67sm1831131qhi.45.2016.02.10.11.16.12 (version=TLS1_2 cipher=ECDHE-RSA-AES128-SHA bits=128/128); Wed, 10 Feb 2016 11:16:12 -0800 (PST) From: Patrick Palka To: gcc-patches@gcc.gnu.org Cc: jason@redhat.com, Patrick Palka Subject: [PATCH] Fix PR c++/69098 (bogus errors with static data member template) Date: Wed, 10 Feb 2016 14:16:04 -0500 Message-Id: <1455131764-11282-1-git-send-email-patrick@parcs.ath.cx> tsubst_qualified_id() is currently not prepared to handle a SCOPED_REF whose RHS is a variable template. r226642 made this deficiency more obvious by marking all variable templates as dependent (thus forcing them to be wrapped in a SCOPED_REF) but before that it was also possible to trigger a bogus error if the scope of the variable template was dependent (e.g. foo2 in the test case 69098-2.C fails to compile even before r226642, whereas foo1 fails to compile only after r226642). Further, check_template_keyword() is currently not prepared to handle variable templates as well. And again r226642 helped to expose this issue but it was already possible to trigger before that (e.g. foo4 always failed to compile whereas foo3 only fails after r226642). This patch makes tsubst_qualified_id() and check_template_keyword() handle variable templates accordingly. The changes in check_template_keyword() are fairly straightforward, and in tsubst_qualified_id() I just copied the way variable templates are handled in tsubst_copy_and_build [TEMPLATE_ID_EXPR]. Boostrap + regtest in progress on x86_64-pc-linux-gnu, Ok to commit after testing? gcc/cp/ChangeLog: PR c++/69098 * pt.c (tsubst_qualified_id): Consider that EXPR might be a variable template. * typeck.c (check_template_keyword): Don't emit an error if DECL is a variable template. gcc/testsuite/ChangeLog: PR c++/69098 * g++.dg/cpp1y/69098.C: New test. * g++.dg/cpp1y/69098-2.C: New test. --- gcc/cp/pt.c | 15 ++++++++++++- gcc/cp/typeck.c | 10 ++++++++- gcc/testsuite/g++.dg/cpp1y/69098-2.C | 37 +++++++++++++++++++++++++++++++ gcc/testsuite/g++.dg/cpp1y/69098.C | 43 ++++++++++++++++++++++++++++++++++++ 4 files changed, 103 insertions(+), 2 deletions(-) create mode 100644 gcc/testsuite/g++.dg/cpp1y/69098-2.C create mode 100644 gcc/testsuite/g++.dg/cpp1y/69098.C diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c index 725adba..6780a98 100644 --- a/gcc/cp/pt.c +++ b/gcc/cp/pt.c @@ -13726,7 +13726,20 @@ tsubst_qualified_id (tree qualified_id, tree args, } if (is_template) - expr = lookup_template_function (expr, template_args); + { + if (variable_template_p (expr)) + { + expr = lookup_template_variable (expr, template_args); + if (!any_dependent_template_arguments_p (template_args)) + { + expr = finish_template_variable (expr, complain); + mark_used (expr); + } + expr = convert_from_reference (expr); + } + else + expr = lookup_template_function (expr, template_args); + } if (expr == error_mark_node && complain & tf_error) qualified_name_lookup_error (scope, TREE_OPERAND (qualified_id, 1), diff --git a/gcc/cp/typeck.c b/gcc/cp/typeck.c index d2c23f4..959dc5a 100644 --- a/gcc/cp/typeck.c +++ b/gcc/cp/typeck.c @@ -2601,7 +2601,15 @@ check_template_keyword (tree decl) if (TREE_CODE (decl) != TEMPLATE_DECL && TREE_CODE (decl) != TEMPLATE_ID_EXPR) { - if (!is_overloaded_fn (decl)) + if (VAR_P (decl)) + { + if (DECL_USE_TEMPLATE (decl) + && PRIMARY_TEMPLATE_P (DECL_TI_TEMPLATE (decl))) + ; + else + permerror (input_location, "%qD is not a template", decl); + } + else if (!is_overloaded_fn (decl)) permerror (input_location, "%qD is not a template", decl); else { diff --git a/gcc/testsuite/g++.dg/cpp1y/69098-2.C b/gcc/testsuite/g++.dg/cpp1y/69098-2.C new file mode 100644 index 0000000..2e968bb --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp1y/69098-2.C @@ -0,0 +1,37 @@ +// PR c++/69098 +// { dg-do compile { target c++14 } } + +struct A +{ + template + static void *pf; +}; + +template +bool foo1 () { + return A::pf; +} + +template +bool foo2 () { + return B::template pf; +} + +template +bool foo3 () { + return &A::pf; +} + +template +bool foo4 () { + return &B::template pf; +} + + +void bar () { + foo1(); + foo2(); + foo3(); + foo4(); +} + diff --git a/gcc/testsuite/g++.dg/cpp1y/69098.C b/gcc/testsuite/g++.dg/cpp1y/69098.C new file mode 100644 index 0000000..afc4294 --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp1y/69098.C @@ -0,0 +1,43 @@ +// PR c++/69098 +// { dg-do compile { target c++14 } } + +template struct SpecPerType; + +class Specializer +{ +public: + template void MbrFnTempl() //Must be a template + { + } + template struct InnerClassTempl + { //Had to be a template whenever I tested for it + static void InnerMemberFn(); + }; + + void Trigger() + { + InnerClassTempl<0u>::InnerMemberFn(); + } +}; + +template<> struct SpecPerType +{ + using FnType = void (Specializer::*)(); + template static constexpr FnType SpecMbrFnPtr = + &Specializer::template MbrFnTempl

; +}; + +template constexpr SpecPerType::FnType + SpecPerType::SpecMbrFnPtr; //Just a formalism + +template void Specializer::InnerClassTempl::InnerMemberFn() +{ + using Spec = SpecPerType; + typename Spec::FnType ErrorSite = Spec::template SpecMbrFnPtr; + //ErrorSite would get called next in the original code + //(this should result in a call to MbrFnTempl) +} + +int main() +{ +}