On Fri, Oct 11, 2019 at 04:14:16PM -0400, Jason Merrill wrote:
> > On x86_64 and most other targets, cleanup here (if non-NULL) is the
> > CALL_EXPR, as destructor return type is void, but on arm, as the dtor return
> > type is some pointer, the CALL_EXPR is wrapped into a NOP_EXPR to void.
> > protected_set_expr_location then on x86_64 clears the CALL_EXPR location,
> > but on arm only NOP_EXPR location.
> > 
> > The following patch (totally untested) should fix that.
> > 
> > For the warning location, perhaps we could special case destructor calls
> > in push_cx_call_context (to offset the intentional clearing of location for
> > debugging purposes), if they don't have location set, don't use
> > input_location for them, but try to pick DECL_SOURCE_LOCATION for the
> > variable being destructed?
> 
> Expanding the CLEANUP_EXPR of a CLEANUP_STMT could use the EXPR_LOCATION of
> the CLEANUP_STMT.  Or the EXPR_LOCATION of *jump_target, if suitable.

The already previously posted patch (now attached as first) has now been
bootstrapped/regtested on x86_64-linux and i686-linux, and regardless if we
improve the location or not should fix the arm vs. the rest of the world
difference.  Is that ok for trunk?

As for CLEANUP_STMT, I've tried it (the second patch), but it didn't change
anything, the diagnostics was still
constexpr-dtor3.C:16:23:   in ‘constexpr’ expansion of ‘f4()’
constexpr-dtor3.C:16:24:   in ‘constexpr’ expansion of ‘(& w13)->W7::~W7()’
constexpr-dtor3.C:5:34: error: inline assembly is not a constant expression
    5 |   constexpr ~W7 () { if (w == 5) asm (""); w = 3; } // { dg-error 
"inline assembly is not a constant expression" }
      |                                  ^~~
constexpr-dtor3.C:5:34: note: only unevaluated inline assembly is allowed in a 
‘constexpr’ function in C++2a
as without that change.

I've also tried the third patch, tested so far with check-c++-all, which
changes that to
constexpr-dtor3.C:16:23:   in ‘constexpr’ expansion of ‘f4()’
constexpr-dtor3.C:12:6:   in ‘constexpr’ expansion of ‘(& w13)->W7::~W7()’
constexpr-dtor3.C:5:34: error: inline assembly is not a constant expression
    5 |   constexpr ~W7 () { if (w == 5) asm (""); w = 3; } // { dg-error 
"inline assembly is not a constant expression" }
      |                                  ^~~
constexpr-dtor3.C:5:34: note: only unevaluated inline assembly is allowed in a 
‘constexpr’ function in C++2a

        Jakub
2019-10-16  Jakub Jelinek  <ja...@redhat.com>

        * decl.c (cxx_maybe_build_cleanup): When clearing location of cleanup,
        if cleanup is a nop, clear location of its operand too.

