]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
c++: print stub object as std::declval
authorJason Merrill <jason@redhat.com>
Mon, 23 Dec 2024 17:32:54 +0000 (12:32 -0500)
committerJason Merrill <jason@redhat.com>
Wed, 8 Jan 2025 21:35:29 +0000 (16:35 -0500)
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.

gcc/cp/cp-tree.h
gcc/cp/error.cc
gcc/cp/method.cc
gcc/testsuite/g++.dg/gomp/declare-variant-3.C
gcc/testsuite/g++.dg/gomp/declare-variant-5.C

index 1d741ecedc379bd5f14fbf0d98b0c1f948f4d22d..6184d99f4afc27edf793b46ad73ebfc8aebd7d58 100644 (file)
@@ -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);
index feb6853b4f7b10b6ca1fc6113e8927d76a510778..cc4cc4a7eb467b437b1a329e0df61194ef7fb92f 100644 (file)
@@ -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
index 0f9f23ae93a46b7bcf735e7ab4e8507d2c5dcb27..64535f52019f0ee24bd8ada299fbc896c22b532a 100644 (file)
@@ -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
index 376eefc2dc1f7468cc93dce7e8f05a6fa228a557..8c0cfd218ad4ddd98883a8d056ee19ecb0e62f85 100644 (file)
@@ -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);
index a52fa528e1ffd5321c5629f4b80834084ccd33db..a4747ac030b984cbb4857f0a22064a6e60c7c5c9 100644 (file)
@@ -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);