Tested x86_64-linux. OK for trunk? -- >8 --
The standard says that std::launder is ill-formed for function pointers and cv void pointers, so there's no reason for __builtin_launder to accept them. This change allows implementations of std::launder to defer to the built-in for error checking, although libstdc++ will continue to diagnose it directly for more user-friendly diagnostics. PR c++/116673 gcc/cp/ChangeLog: * semantics.cc (finish_builtin_launder): Diagnose function pointers and cv void pointers. gcc/testsuite/ChangeLog: * g++.dg/cpp1z/launder10.C: New test. --- gcc/cp/semantics.cc | 17 +++++++++++++---- gcc/testsuite/g++.dg/cpp1z/launder10.C | 15 +++++++++++++++ 2 files changed, 28 insertions(+), 4 deletions(-) create mode 100644 gcc/testsuite/g++.dg/cpp1z/launder10.C diff --git a/gcc/cp/semantics.cc b/gcc/cp/semantics.cc index 63212afafb3..b194b01f865 100644 --- a/gcc/cp/semantics.cc +++ b/gcc/cp/semantics.cc @@ -13482,11 +13482,20 @@ finish_builtin_launder (location_t loc, tree arg, tsubst_flags_t complain) arg = decay_conversion (arg, complain); if (error_operand_p (arg)) return error_mark_node; - if (!type_dependent_expression_p (arg) - && !TYPE_PTR_P (TREE_TYPE (arg))) + if (!type_dependent_expression_p (arg)) { - error_at (loc, "non-pointer argument to %<__builtin_launder%>"); - return error_mark_node; + tree type = TREE_TYPE (arg); + if (!TYPE_PTR_P (type)) + { + error_at (loc, "non-pointer argument to %<__builtin_launder%>"); + return error_mark_node; + } + else if (!object_type_p (TREE_TYPE (type))) + { + // std::launder is ill-formed for function and cv void pointers. + error_at (loc, "invalid argument to %<__builtin_launder%>"); + return error_mark_node; + } } if (processing_template_decl) arg = orig_arg; diff --git a/gcc/testsuite/g++.dg/cpp1z/launder10.C b/gcc/testsuite/g++.dg/cpp1z/launder10.C new file mode 100644 index 00000000000..7c15eeb891f --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp1z/launder10.C @@ -0,0 +1,15 @@ +// PR c++/116673 +// { dg-do compile } + +void +bar (void *p) +{ + __builtin_launder (bar); // { dg-error {invalid argument to '__builtin_launder'} } + __builtin_launder (p); // { dg-error {invalid argument to '__builtin_launder'} } + const void* cp = p; + __builtin_launder (cp); // { dg-error {invalid argument to '__builtin_launder'} } + volatile void* vp = p; + __builtin_launder (vp); // { dg-error {invalid argument to '__builtin_launder'} } + const volatile void* cvp = p; + __builtin_launder (cvp); // { dg-error {invalid argument to '__builtin_launder'} } +} -- 2.46.0