[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