On Wed, Aug 07, 2019 at 03:38:02PM -0400, Jason Merrill wrote: > On Wed, Aug 7, 2019, 2:35 PM Marek Polacek <pola...@redhat.com> wrote: > > > On Wed, Aug 07, 2019 at 12:23:25PM -0400, Jason Merrill wrote: > > > On Wed, Aug 7, 2019, 9:11 AM Marek Polacek <pola...@redhat.com> wrote: > > > > > > > On Tue, Aug 06, 2019 at 09:25:45PM -0400, Jason Merrill wrote: > > > > > Let's downgrade the errors in earlier standard modes to pedwarn. Ok > > with > > > > > that change. > > > > > > > > Works for me, here's what I'll apply once it passes testing. > > > > > > > > I removed the diagnostic in potential_constant_expression_1/ASM_EXPR so > > > > that > > > > we don't generate duplicate pedwarns for the same thing. Hope that's > > OK. > > > > > > > > 2019-08-07 Marek Polacek <pola...@redhat.com> > > > > > > > > PR c++/91346 - Implement P1668R1, allow unevaluated asm in > > > > constexpr. > > > > * constexpr.c (cxx_eval_constant_expression): Handle ASM_EXPR. > > > > (potential_constant_expression_1) <case ASM_EXPR>: Allow. > > > > * cp-tree.h (finish_asm_stmt): Adjust. > > > > * parser.c (cp_parser_asm_definition): Grab the locaion of > > "asm" > > > > and > > > > use it. Change an error to a pedwarn. Allow asm in C++2a, > > warn > > > > otherwise. > > > > * pt.c (tsubst_expr): Pass a location down to finish_asm_stmt. > > > > * semantics.c (finish_asm_stmt): New location_t parameter. > > Use it. > > > > > > > > * g++.dg/cpp2a/inline-asm1.C: New test. > > > > * g++.dg/cpp2a/inline-asm2.C: New test. > > > > * g++.dg/cpp1y/constexpr-neg1.C: Adjust dg-error. > > > > > > > > diff --git gcc/cp/constexpr.c gcc/cp/constexpr.c > > > > index 36a66337433..e86b0789b84 100644 > > > > --- gcc/cp/constexpr.c > > > > +++ gcc/cp/constexpr.c > > > > @@ -5289,6 +5289,18 @@ cxx_eval_constant_expression (const > > constexpr_ctx > > > > *ctx, tree t, > > > > r = void_node; > > > > break; > > > > > > > > + case ASM_EXPR: > > > > + if (!ctx->quiet) > > > > + { > > > > + error_at (cp_expr_loc_or_input_loc (t), > > > > + "inline assembly is not a constant expression"); > > > > + inform (cp_expr_loc_or_input_loc (t), > > > > + "only unevaluated inline assembly is allowed in a " > > > > + "%<constexpr%> function in C++2a"); > > > > + } > > > > + *non_constant_p = true; > > > > + return t; > > > > + > > > > default: > > > > if (STATEMENT_CODE_P (TREE_CODE (t))) > > > > { > > > > @@ -6469,13 +6481,18 @@ potential_constant_expression_1 (tree t, bool > > > > want_rval, bool strict, bool now, > > > > /* GCC internal stuff. */ > > > > case VA_ARG_EXPR: > > > > case TRANSACTION_EXPR: > > > > - case ASM_EXPR: > > > > case AT_ENCODE_EXPR: > > > > fail: > > > > if (flags & tf_error) > > > > error_at (loc, "expression %qE is not a constant expression", > > t); > > > > return false; > > > > > > > > + case ASM_EXPR: > > > > + /* In C++2a, unevaluated inline assembly is permitted in > > constexpr > > > > + functions. If it's used in earlier standard modes, we > > pedwarn in > > > > + cp_parser_asm_definition. */ > > > > + return true; > > > > > > > > > > Actually, do we need this change? If it's (possibly) unevaluated, we > > > shouldn't get here. > > > > We can get here when using asm() in ({ }) like this (ugh): > > > > constexpr int > > foo (bool b) > > { > > if (b) > > { > > constexpr int i = ({ asm(""); 42; }); > > return i; > > } > > else > > return 42; > > } > > static_assert(foo(false) == 42, ""); > > > > With the current state of potential_constant_expression_1, we generate > > > > inline-asm3.C: In function ‘constexpr int foo(bool)’: > > inline-asm3.C:10:27: error: inline assembly is not a constant expression > > 10 | constexpr int i = ({ asm(""); 42; }); > > | ^~~ > > inline-asm3.C:10:27: note: only unevaluated inline assembly is allowed in > > a ‘constexpr’ function in C++2a > > > > which I thought was better than what we emit with the hunk revered: > > > > inline-asm3.C: In function ‘constexpr int foo(bool)’: > > inline-asm3.C:10:27: error: expression ‘<statement>’ is not a constant > > expression > > 10 | constexpr int i = ({ asm(""); 42; }); > > | ^~~ > > > > But I'm happy to revert that hunk if you want. > > > > Sure, perhaps we could share the error message between the two functions. > In general it's better to reject something in potential_... if we can.
Yeah, that makes sense. How about this further tweak then? 2019-08-07 Marek Polacek <pola...@redhat.com> * constexpr.c (inline_asm_in_constexpr_error): New. (cxx_eval_constant_expression) <case ASM_EXPR>: Call it. (potential_constant_expression_1) <case ASM_EXPR>: Likewise. * g++.dg/cpp2a/inline-asm3.C: New test. diff --git gcc/cp/constexpr.c gcc/cp/constexpr.c index e86b0789b84..63c890560e0 100644 --- gcc/cp/constexpr.c +++ gcc/cp/constexpr.c @@ -4411,6 +4411,16 @@ lookup_placeholder (const constexpr_ctx *ctx, bool lval, tree type) return ob; } +/* Complain about an attempt to evaluate inline assembly. */ + +static void +inline_asm_in_constexpr_error (location_t loc) +{ + error_at (loc, "inline assembly is not a constant expression"); + inform (loc, "only unevaluated inline assembly is allowed in a " + "%<constexpr%> function in C++2a"); +} + /* Attempt to reduce the expression T to a constant value. On failure, issue diagnostic and return error_mark_node. */ /* FIXME unify with c_fully_fold */ @@ -5291,13 +5301,7 @@ cxx_eval_constant_expression (const constexpr_ctx *ctx, tree t, case ASM_EXPR: if (!ctx->quiet) - { - error_at (cp_expr_loc_or_input_loc (t), - "inline assembly is not a constant expression"); - inform (cp_expr_loc_or_input_loc (t), - "only unevaluated inline assembly is allowed in a " - "%<constexpr%> function in C++2a"); - } + inline_asm_in_constexpr_error (cp_expr_loc_or_input_loc (t)); *non_constant_p = true; return t; @@ -6488,10 +6492,9 @@ potential_constant_expression_1 (tree t, bool want_rval, bool strict, bool now, return false; case ASM_EXPR: - /* In C++2a, unevaluated inline assembly is permitted in constexpr - functions. If it's used in earlier standard modes, we pedwarn in - cp_parser_asm_definition. */ - return true; + if (flags & tf_error) + inline_asm_in_constexpr_error (loc); + return false; case OBJ_TYPE_REF: if (cxx_dialect >= cxx2a) diff --git gcc/testsuite/g++.dg/cpp2a/inline-asm3.C gcc/testsuite/g++.dg/cpp2a/inline-asm3.C new file mode 100644 index 00000000000..b636e3b2d87 --- /dev/null +++ gcc/testsuite/g++.dg/cpp2a/inline-asm3.C @@ -0,0 +1,12 @@ +// P1668R1: Permit unevaluated inline asm in constexpr functions +// { dg-do compile { target c++2a } } +// { dg-additional-options "-Wno-pedantic" } + +constexpr int +foo () +{ + constexpr int i = ({ asm(""); 42; }); // { dg-error "inline assembly is not a constant expression" } + return i; +} + +constexpr int i = foo ();