[clang] 5b56763 - [Clang] Add __has_constexpr_builtin support

Evgeny Shulgin via cfe-commits cfe-commits at lists.llvm.org
Fri Oct 21 04:23:19 PDT 2022


Author: Evgeny Shulgin
Date: 2022-10-21T11:23:10Z
New Revision: 5b567637e22bfa128514a5a9de7f3296423e8acd

URL: https://github.com/llvm/llvm-project/commit/5b567637e22bfa128514a5a9de7f3296423e8acd
DIFF: https://github.com/llvm/llvm-project/commit/5b567637e22bfa128514a5a9de7f3296423e8acd.diff

LOG: [Clang] Add __has_constexpr_builtin support

The `__has_constexpr_builtin` macro can be used to check
whether the builtin in constant-evaluated by Clang frontend.

Reviewed By: aaron.ballman, shafik

Differential Revision: https://reviews.llvm.org/D136036

Added: 
    

Modified: 
    clang/docs/LanguageExtensions.rst
    clang/docs/ReleaseNotes.rst
    clang/include/clang/Basic/Builtins.def
    clang/include/clang/Basic/Builtins.h
    clang/include/clang/Lex/Preprocessor.h
    clang/lib/AST/ExprConstant.cpp
    clang/lib/Lex/PPMacroExpansion.cpp
    clang/test/Preprocessor/feature_tests.cpp

Removed: 
    


################################################################################
diff  --git a/clang/docs/LanguageExtensions.rst b/clang/docs/LanguageExtensions.rst
index c0f086554e245..c4a8f7e6b399c 100644
--- a/clang/docs/LanguageExtensions.rst
+++ b/clang/docs/LanguageExtensions.rst
@@ -66,6 +66,35 @@ It can be used like this:
   ``__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 ``<cmath>`` 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
index e87a4eea552df..3f952334c3d9a 100644
--- a/clang/docs/ReleaseNotes.rst
+++ b/clang/docs/ReleaseNotes.rst
@@ -360,6 +360,9 @@ Non-comprehensive list of changes in this release
   timestamp to be used in replacement of the current date and time in
   the ``__DATE__``, ``__TIME__``, and ``__TIMESTAMP__`` macros. See
   `<https://reproducible-builds.org/docs/source-date-epoch/>`_.
+- 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.def b/clang/include/clang/Basic/Builtins.def
index b7c52a7292c8c..d9faafd8813ef 100644
--- a/clang/include/clang/Basic/Builtins.def
+++ b/clang/include/clang/Basic/Builtins.def
@@ -105,6 +105,7 @@
 //  C<N,M_0,...,M_k> -> 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_atan2f, "fff"  , "Fne")
 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_frexp , "ddi*"  , "Fn")
 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_modf , "ddd*"  , "Fn")
 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_fmaf, "ffff", "Fne")
 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_ctanhf, "XfXf", "Fne")
 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_islessgreater , "i.", "Fnct")
 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_canonicalizef16, "hh", "nc")
 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_stpcpy, "c*c*cC*", "nF")
 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___clear_cache, "vc*c*", "n")
 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_dwarf_sp_column, "Ui", "n")
 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___vfprintf_chk, "iP*icC*a", "FP:2:")
 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_max, "v.", "t")
 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_test_and_set, "bvD*i", "n")
 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 @@ BUILTIN(__warn_memset_zero_len, "v", "nU")
 // 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(__popcnt16, "UsUs",   "nc", ALL_MS_LANGUAGES)
 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 @@ LIBBUILTIN(strtoull, "ULLicC*c**i", "f",   "stdlib.h", ALL_LANGUAGES)
 // 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(strstr, "c*cC*cC*",    "f",     "string.h", ALL_LANGUAGES)
 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 @@ LIBBUILTIN(toupper, "ii", "fnU", "ctype.h", ALL_LANGUAGES)
 // 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(strndup, "c*cC*z",     "f",     "string.h", ALL_GNU_LANGUAGES)
 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 @@ LIBBUILTIN(_Block_object_dispose, "vvC*iC", "f", "Blocks.h", ALL_LANGUAGES)
 // 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_subcl, "ULiULiCULiCULiCULi*", "n")
 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_half, "dhC*", "nc", ALL_OCL_LANGUAGES)
 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_end, "vc*&", "n")
 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/Basic/Builtins.h b/clang/include/clang/Basic/Builtins.h
