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 ();

Reply via email to