2019-10-03 Jakub Jelinek <jakub@redhat.com>
+ * constexpr.c (cxx_eval_constant_expression) <case CLEANUP_STMT>: If
+ not skipping upon entry to body, run cleanup with the same *jump_target
+ as it started to run the cleanup even if the body returns, breaks or
+ continues.
+ (potential_constant_expression_1): Allow CLEANUP_STMT.
+
* constexpr.c (cxx_eval_store_expression): Formatting fix. Handle
const_object_being_modified with array type.
break;
case CLEANUP_STMT:
- r = cxx_eval_constant_expression (ctx, CLEANUP_BODY (t), lval,
+ {
+ tree initial_jump_target = jump_target ? *jump_target : NULL_TREE;
+ r = cxx_eval_constant_expression (ctx, CLEANUP_BODY (t), lval,
+ non_constant_p, overflow_p,
+ jump_target);
+ if (!CLEANUP_EH_ONLY (t) && !*non_constant_p)
+ /* Also evaluate the cleanup. If we weren't skipping at the
+ start of the CLEANUP_BODY, change jump_target temporarily
+ to &initial_jump_target, so that even a return or break or
+ continue in the body doesn't skip the cleanup. */
+ cxx_eval_constant_expression (ctx, CLEANUP_EXPR (t), true,
non_constant_p, overflow_p,
- jump_target);
- if (!CLEANUP_EH_ONLY (t) && !*non_constant_p)
- /* Also evaluate the cleanup. */
- cxx_eval_constant_expression (ctx, CLEANUP_EXPR (t), true,
- non_constant_p, overflow_p,
- jump_target);
+ jump_target ? &initial_jump_target
+ : NULL);
+ }
break;
/* These differ from cxx_eval_unary_expression in that this doesn't
return true;
case CLEANUP_STMT:
+ if (!RECUR (CLEANUP_BODY (t), any))
+ return false;
+ if (!CLEANUP_EH_ONLY (t) && !RECUR (CLEANUP_EXPR (t), any))
+ return false;
+ return true;
+
case EMPTY_CLASS_EXPR:
case PREDICT_EXPR:
return false;
--- /dev/null
+// { dg-do compile { target c++2a } }
+
+constexpr void
+cleanup (int *x)
+{
+ if (x)
+ asm (""); // { dg-error "inline assembly is not a constant expression" }
+} // { dg-message "only unevaluated inline assembly is allowed in a 'constexpr' function" "" { target *-*-* } .-1 }
+
+constexpr void
+cleanup2 (int *x)
+{
+}
+
+constexpr bool
+foo ()
+{
+ int a __attribute__((cleanup (cleanup))) = 1;
+ return true;
+}
+
+constexpr bool
+bar ()
+{
+ int a __attribute__((cleanup (cleanup2))) = 1;
+ return true;
+}
+
+constexpr auto x = foo (); // { dg-message "in 'constexpr' expansion of" }
+constexpr auto y = bar ();