index ae5a2dd340bce..5396477411106 100644
--- a/clang/include/clang/Basic/Builtins.h
+++ b/clang/include/clang/Basic/Builtins.h
@@ -263,6 +263,11 @@ class Context {
   /// 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/Lex/Preprocessor.h b/clang/include/clang/Lex/Preprocessor.h
index 22fcbf1269629..98596e563e9ee 100644
--- a/clang/include/clang/Lex/Preprocessor.h
+++ b/clang/include/clang/Lex/Preprocessor.h
@@ -164,6 +164,7 @@ class Preprocessor {
   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
index 64c50c8b82e5a..6adc63d0f5f0d 100644
--- a/clang/lib/AST/ExprConstant.cpp
+++ b/clang/lib/AST/ExprConstant.cpp
@@ -1954,8 +1954,8 @@ static bool EvaluateIgnoredValue(EvalInfo &Info, const Expr *E) {
   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 @@ static bool IsGlobalLValue(APValue::LValueBase B) {
   case Expr::ObjCBoxedExprClass:
     return cast<ObjCBoxedExpr>(E)->isExpressibleAsConstantInitializer();
   case Expr::CallExprClass:
-    return IsConstantCall(cast<CallExpr>(E));
+    return IsNoOpCall(cast<CallExpr>(E));
   // For GCC compatibility, &&label has static storage duration.
   case Expr::AddrLabelExprClass:
     return true;
@@ -7405,6 +7405,12 @@ class ExprEvaluatorBase
 
   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::VisitVarDecl(const Expr *E, const VarDecl *VD) {
 }
 
 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::visitNonBuiltinCallExpr(const CallExpr *E) {
 }
 
 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 @@ static bool isOneByteCharacterType(QualType T) {
 
 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 @@ bool PointerExprEvaluator::VisitBuiltinCallExpr(const CallExpr *E,
   }
 
   default:
-    break;
+    return false;
   }
-
-  return visitNonBuiltinCallExpr(E);
 }
 
 static bool EvaluateArrayNewInitList(EvalInfo &Info, LValue &This,
@@ -11770,10 +11778,9 @@ static bool tryEvaluateBuiltinObjectSize(const Expr *E, unsigned Type,
 }
 
 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 @@ bool IntExprEvaluator::VisitBuiltinCallExpr(const CallExpr *E,
                                             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 @@ static bool TryEvaluateBuiltinNaN(const ASTContext &Context,
 }
 
 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::VisitInitListExpr(const InitListExpr *E) {
 }
 
 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 @@ bool ComplexExprEvaluator::VisitCallExpr(const CallExpr *E) {
     return true;
 
   default:
-    break;
+    return false;
   }
-
-  return ExprEvaluatorBaseTy::VisitCallExpr(E);
 }
 
 //===----------------------------------------------------------------------===//
@@ -14758,6 +14769,9 @@ class VoidExprEvaluator
   }
 
   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 @@ class VoidExprEvaluator
       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
index 3734923576381..e79d76cbf3857 100644
--- a/clang/lib/Lex/PPMacroExpansion.cpp
+++ b/clang/lib/Lex/PPMacroExpansion.cpp
@@ -371,6 +371,8 @@ void Preprocessor::RegisterBuiltinMacros() {
   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 @@ void Preprocessor::ExpandBuiltinMacro(Token &Tok) {
               .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
index b501cb7a6e591..848f219339724 100644
--- 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 at +1 {{missing '(' after '__has_constexpr_builtin'}} expected-error at +1 {{expected value}}
+#if __has_constexpr_builtin
+#endif
+
+// expected-error at +1 {{builtin feature check macro requires a parenthesized identifier}}
+#if  __has_constexpr_builtin("__builtin_fmax")
+#endif
+
+// expected-error at +1 {{too many arguments}}
+#if __has_constexpr_builtin(__builtin_fmax, __builtin_fmin)
+#endif


        


More information about the cfe-commits mailing list