aboutsummaryrefslogtreecommitdiff
path: root/libstdc++-v3/testsuite
diff options
context:
space:
mode:
authorNathaniel Shead <nathanieloshead@gmail.com>2025-05-29 20:08:13 +1000
committerNathaniel Shead <nathanieloshead@gmail.com>2025-07-25 08:18:45 +1000
commitf1872cc05b0dc53bb440b7b3ee045bb49e474ccb (patch)
tree1ec1ecbf25322cd0760db2eb9cecda5307eb126f /libstdc++-v3/testsuite
parent257b640d256d3f84e7307f5fdb08d2208d84f4b8 (diff)
downloadgcc-f1872cc05b0dc53bb440b7b3ee045bb49e474ccb.zip
gcc-f1872cc05b0dc53bb440b7b3ee045bb49e474ccb.tar.gz
gcc-f1872cc05b0dc53bb440b7b3ee045bb49e474ccb.tar.bz2
c++: Unwrap type traits defined in terms of builtins within diagnostics [PR117294]
Currently, concept failures of standard type traits just report 'expression X<T> evaluates to false'. However, many type traits are actually defined in terms of compiler builtins; we can do better here. For instance, 'is_constructible_v' could go on to explain why the type is not constructible, or 'is_invocable_v' could list potential candidates. Apart from concept diagnostics, this is also useful when using such traits in a 'static_assert' directly, so this patch also adjusts the diagnostics in that context. As a first step to supporting that we need to be able to map the standard type traits to the builtins that they use. Rather than adding another list that would need to be kept up-to-date whenever a builtin is added, this patch instead tries to detect any variable template defined directly in terms of a TRAIT_EXPR. This patch also adjusts 'diagnose_trait_expr' to provide more helpful diagnostics for these cases. Not all type traits have yet been updated, this patch just updates those that seem particularly valuable or straight-forward. The function also gets moved to cp/semantics.cc to be closer to 'trait_expr_value'. Various other parts of the compiler are also adjusted here to assist in making clear diagnostics, such as making more use of 'is_stub_object' to refer to a type directly rather than in terms of 'std::declval<T>()'. Additionally, since there are now more cases of nesting within a 'static_assert'ion I felt it was helpful for the experimental-nesting mode to nest here as well. PR c++/117294 PR c++/113854 gcc/cp/ChangeLog: * call.cc (implicit_conversion_error): Hide label when printing a stub object. (convert_like_internal): Likewise, and nest candidate diagnostics. * constexpr.cc (diagnose_failing_condition): Nest diagnostics, attempt to provide more helpful diagnostics for traits. * constraint.cc (satisfy_atom): Pass result before constant evaluation to diagnose_atomic_constraint. (diagnose_trait_expr): Adjust diagnostics for clarity and detail. (maybe_diagnose_standard_trait): New function. (diagnose_atomic_constraint): Attempt to provide more helpful diagnostics for more traits. * cp-tree.h (explain_not_noexcept): Declare new function. (is_trivially_xible): Add parameter. (is_nothrow_xible): Likewise. (is_xible): Likewise. (is_convertible): Likewise. (is_nothrow_convertible): Likewise. (diagnose_trait_expr): Declare new function. (maybe_diagnose_standard_trait): Declare new function. * error.cc (dump_type) <case TREE_VEC>: Handle trait types. * except.cc (explain_not_noexcept): New function. * method.cc (build_trait_object): Add complain parameter. (build_invoke): Propagate complain parameter. (assignable_expr): Add explain parameter to show diagnostics. (constructible_expr): Likewise. (destructible_expr): Likewise. (is_xible_helper): Replace trivial flag with explain flag, add diagnostics. (is_trivially_xible): New explain flag. (is_nothrow_xible): Likewise. (is_xible): Likewise. (is_convertible_helper): Add complain flag. (is_convertible): New explain flag. (is_nothrow_convertible): Likewise. * typeck.cc (cp_build_function_call_vec): Add handling for stub objects. (convert_arguments): Always return -1 on error. * typeck2.cc (cxx_readonly_error): Add handling for stub objects. libstdc++-v3/ChangeLog: * testsuite/20_util/any/misc/any_cast_neg.cc: Adjust diagnostics. * testsuite/20_util/expected/illformed_neg.cc: Likewise. * testsuite/20_util/optional/monadic/or_else_neg.cc: Likewise. * testsuite/23_containers/array/creation/3_neg.cc: Likewise. * testsuite/24_iterators/range_generators/lwg3900.cc: Likewise. * testsuite/29_atomics/atomic/requirements/types_neg.cc: Likewise. * testsuite/30_threads/stop_token/stop_callback/invocable_neg.cc: Likewise. * testsuite/30_threads/stop_token/stop_callback/destructible_neg.cc: Likewise. * testsuite/std/format/arguments/args_neg.cc: Likewise. * testsuite/std/format/string_neg.cc: Likewise. gcc/testsuite/ChangeLog: * g++.dg/cpp2a/concepts-traits3.C: Adjust diagnostics. * g++.dg/cpp2a/concepts-traits4.C: New test. * g++.dg/diagnostic/static_assert5.C: New test. * g++.dg/ext/has_virtual_destructor2.C: New test. * g++.dg/ext/is_assignable2.C: New test. * g++.dg/ext/is_constructible9.C: New test. * g++.dg/ext/is_convertible7.C: New test. * g++.dg/ext/is_destructible3.C: New test. * g++.dg/ext/is_invocable6.C: New test. * g++.dg/ext/is_virtual_base_of_diagnostic2.C: New test. Signed-off-by: Nathaniel Shead <nathanieloshead@gmail.com> Reviewed-by: Patrick Palka <ppalka@redhat.com> Reviewed-by: Jason Merrill <jason@redhat.com>
Diffstat (limited to 'libstdc++-v3/testsuite')
-rw-r--r--libstdc++-v3/testsuite/20_util/any/misc/any_cast_neg.cc3
-rw-r--r--libstdc++-v3/testsuite/20_util/expected/illformed_neg.cc1
-rw-r--r--libstdc++-v3/testsuite/20_util/optional/monadic/or_else_neg.cc1
-rw-r--r--libstdc++-v3/testsuite/23_containers/array/creation/3_neg.cc2
-rw-r--r--libstdc++-v3/testsuite/24_iterators/range_generators/lwg3900.cc3
-rw-r--r--libstdc++-v3/testsuite/29_atomics/atomic/requirements/types_neg.cc2
-rw-r--r--libstdc++-v3/testsuite/30_threads/stop_token/stop_callback/destructible_neg.cc1
-rw-r--r--libstdc++-v3/testsuite/30_threads/stop_token/stop_callback/invocable_neg.cc1
-rw-r--r--libstdc++-v3/testsuite/std/format/arguments/args_neg.cc1
-rw-r--r--libstdc++-v3/testsuite/std/format/string_neg.cc2
10 files changed, 16 insertions, 1 deletions
diff --git a/libstdc++-v3/testsuite/20_util/any/misc/any_cast_neg.cc b/libstdc++-v3/testsuite/20_util/any/misc/any_cast_neg.cc
index 9740e09..9e5c64c 100644
--- a/libstdc++-v3/testsuite/20_util/any/misc/any_cast_neg.cc
+++ b/libstdc++-v3/testsuite/20_util/any/misc/any_cast_neg.cc
@@ -27,6 +27,7 @@ void test01()
const any y(1);
any_cast<int&>(y); // { dg-error "here" }
// { dg-error "Template argument must be constructible from a const value" "" { target { *-*-* } } 0 }
+ // { dg-error "binding reference of type 'int&' to 'const int' discards qualifiers" "" { target { *-*-* } } 0 }
}
void test02()
@@ -34,6 +35,7 @@ void test02()
any y(1);
any_cast<int&&>(y); // { dg-error "here" }
// { dg-error "Template argument must be constructible from an lvalue" "" { target { *-*-* } } 0 }
+ // { dg-error "cannot bind rvalue reference of type 'int&&' to lvalue of type 'int'" "" { target { *-*-* } } 0 }
}
void test03()
@@ -41,6 +43,7 @@ void test03()
any y(1);
any_cast<int&>(std::move(y)); // { dg-error "here" }
// { dg-error "Template argument must be constructible from an rvalue" "" { target { *-*-* } } 0 }
+ // { dg-error "cannot bind non-const lvalue reference of type 'int&' to an rvalue of type 'int'" "" { target { *-*-* } } 0 }
}
// { dg-prune-output "invalid 'static_cast'" }
diff --git a/libstdc++-v3/testsuite/20_util/expected/illformed_neg.cc b/libstdc++-v3/testsuite/20_util/expected/illformed_neg.cc
index 69c13b4..69aa4a1 100644
--- a/libstdc++-v3/testsuite/20_util/expected/illformed_neg.cc
+++ b/libstdc++-v3/testsuite/20_util/expected/illformed_neg.cc
@@ -13,6 +13,7 @@ test_unexpected()
std::unexpected<void()> func(test_unexpected); // { dg-error "here" }
// { dg-error "no matching function for call to" "" { target *-*-* } 0 }
// { dg-error "invalidly declared function type" "" { target *-*-* } 0 }
+ // { dg-error "could not convert" "" { target *-*-* } 0 }
// an array type,
std::unexpected<int[2]> array(i); // { dg-error "here" }
diff --git a/libstdc++-v3/testsuite/20_util/optional/monadic/or_else_neg.cc b/libstdc++-v3/testsuite/20_util/optional/monadic/or_else_neg.cc
index f5028c1..12a67bb 100644
--- a/libstdc++-v3/testsuite/20_util/optional/monadic/or_else_neg.cc
+++ b/libstdc++-v3/testsuite/20_util/optional/monadic/or_else_neg.cc
@@ -26,4 +26,5 @@ test02()
std::optional<move_only> mo;
mo.or_else([]{ return std::optional<move_only>{}; }); // { dg-error "no matching function" }
+ // { dg-error "use of deleted function" "" { target *-*-* } 0 }
}
diff --git a/libstdc++-v3/testsuite/23_containers/array/creation/3_neg.cc b/libstdc++-v3/testsuite/23_containers/array/creation/3_neg.cc
index ae06302..1335228 100644
--- a/libstdc++-v3/testsuite/23_containers/array/creation/3_neg.cc
+++ b/libstdc++-v3/testsuite/23_containers/array/creation/3_neg.cc
@@ -54,3 +54,5 @@ test03()
}
// { dg-prune-output "static assertion failed" }
+// { dg-prune-output "use of deleted function" }
+// { dg-prune-output "could not convert" }
diff --git a/libstdc++-v3/testsuite/24_iterators/range_generators/lwg3900.cc b/libstdc++-v3/testsuite/24_iterators/range_generators/lwg3900.cc
index 957879e..08fd5c2 100644
--- a/libstdc++-v3/testsuite/24_iterators/range_generators/lwg3900.cc
+++ b/libstdc++-v3/testsuite/24_iterators/range_generators/lwg3900.cc
@@ -13,4 +13,5 @@ bar(std::allocator_arg_t, std::pmr::memory_resource& mr) // { dg-error "here" }
}
// { dg-error "static assertion failed" "" { target *-*-* } 0 }
-// { dg-error "no matching function .*memory_resource&" "" { target *-*-* } 0 }
+// { dg-error "could not convert 'const std::pmr::memory_resource'" "" { target *-*-* } 0 }
+// { dg-error "no matching function \[^\n\r\]*memory_resource&" "" { target *-*-* } 0 }
diff --git a/libstdc++-v3/testsuite/29_atomics/atomic/requirements/types_neg.cc b/libstdc++-v3/testsuite/29_atomics/atomic/requirements/types_neg.cc
index 5aa3243..cfe44d2 100644
--- a/libstdc++-v3/testsuite/29_atomics/atomic/requirements/types_neg.cc
+++ b/libstdc++-v3/testsuite/29_atomics/atomic/requirements/types_neg.cc
@@ -20,6 +20,7 @@
#include <atomic>
std::atomic<const int> a; // { dg-error "here" }
+// { dg-error "assignment to read-only type" "" { target *-*-* } 0 }
struct MoveOnly
{
@@ -40,3 +41,4 @@ struct NoMove
std::atomic<NoMove> c; // { dg-error "here" }
// { dg-error "static assertion failed" "" { target *-*-* } 0 }
+// { dg-error "use of deleted function" "" { target *-*-* } 0 }
diff --git a/libstdc++-v3/testsuite/30_threads/stop_token/stop_callback/destructible_neg.cc b/libstdc++-v3/testsuite/30_threads/stop_token/stop_callback/destructible_neg.cc
index 2c5125b..cdbb2f4 100644
--- a/libstdc++-v3/testsuite/30_threads/stop_token/stop_callback/destructible_neg.cc
+++ b/libstdc++-v3/testsuite/30_threads/stop_token/stop_callback/destructible_neg.cc
@@ -54,3 +54,4 @@ test02(std::stop_token& tok, G& g)
}
// { dg-error "static assertion failed" "" { target *-*-* } 0 }
+// { dg-error "private within this context" "" { target *-*-* } 0 }
diff --git a/libstdc++-v3/testsuite/30_threads/stop_token/stop_callback/invocable_neg.cc b/libstdc++-v3/testsuite/30_threads/stop_token/stop_callback/invocable_neg.cc
index 93b3186..2b2fce4 100644
--- a/libstdc++-v3/testsuite/30_threads/stop_token/stop_callback/invocable_neg.cc
+++ b/libstdc++-v3/testsuite/30_threads/stop_token/stop_callback/invocable_neg.cc
@@ -32,3 +32,4 @@ test01(std::stop_token& tok, F& f)
}
// { dg-error "static assertion failed" "" { target *-*-* } 0 }
+// { dg-error "no match for call" "" { target *-*-* } 0 }
diff --git a/libstdc++-v3/testsuite/std/format/arguments/args_neg.cc b/libstdc++-v3/testsuite/std/format/arguments/args_neg.cc
index ded56fe..83c7b22 100644
--- a/libstdc++-v3/testsuite/std/format/arguments/args_neg.cc
+++ b/libstdc++-v3/testsuite/std/format/arguments/args_neg.cc
@@ -42,3 +42,4 @@ void test_const_arg()
}
// { dg-prune-output "no matching function for call to .*::basic_format_arg<" }
+// { dg-prune-output "use of deleted function" }
diff --git a/libstdc++-v3/testsuite/std/format/string_neg.cc b/libstdc++-v3/testsuite/std/format/string_neg.cc
index 09cc9a2..acae88e 100644
--- a/libstdc++-v3/testsuite/std/format/string_neg.cc
+++ b/libstdc++-v3/testsuite/std/format/string_neg.cc
@@ -8,3 +8,5 @@ auto s = std::format(" {9} "); // { dg-error "call to consteval function" }
struct X { };
std::format_string<X> str(""); // { dg-error "here" }
// { dg-error "std::formatter must be specialized" "" { target *-*-* } 0 }
+
+// { dg-prune-output "use of deleted function" }