diff options
| -rw-r--r-- | gcc/cp/cp-gimplify.cc | 14 | ||||
| -rw-r--r-- | gcc/testsuite/g++.dg/cpp1z/pr122185.C | 49 |
2 files changed, 61 insertions, 2 deletions
diff --git a/gcc/cp/cp-gimplify.cc b/gcc/cp/cp-gimplify.cc index 1662336e165..994d4deb0f1 100644 --- a/gcc/cp/cp-gimplify.cc +++ b/gcc/cp/cp-gimplify.cc @@ -3447,8 +3447,18 @@ cp_fold (tree x, fold_flags_t flags) || id_equal (DECL_NAME (callee), "as_const"))) { r = CALL_EXPR_ARG (x, 0); - r = build_nop (TREE_TYPE (x), r); - x = cp_fold (r, flags); + /* These type-checks must be performed here, because invalid + definitions of these functions could fail to ensure those and + build_nop could misbehave. See PR122185. */ + if (id_equal (DECL_NAME (callee), "to_underlying") + ? TREE_CODE (TREE_TYPE (r)) == ENUMERAL_TYPE + && INTEGRAL_TYPE_P (TREE_TYPE (x)) + : INDIRECT_TYPE_P (TREE_TYPE (x)) + && INDIRECT_TYPE_P (TREE_TYPE (r))) + { + r = build_nop (TREE_TYPE (x), r); + x = cp_fold (r, flags); + } break; } diff --git a/gcc/testsuite/g++.dg/cpp1z/pr122185.C b/gcc/testsuite/g++.dg/cpp1z/pr122185.C new file mode 100644 index 00000000000..73cba761b01 --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp1z/pr122185.C @@ -0,0 +1,49 @@ +// PR c++/122185 +// { dg-do compile { target c++17 } } +// { dg-options "-w -O2" } + +namespace std { +template <typename _Tp> struct remove_reference { + using type = __remove_reference(_Tp); +}; +template <typename _Tp> _Tp forward(typename remove_reference<_Tp>::type); +} +template <typename T> struct static_const { + static constexpr T value{}; +}; +template <typename, typename> struct adl_serializer; +template <template <typename, typename> class = adl_serializer> +class basic_json; +struct from_json_fn { + template <typename BasicJsonType, typename T> + void operator()(BasicJsonType, T) const; +}; +template <typename, typename> struct adl_serializer { + template <typename BasicJsonType, typename TargetType> + static void from_json(BasicJsonType &&j, TargetType val) { + static_const<from_json_fn>::value(std::forward<BasicJsonType>(j), val); + } +}; +struct iter_impl { + basic_json<> operator*(); + void operator++(); + bool operator!=(iter_impl); +}; +template <template <typename, typename = void> class JSONSerializer> +struct basic_json { + template <typename> using iter_impl = iter_impl; + using iterator = iter_impl<basic_json>; + template <typename> void get_impl(int) { + auto ret = int(); + JSONSerializer<int>::from_json(*this, ret); + } + template <typename> void get() { get_impl<int>({}); } + iterator begin(); + iterator end(); + char type_name; +}; +void _ValidateSignatureFile() { + basic_json signatures; + for (auto signature : signatures) + signature.get<int>(); +} |
