https://gcc.gnu.org/g:72bb6fbbc56fe6a45058f4f6eac0ed6cc4f16473

commit r15-6708-g72bb6fbbc56fe6a45058f4f6eac0ed6cc4f16473
Author: Jason Merrill <ja...@redhat.com>
Date:   Mon Dec 23 12:32:54 2024 -0500

    c++: print stub object as std::declval
    
    If the result of build_stub_object gets printed by %E it looks something
    like '(A&&)1', which seems confusing.  Let's instead print it as
    'std::declval<A>()' since that's how the library writes the same idea.
    
    gcc/cp/ChangeLog:
    
            * method.cc (is_stub_object): New.
            * cp-tree.h (is_stub_object): Declare.
            * error.cc (dump_expr): Use it.
    
    gcc/testsuite/ChangeLog:
    
            * g++.dg/gomp/declare-variant-3.C: Update diagnostic.
            * g++.dg/gomp/declare-variant-5.C: Likewise.

Diff:
---
 gcc/cp/cp-tree.h                              |  1 +
 gcc/cp/error.cc                               |  9 +++++++++
 gcc/cp/method.cc                              | 12 ++++++++++++
 gcc/testsuite/g++.dg/gomp/declare-variant-3.C |  4 ++--
 gcc/testsuite/g++.dg/gomp/declare-variant-5.C |  4 ++--
 5 files changed, 26 insertions(+), 4 deletions(-)

diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h
index 1d741ecedc37..6184d99f4afc 100644
--- a/gcc/cp/cp-tree.h
+++ b/gcc/cp/cp-tree.h
@@ -7456,6 +7456,7 @@ extern tree get_copy_assign                       (tree);
 extern tree get_default_ctor                   (tree);
 extern tree get_dtor                           (tree, tsubst_flags_t);
 extern tree build_stub_object                  (tree);
+extern bool is_stub_object                     (tree);
 extern tree build_invoke                       (tree, const_tree,
                                                 tsubst_flags_t);
 extern tree strip_inheriting_ctors             (tree);
diff --git a/gcc/cp/error.cc b/gcc/cp/error.cc
index feb6853b4f7b..cc4cc4a7eb46 100644
--- a/gcc/cp/error.cc
+++ b/gcc/cp/error.cc
@@ -2604,6 +2604,15 @@ dump_expr (cxx_pretty_printer *pp, tree t, int flags)
          dump_expr (pp, CALL_EXPR_FN (t), flags | TFF_EXPR_IN_PARENS);
          dump_call_expr_args (pp, t, flags, true);
        }
+      else if (is_stub_object (t))
+       {
+         pp_string (pp, "std::declval<");
+         if (lvalue_p (t)) /* T& */
+           dump_type (pp, TREE_TYPE (STRIP_REFERENCE_REF (t)), flags);
+         else /* T */
+           dump_type (pp, TREE_TYPE (t), flags);
+         pp_string (pp, ">()");
+       }
       else
        {
          if (TREE_OPERAND (t,0) != NULL_TREE
diff --git a/gcc/cp/method.cc b/gcc/cp/method.cc
index 0f9f23ae93a4..64535f52019f 100644
--- a/gcc/cp/method.cc
+++ b/gcc/cp/method.cc
@@ -1914,6 +1914,18 @@ build_stub_object (tree reftype)
   return convert_from_reference (stub);
 }
 
+/* True iff EXPR is the result of build_stub_object.  */
+
+bool
+is_stub_object (tree expr)
+{
+  if (!REFERENCE_REF_P (expr))
+    return false;
+  expr = TREE_OPERAND (expr, 0);
+  return (TREE_CODE (expr) == CONVERT_EXPR
+         && TREE_OPERAND (expr, 0) == integer_one_node);
+}
+
 /* Build a std::declval<TYPE>() expression and return it.  */
 
 tree
diff --git a/gcc/testsuite/g++.dg/gomp/declare-variant-3.C 
b/gcc/testsuite/g++.dg/gomp/declare-variant-3.C
index 376eefc2dc1f..8c0cfd218ad4 100644
--- a/gcc/testsuite/g++.dg/gomp/declare-variant-3.C
+++ b/gcc/testsuite/g++.dg/gomp/declare-variant-3.C
@@ -86,7 +86,7 @@ struct E { int e; };
 
 void fn19 (E, int);
 
-#pragma omp declare variant (fn19)match(user={condition(0)})   // { dg-error 
{could not convert '[^']*' from 'int' to 'E'} }
+#pragma omp declare variant (fn19)match(user={condition(0)})   // { dg-error 
{could not convert 'std::declval<int>\(\)' from 'int' to 'E'} }
 void fn20 (int, E);
 
 struct F { operator int () const { return 42; } int f; };
@@ -95,7 +95,7 @@ void fn21 (int, F);
 #pragma omp declare variant ( fn21 ) match (user = { condition ( 1 - 1 ) } )   
// { dg-error "variant 'void fn21\\\(int, F\\\)' and base 'void fn22\\\(F, 
F\\\)' have incompatible types" }
 void fn22 (F, F);
 
-#pragma omp declare variant (fn19) match (user={condition(0)})         // { 
dg-error {could not convert '[^']*' from 'F' to 'E'} }
+#pragma omp declare variant (fn19) match (user={condition(0)})         // { 
dg-error {could not convert 'std::declval<F>\(\)' from 'F' to 'E'} }
 void fn23 (F, int);
 
 void fn24 (int);
diff --git a/gcc/testsuite/g++.dg/gomp/declare-variant-5.C 
b/gcc/testsuite/g++.dg/gomp/declare-variant-5.C
index a52fa528e1ff..a4747ac030b9 100644
--- a/gcc/testsuite/g++.dg/gomp/declare-variant-5.C
+++ b/gcc/testsuite/g++.dg/gomp/declare-variant-5.C
@@ -74,7 +74,7 @@ struct E { int e; };
 
 void fn19 (E, int) {}
 
-#pragma omp declare variant (fn19)match(user={condition(0)})   // { dg-error 
{could not convert '[^']*' from 'int' to 'E'} }
+#pragma omp declare variant (fn19)match(user={condition(0)})   // { dg-error 
{could not convert 'std::declval<int>\(\)' from 'int' to 'E'} }
 void fn20 (int, E) {}
 
 struct F { operator int () const { return 42; } int f; };
@@ -83,7 +83,7 @@ void fn21 (int, F) {}
 #pragma omp declare variant ( fn21 ) match (user = { condition ( 1 - 1 ) } )   
// { dg-error "variant 'void fn21\\\(int, F\\\)' and base 'void fn22\\\(F, 
F\\\)' have incompatible types" }
 void fn22 (F, F) {}
 
-#pragma omp declare variant (fn19) match (user={condition(0)})         // { 
dg-error {could not convert '[^']*' from 'F' to 'E'} }
+#pragma omp declare variant (fn19) match (user={condition(0)})         // { 
dg-error {could not convert 'std::declval<F>\(\)' from 'F' to 'E'} }
 void fn23 (F, int) {}
 
 void fn24 (int);

Reply via email to