diff --git a/clang/docs/LanguageExtensions.rst b/clang/docs/LanguageExtensions.rst --- a/clang/docs/LanguageExtensions.rst +++ b/clang/docs/LanguageExtensions.rst @@ -66,6 +66,35 @@ ``__has_builtin`` should not be used to detect support for a builtin macro; use ``#ifdef`` instead. +``__has_constexpr_builtin`` +--------------------------- + +This function-like macro takes a single identifier argument that is the name of +a builtin function, a builtin pseudo-function (taking one or more type +arguments), or a builtin template. +It evaluates to 1 if the builtin is supported and can be constant evaluated or +0 if not. It can be used for writing conditionally constexpr code like this: + +.. code-block:: c++ + + #ifndef __has_constexpr_builtin // Optional of course. + #define __has_constexpr_builtin(x) 0 // Compatibility with non-clang compilers. + #endif + + ... + #if __has_constexpr_builtin(__builtin_fmax) + constexpr + #endif + double money_fee(double amount) { + return __builtin_fmax(amount * 0.03, 10.0); + } + ... + +For example, ``__has_constexpr_builtin`` is used in libcxx's implementation of +the ```` header file to conditionally make a function constexpr whenever +the constant evaluation of the corresponding builtin (for example, +``std::fmax`` calls ``__builtin_fmax``) is supported in Clang. + .. _langext-__has_feature-__has_extension: ``__has_feature`` and ``__has_extension`` diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst --- a/clang/docs/ReleaseNotes.rst +++ b/clang/docs/ReleaseNotes.rst @@ -360,6 +360,9 @@ timestamp to be used in replacement of the current date and time in the ``__DATE__``, ``__TIME__``, and ``__TIMESTAMP__`` macros. See ``_. +- Clang now supports ``__has_constexpr_builtin`` function-like macro that + evaluates to 1 if the builtin is supported and can be constant evaluated. + It can be used to writing conditionally constexpr code that uses builtins. New Compiler Flags ------------------ diff --git a/clang/include/clang/Basic/Builtins.h b/clang/include/clang/Basic/Builtins.h --- a/clang/include/clang/Basic/Builtins.h +++ b/clang/include/clang/Basic/Builtins.h @@ -263,6 +263,11 @@ /// for non-builtins. bool canBeRedeclared(unsigned ID) const; + /// Return true if this function can be constant evaluated by Clang frontend. + bool isConstantEvaluated(unsigned ID) const { + return strchr(getRecord(ID).Attributes, 'E') != nullptr; + } + private: const Info &getRecord(unsigned ID) const; diff --git a/clang/include/clang/Basic/Builtins.def b/clang/include/clang/Basic/Builtins.def --- a/clang/include/clang/Basic/Builtins.def +++ b/clang/include/clang/Basic/Builtins.def @@ -105,6 +105,7 @@ // C -> callback behavior: argument N is called with argument // M_0, ..., M_k as payload // z -> this is a function in (possibly-versioned) namespace std +// E -> this function can be constant evaluated by Clang frontend // FIXME: gcc has nonnull #if defined(BUILTIN) && !defined(LIBBUILTIN) @@ -121,16 +122,16 @@ BUILTIN(__builtin_atan2l, "LdLdLd", "Fne") BUILTIN(__builtin_atan2f128, "LLdLLdLLd", "Fne") BUILTIN(__builtin_abs , "ii" , "ncF") -BUILTIN(__builtin_copysign, "ddd", "ncF") -BUILTIN(__builtin_copysignf, "fff", "ncF") +BUILTIN(__builtin_copysign, "ddd", "ncFE") +BUILTIN(__builtin_copysignf, "fff", "ncFE") BUILTIN(__builtin_copysignf16, "hhh", "ncF") -BUILTIN(__builtin_copysignl, "LdLdLd", "ncF") -BUILTIN(__builtin_copysignf128, "LLdLLdLLd", "ncF") -BUILTIN(__builtin_fabs , "dd" , "ncF") -BUILTIN(__builtin_fabsf, "ff" , "ncF") -BUILTIN(__builtin_fabsl, "LdLd", "ncF") +BUILTIN(__builtin_copysignl, "LdLdLd", "ncFE") +BUILTIN(__builtin_copysignf128, "LLdLLdLLd", "ncFE") +BUILTIN(__builtin_fabs , "dd" , "ncFE") +BUILTIN(__builtin_fabsf, "ff" , "ncFE") +BUILTIN(__builtin_fabsl, "LdLd", "ncFE") BUILTIN(__builtin_fabsf16, "hh" , "ncF") -BUILTIN(__builtin_fabsf128, "LLdLLd", "ncF") +BUILTIN(__builtin_fabsf128, "LLdLLd", "ncFE") BUILTIN(__builtin_fmod , "ddd" , "Fne") BUILTIN(__builtin_fmodf, "fff" , "Fne") BUILTIN(__builtin_fmodf16, "hhh" , "Fne") @@ -140,16 +141,16 @@ BUILTIN(__builtin_frexpf, "ffi*" , "Fn") BUILTIN(__builtin_frexpl, "LdLdi*", "Fn") BUILTIN(__builtin_frexpf128, "LLdLLdi*", "Fn") -BUILTIN(__builtin_huge_val, "d", "nc") -BUILTIN(__builtin_huge_valf, "f", "nc") -BUILTIN(__builtin_huge_vall, "Ld", "nc") -BUILTIN(__builtin_huge_valf16, "x", "nc") -BUILTIN(__builtin_huge_valf128, "LLd", "nc") -BUILTIN(__builtin_inf , "d" , "nc") -BUILTIN(__builtin_inff , "f" , "nc") -BUILTIN(__builtin_infl , "Ld" , "nc") -BUILTIN(__builtin_inff16 , "x" , "nc") -BUILTIN(__builtin_inff128 , "LLd" , "nc") +BUILTIN(__builtin_huge_val, "d", "ncE") +BUILTIN(__builtin_huge_valf, "f", "ncE") +BUILTIN(__builtin_huge_vall, "Ld", "ncE") +BUILTIN(__builtin_huge_valf16, "x", "ncE") +BUILTIN(__builtin_huge_valf128, "LLd", "ncE") +BUILTIN(__builtin_inf , "d" , "ncE") +BUILTIN(__builtin_inff , "f" , "ncE") +BUILTIN(__builtin_infl , "Ld" , "ncE") +BUILTIN(__builtin_inff16 , "x" , "ncE") +BUILTIN(__builtin_inff128 , "LLd" , "ncE") BUILTIN(__builtin_labs , "LiLi" , "Fnc") BUILTIN(__builtin_llabs, "LLiLLi", "Fnc") BUILTIN(__builtin_ldexp , "ddi" , "Fne") @@ -160,16 +161,16 @@ BUILTIN(__builtin_modff, "fff*" , "Fn") BUILTIN(__builtin_modfl, "LdLdLd*", "Fn") BUILTIN(__builtin_modff128, "LLdLLdLLd*", "Fn") -BUILTIN(__builtin_nan, "dcC*" , "FnU") -BUILTIN(__builtin_nanf, "fcC*" , "FnU") -BUILTIN(__builtin_nanl, "LdcC*", "FnU") -BUILTIN(__builtin_nanf16, "xcC*", "FnU") -BUILTIN(__builtin_nanf128, "LLdcC*", "FnU") -BUILTIN(__builtin_nans, "dcC*" , "FnU") -BUILTIN(__builtin_nansf, "fcC*" , "FnU") -BUILTIN(__builtin_nansl, "LdcC*", "FnU") -BUILTIN(__builtin_nansf16, "xcC*", "FnU") -BUILTIN(__builtin_nansf128, "LLdcC*", "FnU") +BUILTIN(__builtin_nan, "dcC*" , "FnUE") +BUILTIN(__builtin_nanf, "fcC*" , "FnUE") +BUILTIN(__builtin_nanl, "LdcC*", "FnUE") +BUILTIN(__builtin_nanf16, "xcC*", "FnUE") +BUILTIN(__builtin_nanf128, "LLdcC*", "FnUE") +BUILTIN(__builtin_nans, "dcC*" , "FnUE") +BUILTIN(__builtin_nansf, "fcC*" , "FnUE") +BUILTIN(__builtin_nansl, "LdcC*", "FnUE") +BUILTIN(__builtin_nansf16, "xcC*", "FnUE") +BUILTIN(__builtin_nansf128, "LLdcC*", "FnUE") BUILTIN(__builtin_powi , "ddi" , "Fnc") BUILTIN(__builtin_powif, "ffi" , "Fnc") BUILTIN(__builtin_powil, "LdLdi", "Fnc") @@ -258,16 +259,16 @@ BUILTIN(__builtin_fmaf16, "hhhh", "Fne") BUILTIN(__builtin_fmal, "LdLdLdLd", "Fne") BUILTIN(__builtin_fmaf128, "LLdLLdLLdLLd", "Fne") -BUILTIN(__builtin_fmax, "ddd", "Fnc") -BUILTIN(__builtin_fmaxf, "fff", "Fnc") -BUILTIN(__builtin_fmaxf16, "hhh", "Fnc") -BUILTIN(__builtin_fmaxl, "LdLdLd", "Fnc") -BUILTIN(__builtin_fmaxf128, "LLdLLdLLd", "Fnc") -BUILTIN(__builtin_fmin, "ddd", "Fnc") -BUILTIN(__builtin_fminf, "fff", "Fnc") -BUILTIN(__builtin_fminf16, "hhh", "Fnc") -BUILTIN(__builtin_fminl, "LdLdLd", "Fnc") -BUILTIN(__builtin_fminf128, "LLdLLdLLd", "Fnc") +BUILTIN(__builtin_fmax, "ddd", "FncE") +BUILTIN(__builtin_fmaxf, "fff", "FncE") +BUILTIN(__builtin_fmaxf16, "hhh", "FncE") +BUILTIN(__builtin_fmaxl, "LdLdLd", "FncE") +BUILTIN(__builtin_fmaxf128, "LLdLLdLLd", "FncE") +BUILTIN(__builtin_fmin, "ddd", "FncE") +BUILTIN(__builtin_fminf, "fff", "FncE") +BUILTIN(__builtin_fminf16, "hhh", "FncE") +BUILTIN(__builtin_fminl, "LdLdLd", "FncE") +BUILTIN(__builtin_fminf128, "LLdLLdLLd", "FncE") BUILTIN(__builtin_hypot , "ddd" , "Fne") BUILTIN(__builtin_hypotf, "fff" , "Fne") BUILTIN(__builtin_hypotl, "LdLdLd", "Fne") @@ -461,7 +462,7 @@ BUILTIN(__builtin_ctanhl, "XLdXLd", "Fne") // GCC-compatible C99 CMPLX implementation. -BUILTIN(__builtin_complex, "v.", "nct") +BUILTIN(__builtin_complex, "v.", "nctE") // FP Comparisons. BUILTIN(__builtin_isgreater , "i.", "Fnct") @@ -472,12 +473,12 @@ BUILTIN(__builtin_isunordered , "i.", "Fnct") // Unary FP classification -BUILTIN(__builtin_fpclassify, "iiiiii.", "Fnct") -BUILTIN(__builtin_isfinite, "i.", "Fnct") -BUILTIN(__builtin_isinf, "i.", "Fnct") -BUILTIN(__builtin_isinf_sign, "i.", "Fnct") -BUILTIN(__builtin_isnan, "i.", "Fnct") -BUILTIN(__builtin_isnormal, "i.", "Fnct") +BUILTIN(__builtin_fpclassify, "iiiiii.", "FnctE") +BUILTIN(__builtin_isfinite, "i.", "FnctE") +BUILTIN(__builtin_isinf, "i.", "FnctE") +BUILTIN(__builtin_isinf_sign, "i.", "FnctE") +BUILTIN(__builtin_isnan, "i.", "FnctE") +BUILTIN(__builtin_isnormal, "i.", "FnctE") // FP signbit builtins BUILTIN(__builtin_signbit, "i.", "Fnct") @@ -491,73 +492,73 @@ BUILTIN(__builtin_canonicalizel, "LdLd", "nc") // Builtins for arithmetic. -BUILTIN(__builtin_clzs , "iUs" , "nc") -BUILTIN(__builtin_clz , "iUi" , "nc") -BUILTIN(__builtin_clzl , "iULi" , "nc") -BUILTIN(__builtin_clzll, "iULLi", "nc") +BUILTIN(__builtin_clzs , "iUs" , "ncE") +BUILTIN(__builtin_clz , "iUi" , "ncE") +BUILTIN(__builtin_clzl , "iULi" , "ncE") +BUILTIN(__builtin_clzll, "iULLi", "ncE") // TODO: int clzimax(uintmax_t) -BUILTIN(__builtin_ctzs , "iUs" , "nc") -BUILTIN(__builtin_ctz , "iUi" , "nc") -BUILTIN(__builtin_ctzl , "iULi" , "nc") -BUILTIN(__builtin_ctzll, "iULLi", "nc") +BUILTIN(__builtin_ctzs , "iUs" , "ncE") +BUILTIN(__builtin_ctz , "iUi" , "ncE") +BUILTIN(__builtin_ctzl , "iULi" , "ncE") +BUILTIN(__builtin_ctzll, "iULLi", "ncE") // TODO: int ctzimax(uintmax_t) -BUILTIN(__builtin_ffs , "ii" , "Fnc") -BUILTIN(__builtin_ffsl , "iLi" , "Fnc") -BUILTIN(__builtin_ffsll, "iLLi", "Fnc") -BUILTIN(__builtin_parity , "iUi" , "nc") -BUILTIN(__builtin_parityl , "iULi" , "nc") -BUILTIN(__builtin_parityll, "iULLi", "nc") -BUILTIN(__builtin_popcount , "iUi" , "nc") -BUILTIN(__builtin_popcountl , "iULi" , "nc") -BUILTIN(__builtin_popcountll, "iULLi", "nc") -BUILTIN(__builtin_clrsb , "ii" , "nc") -BUILTIN(__builtin_clrsbl , "iLi" , "nc") -BUILTIN(__builtin_clrsbll, "iLLi", "nc") +BUILTIN(__builtin_ffs , "ii" , "FncE") +BUILTIN(__builtin_ffsl , "iLi" , "FncE") +BUILTIN(__builtin_ffsll, "iLLi", "FncE") +BUILTIN(__builtin_parity , "iUi" , "ncE") +BUILTIN(__builtin_parityl , "iULi" , "ncE") +BUILTIN(__builtin_parityll, "iULLi", "ncE") +BUILTIN(__builtin_popcount , "iUi" , "ncE") +BUILTIN(__builtin_popcountl , "iULi" , "ncE") +BUILTIN(__builtin_popcountll, "iULLi", "ncE") +BUILTIN(__builtin_clrsb , "ii" , "ncE") +BUILTIN(__builtin_clrsbl , "iLi" , "ncE") +BUILTIN(__builtin_clrsbll, "iLLi", "ncE") // The following builtins rely on that char == 8 bits, short == 16 bits and that // there exists native types on the target that are 32- and 64-bits wide, unless // these conditions are fulfilled these builtins will operate on a not intended // bitwidth. -BUILTIN(__builtin_bswap16, "UsUs", "nc") -BUILTIN(__builtin_bswap32, "UZiUZi", "nc") -BUILTIN(__builtin_bswap64, "UWiUWi", "nc") - -BUILTIN(__builtin_bitreverse8, "UcUc", "nc") -BUILTIN(__builtin_bitreverse16, "UsUs", "nc") -BUILTIN(__builtin_bitreverse32, "UZiUZi", "nc") -BUILTIN(__builtin_bitreverse64, "UWiUWi", "nc") - -BUILTIN(__builtin_rotateleft8, "UcUcUc", "nc") -BUILTIN(__builtin_rotateleft16, "UsUsUs", "nc") -BUILTIN(__builtin_rotateleft32, "UZiUZiUZi", "nc") -BUILTIN(__builtin_rotateleft64, "UWiUWiUWi", "nc") -BUILTIN(__builtin_rotateright8, "UcUcUc", "nc") -BUILTIN(__builtin_rotateright16, "UsUsUs", "nc") -BUILTIN(__builtin_rotateright32, "UZiUZiUZi", "nc") -BUILTIN(__builtin_rotateright64, "UWiUWiUWi", "nc") +BUILTIN(__builtin_bswap16, "UsUs", "ncE") +BUILTIN(__builtin_bswap32, "UZiUZi", "ncE") +BUILTIN(__builtin_bswap64, "UWiUWi", "ncE") + +BUILTIN(__builtin_bitreverse8, "UcUc", "ncE") +BUILTIN(__builtin_bitreverse16, "UsUs", "ncE") +BUILTIN(__builtin_bitreverse32, "UZiUZi", "ncE") +BUILTIN(__builtin_bitreverse64, "UWiUWi", "ncE") + +BUILTIN(__builtin_rotateleft8, "UcUcUc", "ncE") +BUILTIN(__builtin_rotateleft16, "UsUsUs", "ncE") +BUILTIN(__builtin_rotateleft32, "UZiUZiUZi", "ncE") +BUILTIN(__builtin_rotateleft64, "UWiUWiUWi", "ncE") +BUILTIN(__builtin_rotateright8, "UcUcUc", "ncE") +BUILTIN(__builtin_rotateright16, "UsUsUs", "ncE") +BUILTIN(__builtin_rotateright32, "UZiUZiUZi", "ncE") +BUILTIN(__builtin_rotateright64, "UWiUWiUWi", "ncE") // Random GCC builtins BUILTIN(__builtin_calloc, "v*zz", "nF") -BUILTIN(__builtin_constant_p, "i.", "nctu") -BUILTIN(__builtin_classify_type, "i.", "nctu") -BUILTIN(__builtin___CFStringMakeConstantString, "FC*cC*", "nc") -BUILTIN(__builtin___NSStringMakeConstantString, "FC*cC*", "nc") +BUILTIN(__builtin_constant_p, "i.", "nctuE") +BUILTIN(__builtin_classify_type, "i.", "nctuE") +BUILTIN(__builtin___CFStringMakeConstantString, "FC*cC*", "ncE") +BUILTIN(__builtin___NSStringMakeConstantString, "FC*cC*", "ncE") BUILTIN(__builtin_va_start, "vA.", "nt") BUILTIN(__builtin_va_end, "vA", "n") BUILTIN(__builtin_va_copy, "vAA", "n") BUILTIN(__builtin_stdarg_start, "vA.", "nt") -BUILTIN(__builtin_assume_aligned, "v*vC*z.", "nct") -BUILTIN(__builtin_bcmp, "ivC*vC*z", "Fn") +BUILTIN(__builtin_assume_aligned, "v*vC*z.", "nctE") +BUILTIN(__builtin_bcmp, "ivC*vC*z", "FnE") BUILTIN(__builtin_bcopy, "vv*v*z", "n") BUILTIN(__builtin_bzero, "vv*z", "nF") BUILTIN(__builtin_fprintf, "iP*cC*.", "Fp:1:") BUILTIN(__builtin_free, "vv*", "nF") BUILTIN(__builtin_malloc, "v*z", "nF") -BUILTIN(__builtin_memchr, "v*vC*iz", "nF") -BUILTIN(__builtin_memcmp, "ivC*vC*z", "nF") -BUILTIN(__builtin_memcpy, "v*v*vC*z", "nF") +BUILTIN(__builtin_memchr, "v*vC*iz", "nFE") +BUILTIN(__builtin_memcmp, "ivC*vC*z", "nFE") +BUILTIN(__builtin_memcpy, "v*v*vC*z", "nFE") BUILTIN(__builtin_memcpy_inline, "vv*vC*Iz", "n") -BUILTIN(__builtin_memmove, "v*v*vC*z", "nF") +BUILTIN(__builtin_memmove, "v*v*vC*z", "nFE") BUILTIN(__builtin_mempcpy, "v*v*vC*z", "nF") BUILTIN(__builtin_memset, "v*v*iz", "nF") BUILTIN(__builtin_memset_inline, "vv*iIz", "n") @@ -566,29 +567,29 @@ BUILTIN(__builtin_stpncpy, "c*c*cC*z", "nF") BUILTIN(__builtin_strcasecmp, "icC*cC*", "nF") BUILTIN(__builtin_strcat, "c*c*cC*", "nF") -BUILTIN(__builtin_strchr, "c*cC*i", "nF") -BUILTIN(__builtin_strcmp, "icC*cC*", "nF") +BUILTIN(__builtin_strchr, "c*cC*i", "nFE") +BUILTIN(__builtin_strcmp, "icC*cC*", "nFE") BUILTIN(__builtin_strcpy, "c*c*cC*", "nF") BUILTIN(__builtin_strcspn, "zcC*cC*", "nF") BUILTIN(__builtin_strdup, "c*cC*", "nF") -BUILTIN(__builtin_strlen, "zcC*", "nF") +BUILTIN(__builtin_strlen, "zcC*", "nFE") BUILTIN(__builtin_strncasecmp, "icC*cC*z", "nF") BUILTIN(__builtin_strncat, "c*c*cC*z", "nF") -BUILTIN(__builtin_strncmp, "icC*cC*z", "nF") +BUILTIN(__builtin_strncmp, "icC*cC*z", "nFE") BUILTIN(__builtin_strncpy, "c*c*cC*z", "nF") BUILTIN(__builtin_strndup, "c*cC*z", "nF") BUILTIN(__builtin_strpbrk, "c*cC*cC*", "nF") BUILTIN(__builtin_strrchr, "c*cC*i", "nF") BUILTIN(__builtin_strspn, "zcC*cC*", "nF") BUILTIN(__builtin_strstr, "c*cC*cC*", "nF") -BUILTIN(__builtin_wcschr, "w*wC*w", "nF") -BUILTIN(__builtin_wcscmp, "iwC*wC*", "nF") -BUILTIN(__builtin_wcslen, "zwC*", "nF") -BUILTIN(__builtin_wcsncmp, "iwC*wC*z", "nF") -BUILTIN(__builtin_wmemchr, "w*wC*wz", "nF") -BUILTIN(__builtin_wmemcmp, "iwC*wC*z", "nF") -BUILTIN(__builtin_wmemcpy, "w*w*wC*z", "nF") -BUILTIN(__builtin_wmemmove, "w*w*wC*z", "nF") +BUILTIN(__builtin_wcschr, "w*wC*w", "nFE") +BUILTIN(__builtin_wcscmp, "iwC*wC*", "nFE") +BUILTIN(__builtin_wcslen, "zwC*", "nFE") +BUILTIN(__builtin_wcsncmp, "iwC*wC*z", "nFE") +BUILTIN(__builtin_wmemchr, "w*wC*wz", "nFE") +BUILTIN(__builtin_wmemcmp, "iwC*wC*z", "nFE") +BUILTIN(__builtin_wmemcpy, "w*w*wC*z", "nFE") +BUILTIN(__builtin_wmemmove, "w*w*wC*z", "nFE") BUILTIN(__builtin_realloc, "v*v*z", "nF") BUILTIN(__builtin_return_address, "v*IUi", "n") BUILTIN(__builtin_extract_return_addr, "v*v*", "n") @@ -597,14 +598,14 @@ BUILTIN(__builtin_setjmp, "iv**", "j") BUILTIN(__builtin_longjmp, "vv**i", "r") BUILTIN(__builtin_unwind_init, "v", "") -BUILTIN(__builtin_eh_return_data_regno, "iIi", "nc") +BUILTIN(__builtin_eh_return_data_regno, "iIi", "ncE") BUILTIN(__builtin_snprintf, "ic*zcC*.", "nFp:2:") BUILTIN(__builtin_sprintf, "ic*cC*.", "nFP:1:") BUILTIN(__builtin_vsnprintf, "ic*zcC*a", "nFP:2:") BUILTIN(__builtin_vsprintf, "ic*cC*a", "nFP:1:") BUILTIN(__builtin_thread_pointer, "v*", "nc") -BUILTIN(__builtin_launder, "v*v*", "nt") -LANGBUILTIN(__builtin_is_constant_evaluated, "b", "n", CXX_LANG) +BUILTIN(__builtin_launder, "v*v*", "ntE") +LANGBUILTIN(__builtin_is_constant_evaluated, "b", "nE", CXX_LANG) // GCC exception builtins BUILTIN(__builtin_eh_return, "vzv*", "r") // FIXME: Takes intptr_t, not size_t! @@ -615,8 +616,8 @@ BUILTIN(__builtin_extend_pointer, "ULLiv*", "n") // _Unwind_Word == uint64_t // GCC Object size checking builtins -BUILTIN(__builtin_object_size, "zvC*i", "nu") -BUILTIN(__builtin_dynamic_object_size, "zvC*i", "nu") // Clang only. +BUILTIN(__builtin_object_size, "zvC*i", "nuE") +BUILTIN(__builtin_dynamic_object_size, "zvC*i", "nuE") // Clang only. BUILTIN(__builtin___memcpy_chk, "v*v*vC*zz", "nF") BUILTIN(__builtin___memccpy_chk, "v*v*vC*izz", "nF") BUILTIN(__builtin___memmove_chk, "v*v*vC*zz", "nF") @@ -640,8 +641,8 @@ BUILTIN(__builtin___vprintf_chk, "iicC*a", "FP:1:") BUILTIN(__builtin_unpredictable, "LiLi" , "nc") -BUILTIN(__builtin_expect, "LiLiLi" , "nc") -BUILTIN(__builtin_expect_with_probability, "LiLiLid", "nc") +BUILTIN(__builtin_expect, "LiLiLi" , "ncE") +BUILTIN(__builtin_expect_with_probability, "LiLiLid", "ncE") BUILTIN(__builtin_prefetch, "vvC*.", "nc") BUILTIN(__builtin_readcyclecounter, "ULLi", "n") BUILTIN(__builtin_trap, "v", "nr") @@ -826,7 +827,7 @@ ATOMIC_BUILTIN(__c11_atomic_fetch_min, "v.", "t") BUILTIN(__c11_atomic_thread_fence, "vi", "n") BUILTIN(__c11_atomic_signal_fence, "vi", "n") -BUILTIN(__c11_atomic_is_lock_free, "bz", "n") +BUILTIN(__c11_atomic_is_lock_free, "bz", "nE") // GNU atomic builtins. ATOMIC_BUILTIN(__atomic_load, "v.", "t") @@ -855,8 +856,8 @@ BUILTIN(__atomic_clear, "vvD*i", "n") BUILTIN(__atomic_thread_fence, "vi", "n") BUILTIN(__atomic_signal_fence, "vi", "n") -BUILTIN(__atomic_always_lock_free, "bzvCD*", "n") -BUILTIN(__atomic_is_lock_free, "bzvCD*", "n") +BUILTIN(__atomic_always_lock_free, "bzvCD*", "nE") +BUILTIN(__atomic_is_lock_free, "bzvCD*", "nE") // OpenCL 2.0 atomic builtins. ATOMIC_BUILTIN(__opencl_atomic_init, "v.", "t") @@ -911,7 +912,7 @@ // Microsoft builtins. These are only active with -fms-extensions. LANGBUILTIN(_alloca, "v*z", "n", ALL_MS_LANGUAGES) LANGBUILTIN(__annotation, "wC*.","n", ALL_MS_LANGUAGES) -LANGBUILTIN(__assume, "vb", "n", ALL_MS_LANGUAGES) +LANGBUILTIN(__assume, "vb", "nE", ALL_MS_LANGUAGES) LANGBUILTIN(_bittest, "UcNiC*Ni", "n", ALL_MS_LANGUAGES) LANGBUILTIN(_bittestandcomplement, "UcNi*Ni", "n", ALL_MS_LANGUAGES) LANGBUILTIN(_bittestandreset, "UcNi*Ni", "n", ALL_MS_LANGUAGES) @@ -986,16 +987,16 @@ LANGBUILTIN(__popcnt, "UiUi", "nc", ALL_MS_LANGUAGES) LANGBUILTIN(__popcnt64, "UWiUWi", "nc", ALL_MS_LANGUAGES) LANGBUILTIN(_ReturnAddress, "v*", "n", ALL_MS_LANGUAGES) -LANGBUILTIN(_rotl8, "UcUcUc", "n", ALL_MS_LANGUAGES) -LANGBUILTIN(_rotl16, "UsUsUc", "n", ALL_MS_LANGUAGES) -LANGBUILTIN(_rotl, "UiUii", "n", ALL_MS_LANGUAGES) -LANGBUILTIN(_lrotl, "ULiULii", "n", ALL_MS_LANGUAGES) -LANGBUILTIN(_rotl64, "UWiUWii", "n", ALL_MS_LANGUAGES) -LANGBUILTIN(_rotr8, "UcUcUc", "n", ALL_MS_LANGUAGES) -LANGBUILTIN(_rotr16, "UsUsUc", "n", ALL_MS_LANGUAGES) -LANGBUILTIN(_rotr, "UiUii", "n", ALL_MS_LANGUAGES) -LANGBUILTIN(_lrotr, "ULiULii", "n", ALL_MS_LANGUAGES) -LANGBUILTIN(_rotr64, "UWiUWii", "n", ALL_MS_LANGUAGES) +LANGBUILTIN(_rotl8, "UcUcUc", "nE", ALL_MS_LANGUAGES) +LANGBUILTIN(_rotl16, "UsUsUc", "nE", ALL_MS_LANGUAGES) +LANGBUILTIN(_rotl, "UiUii", "nE", ALL_MS_LANGUAGES) +LANGBUILTIN(_lrotl, "ULiULii", "nE", ALL_MS_LANGUAGES) +LANGBUILTIN(_rotl64, "UWiUWii", "nE", ALL_MS_LANGUAGES) +LANGBUILTIN(_rotr8, "UcUcUc", "nE", ALL_MS_LANGUAGES) +LANGBUILTIN(_rotr16, "UsUsUc", "nE", ALL_MS_LANGUAGES) +LANGBUILTIN(_rotr, "UiUii", "nE", ALL_MS_LANGUAGES) +LANGBUILTIN(_lrotr, "ULiULii", "nE", ALL_MS_LANGUAGES) +LANGBUILTIN(_rotr64, "UWiUWii", "nE", ALL_MS_LANGUAGES) LANGBUILTIN(__va_start, "vc**.", "nt", ALL_MS_LANGUAGES) LANGBUILTIN(__fastfail, "vUi", "nr", ALL_MS_LANGUAGES) @@ -1025,18 +1026,18 @@ // C11 stdlib.h LIBBUILTIN(aligned_alloc, "v*zz", "f", "stdlib.h", ALL_LANGUAGES) // C99 string.h -LIBBUILTIN(memcpy, "v*v*vC*z", "f", "string.h", ALL_LANGUAGES) -LIBBUILTIN(memcmp, "ivC*vC*z", "f", "string.h", ALL_LANGUAGES) -LIBBUILTIN(memmove, "v*v*vC*z", "f", "string.h", ALL_LANGUAGES) +LIBBUILTIN(memcpy, "v*v*vC*z", "fE", "string.h", ALL_LANGUAGES) +LIBBUILTIN(memcmp, "ivC*vC*z", "fE", "string.h", ALL_LANGUAGES) +LIBBUILTIN(memmove, "v*v*vC*z", "fE", "string.h", ALL_LANGUAGES) LIBBUILTIN(strcpy, "c*c*cC*", "f", "string.h", ALL_LANGUAGES) LIBBUILTIN(strncpy, "c*c*cC*z", "f", "string.h", ALL_LANGUAGES) -LIBBUILTIN(strcmp, "icC*cC*", "f", "string.h", ALL_LANGUAGES) -LIBBUILTIN(strncmp, "icC*cC*z", "f", "string.h", ALL_LANGUAGES) +LIBBUILTIN(strcmp, "icC*cC*", "fE", "string.h", ALL_LANGUAGES) +LIBBUILTIN(strncmp, "icC*cC*z", "fE", "string.h", ALL_LANGUAGES) LIBBUILTIN(strcat, "c*c*cC*", "f", "string.h", ALL_LANGUAGES) LIBBUILTIN(strncat, "c*c*cC*z", "f", "string.h", ALL_LANGUAGES) LIBBUILTIN(strxfrm, "zc*cC*z", "f", "string.h", ALL_LANGUAGES) -LIBBUILTIN(memchr, "v*vC*iz", "f", "string.h", ALL_LANGUAGES) -LIBBUILTIN(strchr, "c*cC*i", "f", "string.h", ALL_LANGUAGES) +LIBBUILTIN(memchr, "v*vC*iz", "fE", "string.h", ALL_LANGUAGES) +LIBBUILTIN(strchr, "c*cC*i", "fE", "string.h", ALL_LANGUAGES) LIBBUILTIN(strcspn, "zcC*cC*", "f", "string.h", ALL_LANGUAGES) LIBBUILTIN(strpbrk, "c*cC*cC*", "f", "string.h", ALL_LANGUAGES) LIBBUILTIN(strrchr, "c*cC*i", "f", "string.h", ALL_LANGUAGES) @@ -1045,7 +1046,7 @@ LIBBUILTIN(strtok, "c*c*cC*", "f", "string.h", ALL_LANGUAGES) LIBBUILTIN(memset, "v*v*iz", "f", "string.h", ALL_LANGUAGES) LIBBUILTIN(strerror, "c*i", "f", "string.h", ALL_LANGUAGES) -LIBBUILTIN(strlen, "zcC*", "f", "string.h", ALL_LANGUAGES) +LIBBUILTIN(strlen, "zcC*", "fE", "string.h", ALL_LANGUAGES) // C99 stdio.h // FIXME: This list is incomplete. LIBBUILTIN(printf, "icC*.", "fp:0:", "stdio.h", ALL_LANGUAGES) @@ -1084,14 +1085,14 @@ // C99 wchar.h // FIXME: This list is incomplete. We should cover at least the functions that // take format strings. -LIBBUILTIN(wcschr, "w*wC*w", "f", "wchar.h", ALL_LANGUAGES) -LIBBUILTIN(wcscmp, "iwC*wC*", "f", "wchar.h", ALL_LANGUAGES) -LIBBUILTIN(wcslen, "zwC*", "f", "wchar.h", ALL_LANGUAGES) -LIBBUILTIN(wcsncmp, "iwC*wC*z", "f", "wchar.h", ALL_LANGUAGES) -LIBBUILTIN(wmemchr, "w*wC*wz", "f", "wchar.h", ALL_LANGUAGES) -LIBBUILTIN(wmemcmp, "iwC*wC*z", "f", "wchar.h", ALL_LANGUAGES) -LIBBUILTIN(wmemcpy, "w*w*wC*z", "f", "wchar.h", ALL_LANGUAGES) -LIBBUILTIN(wmemmove,"w*w*wC*z", "f", "wchar.h", ALL_LANGUAGES) +LIBBUILTIN(wcschr, "w*wC*w", "fE", "wchar.h", ALL_LANGUAGES) +LIBBUILTIN(wcscmp, "iwC*wC*", "fE", "wchar.h", ALL_LANGUAGES) +LIBBUILTIN(wcslen, "zwC*", "fE", "wchar.h", ALL_LANGUAGES) +LIBBUILTIN(wcsncmp, "iwC*wC*z", "fE", "wchar.h", ALL_LANGUAGES) +LIBBUILTIN(wmemchr, "w*wC*wz", "fE", "wchar.h", ALL_LANGUAGES) +LIBBUILTIN(wmemcmp, "iwC*wC*z", "fE", "wchar.h", ALL_LANGUAGES) +LIBBUILTIN(wmemcpy, "w*w*wC*z", "fE", "wchar.h", ALL_LANGUAGES) +LIBBUILTIN(wmemmove,"w*w*wC*z", "fE", "wchar.h", ALL_LANGUAGES) // C99 // In some systems setjmp is a macro that expands to _setjmp. We undefine @@ -1118,7 +1119,7 @@ LIBBUILTIN(index, "c*cC*i", "f", "strings.h", ALL_GNU_LANGUAGES) LIBBUILTIN(rindex, "c*cC*i", "f", "strings.h", ALL_GNU_LANGUAGES) LIBBUILTIN(bzero, "vv*z", "f", "strings.h", ALL_GNU_LANGUAGES) -LIBBUILTIN(bcmp, "ivC*vC*z", "f", "strings.h", ALL_GNU_LANGUAGES) +LIBBUILTIN(bcmp, "ivC*vC*z", "fE", "strings.h", ALL_GNU_LANGUAGES) // In some systems str[n]casejmp is a macro that expands to _str[n]icmp. // We undefine then here to avoid wrong name. #undef strcasecmp @@ -1555,19 +1556,19 @@ // FIXME: Also declare NSConcreteGlobalBlock and NSConcreteStackBlock. // C++ standard library builtins in namespace 'std'. -LIBBUILTIN(addressof, "v*v&", "zfncTh", "memory", CXX_LANG) +LIBBUILTIN(addressof, "v*v&", "zfncThE", "memory", CXX_LANG) // Synonym for addressof used internally by libstdc++. -LANGBUILTIN(__addressof, "v*v&", "zfncT", CXX_LANG) -LIBBUILTIN(as_const, "v&v&", "zfncTh", "utility", CXX_LANG) -LIBBUILTIN(forward, "v&v&", "zfncTh", "utility", CXX_LANG) -LIBBUILTIN(move, "v&v&", "zfncTh", "utility", CXX_LANG) -LIBBUILTIN(move_if_noexcept, "v&v&", "zfncTh", "utility", CXX_LANG) +LANGBUILTIN(__addressof, "v*v&", "zfncTE", CXX_LANG) +LIBBUILTIN(as_const, "v&v&", "zfncThE", "utility", CXX_LANG) +LIBBUILTIN(forward, "v&v&", "zfncThE", "utility", CXX_LANG) +LIBBUILTIN(move, "v&v&", "zfncThE", "utility", CXX_LANG) +LIBBUILTIN(move_if_noexcept, "v&v&", "zfncThE", "utility", CXX_LANG) // Annotation function BUILTIN(__builtin_annotation, "v.", "tn") // Invariants -BUILTIN(__builtin_assume, "vb", "n") +BUILTIN(__builtin_assume, "vb", "nE") // Multiprecision Arithmetic Builtins. BUILTIN(__builtin_addcb, "UcUcCUcCUcCUc*", "n") @@ -1582,41 +1583,41 @@ BUILTIN(__builtin_subcll, "ULLiULLiCULLiCULLiCULLi*", "n") // Checked Arithmetic Builtins for Security. -BUILTIN(__builtin_add_overflow, "b.", "nt") -BUILTIN(__builtin_sub_overflow, "b.", "nt") -BUILTIN(__builtin_mul_overflow, "b.", "nt") -BUILTIN(__builtin_uadd_overflow, "bUiCUiCUi*", "n") -BUILTIN(__builtin_uaddl_overflow, "bULiCULiCULi*", "n") -BUILTIN(__builtin_uaddll_overflow, "bULLiCULLiCULLi*", "n") -BUILTIN(__builtin_usub_overflow, "bUiCUiCUi*", "n") -BUILTIN(__builtin_usubl_overflow, "bULiCULiCULi*", "n") -BUILTIN(__builtin_usubll_overflow, "bULLiCULLiCULLi*", "n") -BUILTIN(__builtin_umul_overflow, "bUiCUiCUi*", "n") -BUILTIN(__builtin_umull_overflow, "bULiCULiCULi*", "n") -BUILTIN(__builtin_umulll_overflow, "bULLiCULLiCULLi*", "n") -BUILTIN(__builtin_sadd_overflow, "bSiCSiCSi*", "n") -BUILTIN(__builtin_saddl_overflow, "bSLiCSLiCSLi*", "n") -BUILTIN(__builtin_saddll_overflow, "bSLLiCSLLiCSLLi*", "n") -BUILTIN(__builtin_ssub_overflow, "bSiCSiCSi*", "n") -BUILTIN(__builtin_ssubl_overflow, "bSLiCSLiCSLi*", "n") -BUILTIN(__builtin_ssubll_overflow, "bSLLiCSLLiCSLLi*", "n") -BUILTIN(__builtin_smul_overflow, "bSiCSiCSi*", "n") -BUILTIN(__builtin_smull_overflow, "bSLiCSLiCSLi*", "n") -BUILTIN(__builtin_smulll_overflow, "bSLLiCSLLiCSLLi*", "n") +BUILTIN(__builtin_add_overflow, "b.", "ntE") +BUILTIN(__builtin_sub_overflow, "b.", "ntE") +BUILTIN(__builtin_mul_overflow, "b.", "ntE") +BUILTIN(__builtin_uadd_overflow, "bUiCUiCUi*", "nE") +BUILTIN(__builtin_uaddl_overflow, "bULiCULiCULi*", "nE") +BUILTIN(__builtin_uaddll_overflow, "bULLiCULLiCULLi*", "nE") +BUILTIN(__builtin_usub_overflow, "bUiCUiCUi*", "nE") +BUILTIN(__builtin_usubl_overflow, "bULiCULiCULi*", "nE") +BUILTIN(__builtin_usubll_overflow, "bULLiCULLiCULLi*", "nE") +BUILTIN(__builtin_umul_overflow, "bUiCUiCUi*", "nE") +BUILTIN(__builtin_umull_overflow, "bULiCULiCULi*", "nE") +BUILTIN(__builtin_umulll_overflow, "bULLiCULLiCULLi*", "nE") +BUILTIN(__builtin_sadd_overflow, "bSiCSiCSi*", "nE") +BUILTIN(__builtin_saddl_overflow, "bSLiCSLiCSLi*", "nE") +BUILTIN(__builtin_saddll_overflow, "bSLLiCSLLiCSLLi*", "nE") +BUILTIN(__builtin_ssub_overflow, "bSiCSiCSi*", "nE") +BUILTIN(__builtin_ssubl_overflow, "bSLiCSLiCSLi*", "nE") +BUILTIN(__builtin_ssubll_overflow, "bSLLiCSLLiCSLLi*", "nE") +BUILTIN(__builtin_smul_overflow, "bSiCSiCSi*", "nE") +BUILTIN(__builtin_smull_overflow, "bSLiCSLiCSLi*", "nE") +BUILTIN(__builtin_smulll_overflow, "bSLLiCSLLiCSLLi*", "nE") // Clang builtins (not available in GCC). -BUILTIN(__builtin_addressof, "v*v&", "nct") -BUILTIN(__builtin_function_start, "v*v&", "nct") -BUILTIN(__builtin_operator_new, "v*z", "tc") -BUILTIN(__builtin_operator_delete, "vv*", "tn") -BUILTIN(__builtin_char_memchr, "c*cC*iz", "n") +BUILTIN(__builtin_addressof, "v*v&", "nctE") +BUILTIN(__builtin_function_start, "v*v&", "nctE") +BUILTIN(__builtin_operator_new, "v*z", "tcE") +BUILTIN(__builtin_operator_delete, "vv*", "tnE") +BUILTIN(__builtin_char_memchr, "c*cC*iz", "nE") BUILTIN(__builtin_dump_struct, "v.", "t") BUILTIN(__builtin_preserve_access_index, "v.", "t") // Alignment builtins (uses custom parsing to support pointers and integers) -BUILTIN(__builtin_is_aligned, "bvC*z", "nct") -BUILTIN(__builtin_align_up, "v*vC*z", "nct") -BUILTIN(__builtin_align_down, "v*vC*z", "nct") +BUILTIN(__builtin_is_aligned, "bvC*z", "nctE") +BUILTIN(__builtin_align_up, "v*vC*z", "nctE") +BUILTIN(__builtin_align_down, "v*vC*z", "nctE") // Safestack builtins BUILTIN(__builtin___get_unsafe_stack_start, "v*", "Fn") @@ -1694,7 +1695,7 @@ LANGBUILTIN(__builtin_load_halff, "fhC*", "nc", ALL_OCL_LANGUAGES) // Builtins for os_log/os_trace -BUILTIN(__builtin_os_log_format_buffer_size, "zcC*.", "p:0:nut") +BUILTIN(__builtin_os_log_format_buffer_size, "zcC*.", "p:0:nutE") BUILTIN(__builtin_os_log_format, "v*v*cC*.", "p:0:nt") // CUDA/HIP @@ -1714,7 +1715,7 @@ BUILTIN(__builtin_ms_va_copy, "vc*&c*&", "n") // Arithmetic Fence: to prevent FP reordering and reassociation optimizations -LANGBUILTIN(__arithmetic_fence, "v.", "t", ALL_LANGUAGES) +LANGBUILTIN(__arithmetic_fence, "v.", "tE", ALL_LANGUAGES) #undef BUILTIN #undef LIBBUILTIN diff --git a/clang/include/clang/Lex/Preprocessor.h b/clang/include/clang/Lex/Preprocessor.h --- a/clang/include/clang/Lex/Preprocessor.h +++ b/clang/include/clang/Lex/Preprocessor.h @@ -164,6 +164,7 @@ IdentifierInfo *Ident__has_feature; // __has_feature IdentifierInfo *Ident__has_extension; // __has_extension IdentifierInfo *Ident__has_builtin; // __has_builtin + IdentifierInfo *Ident__has_constexpr_builtin; // __has_constexpr_builtin IdentifierInfo *Ident__has_attribute; // __has_attribute IdentifierInfo *Ident__has_include; // __has_include IdentifierInfo *Ident__has_include_next; // __has_include_next diff --git a/clang/lib/AST/ExprConstant.cpp b/clang/lib/AST/ExprConstant.cpp --- a/clang/lib/AST/ExprConstant.cpp +++ b/clang/lib/AST/ExprConstant.cpp @@ -1954,8 +1954,8 @@ return true; } -/// Should this call expression be treated as a constant? -static bool IsConstantCall(const CallExpr *E) { +/// Should this call expression be treated as a no-op? +static bool IsNoOpCall(const CallExpr *E) { unsigned Builtin = E->getBuiltinCallee(); return (Builtin == Builtin::BI__builtin___CFStringMakeConstantString || Builtin == Builtin::BI__builtin___NSStringMakeConstantString || @@ -2006,7 +2006,7 @@ case Expr::ObjCBoxedExprClass: return cast(E)->isExpressibleAsConstantInitializer(); case Expr::CallExprClass: - return IsConstantCall(cast(E)); + return IsNoOpCall(cast(E)); // For GCC compatibility, &&label has static storage duration. case Expr::AddrLabelExprClass: return true; @@ -7405,6 +7405,12 @@ bool ZeroInitialization(const Expr *E) { return Error(E); } + bool IsConstantEvaluatedBuiltinCall(const CallExpr *E) { + unsigned BuiltinOp = E->getBuiltinCallee(); + return BuiltinOp != 0 && + Info.Ctx.BuiltinInfo.isConstantEvaluated(BuiltinOp); + } + public: ExprEvaluatorBase(EvalInfo &Info) : Info(Info) {} @@ -8317,7 +8323,12 @@ } bool LValueExprEvaluator::VisitCallExpr(const CallExpr *E) { + if (!IsConstantEvaluatedBuiltinCall(E)) + return ExprEvaluatorBaseTy::VisitCallExpr(E); + switch (E->getBuiltinCallee()) { + default: + return false; case Builtin::BIas_const: case Builtin::BIforward: case Builtin::BImove: @@ -9092,13 +9103,9 @@ } bool PointerExprEvaluator::VisitCallExpr(const CallExpr *E) { - if (IsConstantCall(E)) - return Success(E); - - if (unsigned BuiltinOp = E->getBuiltinCallee()) - return VisitBuiltinCallExpr(E, BuiltinOp); - - return visitNonBuiltinCallExpr(E); + if (!IsConstantEvaluatedBuiltinCall(E)) + return visitNonBuiltinCallExpr(E); + return VisitBuiltinCallExpr(E, E->getBuiltinCallee()); } // Determine if T is a character type for which we guarantee that @@ -9109,6 +9116,9 @@ bool PointerExprEvaluator::VisitBuiltinCallExpr(const CallExpr *E, unsigned BuiltinOp) { + if (IsNoOpCall(E)) + return Success(E); + switch (BuiltinOp) { case Builtin::BIaddressof: case Builtin::BI__addressof: @@ -9463,10 +9473,8 @@ } default: - break; + return false; } - - return visitNonBuiltinCallExpr(E); } static bool EvaluateArrayNewInitList(EvalInfo &Info, LValue &This, @@ -11770,10 +11778,9 @@ } bool IntExprEvaluator::VisitCallExpr(const CallExpr *E) { - if (unsigned BuiltinOp = E->getBuiltinCallee()) - return VisitBuiltinCallExpr(E, BuiltinOp); - - return ExprEvaluatorBaseTy::VisitCallExpr(E); + if (!IsConstantEvaluatedBuiltinCall(E)) + return ExprEvaluatorBaseTy::VisitCallExpr(E); + return VisitBuiltinCallExpr(E, E->getBuiltinCallee()); } static bool getBuiltinAlignArguments(const CallExpr *E, EvalInfo &Info, @@ -11807,7 +11814,7 @@ unsigned BuiltinOp) { switch (BuiltinOp) { default: - return ExprEvaluatorBaseTy::VisitCallExpr(E); + return false; case Builtin::BI__builtin_dynamic_object_size: case Builtin::BI__builtin_object_size: { @@ -13947,9 +13954,12 @@ } bool FloatExprEvaluator::VisitCallExpr(const CallExpr *E) { + if (!IsConstantEvaluatedBuiltinCall(E)) + return ExprEvaluatorBaseTy::VisitCallExpr(E); + switch (E->getBuiltinCallee()) { default: - return ExprEvaluatorBaseTy::VisitCallExpr(E); + return false; case Builtin::BI__builtin_huge_val: case Builtin::BI__builtin_huge_valf: @@ -14669,6 +14679,9 @@ } bool ComplexExprEvaluator::VisitCallExpr(const CallExpr *E) { + if (!IsConstantEvaluatedBuiltinCall(E)) + return ExprEvaluatorBaseTy::VisitCallExpr(E); + switch (E->getBuiltinCallee()) { case Builtin::BI__builtin_complex: Result.makeComplexFloat(); @@ -14679,10 +14692,8 @@ return true; default: - break; + return false; } - - return ExprEvaluatorBaseTy::VisitCallExpr(E); } //===----------------------------------------------------------------------===// @@ -14758,6 +14769,9 @@ } bool VisitCallExpr(const CallExpr *E) { + if (!IsConstantEvaluatedBuiltinCall(E)) + return ExprEvaluatorBaseTy::VisitCallExpr(E); + switch (E->getBuiltinCallee()) { case Builtin::BI__assume: case Builtin::BI__builtin_assume: @@ -14768,10 +14782,8 @@ return HandleOperatorDeleteCall(Info, E); default: - break; + return false; } - - return ExprEvaluatorBaseTy::VisitCallExpr(E); } bool VisitCXXDeleteExpr(const CXXDeleteExpr *E); diff --git a/clang/lib/Lex/PPMacroExpansion.cpp b/clang/lib/Lex/PPMacroExpansion.cpp --- a/clang/lib/Lex/PPMacroExpansion.cpp +++ b/clang/lib/Lex/PPMacroExpansion.cpp @@ -371,6 +371,8 @@ Ident__has_feature = RegisterBuiltinMacro(*this, "__has_feature"); Ident__has_extension = RegisterBuiltinMacro(*this, "__has_extension"); Ident__has_builtin = RegisterBuiltinMacro(*this, "__has_builtin"); + Ident__has_constexpr_builtin = + RegisterBuiltinMacro(*this, "__has_constexpr_builtin"); Ident__has_attribute = RegisterBuiltinMacro(*this, "__has_attribute"); if (!getLangOpts().CPlusPlus) Ident__has_c_attribute = RegisterBuiltinMacro(*this, "__has_c_attribute"); @@ -1735,6 +1737,18 @@ .Default(false); } }); + } else if (II == Ident__has_constexpr_builtin) { + EvaluateFeatureLikeBuiltinMacro( + OS, Tok, II, *this, false, + [this](Token &Tok, bool &HasLexedNextToken) -> int { + IdentifierInfo *II = ExpectFeatureIdentifierInfo( + Tok, *this, diag::err_feature_check_malformed); + if (!II) + return false; + unsigned BuiltinOp = II->getBuiltinID(); + return BuiltinOp != 0 && + this->getBuiltinInfo().isConstantEvaluated(BuiltinOp); + }); } else if (II == Ident__is_identifier) { EvaluateFeatureLikeBuiltinMacro(OS, Tok, II, *this, false, [](Token &Tok, bool &HasLexedNextToken) -> int { diff --git a/clang/test/Preprocessor/feature_tests.cpp b/clang/test/Preprocessor/feature_tests.cpp --- a/clang/test/Preprocessor/feature_tests.cpp +++ b/clang/test/Preprocessor/feature_tests.cpp @@ -1,5 +1,4 @@ // RUN: %clang_cc1 %s -triple=i686-apple-darwin9 -verify -DVERIFY -// expected-no-diagnostics #ifndef __has_feature #error Should have __has_feature @@ -42,3 +41,29 @@ #if __has_builtin(__builtin_insanity) #error Clang should not have this #endif + +// Check __has_constexpr_builtin +#if !__has_constexpr_builtin(__builtin_fmax) || \ + !__has_constexpr_builtin(__builtin_fmin) +#error Clang should have these constexpr builtins +#endif + +#if __has_constexpr_builtin(__builtin_cbrt) +#error This builtin should not be constexpr in Clang +#endif + +#if __has_constexpr_builtin(__builtin_insanity) +#error This is not a builtin in Clang +#endif + +// expected-error@+1 {{missing '(' after '__has_constexpr_builtin'}} expected-error@+1 {{expected value}} +#if __has_constexpr_builtin +#endif + +// expected-error@+1 {{builtin feature check macro requires a parenthesized identifier}} +#if __has_constexpr_builtin("__builtin_fmax") +#endif + +// expected-error@+1 {{too many arguments}} +#if __has_constexpr_builtin(__builtin_fmax, __builtin_fmin) +#endif