From patchwork Thu Apr 11 19:50:58 2013 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jason Merrill X-Patchwork-Id: 235916 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]) (using TLSv1 with cipher DHE-RSA-AES256-SHA (256/256 bits)) (Client CN "localhost", Issuer "www.qmailtoaster.com" (not verified)) by ozlabs.org (Postfix) with ESMTPS id 743982C009F for ; Fri, 12 Apr 2013 05:51:12 +1000 (EST) DomainKey-Signature: a=rsa-sha1; c=nofws; d=gcc.gnu.org; h=list-id :list-unsubscribe:list-archive:list-post:list-help:sender :message-id:date:from:mime-version:to:subject:content-type; q= dns; s=default; b=Chhcm8DrHA7GTSLNzpPPDzRl7VJ7gWfvIabaV+PbcZuKJt BEUn5lgBctiLNaqxt1cYHZj3FBYorOqzcqUgsgkX5xZJfPJPHK4ipp2a/NQ4n5Ld GAu8hiomgNU4TyWtFY68uhZgketBSDygwp2/dJ5j3F+cGXF/t4z8oOuAkeg6I= 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 :message-id:date:from:mime-version:to:subject:content-type; s= default; bh=ND3RQ3Pyx3Ttn4WSDQp/atPYVOI=; b=HaHw+ueu5PuE3gO0wLUr MlkElKQN23PWy1m7jsqg9F+zp+iuK+/4UXUHzQ6vt6MdHGPwcxJkL2Bl5y/+mrrG WQjMCQKX1YWV1l34b5Ltm5Xg+i8exlVqblR02pztFkTI/gWIWB4TimLnYzs2EoE6 GuMutT0MGo1VbN/fqtFTros= Received: (qmail 10192 invoked by alias); 11 Apr 2013 19:51:04 -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 10182 invoked by uid 89); 11 Apr 2013 19:51:04 -0000 X-Spam-SWARE-Status: No, score=-7.6 required=5.0 tests=AWL, BAYES_00, KHOP_RCVD_UNTRUST, RCVD_IN_DNSWL_HI, RCVD_IN_HOSTKARMA_W, RP_MATCHES_RCVD, SPF_HELO_PASS autolearn=ham version=3.3.1 Received: from mx1.redhat.com (HELO mx1.redhat.com) (209.132.183.28) by sourceware.org (qpsmtpd/0.84/v0.84-167-ge50287c) with ESMTP; Thu, 11 Apr 2013 19:51:03 +0000 Received: from int-mx12.intmail.prod.int.phx2.redhat.com (int-mx12.intmail.prod.int.phx2.redhat.com [10.5.11.25]) by mx1.redhat.com (8.14.4/8.14.4) with ESMTP id r3BJp11U000348 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK) for ; Thu, 11 Apr 2013 15:51:01 -0400 Received: from [10.3.113.66] (ovpn-113-66.phx2.redhat.com [10.3.113.66]) by int-mx12.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with ESMTP id r3BJp0cP022708 for ; Thu, 11 Apr 2013 15:51:00 -0400 Message-ID: <51671422.6030304@redhat.com> Date: Thu, 11 Apr 2013 15:50:58 -0400 From: Jason Merrill User-Agent: Mozilla/5.0 (X11; Linux i686; rv:22.0) Gecko/20100101 Thunderbird/22.0a2 MIME-Version: 1.0 To: gcc-patches List Subject: Another C++ PATCH for c++/52748 (N3276 and operator overloading) X-Virus-Found: No My earlier N3276 work only affected the function call syntax, but it needs to affect implicit function calls from overloaded operators as well. Tested x86_64-pc-linux-gnu, applying to trunk and 4.8. commit c3deee14326a96c9b058fb5433cf98fd64f8d618 Author: Jason Merrill Date: Thu Apr 11 13:46:49 2013 -0400 PR c++/52748 * parser.c (complain_flags): New. (cp_parser_postfix_expression): Use it. (cp_parser_unary_expression): Likewise. (cp_parser_binary_expression): Likewise. (cp_parser_assignment_expression): Likewise. (cp_parser_expression): Likewise. (cp_parser_postfix_open_square_expression): Take decltype_p. (cp_parser_builtin_offsetof): Adjust. (cp_convert_range_for): Pass complain to finish_unary_op_expr. * semantics.c (finish_unary_op_expr): Add complain parm. diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h index e1d1238..f7c65b6 100644 --- a/gcc/cp/cp-tree.h +++ b/gcc/cp/cp-tree.h @@ -5241,7 +5241,7 @@ extern void maybe_make_one_only (tree); extern bool vague_linkage_p (tree); extern void grokclassfn (tree, tree, enum overload_flags); -extern tree grok_array_decl (location_t, tree, tree); +extern tree grok_array_decl (location_t, tree, tree, bool); extern tree delete_sanity (tree, tree, bool, int, tsubst_flags_t); extern tree check_classfn (tree, tree, tree); extern void check_member_template (tree); @@ -5706,7 +5706,8 @@ extern tree finish_call_expr (tree, vec **, bool, extern tree finish_increment_expr (tree, enum tree_code); extern tree finish_this_expr (void); extern tree finish_pseudo_destructor_expr (tree, tree, tree); -extern tree finish_unary_op_expr (location_t, enum tree_code, tree); +extern tree finish_unary_op_expr (location_t, enum tree_code, tree, + tsubst_flags_t); extern tree finish_compound_literal (tree, tree, tsubst_flags_t); extern tree finish_fname (tree); extern void finish_translation_unit (void); diff --git a/gcc/cp/decl2.c b/gcc/cp/decl2.c index 407b461..a5b2655 100644 --- a/gcc/cp/decl2.c +++ b/gcc/cp/decl2.c @@ -335,10 +335,11 @@ grokclassfn (tree ctype, tree function, enum overload_flags flags) } /* Create an ARRAY_REF, checking for the user doing things backwards - along the way. */ + along the way. DECLTYPE_P is for N3276, as in the parser. */ tree -grok_array_decl (location_t loc, tree array_expr, tree index_exp) +grok_array_decl (location_t loc, tree array_expr, tree index_exp, + bool decltype_p) { tree type; tree expr; @@ -364,8 +365,13 @@ grok_array_decl (location_t loc, tree array_expr, tree index_exp) /* If they have an `operator[]', use that. */ if (MAYBE_CLASS_TYPE_P (type) || MAYBE_CLASS_TYPE_P (TREE_TYPE (index_exp))) - expr = build_new_op (loc, ARRAY_REF, LOOKUP_NORMAL, array_expr, index_exp, - NULL_TREE, /*overload=*/NULL, tf_warning_or_error); + { + tsubst_flags_t complain = tf_warning_or_error; + if (decltype_p) + complain |= tf_decltype; + expr = build_new_op (loc, ARRAY_REF, LOOKUP_NORMAL, array_expr, + index_exp, NULL_TREE, /*overload=*/NULL, complain); + } else { tree p1, p2, i1, i2; diff --git a/gcc/cp/parser.c b/gcc/cp/parser.c index e015c4f..6b5020e 100644 --- a/gcc/cp/parser.c +++ b/gcc/cp/parser.c @@ -1852,7 +1852,7 @@ static tree cp_parser_qualifying_entity static tree cp_parser_postfix_expression (cp_parser *, bool, bool, bool, bool, cp_id_kind *); static tree cp_parser_postfix_open_square_expression - (cp_parser *, tree, bool); + (cp_parser *, tree, bool, bool); static tree cp_parser_postfix_dot_deref_expression (cp_parser *, enum cpp_ttype, tree, bool, cp_id_kind *, location_t); static vec *cp_parser_parenthesized_expression_list @@ -3891,6 +3891,18 @@ cp_parser_translation_unit (cp_parser* parser) return success; } +/* Return the appropriate tsubst flags for parsing, possibly in N3276 + decltype context. */ + +static inline tsubst_flags_t +complain_flags (bool decltype_p) +{ + tsubst_flags_t complain = tf_warning_or_error; + if (decltype_p) + complain |= tf_decltype; + return complain; +} + /* Expressions [gram.expr] */ /* Parse a primary-expression. @@ -5726,7 +5738,8 @@ cp_parser_postfix_expression (cp_parser *parser, bool address_p, bool cast_p, postfix_expression = cp_parser_postfix_open_square_expression (parser, postfix_expression, - false); + false, + decltype_p); idk = CP_ID_KIND_NONE; is_member_access = false; break; @@ -5738,12 +5751,9 @@ cp_parser_postfix_expression (cp_parser *parser, bool address_p, bool cast_p, bool is_builtin_constant_p; bool saved_integral_constant_expression_p = false; bool saved_non_integral_constant_expression_p = false; - int complain = tf_warning_or_error; + tsubst_flags_t complain = complain_flags (decltype_p); vec *args; - if (decltype_p) - complain |= tf_decltype; - is_member_access = false; is_builtin_constant_p @@ -5972,7 +5982,8 @@ cp_parser_postfix_expression (cp_parser *parser, bool address_p, bool cast_p, static tree cp_parser_postfix_open_square_expression (cp_parser *parser, tree postfix_expression, - bool for_offsetof) + bool for_offsetof, + bool decltype_p) { tree index; location_t loc = cp_lexer_peek_token (parser->lexer)->location; @@ -6006,7 +6017,8 @@ cp_parser_postfix_open_square_expression (cp_parser *parser, cp_parser_require (parser, CPP_CLOSE_SQUARE, RT_CLOSE_SQUARE); /* Build the ARRAY_REF. */ - postfix_expression = grok_array_decl (loc, postfix_expression, index); + postfix_expression = grok_array_decl (loc, postfix_expression, + index, decltype_p); /* When not doing offsetof, array references are not permitted in constant-expressions. */ @@ -6702,6 +6714,7 @@ cp_parser_unary_expression (cp_parser *parser, bool address_p, bool cast_p, tree expression = error_mark_node; non_integral_constant non_constant_p = NIC_NONE; location_t loc = token->location; + tsubst_flags_t complain = complain_flags (decltype_p); /* Consume the operator token. */ token = cp_lexer_consume_token (parser->lexer); @@ -6719,7 +6732,7 @@ cp_parser_unary_expression (cp_parser *parser, bool address_p, bool cast_p, non_constant_p = NIC_STAR; expression = build_x_indirect_ref (loc, cast_expression, RO_UNARY_STAR, - tf_warning_or_error); + complain); break; case ADDR_EXPR: @@ -6728,7 +6741,7 @@ cp_parser_unary_expression (cp_parser *parser, bool address_p, bool cast_p, case BIT_NOT_EXPR: expression = build_x_unary_op (loc, unary_operator, cast_expression, - tf_warning_or_error); + complain); break; case PREINCREMENT_EXPR: @@ -6740,7 +6753,7 @@ cp_parser_unary_expression (cp_parser *parser, bool address_p, bool cast_p, case NEGATE_EXPR: case TRUTH_NOT_EXPR: expression = finish_unary_op_expr (loc, unary_operator, - cast_expression); + cast_expression, complain); break; default: @@ -7567,7 +7580,7 @@ cp_parser_binary_expression (cp_parser* parser, bool cast_p, current.lhs = build_x_binary_op (current.loc, current.tree_type, current.lhs, current.lhs_type, rhs, rhs_type, &overload, - tf_warning_or_error); + complain_flags (decltype_p)); current.lhs_type = current.tree_type; if (EXPR_P (current.lhs)) SET_EXPR_LOCATION (current.lhs, current.loc); @@ -7722,7 +7735,7 @@ cp_parser_assignment_expression (cp_parser* parser, bool cast_p, expr = build_x_modify_expr (loc, expr, assignment_operator, rhs, - tf_warning_or_error); + complain_flags (decltype_p)); input_location = saved_input_location; } } @@ -7868,7 +7881,7 @@ cp_parser_expression (cp_parser* parser, bool cast_p, bool decltype_p, else expression = build_x_compound_expr (loc, expression, assignment_expression, - tf_warning_or_error); + complain_flags (decltype_p)); /* If the next token is not a comma, then we are done with the expression. */ if (cp_lexer_next_token_is_not (parser->lexer, CPP_COMMA)) @@ -8019,12 +8032,14 @@ cp_parser_builtin_offsetof (cp_parser *parser) { case CPP_OPEN_SQUARE: /* offsetof-member-designator "[" expression "]" */ - expr = cp_parser_postfix_open_square_expression (parser, expr, true); + expr = cp_parser_postfix_open_square_expression (parser, expr, + true, false); break; case CPP_DEREF: /* offsetof-member-designator "->" identifier */ - expr = grok_array_decl (token->location, expr, integer_zero_node); + expr = grok_array_decl (token->location, expr, + integer_zero_node, false); /* FALLTHRU */ case CPP_DOT: @@ -9766,7 +9781,8 @@ cp_convert_range_for (tree statement, tree range_decl, tree range_expr) /* The new increment expression. */ expression = finish_unary_op_expr (input_location, - PREINCREMENT_EXPR, begin); + PREINCREMENT_EXPR, begin, + tf_warning_or_error); finish_for_expr (expression, statement); /* The declaration is initialized with *__begin inside the loop body. */ diff --git a/gcc/cp/semantics.c b/gcc/cp/semantics.c index 0631833..a09a7f4 100644 --- a/gcc/cp/semantics.c +++ b/gcc/cp/semantics.c @@ -2408,10 +2408,12 @@ finish_pseudo_destructor_expr (tree object, tree scope, tree destructor) /* Finish an expression of the form CODE EXPR. */ tree -finish_unary_op_expr (location_t loc, enum tree_code code, tree expr) +finish_unary_op_expr (location_t loc, enum tree_code code, tree expr, + tsubst_flags_t complain) { - tree result = build_x_unary_op (loc, code, expr, tf_warning_or_error); - if (TREE_OVERFLOW_P (result) && !TREE_OVERFLOW_P (expr)) + tree result = build_x_unary_op (loc, code, expr, complain); + if ((complain & tf_warning) + && TREE_OVERFLOW_P (result) && !TREE_OVERFLOW_P (expr)) overflow_warning (input_location, result); return result; diff --git a/gcc/testsuite/g++.dg/cpp0x/decltype-call3.C b/gcc/testsuite/g++.dg/cpp0x/decltype-call3.C new file mode 100644 index 0000000..1d12b01 --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp0x/decltype-call3.C @@ -0,0 +1,86 @@ +// Testcase for N3276 and operator overloading +// { dg-require-effective-target c++11 } + +struct A; +struct B { + A operator()(int); + A operator[](int); + A operator=(int); + A operator+=(int); + A operator-=(int); + A operator*=(int); + A operator/=(int); + A operator^=(int); + A operator&=(int); + A operator|=(int); + A operator<<=(int); + A operator>>=(int); +}; + +A operator-(B); +A operator+(B); +A operator*(B); +A operator&(B); +A operator!(B); +A operator~(B); +A operator++(B); +A operator--(B); + +A operator+(B,B); +A operator-(B,B); +A operator*(B,B); +A operator/(B,B); +A operator%(B,B); +A operator^(B,B); +A operator&(B,B); +A operator|(B,B); +A operator<(B,B); +A operator>(B,B); +A operator,(B,B); +A operator<<(B,B); +A operator>>(B,B); +A operator==(B,B); +A operator->*(B,B); + +#define TRY(E) static_cast(0) +int main() +{ + B b; + TRY(b(0)); + TRY(b[0]); + TRY(b=0); + TRY(b+=0); + TRY(b-=0); + TRY(b*=0); + TRY(b/=0); + TRY(b^=0); + TRY(b&=0); + TRY(b|=0); + TRY(b<<=0); + TRY(b>>=0); + + TRY(-b); + TRY(+b); + TRY(*b); + TRY(&b); + TRY(!b); + TRY(~b); + TRY(++b); + TRY(--b); + + TRY(b+b); + TRY(b-b); + TRY(b*b); + TRY(b/b); + TRY(b%b); + TRY(b^b); + TRY(b&b); + TRY(b|b); + TRY(b>b); + TRY(b>b); + TRY(b==b); + TRY(b->*b); +}