From patchwork Mon Jun 20 14:29:33 2011 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jason Merrill X-Patchwork-Id: 101137 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]) by ozlabs.org (Postfix) with SMTP id CA689B6F77 for ; Tue, 21 Jun 2011 00:29:57 +1000 (EST) Received: (qmail 4982 invoked by alias); 20 Jun 2011 14:29:55 -0000 Received: (qmail 4950 invoked by uid 22791); 20 Jun 2011 14:29:51 -0000 X-SWARE-Spam-Status: No, hits=-6.4 required=5.0 tests=AWL, BAYES_00, RCVD_IN_DNSWL_HI, SPF_HELO_PASS, T_RP_MATCHES_RCVD X-Spam-Check-By: sourceware.org Received: from mx1.redhat.com (HELO mx1.redhat.com) (209.132.183.28) by sourceware.org (qpsmtpd/0.43rc1) with ESMTP; Mon, 20 Jun 2011 14:29:35 +0000 Received: from int-mx02.intmail.prod.int.phx2.redhat.com (int-mx02.intmail.prod.int.phx2.redhat.com [10.5.11.12]) by mx1.redhat.com (8.14.4/8.14.4) with ESMTP id p5KETYiB017907 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK) for ; Mon, 20 Jun 2011 10:29:34 -0400 Received: from [127.0.0.1] ([10.3.113.2]) by int-mx02.intmail.prod.int.phx2.redhat.com (8.13.8/8.13.8) with ESMTP id p5KETYaF023535 for ; Mon, 20 Jun 2011 10:29:34 -0400 Message-ID: <4DFF594D.6010703@redhat.com> Date: Mon, 20 Jun 2011 10:29:33 -0400 From: Jason Merrill User-Agent: Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.9.2.17) Gecko/20110428 Fedora/3.1.10-1.fc14 Lightning/1.0b2 Thunderbird/3.1.10 MIME-Version: 1.0 To: gcc-patches List Subject: C++ PATCH for c++/43321 (error on valid C++0x auto) 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 Here describable_type thought that a particular INDIRECT_REF was describable, but it really wasn't. Fixed by removing describable_type entirely; we can just try to deduce, and defer until instantiation if it doesn't work. Tested x86_64-pc-linux-gnu, applying to trunk. commit 9ffe8ed0665020e00f7923314fe2e9aa99a155b1 Author: Jason Merrill Date: Sat Jun 18 15:35:45 2011 -0400 PR c++/43321 * semantics.c (describable_type): Remove. * cp-tree.h: Likewise. * decl.c (cp_finish_decl): Don't call it. * init.c (build_new): Likewise. * parser.c (cp_parser_omp_for_loop): Likewise. * pt.c (tsubst_decl): Likewise. (do_auto_deduction): If we fail in a template, try again at instantiation time. diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h index 2773e34..904e44c 100644 --- a/gcc/cp/cp-tree.h +++ b/gcc/cp/cp-tree.h @@ -5445,7 +5445,6 @@ extern bool cxx_omp_create_clause_info (tree, tree, bool, bool, bool); extern tree baselink_for_fns (tree); extern void finish_static_assert (tree, tree, location_t, bool); -extern tree describable_type (tree); extern tree finish_decltype_type (tree, bool, tsubst_flags_t); extern tree finish_trait_expr (enum cp_trait_kind, tree, tree); extern tree build_lambda_expr (void); diff --git a/gcc/cp/decl.c b/gcc/cp/decl.c index 59c4a4c..85249f1 100644 --- a/gcc/cp/decl.c +++ b/gcc/cp/decl.c @@ -5944,13 +5944,10 @@ cp_finish_decl (tree decl, tree init, bool init_const_expr_p, d_init = build_x_compound_expr_from_list (d_init, ELK_INIT, tf_warning_or_error); d_init = resolve_nondeduced_context (d_init); - if (describable_type (d_init)) - { - type = TREE_TYPE (decl) = do_auto_deduction (type, d_init, - auto_node); - if (type == error_mark_node) - return; - } + type = TREE_TYPE (decl) = do_auto_deduction (type, d_init, + auto_node); + if (type == error_mark_node) + return; } if (!ensure_literal_type_for_constexpr_object (decl)) diff --git a/gcc/cp/init.c b/gcc/cp/init.c index 3b92665..140e064 100644 --- a/gcc/cp/init.c +++ b/gcc/cp/init.c @@ -2600,8 +2600,7 @@ build_new (VEC(tree,gc) **placement, tree type, tree nelts, { tree d_init = VEC_index (tree, *init, 0); d_init = resolve_nondeduced_context (d_init); - if (describable_type (d_init)) - type = do_auto_deduction (type, d_init, auto_node); + type = do_auto_deduction (type, d_init, auto_node); } } diff --git a/gcc/cp/parser.c b/gcc/cp/parser.c index 75dac6a..856a8a7 100644 --- a/gcc/cp/parser.c +++ b/gcc/cp/parser.c @@ -24504,7 +24504,7 @@ cp_parser_omp_for_loop (cp_parser *parser, tree clauses, tree *par_clauses) &is_direct_init, &is_non_constant_init); - if (auto_node && describable_type (init)) + if (auto_node) { TREE_TYPE (decl) = do_auto_deduction (TREE_TYPE (decl), init, diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c index 85f2749..6f15101 100644 --- a/gcc/cp/pt.c +++ b/gcc/cp/pt.c @@ -10122,11 +10122,8 @@ tsubst_decl (tree t, tree args, tsubst_flags_t complain) if (auto_node && init) { init = resolve_nondeduced_context (init); - if (describable_type (init)) - { - type = do_auto_deduction (type, init, auto_node); - TREE_TYPE (r) = type; - } + TREE_TYPE (r) = type + = do_auto_deduction (type, init, auto_node); } } else @@ -19302,6 +19299,12 @@ do_auto_deduction (tree type, tree init, tree auto_node) tree decl; int val; + if (processing_template_decl + && (TREE_TYPE (init) == NULL_TREE + || BRACE_ENCLOSED_INITIALIZER_P (init))) + /* Not enough information to try this yet. */ + return type; + /* The name of the object being declared shall not appear in the initializer expression. */ decl = cp_walk_tree_without_duplicates (&init, contains_auto_r, type); @@ -19331,6 +19334,9 @@ do_auto_deduction (tree type, tree init, tree auto_node) DEDUCE_CALL, LOOKUP_NORMAL); if (val > 0) { + if (processing_template_decl) + /* Try again at instantiation time. */ + return type; if (type && type != error_mark_node) /* If type is error_mark_node a diagnostic must have been emitted by now. Also, having a mention to '' diff --git a/gcc/cp/semantics.c b/gcc/cp/semantics.c index 1f683c7..cfe3959 100644 --- a/gcc/cp/semantics.c +++ b/gcc/cp/semantics.c @@ -4803,65 +4803,6 @@ finish_static_assert (tree condition, tree message, location_t location, } } -/* Returns the type of EXPR for cases where we can determine it even though - EXPR is a type-dependent expression. */ - -tree -describable_type (tree expr) -{ - tree type = NULL_TREE; - - if (! type_dependent_expression_p (expr) - && ! type_unknown_p (expr)) - { - type = unlowered_expr_type (expr); - if (real_lvalue_p (expr)) - type = build_reference_type (type); - } - - if (type) - return type; - - switch (TREE_CODE (expr)) - { - case VAR_DECL: - case PARM_DECL: - case RESULT_DECL: - case FUNCTION_DECL: - return TREE_TYPE (expr); - break; - - case NEW_EXPR: - case CONST_DECL: - case TEMPLATE_PARM_INDEX: - case CAST_EXPR: - case STATIC_CAST_EXPR: - case REINTERPRET_CAST_EXPR: - case CONST_CAST_EXPR: - case DYNAMIC_CAST_EXPR: - type = TREE_TYPE (expr); - break; - - case INDIRECT_REF: - { - tree ptrtype = describable_type (TREE_OPERAND (expr, 0)); - if (ptrtype && POINTER_TYPE_P (ptrtype)) - type = build_reference_type (TREE_TYPE (ptrtype)); - } - break; - - default: - if (TREE_CODE_CLASS (TREE_CODE (expr)) == tcc_constant) - type = TREE_TYPE (expr); - break; - } - - if (type && type_uses_auto (type)) - return NULL_TREE; - else - return type; -} - /* Implements the C++0x decltype keyword. Returns the type of EXPR, suitable for use as a type-specifier. diff --git a/gcc/cp/typeck.c b/gcc/cp/typeck.c index 39e974b..7af76b1 100644 --- a/gcc/cp/typeck.c +++ b/gcc/cp/typeck.c @@ -2681,8 +2681,7 @@ build_x_indirect_ref (tree expr, ref_operator errorstring, if (processing_template_decl) { - /* Retain the type if we know the operand is a pointer so that - describable_type doesn't make auto deduction break. */ + /* Retain the type if we know the operand is a pointer. */ if (TREE_TYPE (expr) && POINTER_TYPE_P (TREE_TYPE (expr))) return build_min (INDIRECT_REF, TREE_TYPE (TREE_TYPE (expr)), expr); if (type_dependent_expression_p (expr)) diff --git a/gcc/testsuite/g++.dg/cpp0x/auto26.C b/gcc/testsuite/g++.dg/cpp0x/auto26.C new file mode 100644 index 0000000..6e55aa4 --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp0x/auto26.C @@ -0,0 +1,21 @@ +// PR c++/43321 +// { dg-options -std=c++0x } + +template +void f(T t) +{ + auto *p = t; +} + +template +void g(const T& tr) +{ + auto p = *tr; +} + +int main() +{ + int b; + f(&b); + g(&b); +}