--- gcc/cp/decl.c.jj    2019-10-10 01:33:38.154943945 +0200
+++ gcc/cp/decl.c       2019-10-11 10:09:24.321277942 +0200
@@ -16864,6 +16864,8 @@ cxx_maybe_build_cleanup (tree decl, tsub
      the end of the block.  So let's unset the location of the
      destructor call instead.  */
   protected_set_expr_location (cleanup, UNKNOWN_LOCATION);
+  if (cleanup && CONVERT_EXPR_P (cleanup))
+    protected_set_expr_location (TREE_OPERAND (cleanup, 0), UNKNOWN_LOCATION);
 
   if (cleanup
       && DECL_P (decl)
2019-10-16  Jakub Jelinek  <ja...@redhat.com>

        * constexpr.c (cxx_eval_constant_expression) <case CLEANUP_STMT>:
        Temporarily change input_location to CLEANUP_STMT location.

--- gcc/cp/constexpr.c.jj       2019-10-10 01:33:38.185943480 +0200
+++ gcc/cp/constexpr.c  2019-10-11 22:54:32.628051700 +0200
@@ -4980,9 +4980,13 @@ cxx_eval_constant_expression (const cons
     case CLEANUP_STMT:
       {
        tree initial_jump_target = jump_target ? *jump_target : NULL_TREE;
+       location_t loc = input_location;
+       if (EXPR_HAS_LOCATION (t))
+         input_location = EXPR_LOCATION (t);
        r = cxx_eval_constant_expression (ctx, CLEANUP_BODY (t), lval,
                                          non_constant_p, overflow_p,
                                          jump_target);
+       input_location = loc;
        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
2019-10-16  Jakub Jelinek  <ja...@redhat.com>

        * decl.c (cxx_maybe_build_cleanup): When clearing location of cleanup,
        if cleanup is a nop, clear location of its operand too.
        * constexpr.c (push_cx_call_context): For calls to destructors, use
        DECL_SOURCE_LOCATION of destructed variable in preference to
        input_location.

        * g++.dg/cpp2a/constexpr-dtor3.C: Expect in 'constexpr' expansion of
        message on the line with variable declaration.

--- gcc/cp/decl.c.jj    2019-10-16 09:30:57.490109872 +0200
+++ gcc/cp/decl.c       2019-10-16 17:45:48.647529567 +0200
@@ -16864,6 +16864,8 @@ cxx_maybe_build_cleanup (tree decl, tsub
      the end of the block.  So let's unset the location of the
      destructor call instead.  */
   protected_set_expr_location (cleanup, UNKNOWN_LOCATION);
+  if (cleanup && CONVERT_EXPR_P (cleanup))
+    protected_set_expr_location (TREE_OPERAND (cleanup, 0), UNKNOWN_LOCATION);
 
   if (cleanup
       && DECL_P (decl)
--- gcc/cp/constexpr.c.jj       2019-10-16 17:35:37.848752468 +0200
+++ gcc/cp/constexpr.c  2019-10-16 18:07:42.472688066 +0200
@@ -1457,7 +1457,26 @@ push_cx_call_context (tree call)
 {
   ++call_stack_tick;
   if (!EXPR_HAS_LOCATION (call))
-    SET_EXPR_LOCATION (call, input_location);
+    {
+      tree fun = get_function_named_in_call (call);
+      location_t loc = input_location;
+      /* Calls to destructors have UNKNOWN_LOCATION, in order to avoid
+        problems debugging at the end of scopes.  For diagnostic purposes,
+        try to use location of the variable that needs destruction.  */
+      if (fun && DECL_DESTRUCTOR_P (fun))
+       {
+         tree arg = CALL_EXPR_ARG (call, 0);
+         STRIP_NOPS (arg);
+         if (TREE_CODE (arg) == ADDR_EXPR)
+           {
+             tree var = get_base_address (TREE_OPERAND (arg, 0));
+             if (DECL_P (var)
+                 && DECL_SOURCE_LOCATION (var) != UNKNOWN_LOCATION)
+               loc = DECL_SOURCE_LOCATION (var);
+           }
+       }
+      SET_EXPR_LOCATION (call, loc);
+    }
   call_stack.safe_push (call);
   int len = call_stack.length ();
   if (len > max_constexpr_depth)
--- gcc/testsuite/g++.dg/cpp2a/constexpr-dtor3.C.jj     2019-10-05 
09:36:39.250674497 +0200
+++ gcc/testsuite/g++.dg/cpp2a/constexpr-dtor3.C        2019-10-16 
18:10:48.603877004 +0200
@@ -149,7 +149,7 @@ constexpr int x3 = f3 ();
 constexpr int
 f4 ()
 {
-  W7 w13 = 5;
+  W7 w13 = 5;                  // { dg-message "in 'constexpr' expansion of" }
   return 0;
 }
 

Reply via email to