From patchwork Fri Mar 16 21:38:08 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Alexandre Oliva X-Patchwork-Id: 887174 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-474888-incoming=patchwork.ozlabs.org@gcc.gnu.org; receiver=) Authentication-Results: ozlabs.org; dmarc=fail (p=none dis=none) header.from=redhat.com Authentication-Results: ozlabs.org; dkim=pass (1024-bit key; unprotected) header.d=gcc.gnu.org header.i=@gcc.gnu.org header.b="dwAb3NMp"; 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 402zNV3mDCz9sMl for ; Sat, 17 Mar 2018 08:38:32 +1100 (AEDT) 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:subject:date:message-id:mime-version:content-type; q=dns; s= default; b=Lw02OEPcQNsJMxf4rCKPf5jjtNLx/Anw6xroXDPSUukHNP69k0TsW udatEGCrXby15a+1eJst+hHQVXMq9w8z+uLMdBlt16rvpsM5nzTXF1dYTJn1m4la EoItHszdderGqEGgtlGtVfQXW7xpftabJ9a88nFRDh9cCCfwXM54Dg= 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:subject:date:message-id:mime-version:content-type; s= default; bh=vVsuSVxwHvOCYU+MSPqnLvyoc8g=; b=dwAb3NMptCicC8aWz8Yc svsrwC1aQCbte4ZIq07oFpaXGe6rld/e/MudFhaWgZEl914SkYt6ofXTxYJBJ/sO QLsPqOsRiCZ6hPQ7skooxZC9YYD4s0WXOwlkp+A6mAhKpEdnJVWb8nTxkApNv/X4 I+P2XBpk4//J5wpgKFoT7ao= Received: (qmail 78508 invoked by alias); 16 Mar 2018 21:38:26 -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 78499 invoked by uid 89); 16 Mar 2018 21:38:25 -0000 Authentication-Results: sourceware.org; auth=none X-Virus-Found: No X-Spam-SWARE-Status: No, score=-26.9 required=5.0 tests=BAYES_00, GIT_PATCH_0, GIT_PATCH_1, GIT_PATCH_2, GIT_PATCH_3, T_RP_MATCHES_RCVD autolearn=ham version=3.3.2 spammy=america, America X-HELO: mx1.redhat.com Received: from mx1.redhat.com (HELO mx1.redhat.com) (209.132.183.28) by sourceware.org (qpsmtpd/0.93/v0.84-503-g423c35a) with ESMTP; Fri, 16 Mar 2018 21:38:24 +0000 Received: from smtp.corp.redhat.com (int-mx03.intmail.prod.int.phx2.redhat.com [10.5.11.13]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id 2DFFDC03D47E for ; Fri, 16 Mar 2018 21:38:23 +0000 (UTC) Received: from freie.home (ovpn04.gateway.prod.ext.phx2.redhat.com [10.5.9.4]) by smtp.corp.redhat.com (Postfix) with ESMTPS id DF8E817AA8 for ; Fri, 16 Mar 2018 21:38:22 +0000 (UTC) Received: from livre (livre.home [172.31.160.2]) by freie.home (8.15.2/8.15.2) with ESMTP id w2GLc8Y0138214; Fri, 16 Mar 2018 18:38:08 -0300 From: Alexandre Oliva To: gcc-patches@gcc.gnu.org Subject: [PR c++/84789] do not resolve typename into template-independent Date: Fri, 16 Mar 2018 18:38:08 -0300 Message-ID: User-Agent: Gnus/5.13 (Gnus v5.13) Emacs/25.3 (gnu/linux) MIME-Version: 1.0 resolve_typename_type may peek into template types that might still be specialized. In some cases, e.g. g++.dg/template/friend48.C or g++.dg/template/decl2.C, that is exactly the right thing to do. In others, like the newly-added testcase g++.dg/template/pr84789.C, it isn't, and if the qualifying scope happens to resolve to a non-template type, we resolve to that and then fail the assert that checks we still have a template-dependent scope. It appears to me that, in cases in which the assert would fail, we are missing the typename keyword, and we ought to report an error; if we just return the incoming type unchanged, that's exactly what we get. So, I'm turning such failed asserts into early returns, so that the parser can recover and report an error. Regstrapped on i686- and x86_64-linux-gnu. Ok to install? for gcc/cp/ChangeLog PR c++/84789 * pt.c (resolve_typename_type): Keep the type template-dependent. for gcc/testsuite/ChangeLog PR c++/84789 * g++.dg/template/pr84789.C: New. --- gcc/cp/pt.c | 19 +++++++++++++++++-- gcc/testsuite/g++.dg/template/pr84789.C | 13 +++++++++++++ 2 files changed, 30 insertions(+), 2 deletions(-) create mode 100644 gcc/testsuite/g++.dg/template/pr84789.C diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c index 89024c10fe2b..067221fa78ea 100644 --- a/gcc/cp/pt.c +++ b/gcc/cp/pt.c @@ -25195,8 +25195,23 @@ resolve_typename_type (tree type, bool only_current_p) /* scope is either the template itself or a compatible instantiation like X, so look up the name in the original template. */ scope = CLASSTYPE_PRIMARY_TEMPLATE_TYPE (scope); - /* We shouldn't have built a TYPENAME_TYPE with a non-dependent scope. */ - gcc_checking_assert (uses_template_parms (scope)); + /* We shouldn't have built a TYPENAME_TYPE with a non-dependent + scope. However, it might be a dependent scope that's being + resolved to a non-dependent scope just because we're looking up + scopes we shouldn't, e.g. + + template class B { typedef int I; }; + template class C : B { B::I i; }; + + We need 'typename' before C::i's type, because we can't enter + the scope of B for an unbound template parameter T to tell I + identifies a type (that's why we need typename), but the parser + attempts to do so, presumably so that it can produce better error + messages. However, we'd skip necessary errors if we resolved a + template-dependent type to a template-independent one, so don't + do that. */ + if (!uses_template_parms (scope)) + return type; /* If scope has no fields, it can't be a current instantiation. Check this before currently_open_class to avoid infinite recursion (71515). */ if (!TYPE_FIELDS (scope)) diff --git a/gcc/testsuite/g++.dg/template/pr84789.C b/gcc/testsuite/g++.dg/template/pr84789.C new file mode 100644 index 000000000000..bc1567f3fe77 --- /dev/null +++ b/gcc/testsuite/g++.dg/template/pr84789.C @@ -0,0 +1,13 @@ +// { dg-do compile } + +struct A +{ + typedef int I; +}; + +template struct B : A {}; + +template struct C : B +{ + B::A::I::I i; // { dg-error "typename" } +};