re PR c++/52748 ([C++11] N3276 changes to decltype)
authorJason Merrill <jason@redhat.com>
Thu, 11 Apr 2013 19:51:52 +0000 (15:51 -0400)
committerJason Merrill <jason@gcc.gnu.org>
Thu, 11 Apr 2013 19:51:52 +0000 (15:51 -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.

From-SVN: r197826

gcc/cp/ChangeLog
gcc/cp/cp-tree.h
gcc/cp/decl2.c
gcc/cp/parser.c
gcc/cp/semantics.c
gcc/testsuite/g++.dg/cpp0x/decltype-call3.C [new file with mode: 0644]

index a9e40c29022359d1ef4a5f2c0c819da7d16afb51..d396893a59af684c7bd3ff8fb5d6873f05c10aa6 100644 (file)
@@ -1,3 +1,17 @@
+2013-04-11  Jason Merrill  <jason@redhat.com>
+
+       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.
+
 2013-04-11  Jakub Jelinek  <jakub@redhat.com>
 
        PR c++/56895
index e1d12381d77c8a46750a5111515feb5b63681443..f7c65b68dc9954c78f7a04097a5fafad068fb578 100644 (file)
@@ -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);
index 407b46159d2f90161fa57f01717ef0ba7d5e5e39..a5b265502f77f9bc0478629aff40f9daa86e4e22 100644 (file)
@@ -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;
index e015c4f3540ff919b4cf2762d513fd1a19938388..6b5020eefb6045daefcf4838e2cf8ca9b15cc7d5 100644 (file)
@@ -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.  */
index 063183308f285690040c75698afaaa382c2ce037..a09a7f480edc857c828c007ef6004c2b2b271764 100644 (file)
@@ -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 (file)
index 0000000..1d12b01
--- /dev/null
@@ -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);
+}