From patchwork Thu Nov 16 20:12:35 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jason Merrill X-Patchwork-Id: 838772 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-467048-incoming=patchwork.ozlabs.org@gcc.gnu.org; receiver=) Authentication-Results: ozlabs.org; dkim=pass (1024-bit key; unprotected) header.d=gcc.gnu.org header.i=@gcc.gnu.org header.b="lNOTPSsH"; 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 3ydC9P6cZzz9s5L for ; Fri, 17 Nov 2017 07:13:11 +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 :mime-version:from:date:message-id:subject:to:content-type; q= dns; s=default; b=S+SlM68+qP/bSIdPZj/qV9NgR/kox2KKl6JSrTP+SaKVkm MFL0+hEVYYV9brFV+JRcIIeOji9bES0DR5q+o9V17PZPI3fJhGQdDyNMmomCRT8C xmN+F5lkXYDR5/aLl+FO8KlnPf6LarCHPQTyuRF2/fvNypoPiHvtPcuV/WTpQ= 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=8SB34S/vMssLubDL3duVv5nuDig=; b=lNOTPSsHat80HQ9kUzxz RTc3ZzjKUBwDCdrLBnA4kDMzN/EEhzPKH3BFBJf7uRvMY0hf3BdG7JqR6OkwUV38 G8xiA2QkfYGyp8lG7uwnlI7PlowjEz4eUgqjF4hb9oqVjOrJmgsOJi2ZVPvBCJk0 RK5xKv8lstT6otr+5RN5Q/c= Received: (qmail 82952 invoked by alias); 16 Nov 2017 20:13:02 -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 82927 invoked by uid 89); 16 Nov 2017 20:13:00 -0000 Authentication-Results: sourceware.org; auth=none X-Virus-Found: No X-Spam-SWARE-Status: No, score=-24.3 required=5.0 tests=AWL, BAYES_00, GIT_PATCH_0, GIT_PATCH_1, GIT_PATCH_2, GIT_PATCH_3, KAM_LAZY_DOMAIN_SECURITY, KB_WAM_FROM_NAME_SINGLEWORD, RCVD_IN_DNSWL_NONE autolearn=ham version=3.3.2 spammy=manglec, UD:mangle.c, mangle.c, sk:noexcep X-HELO: mail-io0-f195.google.com Received: from mail-io0-f195.google.com (HELO mail-io0-f195.google.com) (209.85.223.195) by sourceware.org (qpsmtpd/0.93/v0.84-503-g423c35a) with ESMTP; Thu, 16 Nov 2017 20:12:58 +0000 Received: by mail-io0-f195.google.com with SMTP id 134so6510518ioo.0 for ; Thu, 16 Nov 2017 12:12:58 -0800 (PST) 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=YL9M/NRxaIckP6IDA5L1nEz8cZY9QlF0w1mbD8r+H2k=; b=UHEyAw0vnt19y4+tBZYlyGhSe6zkfm0fv3/p+b5mcI9cuziH6vzdxWmoaq9H4m5byM y5p7UIWCR13f5uJyuHiKlLAeiGFqeVe4l0PbuTlvlQCQy+2l97zL5z9brCKo0ouhDr0G 4BjkNhea3Zc9zvNheeMdYQ+krj+A1rZn9Mch9wgTjqIwX+zE9F02SXFTNaD/uDaO4EbT 1lWh15NbHGk4E4rM3pFbhA8MPmDGtUsgWQXmmglAo9/A6uFD3noxJLMeflNrpTsmyQqW BjZ7y04adhq4i6Lm66q5Y2DGpV4WiY8KKfFE/JCpsdaQubJzMXKuIuKArDLTqsJzjY3/ V5pw== X-Gm-Message-State: AJaThX48d3lCAQdfO370hzbcZa/59pfI234LBVzBrIMwY0j/uIzvmHjf 4xLtoLtZ7l8UW+ae1RI4A+Aj2fkjZ1alClS2J31+v+ml X-Google-Smtp-Source: AGs4zMZKmYE4K84d4LwdVYcORM7e9zKABtpg6MxmXSmN65C6Ee9h7dGU5NIDtLrM9bI2eE6QE4+yxvWlTcAZUn78aY4= X-Received: by 10.107.178.145 with SMTP id b139mr97316iof.52.1510863176373; Thu, 16 Nov 2017 12:12:56 -0800 (PST) MIME-Version: 1.0 Received: by 10.107.171.196 with HTTP; Thu, 16 Nov 2017 12:12:35 -0800 (PST) From: Jason Merrill Date: Thu, 16 Nov 2017 15:12:35 -0500 Message-ID: Subject: C++ PATCH for c++/79092, auto template args of different type and same value To: gcc-patches List X-IsSubscribed: yes For an auto template parameter, the type of the argument matters, so we can't treat 0 and 0u as equivalent. But if we adjust cp_tree_equal to consider the type of a constant, we need to be more careful about actually converting template arguments to the type of the (non-auto) parameter, so that comparison of template arguments works properly. Specifically, in g++.dg/cpp0x/temp_default7.C, unify needs to compare A to A; in A, dummy is implicitly converted to int, so if we leave dummy unconverted in A, we compare a constant enumerator to a constant integer, and fail because they have different types. If we explicitly convert dummy in A to the dependent type of the parameter, we avoid this problem, because we can see that the result is dependent and needs substitution before comparison. I'm representing this conversion with a magic-ish IMPLICIT_CONV_EXPR, marked for this situation. We only add it in cases that are not value-dependent, and therefore would only be used for comparison rather than deduction. In tsubst_copy_and_build we just drop these once they become non-dependent, as the result will go back through convert_template_argument. Checking at this point for value-dependence required implementation of a recent core DR that clarifies that all type-dependent expressions are also value-dependent; previously I have felt that we shouldn't even ask whether a type-dependent expression is value-dependent, but now I see that this simplifies things. I'm a bit unsure about treating DEFERRED_NOEXCEPT as non-dependent, but it seems necessary, since non-template functions can have DEFERRED_NOEXCEPT, and those certainly won't be dependent. Tested x86_64-pc-linux-gnu, applying to trunk. commit 5cf3f26db8e0d89e207453bbd9fd4c1a8cf79631 Author: Jason Merrill Date: Wed Oct 25 15:42:54 2017 -0400 PR c++/79092 - non-type args of different types are different * tree.c (cp_tree_equal): Check the type of constants. * pt.c (unify) [TEMPLATE_PARM_INDEX]: Handle UNIFY_ALLOW_INTEGER when comparing to previously deduced argument. (maybe_convert_nontype_argument): New. (convert_nontype_argument): Call it. (tsubst_copy_and_build): Handle partial instantiation of IMPLICIT_CONV_EXPR. (unify): Ignore type when deducing from array bound. (dependent_type_p_r): Handle DEFERRED_NOEXCEPT. (value_dependent_expression_p): Any type-dependent expression is value-dependent. Handle IMPLICIT_CONV_EXPR. * cp-tree.h (IMPLICIT_CONV_EXPR_NONTYPE_ARG): New. * mangle.c (write_template_arg): Strip IMPLICIT_CONV_EXPR. diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h index c6554162078..1c19c3d31f8 100644 --- a/gcc/cp/cp-tree.h +++ b/gcc/cp/cp-tree.h @@ -382,6 +382,7 @@ extern GTY(()) tree cp_global_trees[CPTI_MAX]; TINFO_USED_TEMPLATE_ID (in TEMPLATE_INFO) PACK_EXPANSION_SIZEOF_P (in *_PACK_EXPANSION) OVL_USING_P (in OVERLOAD) + IMPLICIT_CONV_EXPR_NONTYPE_ARG (in IMPLICIT_CONV_EXPR) 2: IDENTIFIER_KIND_BIT_2 (in IDENTIFIER_NODE) ICS_THIS_FLAG (in _CONV) DECL_INITIALIZED_BY_CONSTANT_EXPRESSION_P (in VAR_DECL) @@ -4126,6 +4127,11 @@ more_aggr_init_expr_args_p (const aggr_init_expr_arg_iterator *iter) #define IMPLICIT_CONV_EXPR_DIRECT_INIT(NODE) \ (TREE_LANG_FLAG_0 (IMPLICIT_CONV_EXPR_CHECK (NODE))) +/* True if NODE represents a dependent conversion of a non-type template + argument. Set by maybe_convert_nontype_argument. */ +#define IMPLICIT_CONV_EXPR_NONTYPE_ARG(NODE) \ + (TREE_LANG_FLAG_1 (IMPLICIT_CONV_EXPR_CHECK (NODE))) + /* Nonzero means that an object of this type can not be initialized using an initializer list. */ #define CLASSTYPE_NON_AGGREGATE(NODE) \ diff --git a/gcc/cp/mangle.c b/gcc/cp/mangle.c index 050055bd26c..6d4e59101ee 100644 --- a/gcc/cp/mangle.c +++ b/gcc/cp/mangle.c @@ -2836,7 +2836,7 @@ write_expression (tree expr) while (CONVERT_EXPR_CODE_P (code) /* Parentheses aren't mangled. */ || code == PAREN_EXPR - || TREE_CODE (expr) == NON_LVALUE_EXPR) + || code == NON_LVALUE_EXPR) { expr = TREE_OPERAND (expr, 0); code = TREE_CODE (expr); @@ -3407,6 +3407,9 @@ write_template_arg (tree node) } } + /* Strip a conversion added by convert_nontype_argument. */ + if (TREE_CODE (node) == IMPLICIT_CONV_EXPR) + node = TREE_OPERAND (node, 0); if (REFERENCE_REF_P (node)) node = TREE_OPERAND (node, 0); if (TREE_CODE (node) == NOP_EXPR diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c index 562b9272596..2b70969999e 100644 --- a/gcc/cp/pt.c +++ b/gcc/cp/pt.c @@ -7519,6 +7519,31 @@ convert_wildcard_argument (tree parm, tree arg) return arg; } +/* We can't fully resolve ARG given as a non-type template argument to TYPE, + because one of them is dependent. But we need to represent the + conversion for the benefit of cp_tree_equal. */ + +static tree +maybe_convert_nontype_argument (tree type, tree arg) +{ + /* Auto parms get no conversion. */ + if (type_uses_auto (type)) + return arg; + /* We don't need or want to add this conversion now if we're going to use the + argument for deduction. */ + if (value_dependent_expression_p (arg)) + return arg; + + type = cv_unqualified (type); + tree argtype = TREE_TYPE (arg); + if (same_type_p (type, argtype)) + return arg; + + arg = build1 (IMPLICIT_CONV_EXPR, type, arg); + IMPLICIT_CONV_EXPR_NONTYPE_ARG (arg) = true; + return arg; +} + /* Convert the indicated template ARG as necessary to match the indicated template PARM. Returns the converted ARG, or error_mark_node if the conversion was unsuccessful. Error and @@ -7774,7 +7799,11 @@ convert_template_argument (tree parm, argument specification is valid. */ val = convert_nontype_argument (t, orig_arg, complain); else - val = canonicalize_expr_argument (orig_arg, complain); + { + val = canonicalize_expr_argument (orig_arg, complain); + val = maybe_convert_nontype_argument (t, val); + } + if (val == NULL_TREE) val = error_mark_node; @@ -17097,6 +17126,17 @@ tsubst_copy_and_build (tree t, { tree type = tsubst (TREE_TYPE (t), args, complain, in_decl); tree expr = RECUR (TREE_OPERAND (t, 0)); + if (dependent_type_p (type) || type_dependent_expression_p (expr)) + { + retval = copy_node (t); + TREE_TYPE (retval) = type; + TREE_OPERAND (retval, 0) = expr; + RETURN (retval); + } + if (IMPLICIT_CONV_EXPR_NONTYPE_ARG (t)) + /* We'll pass this to convert_nontype_argument again, we don't need + to actually perform any conversion here. */ + RETURN (expr); int flags = LOOKUP_IMPLICIT; if (IMPLICIT_CONV_EXPR_DIRECT_INIT (t)) flags = LOOKUP_NORMAL; @@ -20886,6 +20926,11 @@ unify (tree tparms, tree targs, tree parm, tree arg, int strict, if (targ) { + if ((strict & UNIFY_ALLOW_INTEGER) + && TREE_TYPE (targ) && TREE_TYPE (arg) + && CP_INTEGRAL_TYPE_P (TREE_TYPE (targ))) + /* We're deducing from an array bound, the type doesn't matter. */ + arg = fold_convert (TREE_TYPE (targ), arg); int x = !cp_tree_equal (targ, arg); if (x) unify_inconsistency (explain_p, parm, targ, arg); @@ -23704,13 +23749,15 @@ dependent_type_p_r (tree type) if (dependent_type_p (TREE_VALUE (arg_type))) return true; if (cxx_dialect >= cxx17) - { - /* A value-dependent noexcept-specifier makes the type dependent. */ - tree spec = TYPE_RAISES_EXCEPTIONS (type); - if (spec && TREE_PURPOSE (spec) - && value_dependent_expression_p (TREE_PURPOSE (spec))) - return true; - } + /* A value-dependent noexcept-specifier makes the type dependent. */ + if (tree spec = TYPE_RAISES_EXCEPTIONS (type)) + if (tree noex = TREE_PURPOSE (spec)) + /* Treat DEFERRED_NOEXCEPT as non-dependent, since it doesn't + affect overload resolution and treating it as dependent breaks + things. */ + if (TREE_CODE (noex) != DEFERRED_NOEXCEPT + && value_dependent_expression_p (noex)) + return true; return false; } /* -- an array type constructed from any dependent type or whose @@ -23875,8 +23922,8 @@ value_dependent_expression_p (tree expression) if (!processing_template_decl || expression == NULL_TREE) return false; - /* A name declared with a dependent type. */ - if (DECL_P (expression) && type_dependent_expression_p (expression)) + /* A type-dependent expression is also value-dependent. */ + if (type_dependent_expression_p (expression)) return true; switch (TREE_CODE (expression)) @@ -23918,13 +23965,12 @@ value_dependent_expression_p (tree expression) && (TREE_CODE (DECL_INITIAL (expression)) == TREE_LIST /* cp_finish_decl doesn't fold reference initializers. */ || TREE_CODE (TREE_TYPE (expression)) == REFERENCE_TYPE - || type_dependent_expression_p (DECL_INITIAL (expression)) || value_dependent_expression_p (DECL_INITIAL (expression)))) return true; if (DECL_HAS_VALUE_EXPR_P (expression)) { tree value_expr = DECL_VALUE_EXPR (expression); - if (type_dependent_expression_p (value_expr)) + if (value_dependent_expression_p (value_expr)) return true; } return false; @@ -23934,6 +23980,7 @@ value_dependent_expression_p (tree expression) case CONST_CAST_EXPR: case REINTERPRET_CAST_EXPR: case CAST_EXPR: + case IMPLICIT_CONV_EXPR: /* These expressions are value-dependent if the type to which the cast occurs is dependent or the expression being casted is value-dependent. */ @@ -24078,10 +24125,7 @@ value_dependent_expression_p (tree expression) } case TEMPLATE_ID_EXPR: - /* If a TEMPLATE_ID_EXPR involves a dependent name, it will be - type-dependent. */ - return type_dependent_expression_p (expression) - || variable_concept_p (TREE_OPERAND (expression, 0)); + return variable_concept_p (TREE_OPERAND (expression, 0)); case CONSTRUCTOR: { diff --git a/gcc/cp/tree.c b/gcc/cp/tree.c index c60d54ab01f..245657866df 100644 --- a/gcc/cp/tree.c +++ b/gcc/cp/tree.c @@ -3494,6 +3494,10 @@ cp_tree_equal (tree t1, tree t2) if (code1 != code2) return false; + if (CONSTANT_CLASS_P (t1) + && !same_type_p (TREE_TYPE (t1), TREE_TYPE (t2))) + return false; + switch (code1) { case VOID_CST: diff --git a/gcc/testsuite/g++.dg/cpp1z/nontype-auto12.C b/gcc/testsuite/g++.dg/cpp1z/nontype-auto12.C new file mode 100644 index 00000000000..7bff75c3484 --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp1z/nontype-auto12.C @@ -0,0 +1,6 @@ +// PR c++/79092 +// { dg-options -std=c++17 } + +template struct val {}; + +struct type : val<0>, val<0u> {};