* Another C++ PATCH for c++/52748 (N3276 and operator overloading)
@ 2013-04-11 21:38 Jason Merrill
2013-04-15 19:34 ` Jason Merrill
0 siblings, 1 reply; 2+ messages in thread
From: Jason Merrill @ 2013-04-11 21:38 UTC (permalink / raw)
To: gcc-patches List
[-- Attachment #1: Type: text/plain, Size: 201 bytes --]
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.
[-- Attachment #2: 52748.patch --]
[-- Type: text/x-patch, Size: 11753 bytes --]
commit c3deee14326a96c9b058fb5433cf98fd64f8d618
Author: Jason Merrill <jason@redhat.com>
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<tree, va_gc> **, 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<tree, va_gc> *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<tree, va_gc> *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<decltype(E)*>(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);
+ TRY(b>>b);
+ TRY(b==b);
+ TRY(b->*b);
+}
^ permalink raw reply [flat|nested] 2+ messages in thread
* Re: Another C++ PATCH for c++/52748 (N3276 and operator overloading)
2013-04-11 21:38 Another C++ PATCH for c++/52748 (N3276 and operator overloading) Jason Merrill
@ 2013-04-15 19:34 ` Jason Merrill
0 siblings, 0 replies; 2+ messages in thread
From: Jason Merrill @ 2013-04-15 19:34 UTC (permalink / raw)
To: gcc-patches List
[-- Attachment #1: Type: text/plain, Size: 272 bytes --]
On 04/11/2013 08:50 PM, Jason Merrill wrote:
> My earlier N3276 work only affected the function call syntax, but it
> needs to affect implicit function calls from overloaded operators as well.
...and in templates.
Tested x86_64-pc-linux-gnu, applying to trunk and 4.8.
[-- Attachment #2: 52748-3.patch --]
[-- Type: text/x-patch, Size: 5892 bytes --]
commit 9448b41e5f5a64a2a92519049898fba4c9d43633
Author: Jason Merrill <jason@redhat.com>
Date: Sat Apr 13 21:12:45 2013 +0200
PR c++/52748
* pt.c (tsubst) [DECLTYPE_TYPE]: If ~id is an expression
rather than a destructor name, it isn't an unqualified-name.
(tsubst_copy_and_build): Pass down decltype_flag to operator
handling code, too.
diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c
index 0c7b2ed..5c960e0 100644
--- a/gcc/cp/pt.c
+++ b/gcc/cp/pt.c
@@ -11800,8 +11800,17 @@ tsubst (tree t, tree args, tsubst_flags_t complain, tree in_decl)
else if (DECLTYPE_FOR_LAMBDA_PROXY (t))
type = lambda_proxy_type (type);
else
- type = finish_decltype_type
- (type, DECLTYPE_TYPE_ID_EXPR_OR_MEMBER_ACCESS_P (t), complain);
+ {
+ bool id = DECLTYPE_TYPE_ID_EXPR_OR_MEMBER_ACCESS_P (t);
+ if (id && TREE_CODE (DECLTYPE_TYPE_EXPR (t)) == BIT_NOT_EXPR
+ && EXPR_P (type))
+ /* In a template ~id could be either a complement expression
+ or an unqualified-id naming a destructor; if instantiating
+ it produces an expression, it's not an id-expression or
+ member access. */
+ id = false;
+ type = finish_decltype_type (type, id, complain);
+ }
return cp_build_qualified_type_real (type,
cp_type_quals (t)
| cp_type_quals (type),
@@ -13427,9 +13436,8 @@ tsubst_copy_and_build (tree t,
/* N3276 decltype magic only applies to calls at the top level or on the
right side of a comma. */
- if (TREE_CODE (t) != CALL_EXPR
- && TREE_CODE (t) != COMPOUND_EXPR)
- complain &= ~tf_decltype;
+ tsubst_flags_t decltype_flag = (complain & tf_decltype);
+ complain &= ~tf_decltype;
switch (TREE_CODE (t))
{
@@ -13517,7 +13525,8 @@ tsubst_copy_and_build (tree t,
r = convert_from_reference (r);
}
else
- r = build_x_indirect_ref (input_location, r, RO_UNARY_STAR, complain);
+ r = build_x_indirect_ref (input_location, r, RO_UNARY_STAR,
+ complain|decltype_flag);
RETURN (r);
}
@@ -13594,7 +13603,8 @@ tsubst_copy_and_build (tree t,
case POSTINCREMENT_EXPR:
op1 = tsubst_non_call_postfix_expression (TREE_OPERAND (t, 0),
args, complain, in_decl);
- RETURN (build_x_unary_op (input_location, TREE_CODE (t), op1, complain));
+ RETURN (build_x_unary_op (input_location, TREE_CODE (t), op1,
+ complain|decltype_flag));
case PREDECREMENT_EXPR:
case PREINCREMENT_EXPR:
@@ -13606,7 +13616,8 @@ tsubst_copy_and_build (tree t,
case REALPART_EXPR:
case IMAGPART_EXPR:
RETURN (build_x_unary_op (input_location, TREE_CODE (t),
- RECUR (TREE_OPERAND (t, 0)), complain));
+ RECUR (TREE_OPERAND (t, 0)),
+ complain|decltype_flag));
case FIX_TRUNC_EXPR:
RETURN (cp_build_unary_op (FIX_TRUNC_EXPR, RECUR (TREE_OPERAND (t, 0)),
@@ -13623,7 +13634,8 @@ tsubst_copy_and_build (tree t,
else
op1 = tsubst_non_call_postfix_expression (op1, args, complain,
in_decl);
- RETURN (build_x_unary_op (input_location, ADDR_EXPR, op1, complain));
+ RETURN (build_x_unary_op (input_location, ADDR_EXPR, op1,
+ complain|decltype_flag));
case PLUS_EXPR:
case MINUS_EXPR:
@@ -13672,7 +13684,7 @@ tsubst_copy_and_build (tree t,
? ERROR_MARK
: TREE_CODE (TREE_OPERAND (t, 1))),
/*overload=*/NULL,
- complain);
+ complain|decltype_flag);
if (EXPR_P (r) && TREE_NO_WARNING (t))
TREE_NO_WARNING (r) = TREE_NO_WARNING (t);
@@ -13688,7 +13700,8 @@ tsubst_copy_and_build (tree t,
op1 = tsubst_non_call_postfix_expression (TREE_OPERAND (t, 0),
args, complain, in_decl);
RETURN (build_x_array_ref (EXPR_LOCATION (t), op1,
- RECUR (TREE_OPERAND (t, 1)), complain));
+ RECUR (TREE_OPERAND (t, 1)),
+ complain|decltype_flag));
case SIZEOF_EXPR:
if (PACK_EXPANSION_P (TREE_OPERAND (t, 0)))
@@ -13781,7 +13794,7 @@ tsubst_copy_and_build (tree t,
RECUR (TREE_OPERAND (t, 0)),
TREE_CODE (TREE_OPERAND (t, 1)),
RECUR (TREE_OPERAND (t, 2)),
- complain);
+ complain|decltype_flag);
/* TREE_NO_WARNING must be set if either the expression was
parenthesized or it uses an operator such as >>= rather
than plain assignment. In the former case, it was already
@@ -13870,7 +13883,7 @@ tsubst_copy_and_build (tree t,
RETURN (build_x_compound_expr (EXPR_LOCATION (t),
op0,
RECUR (TREE_OPERAND (t, 1)),
- complain));
+ complain|decltype_flag));
}
case CALL_EXPR:
@@ -13882,10 +13895,6 @@ tsubst_copy_and_build (tree t,
bool koenig_p;
tree ret;
- /* Don't pass tf_decltype down to subexpressions. */
- tsubst_flags_t decltype_flag = (complain & tf_decltype);
- complain &= ~tf_decltype;
-
function = CALL_EXPR_FN (t);
/* When we parsed the expression, we determined whether or
not Koenig lookup should be performed. */
diff --git a/gcc/testsuite/g++.dg/cpp0x/decltype-call3.C b/gcc/testsuite/g++.dg/cpp0x/decltype-call3.C
index 1d12b01..27797a2 100644
--- a/gcc/testsuite/g++.dg/cpp0x/decltype-call3.C
+++ b/gcc/testsuite/g++.dg/cpp0x/decltype-call3.C
@@ -43,6 +43,50 @@ A operator==(B,B);
A operator->*(B,B);
#define TRY(E) static_cast<decltype(E)*>(0)
+
+template <class B>
+void f()
+{
+ 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);
+ TRY(b>>b);
+ TRY(b==b);
+ TRY(b->*b);
+}
+
int main()
{
B b;
@@ -83,4 +127,6 @@ int main()
TRY(b>>b);
TRY(b==b);
TRY(b->*b);
+
+ f<B>();
}
^ permalink raw reply [flat|nested] 2+ messages in thread
end of thread, other threads:[~2013-04-15 15:18 UTC | newest]
Thread overview: 2+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2013-04-11 21:38 Another C++ PATCH for c++/52748 (N3276 and operator overloading) Jason Merrill
2013-04-15 19:34 ` Jason Merrill
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).