From patchwork Thu Mar 1 14:26:30 2012 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Paolo Carlini X-Patchwork-Id: 144028 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 710231007D2 for ; Fri, 2 Mar 2012 01:29:31 +1100 (EST) Comment: DKIM? See http://www.dkim.org DKIM-Signature: v=1; a=rsa-sha1; c=relaxed/relaxed; d=gcc.gnu.org; s=default; x=1331216972; h=Comment: DomainKey-Signature:Received:Received:Received:Received:Received: Received:Received:Message-ID:Date:From:User-Agent:MIME-Version: To:CC:Subject:References:In-Reply-To:Content-Type:Mailing-List: Precedence:List-Id:List-Unsubscribe:List-Archive:List-Post: List-Help:Sender:Delivered-To; bh=ZEa3wKiyKq5VgSFa8o1ZP5A37tQ=; b=fORXDnzBJIP2FWXKZ4UE1Q/c6j36RmA4K6eUJYDDwA0/7ygYRoOs7ngdha9A0m +3qU49ydrDh2JAqvo3w/9eRPXXD3g/lisaFK0s0d0D6hqJV8Ae8pzhKqFdU1oJZg IkTEs6c99wpF6bl+TFcndcIIaVfgzmPVsaRyeJzepuwW8= Comment: DomainKeys? See http://antispam.yahoo.com/domainkeys DomainKey-Signature: a=rsa-sha1; q=dns; c=nofws; s=default; d=gcc.gnu.org; h=Received:Received:X-SWARE-Spam-Status:X-Spam-Check-By:Received:Received:Received:Received:Received:Message-ID:Date:From:User-Agent:MIME-Version:To:CC:Subject:References:In-Reply-To:Content-Type:X-IsSubscribed:Mailing-List:Precedence:List-Id:List-Unsubscribe:List-Archive:List-Post:List-Help:Sender:Delivered-To; b=rX3rfNeKHz0zE8L4ANGW2+3aU7Sl/V45V2Y2YDEqQ7ethFf2mdxCTpd4D6/ppX Tj/rm98OQIQXWPTg/9IXJt9cAy7we6VS0PFfHH2YOe33CETHxD15ZWPBXY/t9iZb x8wkd1kKzF6Vt1ocHT5PoCh11qFb9zNDMdMTOk30ZgGfI=; Received: (qmail 11895 invoked by alias); 1 Mar 2012 14:29:27 -0000 Received: (qmail 11880 invoked by uid 22791); 1 Mar 2012 14:29:23 -0000 X-SWARE-Spam-Status: No, hits=-5.8 required=5.0 tests=AWL, BAYES_00, RCVD_IN_DNSWL_HI, TW_BJ, TW_CX, TW_EG, TW_FN, TW_PM, TW_TM, TW_VT, T_RP_MATCHES_RCVD X-Spam-Check-By: sourceware.org Received: from acsinet15.oracle.com (HELO acsinet15.oracle.com) (141.146.126.227) by sourceware.org (qpsmtpd/0.43rc1) with ESMTP; Thu, 01 Mar 2012 14:28:57 +0000 Received: from acsinet21.oracle.com (acsinet21.oracle.com [141.146.126.237]) by acsinet15.oracle.com (Sentrion-MTA-4.2.2/Sentrion-MTA-4.2.2) with ESMTP id q21EStLA004901 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK); Thu, 1 Mar 2012 14:28:55 GMT Received: from acsmt356.oracle.com (acsmt356.oracle.com [141.146.40.156]) by acsinet21.oracle.com (8.14.4+Sun/8.14.4) with ESMTP id q21ESs6u027944 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=NO); Thu, 1 Mar 2012 14:28:54 GMT Received: from abhmt102.oracle.com (abhmt102.oracle.com [141.146.116.54]) by acsmt356.oracle.com (8.12.11.20060308/8.12.11) with ESMTP id q21ESsQi027351; Thu, 1 Mar 2012 08:28:54 -0600 Received: from [192.168.1.4] (/79.53.13.80) by default (Oracle Beehive Gateway v4.0) with ESMTP ; Thu, 01 Mar 2012 06:28:53 -0800 Message-ID: <4F4F8716.3090401@oracle.com> Date: Thu, 01 Mar 2012 15:26:30 +0100 From: Paolo Carlini User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:10.0.2) Gecko/20120215 Thunderbird/10.0.2 MIME-Version: 1.0 To: Jason Merrill CC: "gcc-patches@gcc.gnu.org" Subject: Re: [4.8, C++ Patch] PR 52422 References: <4F4E11D5.8030408@oracle.com> <4F4ED2FD.7070207@redhat.com> In-Reply-To: <4F4ED2FD.7070207@redhat.com> X-IsSubscribed: yes 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 Hi, > On 02/29/2012 06:53 AM, Paolo Carlini wrote: >> Daniel noticed a couple other SFINAE issues, which I'm fixing in the >> usual straightforward way. Tested x86_64-linux. > > When fixing these things, please add checking for error_mark_node > return as well. For instance, in this patch the calls to > decay_conversion from build_conditional_expr_1 could return > error_mark_node, in which case we want to return out of > build_conditional_expr_1 as well. Similarly with the call in > convert_like_real, and so on. I see. Thus I added many of those checks, essentially all I could see besides some special cases like we call decay_conversion with an explicit tf_warning_or_error (thus we have the status quo behavior anyway) or when there are already checks, just a few lines below. In the feature I'll keep an eye to that. Does the below look better? (booted and tested x86_64-linux) >> PS: while working on the patch, I noticed that a few functions, which in >> the meanwhile acquired a tsubst_flags_t parameter, aren't fully >> propagating it, are still passing tf_warning_or_error. Apparently a >> clean-up is in order. > Please. :) Ok, will do (and in case more error_mark_node checks too, of course) Thanks, Paolo. ////////////////////// Index: testsuite/g++.dg/cpp0x/sfinae33.C =================================================================== --- testsuite/g++.dg/cpp0x/sfinae33.C (revision 0) +++ testsuite/g++.dg/cpp0x/sfinae33.C (revision 0) @@ -0,0 +1,27 @@ +// PR c++/52422 +// { dg-options -std=c++0x } + +template +struct add_rval_ref +{ + typedef T&& type; +}; + +template<> +struct add_rval_ref +{ + typedef void type; +}; + +template +typename add_rval_ref::type create(); + +template()()) +> +auto f(int) -> char(&)[1]; + +template +auto f(...) -> char(&)[2]; + +static_assert(sizeof(f(0)) != 1, ""); Index: testsuite/g++.dg/cpp0x/sfinae34.C =================================================================== --- testsuite/g++.dg/cpp0x/sfinae34.C (revision 0) +++ testsuite/g++.dg/cpp0x/sfinae34.C (revision 0) @@ -0,0 +1,28 @@ +// PR c++/52422 +// { dg-options -std=c++0x } + +template +struct add_rval_ref +{ + typedef T&& type; +}; + +template<> +struct add_rval_ref +{ + typedef void type; +}; + +template +typename add_rval_ref::type create(); + +template().*create())() ) +> +auto f(int) -> char(&)[1]; + +template +auto f(...) -> char(&)[2]; + +static_assert(sizeof(f(0)) != 1, ""); + Index: cp/typeck.c =================================================================== --- cp/typeck.c (revision 184739) +++ cp/typeck.c (working copy) @@ -1813,7 +1813,7 @@ unlowered_expr_type (const_tree exp) that the return value is no longer an lvalue. */ tree -decay_conversion (tree exp) +decay_conversion (tree exp, tsubst_flags_t complain) { tree type; enum tree_code code; @@ -1827,7 +1827,8 @@ tree exp = resolve_nondeduced_context (exp); if (type_unknown_p (exp)) { - cxx_incomplete_type_error (exp, TREE_TYPE (exp)); + if (complain & tf_error) + cxx_incomplete_type_error (exp, TREE_TYPE (exp)); return error_mark_node; } @@ -1846,13 +1847,14 @@ tree code = TREE_CODE (type); if (code == VOID_TYPE) { - error ("void value not ignored as it ought to be"); + if (complain & tf_error) + error ("void value not ignored as it ought to be"); return error_mark_node; } - if (invalid_nonstatic_memfn_p (exp, tf_warning_or_error)) + if (invalid_nonstatic_memfn_p (exp, complain)) return error_mark_node; if (code == FUNCTION_TYPE || is_overloaded_fn (exp)) - return cp_build_addr_expr (exp, tf_warning_or_error); + return cp_build_addr_expr (exp, complain); if (code == ARRAY_TYPE) { tree adr; @@ -1864,7 +1866,9 @@ tree if (TREE_CODE (exp) == COMPOUND_EXPR) { - tree op1 = decay_conversion (TREE_OPERAND (exp, 1)); + tree op1 = decay_conversion (TREE_OPERAND (exp, 1), complain); + if (op1 == error_mark_node) + return error_mark_node; return build2 (COMPOUND_EXPR, TREE_TYPE (op1), TREE_OPERAND (exp, 0), op1); } @@ -1872,7 +1876,8 @@ tree if (!lvalue_p (exp) && ! (TREE_CODE (exp) == CONSTRUCTOR && TREE_STATIC (exp))) { - error ("invalid use of non-lvalue array"); + if (complain & tf_error) + error ("invalid use of non-lvalue array"); return error_mark_node; } @@ -1887,7 +1892,7 @@ tree } /* This way is better for a COMPONENT_REF since it can simplify the offset for a component. */ - adr = cp_build_addr_expr (exp, tf_warning_or_error); + adr = cp_build_addr_expr (exp, complain); return cp_convert (ptrtype, adr); } @@ -1939,7 +1944,7 @@ default_conversion (tree exp) else if (INTEGRAL_OR_UNSCOPED_ENUMERATION_TYPE_P (TREE_TYPE (exp))) exp = perform_integral_promotions (exp); /* Perform the other conversions. */ - exp = decay_conversion (exp); + exp = decay_conversion (exp, tf_warning_or_error); return exp; } @@ -2754,8 +2759,15 @@ cp_build_indirect_ref (tree ptr, ref_operator erro if (ptr == current_class_ptr) return current_class_ref; - pointer = (TREE_CODE (TREE_TYPE (ptr)) == REFERENCE_TYPE - ? ptr : decay_conversion (ptr)); + if (TREE_CODE (TREE_TYPE (ptr)) == REFERENCE_TYPE) + pointer = ptr; + else + { + pointer = decay_conversion (ptr, complain); + if (pointer == error_mark_node) + return error_mark_node; + } + type = TREE_TYPE (pointer); if (POINTER_TYPE_P (type)) @@ -3049,7 +3061,8 @@ get_member_function_from_ptrfunc (tree *instance_p /* Extracting the function address from a pmf is only allowed with -Wno-pmf-conversions. It only works for pmf constants. */ - e1 = build_addr_func (PTRMEM_CST_MEMBER (function)); + e1 = build_addr_func (PTRMEM_CST_MEMBER (function), + tf_warning_or_error); e1 = convert (fntype, e1); return e1; } @@ -3251,13 +3264,13 @@ cp_build_function_call_vec (tree function, VEC(tre pedwarn (input_location, OPT_pedantic, "ISO C++ forbids calling %<::main%> from within program"); - function = build_addr_func (function); + function = build_addr_func (function, complain); } else { fndecl = NULL_TREE; - function = build_addr_func (function); + function = build_addr_func (function, complain); } if (function == error_mark_node) @@ -3422,7 +3435,7 @@ convert_arguments (tree typelist, VEC(tree,gc) **v if (TREE_CODE (TREE_TYPE (val)) == ARRAY_TYPE || TREE_CODE (TREE_TYPE (val)) == FUNCTION_TYPE || TREE_CODE (TREE_TYPE (val)) == METHOD_TYPE) - val = decay_conversion (val); + val = decay_conversion (val, complain); } if (val == error_mark_node) @@ -3549,7 +3562,7 @@ build_x_binary_op (enum tree_code code, tree arg1, } if (code == DOTSTAR_EXPR) - expr = build_m_component_ref (arg1, arg2); + expr = build_m_component_ref (arg1, arg2, complain); else expr = build_new_op (code, LOOKUP_NORMAL, arg1, arg2, NULL_TREE, overload, complain); @@ -3713,9 +3726,9 @@ cp_build_binary_op (location_t location, || code == TRUTH_XOR_EXPR) { if (!really_overloaded_fn (op0) && !VOID_TYPE_P (TREE_TYPE (op0))) - op0 = decay_conversion (op0); + op0 = decay_conversion (op0, complain); if (!really_overloaded_fn (op1) && !VOID_TYPE_P (TREE_TYPE (op1))) - op1 = decay_conversion (op1); + op1 = decay_conversion (op1, complain); } else { @@ -6107,7 +6120,7 @@ convert_member_func_to_ptr (tree type, tree expr) "converting from %qT to %qT", intype, type); if (TREE_CODE (intype) == METHOD_TYPE) - expr = build_addr_func (expr); + expr = build_addr_func (expr, tf_warning_or_error); else if (TREE_CODE (expr) == PTRMEM_CST) expr = build_address (PTRMEM_CST_MEMBER (expr)); else @@ -6199,7 +6212,7 @@ build_reinterpret_cast_1 (tree type, tree expr, bo /* If the cast is not to a reference type, the lvalue-to-rvalue, array-to-pointer, and function-to-pointer conversions are performed. */ - expr = decay_conversion (expr); + expr = decay_conversion (expr, complain); /* build_c_cast puts on a NOP_EXPR to make the result not an lvalue. Strip such NOP_EXPRs if VALUE is being used in non-lvalue context. */ @@ -6438,7 +6451,10 @@ build_const_cast_1 (tree dst_type, tree expr, tsub } else { - expr = decay_conversion (expr); + expr = decay_conversion (expr, complain); + if (expr == error_mark_node) + return error_mark_node; + /* build_c_cast puts on a NOP_EXPR to make the result not an lvalue. Strip such NOP_EXPRs if VALUE is being used in non-lvalue context. */ @@ -7282,7 +7298,8 @@ expand_ptrmemfunc_cst (tree cst, tree *delta, tree /*c_cast_p=*/0, tf_warning_or_error); if (!DECL_VIRTUAL_P (fn)) - *pfn = convert (TYPE_PTRMEMFUNC_FN_TYPE (type), build_addr_func (fn)); + *pfn = convert (TYPE_PTRMEMFUNC_FN_TYPE (type), + build_addr_func (fn, tf_warning_or_error)); else { /* If we're dealing with a virtual function, we have to adjust 'this' @@ -7616,7 +7633,7 @@ convert_for_initialization (tree exp, tree type, t && (TREE_CODE (type) != REFERENCE_TYPE || TREE_CODE (TREE_TYPE (type)) != FUNCTION_TYPE)) || TREE_CODE (TREE_TYPE (rhs)) == METHOD_TYPE) - rhs = decay_conversion (rhs); + rhs = decay_conversion (rhs, complain); rhstype = TREE_TYPE (rhs); coder = TREE_CODE (rhstype); Index: cp/init.c =================================================================== --- cp/init.c (revision 184739) +++ cp/init.c (working copy) @@ -1,7 +1,7 @@ /* Handle initialization things in C++. Copyright (C) 1987, 1989, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, - 2011 Free Software Foundation, Inc. + 2011, 2012 Free Software Foundation, Inc. Contributed by Michael Tiemann (tiemann@cygnus.com) This file is part of GCC. @@ -3186,7 +3186,10 @@ build_vec_init (tree base, tree maxindex, tree ini if (TREE_CODE (atype) == ARRAY_TYPE) { ptype = build_pointer_type (type); - base = cp_convert (ptype, decay_conversion (base)); + base = decay_conversion (base, complain); + if (base == error_mark_node) + return error_mark_node; + base = cp_convert (ptype, base); } else ptype = atype; @@ -3235,7 +3238,9 @@ build_vec_init (tree base, tree maxindex, tree ini { if (lvalue_kind (init) & clk_rvalueref) xvalue = true; - base2 = decay_conversion (init); + base2 = decay_conversion (init, complain); + if (base2 == error_mark_node) + return error_mark_node; itype = TREE_TYPE (base2); base2 = get_temp_regvar (itype, base2); itype = TREE_TYPE (itype); Index: cp/decl.c =================================================================== --- cp/decl.c (revision 184739) +++ cp/decl.c (working copy) @@ -4650,7 +4650,7 @@ grok_reference_init (tree decl, tree type, tree in if (TREE_CODE (TREE_TYPE (type)) != ARRAY_TYPE && TREE_CODE (TREE_TYPE (init)) == ARRAY_TYPE) /* Note: default conversion is only called in very special cases. */ - init = decay_conversion (init); + init = decay_conversion (init, tf_warning_or_error); /* Convert INIT to the reference type TYPE. This may involve the creation of a temporary, whose lifetime must be the same as that @@ -6513,7 +6513,7 @@ get_atexit_node (void) atexit_fndecl = build_library_fn_ptr (name, fn_type); mark_used (atexit_fndecl); pop_lang_context (); - atexit_node = decay_conversion (atexit_fndecl); + atexit_node = decay_conversion (atexit_fndecl, tf_warning_or_error); return atexit_node; } Index: cp/rtti.c =================================================================== --- cp/rtti.c (revision 184739) +++ cp/rtti.c (working copy) @@ -1,6 +1,6 @@ /* RunTime Type Identification Copyright (C) 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, - 2005, 2006, 2007, 2008, 2009, 2010, 2011 + 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012 Free Software Foundation, Inc. Mostly written by Jason Merrill (jason@cygnus.com). @@ -551,7 +551,7 @@ build_dynamic_cast_1 (tree type, tree expr, tsubst if (tc == POINTER_TYPE) { - expr = decay_conversion (expr); + expr = decay_conversion (expr, complain); exprtype = TREE_TYPE (expr); /* If T is a pointer type, v shall be an rvalue of a pointer to @@ -931,7 +931,8 @@ tinfo_base_init (tinfo_s *ti, tree target) v = VEC_alloc (constructor_elt, gc, 2); CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, vtable_ptr); - CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, decay_conversion (name_decl)); + CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, + decay_conversion (name_decl, tf_warning_or_error)); init = build_constructor (init_list_type_node, v); TREE_CONSTANT (init) = 1; Index: cp/except.c =================================================================== --- cp/except.c (revision 184739) +++ cp/except.c (working copy) @@ -1,6 +1,6 @@ /* Handle exceptional things in C++. Copyright (C) 1989, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, - 2000, 2001, 2002, 2003, 2004, 2005, 2007, 2008, 2009, 2010 + 2000, 2001, 2002, 2003, 2004, 2005, 2007, 2008, 2009, 2010, 2012 Free Software Foundation, Inc. Contributed by Michael Tiemann Rewritten by Mike Stump , based upon an @@ -850,7 +850,7 @@ build_throw (tree exp) } else { - tmp = decay_conversion (exp); + tmp = decay_conversion (exp, tf_warning_or_error); if (tmp == error_mark_node) return error_mark_node; exp = build2 (INIT_EXPR, temp_type, object, tmp); Index: cp/typeck2.c =================================================================== --- cp/typeck2.c (revision 184739) +++ cp/typeck2.c (working copy) @@ -1,7 +1,8 @@ /* Report error messages, build initializers, and perform some front-end optimizations for C++ compiler. Copyright (C) 1987, 1988, 1989, 1992, 1993, 1994, 1995, 1996, 1997, 1998, - 1999, 2000, 2001, 2002, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011 + 1999, 2000, 2001, 2002, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011, + 2012 Free Software Foundation, Inc. Hacked by Michael Tiemann (tiemann@cygnus.com) @@ -1518,7 +1519,7 @@ build_x_arrow (tree expr) last_rval = convert_from_reference (last_rval); } else - last_rval = decay_conversion (expr); + last_rval = decay_conversion (expr, tf_warning_or_error); if (TREE_CODE (TREE_TYPE (last_rval)) == POINTER_TYPE) { @@ -1544,7 +1545,7 @@ build_x_arrow (tree expr) already been checked out to be of aggregate type. */ tree -build_m_component_ref (tree datum, tree component) +build_m_component_ref (tree datum, tree component, tsubst_flags_t complain) { tree ptrmem_type; tree objtype; @@ -1561,18 +1562,18 @@ tree ptrmem_type = TREE_TYPE (component); if (!TYPE_PTR_TO_MEMBER_P (ptrmem_type)) { - error ("%qE cannot be used as a member pointer, since it is of " - "type %qT", - component, ptrmem_type); + if (complain & tf_error) + error ("%qE cannot be used as a member pointer, since it is of " + "type %qT", component, ptrmem_type); return error_mark_node; } objtype = TYPE_MAIN_VARIANT (TREE_TYPE (datum)); if (! MAYBE_CLASS_TYPE_P (objtype)) { - error ("cannot apply member pointer %qE to %qE, which is of " - "non-class type %qT", - component, datum, objtype); + if (complain & tf_error) + error ("cannot apply member pointer %qE to %qE, which is of " + "non-class type %qT", component, datum, objtype); return error_mark_node; } @@ -1592,9 +1593,9 @@ tree if (!binfo) { mismatch: - error ("pointer to member type %qT incompatible with object " - "type %qT", - type, objtype); + if (complain & tf_error) + error ("pointer to member type %qT incompatible with object " + "type %qT", type, objtype); return error_mark_node; } else if (binfo == error_mark_node) @@ -1618,14 +1619,13 @@ tree /* Convert object to the correct base. */ if (binfo) - datum = build_base_path (PLUS_EXPR, datum, binfo, 1, - tf_warning_or_error); + datum = build_base_path (PLUS_EXPR, datum, binfo, 1, complain); /* Build an expression for "object + offset" where offset is the value stored in the pointer-to-data-member. */ ptype = build_pointer_type (type); datum = fold_build_pointer_plus (fold_convert (ptype, datum), component); - datum = cp_build_indirect_ref (datum, RO_NULL, tf_warning_or_error); + datum = cp_build_indirect_ref (datum, RO_NULL, complain); /* If the object expression was an rvalue, return an rvalue. */ if (!is_lval) datum = move (datum); Index: cp/pt.c =================================================================== --- cp/pt.c (revision 184739) +++ cp/pt.c (working copy) @@ -5688,7 +5688,7 @@ convert_nontype_argument (tree type, tree expr, ts value_dependent_expression_p. */ if (TYPE_PTROBV_P (type) && TREE_CODE (TREE_TYPE (expr)) == ARRAY_TYPE) - expr = decay_conversion (expr); + expr = decay_conversion (expr, complain); /* If we are in a template, EXPR may be non-dependent, but still have a syntactic, rather than semantic, form. For example, EXPR @@ -5896,7 +5896,7 @@ convert_nontype_argument (tree type, tree expr, ts } } - expr = decay_conversion (expr); + expr = decay_conversion (expr, complain); if (expr == error_mark_node) return error_mark_node; @@ -5981,7 +5981,7 @@ convert_nontype_argument (tree type, tree expr, ts context information to decay the pointer. */ if (!type_unknown_p (expr_type)) { - expr = decay_conversion (expr); + expr = decay_conversion (expr, complain); if (expr == error_mark_node) return error_mark_node; } Index: cp/semantics.c =================================================================== --- cp/semantics.c (revision 184739) +++ cp/semantics.c (working copy) @@ -1382,7 +1382,7 @@ finish_asm_stmt (int volatile_p, tree string, tree for (i = 0, t = input_operands; t; ++i, t = TREE_CHAIN (t)) { constraint = TREE_STRING_POINTER (TREE_VALUE (TREE_PURPOSE (t))); - operand = decay_conversion (TREE_VALUE (t)); + operand = decay_conversion (TREE_VALUE (t), tf_warning_or_error); /* If the type of the operand hasn't been determined (e.g., because it involves an overloaded function), then issue @@ -9356,7 +9356,7 @@ maybe_add_lambda_conv_op (tree type) body = begin_function_body (); compound_stmt = begin_compound_stmt (0); - finish_return_stmt (decay_conversion (statfn)); + finish_return_stmt (decay_conversion (statfn, tf_warning_or_error)); finish_compound_stmt (compound_stmt); finish_function_body (body); Index: cp/call.c =================================================================== --- cp/call.c (revision 184739) +++ cp/call.c (working copy) @@ -263,7 +263,7 @@ check_dtor_name (tree basetype, tree name) pointer-to-member function. */ tree -build_addr_func (tree function) +build_addr_func (tree function, tsubst_flags_t complain) { tree type = TREE_TYPE (function); @@ -280,7 +280,7 @@ tree function = build_address (function); } else - function = decay_conversion (function); + function = decay_conversion (function, complain); return function; } @@ -341,7 +341,7 @@ build_call_a (tree function, int n, tree *argarray tree fntype; int i; - function = build_addr_func (function); + function = build_addr_func (function, tf_warning_or_error); gcc_assert (TYPE_PTR_P (TREE_TYPE (function))); fntype = TREE_TYPE (TREE_TYPE (function)); @@ -4342,9 +4342,19 @@ build_conditional_expr_1 (tree arg1, tree arg2, tr since it can't have any effect and since decay_conversion does not handle that case gracefully. */ if (!VOID_TYPE_P (arg2_type)) - arg2 = decay_conversion (arg2); + { + arg2 = decay_conversion (arg2, complain); + if (arg2 == error_mark_node) + return error_mark_node; + } + if (!VOID_TYPE_P (arg3_type)) - arg3 = decay_conversion (arg3); + { + arg3 = decay_conversion (arg3, complain); + if (arg3 == error_mark_node) + return error_mark_node; + } + arg2_type = TREE_TYPE (arg2); arg3_type = TREE_TYPE (arg3); @@ -5232,7 +5242,7 @@ build_new_op_1 (enum tree_code code, int flags, tr case MEMBER_REF: return build_m_component_ref (cp_build_indirect_ref (arg1, RO_NULL, complain), - arg2); + arg2, complain); /* The caller will deal with these. */ case ADDR_EXPR: @@ -5776,7 +5786,7 @@ convert_like_real (conversion *convs, tree expr, t /* Build up the initializer_list object. */ totype = complete_type (totype); field = next_initializable_field (TYPE_FIELDS (totype)); - CONSTRUCTOR_APPEND_ELT (vec, field, decay_conversion (array)); + CONSTRUCTOR_APPEND_ELT (vec, field, decay_conversion (array, complain)); field = next_initializable_field (DECL_CHAIN (field)); CONSTRUCTOR_APPEND_ELT (vec, field, size_int (len)); new_ctor = build_constructor (totype, vec); @@ -5812,7 +5822,10 @@ convert_like_real (conversion *convs, tree expr, t switch (convs->kind) { case ck_rvalue: - expr = decay_conversion (expr); + expr = decay_conversion (expr, complain); + if (expr == error_mark_node) + return error_mark_node; + if (! MAYBE_CLASS_TYPE_P (totype)) return expr; /* Else fall through. */ @@ -5938,7 +5951,7 @@ convert_like_real (conversion *convs, tree expr, t } case ck_lvalue: - return decay_conversion (expr); + return decay_conversion (expr, complain); case ck_qual: /* Warn about deprecated conversion if appropriate. */ @@ -5982,7 +5995,10 @@ convert_arg_to_ellipsis (tree arg) The lvalue-to-rvalue, array-to-pointer, and function-to-pointer standard conversions are performed. */ - arg = decay_conversion (arg); + arg = decay_conversion (arg, tf_warning_or_error); + if (arg == error_mark_node) + return error_mark_node; + arg_type = TREE_TYPE (arg); /* [expr.call] @@ -6331,9 +6347,9 @@ build_over_call (struct z_candidate *cand, int fla alcarray[ix + 1] = arg; argarray = alcarray; } - expr = build_call_array_loc (input_location, - return_type, build_addr_func (fn), nargs, - argarray); + expr = build_call_array_loc (input_location, return_type, + build_addr_func (fn, complain), + nargs, argarray); if (TREE_THIS_VOLATILE (fn) && cfun) current_function_returns_abnormally = 1; return convert_from_reference (expr); @@ -6750,7 +6766,7 @@ build_over_call (struct z_candidate *cand, int fla TREE_TYPE (fn) = t; } else - fn = build_addr_func (fn); + fn = build_addr_func (fn, complain); return build_cxx_call (fn, nargs, argarray); } @@ -6971,7 +6987,9 @@ build_special_member_call (tree instance, tree nam or destructor, then we fetch the VTT directly. Otherwise, we look it up using the VTT we were given. */ vtt = DECL_CHAIN (CLASSTYPE_VTABLES (current_class_type)); - vtt = decay_conversion (vtt); + vtt = decay_conversion (vtt, complain); + if (vtt == error_mark_node) + return error_mark_node; vtt = build3 (COND_EXPR, TREE_TYPE (vtt), build2 (EQ_EXPR, boolean_type_node, current_in_charge_parm, integer_zero_node), Index: cp/cvt.c =================================================================== --- cp/cvt.c (revision 184739) +++ cp/cvt.c (working copy) @@ -1,7 +1,7 @@ /* Language-level data type conversion for GNU C++. Copyright (C) 1987, 1988, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, - 2011 Free Software Foundation, Inc. + 2011, 2012 Free Software Foundation, Inc. Hacked by Michael Tiemann (tiemann@cygnus.com) This file is part of GCC. @@ -550,7 +550,7 @@ force_rvalue (tree expr, tsubst_flags_t complain) expr = build_cplus_new (type, expr, complain); } else - expr = decay_conversion (expr); + expr = decay_conversion (expr, complain); return expr; } @@ -1495,7 +1495,8 @@ build_expr_type_conversion (int desires, tree expr case FUNCTION_TYPE: case ARRAY_TYPE: - return (desires & WANT_POINTER) ? decay_conversion (expr) + return (desires & WANT_POINTER) ? decay_conversion (expr, + tf_warning_or_error) : NULL_TREE; case COMPLEX_TYPE: Index: cp/cp-tree.h =================================================================== --- cp/cp-tree.h (revision 184739) +++ cp/cp-tree.h (working copy) @@ -4845,7 +4845,7 @@ extern bool check_dtor_name (tree, tree); extern tree build_conditional_expr (tree, tree, tree, tsubst_flags_t); -extern tree build_addr_func (tree); +extern tree build_addr_func (tree, tsubst_flags_t); extern void set_flags_from_callee (tree); extern tree build_call_a (tree, int, tree*); extern tree build_call_n (tree, int, ...); @@ -5769,7 +5769,7 @@ extern tree cxx_sizeof_or_alignof_type (tree, enu extern tree cxx_sizeof_nowarn (tree); extern tree is_bitfield_expr_with_lowered_type (const_tree); extern tree unlowered_expr_type (const_tree); -extern tree decay_conversion (tree); +extern tree decay_conversion (tree, tsubst_flags_t); extern tree build_class_member_access_expr (tree, tree, tree, bool, tsubst_flags_t); extern tree finish_class_member_access_expr (tree, tree, bool, @@ -5881,7 +5881,7 @@ extern tree digest_init (tree, tree, tsubst_fla extern tree digest_init_flags (tree, tree, int); extern tree build_scoped_ref (tree, tree, tree *); extern tree build_x_arrow (tree); -extern tree build_m_component_ref (tree, tree); +extern tree build_m_component_ref (tree, tree, tsubst_flags_t); extern tree build_functional_cast (tree, tree, tsubst_flags_t); extern tree add_exception_specifier (tree, tree, int); extern tree merge_exception_specifiers (tree, tree, tree);