From patchwork Fri Jun 15 20:21:28 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jason Merrill X-Patchwork-Id: 930224 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-479853-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="eLoJOeAA"; 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 416sNB5QYWz9s01 for ; Sat, 16 Jun 2018 06:22:02 +1000 (AEST) DomainKey-Signature: a=rsa-sha1; c=nofws; d=gcc.gnu.org; h=list-id :list-unsubscribe:list-archive:list-post:list-help:sender :mime-version:from:date:message-id:subject:to:content-type; q= dns; s=default; b=qizz1Qp3xvHYYqZUD3ycaK3lHXBnlIcEGZ+g0yfuiB8x44 ONWKNHT7fFC+HCIDeujxk2mGPw/b8XUnaTZuZ+lLDhYOX9xofFbIHH0ocgq1BqoZ jx5XuvrV4m4igXCz7iU0Vqhb/Eck8kzOaLjAHsOeUji64vlhHfiiRRsMXCO5A= 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 :mime-version:from:date:message-id:subject:to:content-type; s= default; bh=TA0CRdlBNrl0mEgtv2AgjgT1bvA=; b=eLoJOeAAK4zA4DWpse74 KXvPCOflLD/iESpFQVxrW8KF9tXtOdGsqVJoZv/IrG2YtdGrrghBDur1tNG9Dn+y HzUdYunVolzqZQFBvfcp92i8c8NocNC1GyFANknqBOZEk/KLR8/JzCV0A5aAfazi 4sz3vLlKdyZinQMni9QSIw4= Received: (qmail 18199 invoked by alias); 15 Jun 2018 20:21:54 -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 18152 invoked by uid 89); 15 Jun 2018 20:21:53 -0000 Authentication-Results: sourceware.org; auth=none X-Virus-Found: No X-Spam-SWARE-Status: No, score=-24.5 required=5.0 tests=AWL, BAYES_00, GIT_PATCH_0, GIT_PATCH_1, GIT_PATCH_2, GIT_PATCH_3, KAM_LAZY_DOMAIN_SECURITY, RCVD_IN_DNSWL_NONE autolearn=ham version=3.3.2 spammy=synthesized, lambdas, sk:lambda-, Restore X-HELO: mail-ot0-f193.google.com Received: from mail-ot0-f193.google.com (HELO mail-ot0-f193.google.com) (74.125.82.193) by sourceware.org (qpsmtpd/0.93/v0.84-503-g423c35a) with ESMTP; Fri, 15 Jun 2018 20:21:51 +0000 Received: by mail-ot0-f193.google.com with SMTP id q17-v6so12343194otg.2 for ; Fri, 15 Jun 2018 13:21:50 -0700 (PDT) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:mime-version:from:date:message-id:subject:to; bh=n9EQFBPLbjZW6HpKPodddA1m0T6O2sm0lAt9kGgebDs=; b=PeczZDiaa2LJiEeJ1PAgv6B912o9NL5pOCGNLraNCCvJ+umEIdWg4PlXJ6zDT5Umhg L3UWkCd6ml0WdIzFWEXAPK1fvxnCOtH2EmZV2Bmw/5fWTxIV3H5zIBLERKwnWn0G75rU nO7us4EJ1WAVe6mFMpfLvek1JQTSnHY/Hwo+se449dGgr0JDHiVWo+b2RP61ooK3zMgR ePucS2Ae/Gb/3uoGxy9UKSY9W4xQj+jXZI8M7NnBR8Vm8EdjO6kut7KDgLwY+6UV0LoY i55rRwxmjdPc/byq+XmesMYC0HuEYx5vKvSwC39Wvy+qUIlDUBPAgwRzGBz8VOrn6Wq+ DEdw== X-Gm-Message-State: APt69E2IF8IfXKiFgtSCWCDgh5TSQpAag5OynnkWxCi8ThUaXcgTvK47 tg4al8K3Tdhx8sth9Mmwa9fPB3h3JU1dRs4K/lVn0cn9 X-Google-Smtp-Source: ADUXVKIilwzmDwOF9cFdX7enVhwGbs+xGG2CWqDxNbgCaoN0FyRCKYhsXttbJSLY0+D7FpyY2bHNUY7He/yivwwOoio= X-Received: by 2002:a9d:34c3:: with SMTP id t3-v6mr2069864otd.313.1529094109006; Fri, 15 Jun 2018 13:21:49 -0700 (PDT) MIME-Version: 1.0 Received: by 2002:ac9:dd0:0:0:0:0:0 with HTTP; Fri, 15 Jun 2018 13:21:28 -0700 (PDT) From: Jason Merrill Date: Fri, 15 Jun 2018 16:21:28 -0400 Message-ID: Subject: C++ PATCHes for c++/82882, ICE with lambda in template default argument To: gcc-patches List X-IsSubscribed: yes This testcase was broken by the lambda rewrite. This turned out to be because the lambda in the template's default argument had namespace scope, while the instantiation had function scope, because of tsubst_default_argument calling push_access_scope and do_pushtag using the resulting value of current_function_decl. The fix is to teach do_pushtag to do better. For GCC 8 I'm applying a focused patch that just recognizes when we're trying to give a lambda a function scope we aren't actually in. This re-broke bug 59949, so to avoid that I needed to fix tsubst_lambda_expr to use and update the discriminator for global lambda scope when the template lambda has no extra scope. Looking at do_pushtag led me to wonder why we were relying on current_* for the scope in the first place; since we're going to add the tag to current_binding_level, we should get the scope from there as well. Making that change revealed a few more issues: * With a lambda in a default argument, we would frequently be in the binding_level for the calling function. Fixed by calling push_to_top_level. * Redeclarations of C++11 enums with specified underlying type were getting pushed into an arbitrary binding level. Fixed by removing the unnecessary permissiveness around such redeclarations with underlying types that are not template-equivalent, so a redeclaration isn't pushed anywhere. * Lambdas in default member initializers were also getting pushed into an arbitrary binding level, due to the code for allowing type definition in a compound literal in a static data member initializer. Fixed by no longer looking through the binding_level for a complete class, but instead not pushing the tag anywhere if the class is complete; a lambda type isn't found by name anyway. Tested x86_64-pc-linux-gnu. First patch applied to trunk and 8, others only to trunk. commit 190aed44d9e0fcbf89cedddcc2003b41a0899374 Author: Jason Merrill Date: Thu Jun 14 21:56:33 2018 -0400 * pt.c (tsubst_default_argument): Use push_to/pop_from_top_level. * name-lookup.c (do_pushtag): Don't look through complete types, but don't add to them either. Get context from current_binding_level. diff --git a/gcc/cp/name-lookup.c b/gcc/cp/name-lookup.c index 7990029d70c..ec001016d3e 100644 --- a/gcc/cp/name-lookup.c +++ b/gcc/cp/name-lookup.c @@ -6521,12 +6521,7 @@ do_pushtag (tree name, tree type, tag_scope scope) || (b->kind == sk_template_parms && (b->explicit_spec_p || scope == ts_global)) || (b->kind == sk_class - && (scope != ts_current - /* We may be defining a new type in the initializer - of a static member variable. We allow this when - not pedantic, and it is particularly useful for - type punning via an anonymous union. */ - || COMPLETE_TYPE_P (b->this_entity)))) + && scope != ts_current)) b = b->level_chain; gcc_assert (identifier_p (name)); @@ -6540,15 +6535,18 @@ do_pushtag (tree name, tree type, tag_scope scope) if (! context) { - tree cs = current_scope (); + cp_binding_level *cb = b; + while (cb->kind != sk_namespace + && cb->kind != sk_class + && (cb->kind != sk_function_parms + || !cb->this_entity)) + cb = cb->level_chain; + tree cs = cb->this_entity; - /* Avoid setting the lambda context to a current_function_decl that - we aren't actually inside, e.g. one set by push_access_scope - during tsubst_default_argument. */ - if (cs && TREE_CODE (cs) == FUNCTION_DECL - && LAMBDA_TYPE_P (type) - && !at_function_scope_p ()) - cs = DECL_CONTEXT (cs); + gcc_checking_assert (TREE_CODE (cs) == FUNCTION_DECL + ? cs == current_function_decl + : TYPE_P (cs) ? cs == current_class_type + : cs == current_namespace); if (scope == ts_current || (cs && TREE_CODE (cs) == FUNCTION_DECL)) @@ -6587,11 +6585,11 @@ do_pushtag (tree name, tree type, tag_scope scope) if (b->kind == sk_class) { - if (!TYPE_BEING_DEFINED (current_class_type) - && !LAMBDA_TYPE_P (type)) - return error_mark_node; - - if (!PROCESSING_REAL_TEMPLATE_DECL_P ()) + if (!TYPE_BEING_DEFINED (current_class_type)) + /* Don't push anywhere if the class is complete; a lambda in an + NSDMI is not a member of the class. */ + ; + else if (!PROCESSING_REAL_TEMPLATE_DECL_P ()) /* Put this TYPE_DECL on the TYPE_FIELDS list for the class. But if it's a member template class, we want the TEMPLATE_DECL, not the TYPE_DECL, so this is done diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c index ed634ddeefb..4ee84b201e9 100644 --- a/gcc/cp/pt.c +++ b/gcc/cp/pt.c @@ -12675,8 +12675,6 @@ tree tsubst_default_argument (tree fn, int parmnum, tree type, tree arg, tsubst_flags_t complain) { - tree saved_class_ptr = NULL_TREE; - tree saved_class_ref = NULL_TREE; int errs = errorcount + sorrycount; /* This can happen in invalid code. */ @@ -12709,19 +12707,10 @@ tsubst_default_argument (tree fn, int parmnum, tree type, tree arg, we must be careful to do name lookup in the scope of S, rather than in the current class. */ + push_to_top_level (); push_access_scope (fn); - /* The "this" pointer is not valid in a default argument. */ - if (cfun) - { - saved_class_ptr = current_class_ptr; - cp_function_chain->x_current_class_ptr = NULL_TREE; - saved_class_ref = current_class_ref; - cp_function_chain->x_current_class_ref = NULL_TREE; - } - start_lambda_scope (parm); - push_deferring_access_checks(dk_no_deferred); /* The default argument expression may cause implicitly defined member functions to be synthesized, which will result in garbage collection. We must treat this situation as if we were within @@ -12732,17 +12721,9 @@ tsubst_default_argument (tree fn, int parmnum, tree type, tree arg, complain, NULL_TREE, /*integral_constant_expression_p=*/false); --function_depth; - pop_deferring_access_checks(); finish_lambda_scope (); - /* Restore the "this" pointer. */ - if (cfun) - { - cp_function_chain->x_current_class_ptr = saved_class_ptr; - cp_function_chain->x_current_class_ref = saved_class_ref; - } - if (errorcount+sorrycount > errs && (complain & tf_warning_or_error)) inform (input_location, @@ -12752,6 +12733,7 @@ tsubst_default_argument (tree fn, int parmnum, tree type, tree arg, arg = check_default_argument (type, arg, complain); pop_access_scope (fn); + pop_from_top_level (); if (arg != error_mark_node && !cp_unevaluated_operand) { diff --git a/gcc/testsuite/g++.dg/template/crash108.C b/gcc/testsuite/g++.dg/template/crash108.C index 9bcabc6009b..3ffadc14c25 100644 --- a/gcc/testsuite/g++.dg/template/crash108.C +++ b/gcc/testsuite/g++.dg/template/crash108.C @@ -1,5 +1,5 @@ // PR c++/50861 -template struct A {A(int b=k(0));}; // { dg-error "parameter|argument" } -void f(int k){A a;} // // { dg-message "declared" } -// { dg-message "note" "note" { target *-*-* } 3 } +template struct A {A(int b=k(0));}; // { dg-error "not declared" } + // { dg-error "that depend on a template parameter" "" { target *-*-* } .-1 } +void f(int k){A a;}