Index: projects/clang700-import/contrib/llvm/tools/clang/include/clang/Basic/Builtins.def =================================================================== --- projects/clang700-import/contrib/llvm/tools/clang/include/clang/Basic/Builtins.def (revision 337309) +++ projects/clang700-import/contrib/llvm/tools/clang/include/clang/Basic/Builtins.def (revision 337310) @@ -1,1507 +1,1503 @@ //===--- Builtins.def - Builtin function info database ----------*- C++ -*-===// // // The LLVM Compiler Infrastructure // // This file is distributed under the University of Illinois Open Source // License. See LICENSE.TXT for details. // //===----------------------------------------------------------------------===// // // This file defines the standard builtin function database. Users of this file // must define the BUILTIN macro to make use of this information. // //===----------------------------------------------------------------------===// // FIXME: This should really be a .td file, but that requires modifying tblgen. // Perhaps tblgen should have plugins. // The first value provided to the macro specifies the function name of the // builtin, and results in a clang::builtin::BIXX enum value for XX. // The second value provided to the macro specifies the type of the function // (result value, then each argument) as follows: // v -> void // b -> boolean // c -> char // s -> short // i -> int // h -> half // f -> float // d -> double // z -> size_t // w -> wchar_t // F -> constant CFString // G -> id // H -> SEL // M -> struct objc_super // a -> __builtin_va_list // A -> "reference" to __builtin_va_list // V -> Vector, followed by the number of elements and the base type. // E -> ext_vector, followed by the number of elements and the base type. // X -> _Complex, followed by the base type. // Y -> ptrdiff_t // P -> FILE // J -> jmp_buf // SJ -> sigjmp_buf // K -> ucontext_t // p -> pid_t // . -> "...". This may only occur at the end of the function list. // // Types may be prefixed with the following modifiers: // L -> long (e.g. Li for 'long int', Ld for 'long double') // LL -> long long (e.g. LLi for 'long long int', LLd for __float128) // LLL -> __int128_t (e.g. LLLi) // W -> int64_t // N -> 'int' size if target is LP64, 'L' otherwise. // S -> signed // U -> unsigned // I -> Required to constant fold to an integer constant expression. // // Types may be postfixed with the following modifiers: // * -> pointer (optionally followed by an address space number, if no address // space is specified than any address space will be accepted) // & -> reference (optionally followed by an address space number) // C -> const // D -> volatile // The third value provided to the macro specifies information about attributes // of the function. These must be kept in sync with the predicates in the // Builtin::Context class. Currently we have: // n -> nothrow // r -> noreturn // U -> pure // c -> const // t -> signature is meaningless, use custom typechecking // F -> this is a libc/libm function with a '__builtin_' prefix added. // f -> this is a libc/libm function without the '__builtin_' prefix. It can // be followed by ':headername:' to state which header this function // comes from. // h -> this function requires a specific header or an explicit declaration. // i -> this is a runtime library implemented function without the // '__builtin_' prefix. It will be implemented in compiler-rt or libgcc. // p:N: -> this is a printf-like function whose Nth argument is the format // string. // P:N: -> similar to the p:N: attribute, but the function is like vprintf // in that it accepts its arguments as a va_list rather than // through an ellipsis // s:N: -> this is a scanf-like function whose Nth argument is the format // string. // S:N: -> similar to the s:N: attribute, but the function is like vscanf // in that it accepts its arguments as a va_list rather than // through an ellipsis // e -> const, but only when -fno-math-errno // j -> returns_twice (like setjmp) // u -> arguments are not evaluated for their side-effects // V:N: -> requires vectors of at least N bits to be legal // FIXME: gcc has nonnull #if defined(BUILTIN) && !defined(LIBBUILTIN) # define LIBBUILTIN(ID, TYPE, ATTRS, HEADER, BUILTIN_LANG) BUILTIN(ID, TYPE, ATTRS) #endif #if defined(BUILTIN) && !defined(LANGBUILTIN) # define LANGBUILTIN(ID, TYPE, ATTRS, BUILTIN_LANG) BUILTIN(ID, TYPE, ATTRS) #endif // Standard libc/libm functions: BUILTIN(__builtin_atan2 , "ddd" , "Fne") BUILTIN(__builtin_atan2f, "fff" , "Fne") BUILTIN(__builtin_atan2l, "LdLdLd", "Fne") BUILTIN(__builtin_abs , "ii" , "ncF") BUILTIN(__builtin_copysign, "ddd", "ncF") BUILTIN(__builtin_copysignf, "fff", "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_fabsf128, "LLdLLd", "ncF") BUILTIN(__builtin_fmod , "ddd" , "Fne") BUILTIN(__builtin_fmodf, "fff" , "Fne") BUILTIN(__builtin_fmodl, "LdLdLd", "Fne") BUILTIN(__builtin_frexp , "ddi*" , "Fn") BUILTIN(__builtin_frexpf, "ffi*" , "Fn") BUILTIN(__builtin_frexpl, "LdLdi*", "Fn") BUILTIN(__builtin_huge_val, "d", "nc") BUILTIN(__builtin_huge_valf, "f", "nc") BUILTIN(__builtin_huge_vall, "Ld", "nc") BUILTIN(__builtin_huge_valf128, "LLd", "nc") BUILTIN(__builtin_inf , "d" , "nc") BUILTIN(__builtin_inff , "f" , "nc") BUILTIN(__builtin_infl , "Ld" , "nc") BUILTIN(__builtin_inff128 , "LLd" , "nc") BUILTIN(__builtin_labs , "LiLi" , "Fnc") BUILTIN(__builtin_llabs, "LLiLLi", "Fnc") BUILTIN(__builtin_ldexp , "ddi" , "Fne") BUILTIN(__builtin_ldexpf, "ffi" , "Fne") BUILTIN(__builtin_ldexpl, "LdLdi", "Fne") BUILTIN(__builtin_modf , "ddd*" , "Fn") BUILTIN(__builtin_modff, "fff*" , "Fn") BUILTIN(__builtin_modfl, "LdLdLd*", "Fn") BUILTIN(__builtin_nan, "dcC*" , "FnU") BUILTIN(__builtin_nanf, "fcC*" , "FnU") BUILTIN(__builtin_nanl, "LdcC*", "FnU") BUILTIN(__builtin_nanf128, "LLdcC*", "FnU") BUILTIN(__builtin_nans, "dcC*" , "FnU") BUILTIN(__builtin_nansf, "fcC*" , "FnU") BUILTIN(__builtin_nansl, "LdcC*", "FnU") BUILTIN(__builtin_nansf128, "LLdcC*", "FnU") BUILTIN(__builtin_powi , "ddi" , "Fnc") BUILTIN(__builtin_powif, "ffi" , "Fnc") BUILTIN(__builtin_powil, "LdLdi", "Fnc") BUILTIN(__builtin_pow , "ddd" , "Fne") BUILTIN(__builtin_powf, "fff" , "Fne") BUILTIN(__builtin_powl, "LdLdLd", "Fne") // Standard unary libc/libm functions with double/float/long double variants: BUILTIN(__builtin_acos , "dd" , "Fne") BUILTIN(__builtin_acosf, "ff" , "Fne") BUILTIN(__builtin_acosl, "LdLd", "Fne") BUILTIN(__builtin_acosh , "dd" , "Fne") BUILTIN(__builtin_acoshf, "ff" , "Fne") BUILTIN(__builtin_acoshl, "LdLd", "Fne") BUILTIN(__builtin_asin , "dd" , "Fne") BUILTIN(__builtin_asinf, "ff" , "Fne") BUILTIN(__builtin_asinl, "LdLd", "Fne") BUILTIN(__builtin_asinh , "dd" , "Fne") BUILTIN(__builtin_asinhf, "ff" , "Fne") BUILTIN(__builtin_asinhl, "LdLd", "Fne") BUILTIN(__builtin_atan , "dd" , "Fne") BUILTIN(__builtin_atanf, "ff" , "Fne") BUILTIN(__builtin_atanl, "LdLd", "Fne") BUILTIN(__builtin_atanh , "dd", "Fne") BUILTIN(__builtin_atanhf, "ff", "Fne") BUILTIN(__builtin_atanhl, "LdLd", "Fne") BUILTIN(__builtin_cbrt , "dd", "Fnc") BUILTIN(__builtin_cbrtf, "ff", "Fnc") BUILTIN(__builtin_cbrtl, "LdLd", "Fnc") BUILTIN(__builtin_ceil , "dd" , "Fnc") BUILTIN(__builtin_ceilf, "ff" , "Fnc") BUILTIN(__builtin_ceill, "LdLd", "Fnc") BUILTIN(__builtin_cos , "dd" , "Fne") BUILTIN(__builtin_cosf, "ff" , "Fne") BUILTIN(__builtin_cosh , "dd" , "Fne") BUILTIN(__builtin_coshf, "ff" , "Fne") BUILTIN(__builtin_coshl, "LdLd", "Fne") BUILTIN(__builtin_cosl, "LdLd", "Fne") BUILTIN(__builtin_erf , "dd", "Fne") BUILTIN(__builtin_erff, "ff", "Fne") BUILTIN(__builtin_erfl, "LdLd", "Fne") BUILTIN(__builtin_erfc , "dd", "Fne") BUILTIN(__builtin_erfcf, "ff", "Fne") BUILTIN(__builtin_erfcl, "LdLd", "Fne") BUILTIN(__builtin_exp , "dd" , "Fne") BUILTIN(__builtin_expf, "ff" , "Fne") BUILTIN(__builtin_expl, "LdLd", "Fne") BUILTIN(__builtin_exp2 , "dd" , "Fne") BUILTIN(__builtin_exp2f, "ff" , "Fne") BUILTIN(__builtin_exp2l, "LdLd", "Fne") BUILTIN(__builtin_expm1 , "dd", "Fne") BUILTIN(__builtin_expm1f, "ff", "Fne") BUILTIN(__builtin_expm1l, "LdLd", "Fne") BUILTIN(__builtin_fdim, "ddd", "Fne") BUILTIN(__builtin_fdimf, "fff", "Fne") BUILTIN(__builtin_fdiml, "LdLdLd", "Fne") BUILTIN(__builtin_floor , "dd" , "Fnc") BUILTIN(__builtin_floorf, "ff" , "Fnc") BUILTIN(__builtin_floorl, "LdLd", "Fnc") BUILTIN(__builtin_fma, "dddd", "Fne") BUILTIN(__builtin_fmaf, "ffff", "Fne") BUILTIN(__builtin_fmal, "LdLdLdLd", "Fne") BUILTIN(__builtin_fmax, "ddd", "Fnc") BUILTIN(__builtin_fmaxf, "fff", "Fnc") BUILTIN(__builtin_fmaxl, "LdLdLd", "Fnc") BUILTIN(__builtin_fmin, "ddd", "Fnc") BUILTIN(__builtin_fminf, "fff", "Fnc") BUILTIN(__builtin_fminl, "LdLdLd", "Fnc") BUILTIN(__builtin_hypot , "ddd" , "Fne") BUILTIN(__builtin_hypotf, "fff" , "Fne") BUILTIN(__builtin_hypotl, "LdLdLd", "Fne") BUILTIN(__builtin_ilogb , "id", "Fne") BUILTIN(__builtin_ilogbf, "if", "Fne") BUILTIN(__builtin_ilogbl, "iLd", "Fne") BUILTIN(__builtin_lgamma , "dd", "Fn") BUILTIN(__builtin_lgammaf, "ff", "Fn") BUILTIN(__builtin_lgammal, "LdLd", "Fn") BUILTIN(__builtin_llrint, "LLid", "Fne") BUILTIN(__builtin_llrintf, "LLif", "Fne") BUILTIN(__builtin_llrintl, "LLiLd", "Fne") BUILTIN(__builtin_llround , "LLid", "Fne") BUILTIN(__builtin_llroundf, "LLif", "Fne") BUILTIN(__builtin_llroundl, "LLiLd", "Fne") BUILTIN(__builtin_log , "dd" , "Fne") BUILTIN(__builtin_log10 , "dd" , "Fne") BUILTIN(__builtin_log10f, "ff" , "Fne") BUILTIN(__builtin_log10l, "LdLd", "Fne") BUILTIN(__builtin_log1p , "dd" , "Fne") BUILTIN(__builtin_log1pf, "ff" , "Fne") BUILTIN(__builtin_log1pl, "LdLd", "Fne") BUILTIN(__builtin_log2, "dd" , "Fne") BUILTIN(__builtin_log2f, "ff" , "Fne") BUILTIN(__builtin_log2l, "LdLd" , "Fne") BUILTIN(__builtin_logb , "dd", "Fne") BUILTIN(__builtin_logbf, "ff", "Fne") BUILTIN(__builtin_logbl, "LdLd", "Fne") BUILTIN(__builtin_logf, "ff" , "Fne") BUILTIN(__builtin_logl, "LdLd", "Fne") BUILTIN(__builtin_lrint , "Lid", "Fne") BUILTIN(__builtin_lrintf, "Lif", "Fne") BUILTIN(__builtin_lrintl, "LiLd", "Fne") BUILTIN(__builtin_lround , "Lid", "Fne") BUILTIN(__builtin_lroundf, "Lif", "Fne") BUILTIN(__builtin_lroundl, "LiLd", "Fne") BUILTIN(__builtin_nearbyint , "dd", "Fnc") BUILTIN(__builtin_nearbyintf, "ff", "Fnc") BUILTIN(__builtin_nearbyintl, "LdLd", "Fnc") BUILTIN(__builtin_nextafter , "ddd", "Fne") BUILTIN(__builtin_nextafterf, "fff", "Fne") BUILTIN(__builtin_nextafterl, "LdLdLd", "Fne") BUILTIN(__builtin_nexttoward , "ddLd", "Fne") BUILTIN(__builtin_nexttowardf, "ffLd", "Fne") BUILTIN(__builtin_nexttowardl, "LdLdLd", "Fne") BUILTIN(__builtin_remainder , "ddd", "Fne") BUILTIN(__builtin_remainderf, "fff", "Fne") BUILTIN(__builtin_remainderl, "LdLdLd", "Fne") BUILTIN(__builtin_remquo , "dddi*", "Fn") BUILTIN(__builtin_remquof, "fffi*", "Fn") BUILTIN(__builtin_remquol, "LdLdLdi*", "Fn") BUILTIN(__builtin_rint , "dd", "Fnc") BUILTIN(__builtin_rintf, "ff", "Fnc") BUILTIN(__builtin_rintl, "LdLd", "Fnc") BUILTIN(__builtin_round, "dd" , "Fnc") BUILTIN(__builtin_roundf, "ff" , "Fnc") BUILTIN(__builtin_roundl, "LdLd" , "Fnc") BUILTIN(__builtin_scalbln , "ddLi", "Fne") BUILTIN(__builtin_scalblnf, "ffLi", "Fne") BUILTIN(__builtin_scalblnl, "LdLdLi", "Fne") BUILTIN(__builtin_scalbn , "ddi", "Fne") BUILTIN(__builtin_scalbnf, "ffi", "Fne") BUILTIN(__builtin_scalbnl, "LdLdi", "Fne") BUILTIN(__builtin_sin , "dd" , "Fne") BUILTIN(__builtin_sinf, "ff" , "Fne") BUILTIN(__builtin_sinh , "dd" , "Fne") BUILTIN(__builtin_sinhf, "ff" , "Fne") BUILTIN(__builtin_sinhl, "LdLd", "Fne") BUILTIN(__builtin_sinl, "LdLd", "Fne") BUILTIN(__builtin_sqrt , "dd" , "Fne") BUILTIN(__builtin_sqrtf, "ff" , "Fne") BUILTIN(__builtin_sqrtl, "LdLd", "Fne") BUILTIN(__builtin_tan , "dd" , "Fne") BUILTIN(__builtin_tanf, "ff" , "Fne") BUILTIN(__builtin_tanh , "dd" , "Fne") BUILTIN(__builtin_tanhf, "ff" , "Fne") BUILTIN(__builtin_tanhl, "LdLd", "Fne") BUILTIN(__builtin_tanl, "LdLd", "Fne") BUILTIN(__builtin_tgamma , "dd", "Fne") BUILTIN(__builtin_tgammaf, "ff", "Fne") BUILTIN(__builtin_tgammal, "LdLd", "Fne") BUILTIN(__builtin_trunc , "dd", "Fnc") BUILTIN(__builtin_truncf, "ff", "Fnc") BUILTIN(__builtin_truncl, "LdLd", "Fnc") // C99 complex builtins BUILTIN(__builtin_cabs, "dXd", "Fne") BUILTIN(__builtin_cabsf, "fXf", "Fne") BUILTIN(__builtin_cabsl, "LdXLd", "Fne") BUILTIN(__builtin_cacos, "XdXd", "Fne") BUILTIN(__builtin_cacosf, "XfXf", "Fne") BUILTIN(__builtin_cacosh, "XdXd", "Fne") BUILTIN(__builtin_cacoshf, "XfXf", "Fne") BUILTIN(__builtin_cacoshl, "XLdXLd", "Fne") BUILTIN(__builtin_cacosl, "XLdXLd", "Fne") BUILTIN(__builtin_carg, "dXd", "Fne") BUILTIN(__builtin_cargf, "fXf", "Fne") BUILTIN(__builtin_cargl, "LdXLd", "Fne") BUILTIN(__builtin_casin, "XdXd", "Fne") BUILTIN(__builtin_casinf, "XfXf", "Fne") BUILTIN(__builtin_casinh, "XdXd", "Fne") BUILTIN(__builtin_casinhf, "XfXf", "Fne") BUILTIN(__builtin_casinhl, "XLdXLd", "Fne") BUILTIN(__builtin_casinl, "XLdXLd", "Fne") BUILTIN(__builtin_catan, "XdXd", "Fne") BUILTIN(__builtin_catanf, "XfXf", "Fne") BUILTIN(__builtin_catanh, "XdXd", "Fne") BUILTIN(__builtin_catanhf, "XfXf", "Fne") BUILTIN(__builtin_catanhl, "XLdXLd", "Fne") BUILTIN(__builtin_catanl, "XLdXLd", "Fne") BUILTIN(__builtin_ccos, "XdXd", "Fne") BUILTIN(__builtin_ccosf, "XfXf", "Fne") BUILTIN(__builtin_ccosl, "XLdXLd", "Fne") BUILTIN(__builtin_ccosh, "XdXd", "Fne") BUILTIN(__builtin_ccoshf, "XfXf", "Fne") BUILTIN(__builtin_ccoshl, "XLdXLd", "Fne") BUILTIN(__builtin_cexp, "XdXd", "Fne") BUILTIN(__builtin_cexpf, "XfXf", "Fne") BUILTIN(__builtin_cexpl, "XLdXLd", "Fne") BUILTIN(__builtin_cimag, "dXd", "Fnc") BUILTIN(__builtin_cimagf, "fXf", "Fnc") BUILTIN(__builtin_cimagl, "LdXLd", "Fnc") BUILTIN(__builtin_conj, "XdXd", "Fnc") BUILTIN(__builtin_conjf, "XfXf", "Fnc") BUILTIN(__builtin_conjl, "XLdXLd", "Fnc") BUILTIN(__builtin_clog, "XdXd", "Fne") BUILTIN(__builtin_clogf, "XfXf", "Fne") BUILTIN(__builtin_clogl, "XLdXLd", "Fne") BUILTIN(__builtin_cproj, "XdXd", "Fnc") BUILTIN(__builtin_cprojf, "XfXf", "Fnc") BUILTIN(__builtin_cprojl, "XLdXLd", "Fnc") BUILTIN(__builtin_cpow, "XdXdXd", "Fne") BUILTIN(__builtin_cpowf, "XfXfXf", "Fne") BUILTIN(__builtin_cpowl, "XLdXLdXLd", "Fne") BUILTIN(__builtin_creal, "dXd", "Fnc") BUILTIN(__builtin_crealf, "fXf", "Fnc") BUILTIN(__builtin_creall, "LdXLd", "Fnc") BUILTIN(__builtin_csin, "XdXd", "Fne") BUILTIN(__builtin_csinf, "XfXf", "Fne") BUILTIN(__builtin_csinl, "XLdXLd", "Fne") BUILTIN(__builtin_csinh, "XdXd", "Fne") BUILTIN(__builtin_csinhf, "XfXf", "Fne") BUILTIN(__builtin_csinhl, "XLdXLd", "Fne") BUILTIN(__builtin_csqrt, "XdXd", "Fne") BUILTIN(__builtin_csqrtf, "XfXf", "Fne") BUILTIN(__builtin_csqrtl, "XLdXLd", "Fne") BUILTIN(__builtin_ctan, "XdXd", "Fne") BUILTIN(__builtin_ctanf, "XfXf", "Fne") BUILTIN(__builtin_ctanl, "XLdXLd", "Fne") BUILTIN(__builtin_ctanh, "XdXd", "Fne") BUILTIN(__builtin_ctanhf, "XfXf", "Fne") BUILTIN(__builtin_ctanhl, "XLdXLd", "Fne") // FP Comparisons. BUILTIN(__builtin_isgreater , "i.", "Fnc") BUILTIN(__builtin_isgreaterequal, "i.", "Fnc") BUILTIN(__builtin_isless , "i.", "Fnc") BUILTIN(__builtin_islessequal , "i.", "Fnc") BUILTIN(__builtin_islessgreater , "i.", "Fnc") BUILTIN(__builtin_isunordered , "i.", "Fnc") // Unary FP classification BUILTIN(__builtin_fpclassify, "iiiiii.", "Fnc") BUILTIN(__builtin_isfinite, "i.", "Fnc") BUILTIN(__builtin_isinf, "i.", "Fnc") BUILTIN(__builtin_isinf_sign, "i.", "Fnc") BUILTIN(__builtin_isnan, "i.", "Fnc") BUILTIN(__builtin_isnormal, "i.", "Fnc") // FP signbit builtins BUILTIN(__builtin_signbit, "i.", "Fnc") BUILTIN(__builtin_signbitf, "if", "Fnc") BUILTIN(__builtin_signbitl, "iLd", "Fnc") // Special FP builtins. BUILTIN(__builtin_canonicalize, "dd", "nc") BUILTIN(__builtin_canonicalizef, "ff", "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") // 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") // 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") // FIXME: These type signatures are not correct for targets with int != 32-bits // or with ULL != 64-bits. BUILTIN(__builtin_bswap16, "UsUs", "nc") BUILTIN(__builtin_bswap32, "UiUi", "nc") BUILTIN(__builtin_bswap64, "ULLiULLi", "nc") BUILTIN(__builtin_bitreverse8, "UcUc", "nc") BUILTIN(__builtin_bitreverse16, "UsUs", "nc") BUILTIN(__builtin_bitreverse32, "UiUi", "nc") BUILTIN(__builtin_bitreverse64, "ULLiULLi", "nc") // Random GCC builtins 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_va_start, "vA.", "nt") BUILTIN(__builtin_va_end, "vA", "n") BUILTIN(__builtin_va_copy, "vAA", "n") BUILTIN(__builtin_stdarg_start, "vA.", "n") BUILTIN(__builtin_assume_aligned, "v*vC*z.", "nc") BUILTIN(__builtin_bcmp, "iv*v*z", "Fn") BUILTIN(__builtin_bcopy, "vv*v*z", "n") BUILTIN(__builtin_bzero, "vv*z", "nF") BUILTIN(__builtin_fprintf, "iP*cC*.", "Fp:1:") BUILTIN(__builtin_memchr, "v*vC*iz", "nF") BUILTIN(__builtin_memcmp, "ivC*vC*z", "nF") BUILTIN(__builtin_memcpy, "v*v*vC*z", "nF") BUILTIN(__builtin_memmove, "v*v*vC*z", "nF") BUILTIN(__builtin_mempcpy, "v*v*vC*z", "nF") BUILTIN(__builtin_memset, "v*v*iz", "nF") BUILTIN(__builtin_printf, "icC*.", "Fp:0:") 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_strcpy, "c*c*cC*", "nF") BUILTIN(__builtin_strcspn, "zcC*cC*", "nF") BUILTIN(__builtin_strdup, "c*cC*", "nF") BUILTIN(__builtin_strlen, "zcC*", "nF") BUILTIN(__builtin_strncasecmp, "icC*cC*z", "nF") BUILTIN(__builtin_strncat, "c*c*cC*z", "nF") BUILTIN(__builtin_strncmp, "icC*cC*z", "nF") 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_return_address, "v*IUi", "n") BUILTIN(__builtin_extract_return_addr, "v*v*", "n") BUILTIN(__builtin_frame_address, "v*IUi", "n") BUILTIN(__builtin___clear_cache, "vc*c*", "n") BUILTIN(__builtin_flt_rounds, "i", "nc") 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_snprintf, "ic*zcC*.", "nFp:2:") BUILTIN(__builtin_vsprintf, "ic*cC*a", "nFP:1:") BUILTIN(__builtin_vsnprintf, "ic*zcC*a", "nFP:2:") BUILTIN(__builtin_thread_pointer, "v*", "nc") // GCC exception builtins BUILTIN(__builtin_eh_return, "vzv*", "r") // FIXME: Takes intptr_t, not size_t! BUILTIN(__builtin_frob_return_addr, "v*v*", "n") BUILTIN(__builtin_dwarf_cfa, "v*", "n") BUILTIN(__builtin_init_dwarf_reg_size_table, "vv*", "n") 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___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") BUILTIN(__builtin___mempcpy_chk, "v*v*vC*zz", "nF") BUILTIN(__builtin___memset_chk, "v*v*izz", "nF") BUILTIN(__builtin___stpcpy_chk, "c*c*cC*z", "nF") BUILTIN(__builtin___strcat_chk, "c*c*cC*z", "nF") BUILTIN(__builtin___strcpy_chk, "c*c*cC*z", "nF") BUILTIN(__builtin___strlcat_chk, "zc*cC*zz", "nF") BUILTIN(__builtin___strlcpy_chk, "zc*cC*zz", "nF") BUILTIN(__builtin___strncat_chk, "c*c*cC*zz", "nF") BUILTIN(__builtin___strncpy_chk, "c*c*cC*zz", "nF") BUILTIN(__builtin___stpncpy_chk, "c*c*cC*zz", "nF") BUILTIN(__builtin___snprintf_chk, "ic*zizcC*.", "Fp:4:") BUILTIN(__builtin___sprintf_chk, "ic*izcC*.", "Fp:3:") BUILTIN(__builtin___vsnprintf_chk, "ic*zizcC*a", "FP:4:") BUILTIN(__builtin___vsprintf_chk, "ic*izcC*a", "FP:3:") BUILTIN(__builtin___fprintf_chk, "iP*icC*.", "Fp:2:") BUILTIN(__builtin___printf_chk, "iicC*.", "Fp:1:") 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_prefetch, "vvC*.", "nc") BUILTIN(__builtin_readcyclecounter, "ULLi", "n") BUILTIN(__builtin_trap, "v", "nr") BUILTIN(__builtin_debugtrap, "v", "n") BUILTIN(__builtin_unreachable, "v", "nr") BUILTIN(__builtin_shufflevector, "v." , "nc") BUILTIN(__builtin_convertvector, "v." , "nct") BUILTIN(__builtin_alloca, "v*z" , "Fn") BUILTIN(__builtin_alloca_with_align, "v*zIz", "Fn") BUILTIN(__builtin_call_with_static_chain, "v.", "nt") // "Overloaded" Atomic operator builtins. These are overloaded to support data // types of i8, i16, i32, i64, and i128. The front-end sees calls to the // non-suffixed version of these (which has a bogus type) and transforms them to // the right overloaded version in Sema (plus casts). // FIXME: These assume that char -> i8, short -> i16, int -> i32, // long long -> i64. BUILTIN(__sync_fetch_and_add, "v.", "t") BUILTIN(__sync_fetch_and_add_1, "ccD*c.", "nt") BUILTIN(__sync_fetch_and_add_2, "ssD*s.", "nt") BUILTIN(__sync_fetch_and_add_4, "iiD*i.", "nt") BUILTIN(__sync_fetch_and_add_8, "LLiLLiD*LLi.", "nt") BUILTIN(__sync_fetch_and_add_16, "LLLiLLLiD*LLLi.", "nt") BUILTIN(__sync_fetch_and_sub, "v.", "t") BUILTIN(__sync_fetch_and_sub_1, "ccD*c.", "nt") BUILTIN(__sync_fetch_and_sub_2, "ssD*s.", "nt") BUILTIN(__sync_fetch_and_sub_4, "iiD*i.", "nt") BUILTIN(__sync_fetch_and_sub_8, "LLiLLiD*LLi.", "nt") BUILTIN(__sync_fetch_and_sub_16, "LLLiLLLiD*LLLi.", "nt") BUILTIN(__sync_fetch_and_or, "v.", "t") BUILTIN(__sync_fetch_and_or_1, "ccD*c.", "nt") BUILTIN(__sync_fetch_and_or_2, "ssD*s.", "nt") BUILTIN(__sync_fetch_and_or_4, "iiD*i.", "nt") BUILTIN(__sync_fetch_and_or_8, "LLiLLiD*LLi.", "nt") BUILTIN(__sync_fetch_and_or_16, "LLLiLLLiD*LLLi.", "nt") BUILTIN(__sync_fetch_and_and, "v.", "t") BUILTIN(__sync_fetch_and_and_1, "ccD*c.", "tn") BUILTIN(__sync_fetch_and_and_2, "ssD*s.", "tn") BUILTIN(__sync_fetch_and_and_4, "iiD*i.", "tn") BUILTIN(__sync_fetch_and_and_8, "LLiLLiD*LLi.", "tn") BUILTIN(__sync_fetch_and_and_16, "LLLiLLLiD*LLLi.", "tn") BUILTIN(__sync_fetch_and_xor, "v.", "t") BUILTIN(__sync_fetch_and_xor_1, "ccD*c.", "tn") BUILTIN(__sync_fetch_and_xor_2, "ssD*s.", "tn") BUILTIN(__sync_fetch_and_xor_4, "iiD*i.", "tn") BUILTIN(__sync_fetch_and_xor_8, "LLiLLiD*LLi.", "tn") BUILTIN(__sync_fetch_and_xor_16, "LLLiLLLiD*LLLi.", "tn") BUILTIN(__sync_fetch_and_nand, "v.", "t") BUILTIN(__sync_fetch_and_nand_1, "ccD*c.", "tn") BUILTIN(__sync_fetch_and_nand_2, "ssD*s.", "tn") BUILTIN(__sync_fetch_and_nand_4, "iiD*i.", "tn") BUILTIN(__sync_fetch_and_nand_8, "LLiLLiD*LLi.", "tn") BUILTIN(__sync_fetch_and_nand_16, "LLLiLLLiD*LLLi.", "tn") BUILTIN(__sync_add_and_fetch, "v.", "t") BUILTIN(__sync_add_and_fetch_1, "ccD*c.", "tn") BUILTIN(__sync_add_and_fetch_2, "ssD*s.", "tn") BUILTIN(__sync_add_and_fetch_4, "iiD*i.", "tn") BUILTIN(__sync_add_and_fetch_8, "LLiLLiD*LLi.", "tn") BUILTIN(__sync_add_and_fetch_16, "LLLiLLLiD*LLLi.", "tn") BUILTIN(__sync_sub_and_fetch, "v.", "t") BUILTIN(__sync_sub_and_fetch_1, "ccD*c.", "tn") BUILTIN(__sync_sub_and_fetch_2, "ssD*s.", "tn") BUILTIN(__sync_sub_and_fetch_4, "iiD*i.", "tn") BUILTIN(__sync_sub_and_fetch_8, "LLiLLiD*LLi.", "tn") BUILTIN(__sync_sub_and_fetch_16, "LLLiLLLiD*LLLi.", "tn") BUILTIN(__sync_or_and_fetch, "v.", "t") BUILTIN(__sync_or_and_fetch_1, "ccD*c.", "tn") BUILTIN(__sync_or_and_fetch_2, "ssD*s.", "tn") BUILTIN(__sync_or_and_fetch_4, "iiD*i.", "tn") BUILTIN(__sync_or_and_fetch_8, "LLiLLiD*LLi.", "tn") BUILTIN(__sync_or_and_fetch_16, "LLLiLLLiD*LLLi.", "tn") BUILTIN(__sync_and_and_fetch, "v.", "t") BUILTIN(__sync_and_and_fetch_1, "ccD*c.", "tn") BUILTIN(__sync_and_and_fetch_2, "ssD*s.", "tn") BUILTIN(__sync_and_and_fetch_4, "iiD*i.", "tn") BUILTIN(__sync_and_and_fetch_8, "LLiLLiD*LLi.", "tn") BUILTIN(__sync_and_and_fetch_16, "LLLiLLLiD*LLLi.", "tn") BUILTIN(__sync_xor_and_fetch, "v.", "t") BUILTIN(__sync_xor_and_fetch_1, "ccD*c.", "tn") BUILTIN(__sync_xor_and_fetch_2, "ssD*s.", "tn") BUILTIN(__sync_xor_and_fetch_4, "iiD*i.", "tn") BUILTIN(__sync_xor_and_fetch_8, "LLiLLiD*LLi.", "tn") BUILTIN(__sync_xor_and_fetch_16, "LLLiLLLiD*LLLi.", "tn") BUILTIN(__sync_nand_and_fetch, "v.", "t") BUILTIN(__sync_nand_and_fetch_1, "ccD*c.", "tn") BUILTIN(__sync_nand_and_fetch_2, "ssD*s.", "tn") BUILTIN(__sync_nand_and_fetch_4, "iiD*i.", "tn") BUILTIN(__sync_nand_and_fetch_8, "LLiLLiD*LLi.", "tn") BUILTIN(__sync_nand_and_fetch_16, "LLLiLLLiD*LLLi.", "tn") BUILTIN(__sync_bool_compare_and_swap, "v.", "t") BUILTIN(__sync_bool_compare_and_swap_1, "bcD*cc.", "tn") BUILTIN(__sync_bool_compare_and_swap_2, "bsD*ss.", "tn") BUILTIN(__sync_bool_compare_and_swap_4, "biD*ii.", "tn") BUILTIN(__sync_bool_compare_and_swap_8, "bLLiD*LLiLLi.", "tn") BUILTIN(__sync_bool_compare_and_swap_16, "bLLLiD*LLLiLLLi.", "tn") BUILTIN(__sync_val_compare_and_swap, "v.", "t") BUILTIN(__sync_val_compare_and_swap_1, "ccD*cc.", "tn") BUILTIN(__sync_val_compare_and_swap_2, "ssD*ss.", "tn") BUILTIN(__sync_val_compare_and_swap_4, "iiD*ii.", "tn") BUILTIN(__sync_val_compare_and_swap_8, "LLiLLiD*LLiLLi.", "tn") BUILTIN(__sync_val_compare_and_swap_16, "LLLiLLLiD*LLLiLLLi.", "tn") BUILTIN(__sync_lock_test_and_set, "v.", "t") BUILTIN(__sync_lock_test_and_set_1, "ccD*c.", "tn") BUILTIN(__sync_lock_test_and_set_2, "ssD*s.", "tn") BUILTIN(__sync_lock_test_and_set_4, "iiD*i.", "tn") BUILTIN(__sync_lock_test_and_set_8, "LLiLLiD*LLi.", "tn") BUILTIN(__sync_lock_test_and_set_16, "LLLiLLLiD*LLLi.", "tn") BUILTIN(__sync_lock_release, "v.", "t") BUILTIN(__sync_lock_release_1, "vcD*.", "tn") BUILTIN(__sync_lock_release_2, "vsD*.", "tn") BUILTIN(__sync_lock_release_4, "viD*.", "tn") BUILTIN(__sync_lock_release_8, "vLLiD*.", "tn") BUILTIN(__sync_lock_release_16, "vLLLiD*.", "tn") BUILTIN(__sync_swap, "v.", "t") BUILTIN(__sync_swap_1, "ccD*c.", "tn") BUILTIN(__sync_swap_2, "ssD*s.", "tn") BUILTIN(__sync_swap_4, "iiD*i.", "tn") BUILTIN(__sync_swap_8, "LLiLLiD*LLi.", "tn") BUILTIN(__sync_swap_16, "LLLiLLLiD*LLLi.", "tn") // Some of our atomics builtins are handled by AtomicExpr rather than // as normal builtin CallExprs. This macro is used for such builtins. #ifndef ATOMIC_BUILTIN #define ATOMIC_BUILTIN(ID, TYPE, ATTRS) BUILTIN(ID, TYPE, ATTRS) #endif // C11 _Atomic operations for . ATOMIC_BUILTIN(__c11_atomic_init, "v.", "t") ATOMIC_BUILTIN(__c11_atomic_load, "v.", "t") ATOMIC_BUILTIN(__c11_atomic_store, "v.", "t") ATOMIC_BUILTIN(__c11_atomic_exchange, "v.", "t") ATOMIC_BUILTIN(__c11_atomic_compare_exchange_strong, "v.", "t") ATOMIC_BUILTIN(__c11_atomic_compare_exchange_weak, "v.", "t") ATOMIC_BUILTIN(__c11_atomic_fetch_add, "v.", "t") ATOMIC_BUILTIN(__c11_atomic_fetch_sub, "v.", "t") ATOMIC_BUILTIN(__c11_atomic_fetch_and, "v.", "t") ATOMIC_BUILTIN(__c11_atomic_fetch_or, "v.", "t") ATOMIC_BUILTIN(__c11_atomic_fetch_xor, "v.", "t") BUILTIN(__c11_atomic_thread_fence, "vi", "n") BUILTIN(__c11_atomic_signal_fence, "vi", "n") BUILTIN(__c11_atomic_is_lock_free, "iz", "n") // GNU atomic builtins. ATOMIC_BUILTIN(__atomic_load, "v.", "t") ATOMIC_BUILTIN(__atomic_load_n, "v.", "t") ATOMIC_BUILTIN(__atomic_store, "v.", "t") ATOMIC_BUILTIN(__atomic_store_n, "v.", "t") ATOMIC_BUILTIN(__atomic_exchange, "v.", "t") ATOMIC_BUILTIN(__atomic_exchange_n, "v.", "t") ATOMIC_BUILTIN(__atomic_compare_exchange, "v.", "t") ATOMIC_BUILTIN(__atomic_compare_exchange_n, "v.", "t") ATOMIC_BUILTIN(__atomic_fetch_add, "v.", "t") ATOMIC_BUILTIN(__atomic_fetch_sub, "v.", "t") ATOMIC_BUILTIN(__atomic_fetch_and, "v.", "t") ATOMIC_BUILTIN(__atomic_fetch_or, "v.", "t") ATOMIC_BUILTIN(__atomic_fetch_xor, "v.", "t") ATOMIC_BUILTIN(__atomic_fetch_nand, "v.", "t") ATOMIC_BUILTIN(__atomic_add_fetch, "v.", "t") ATOMIC_BUILTIN(__atomic_sub_fetch, "v.", "t") ATOMIC_BUILTIN(__atomic_and_fetch, "v.", "t") ATOMIC_BUILTIN(__atomic_or_fetch, "v.", "t") ATOMIC_BUILTIN(__atomic_xor_fetch, "v.", "t") ATOMIC_BUILTIN(__atomic_nand_fetch, "v.", "t") 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, "izvCD*", "n") BUILTIN(__atomic_is_lock_free, "izvCD*", "n") // OpenCL 2.0 atomic builtins. ATOMIC_BUILTIN(__opencl_atomic_init, "v.", "t") ATOMIC_BUILTIN(__opencl_atomic_load, "v.", "t") ATOMIC_BUILTIN(__opencl_atomic_store, "v.", "t") ATOMIC_BUILTIN(__opencl_atomic_exchange, "v.", "t") ATOMIC_BUILTIN(__opencl_atomic_compare_exchange_strong, "v.", "t") ATOMIC_BUILTIN(__opencl_atomic_compare_exchange_weak, "v.", "t") ATOMIC_BUILTIN(__opencl_atomic_fetch_add, "v.", "t") ATOMIC_BUILTIN(__opencl_atomic_fetch_sub, "v.", "t") ATOMIC_BUILTIN(__opencl_atomic_fetch_and, "v.", "t") ATOMIC_BUILTIN(__opencl_atomic_fetch_or, "v.", "t") ATOMIC_BUILTIN(__opencl_atomic_fetch_xor, "v.", "t") ATOMIC_BUILTIN(__opencl_atomic_fetch_min, "v.", "t") ATOMIC_BUILTIN(__opencl_atomic_fetch_max, "v.", "t") // GCC does not support these, they are a Clang extension. ATOMIC_BUILTIN(__atomic_fetch_min, "v.", "t") ATOMIC_BUILTIN(__atomic_fetch_max, "v.", "t") #undef ATOMIC_BUILTIN // Non-overloaded atomic builtins. BUILTIN(__sync_synchronize, "v", "n") // GCC does not support these, they are a Clang extension. BUILTIN(__sync_fetch_and_min, "iiD*i", "n") BUILTIN(__sync_fetch_and_max, "iiD*i", "n") BUILTIN(__sync_fetch_and_umin, "UiUiD*Ui", "n") BUILTIN(__sync_fetch_and_umax, "UiUiD*Ui", "n") // Random libc builtins. BUILTIN(__builtin_abort, "v", "Fnr") BUILTIN(__builtin_index, "c*cC*i", "Fn") BUILTIN(__builtin_rindex, "c*cC*i", "Fn") // 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(_bittest, "UcNiC*Ni", "n", ALL_MS_LANGUAGES) LANGBUILTIN(_bittestandcomplement, "UcNi*Ni", "n", ALL_MS_LANGUAGES) LANGBUILTIN(_bittestandreset, "UcNi*Ni", "n", ALL_MS_LANGUAGES) LANGBUILTIN(_bittestandset, "UcNi*Ni", "n", ALL_MS_LANGUAGES) LANGBUILTIN(_bittest64, "UcWiC*Wi", "n", ALL_MS_LANGUAGES) LANGBUILTIN(_bittestandcomplement64, "UcWi*Wi", "n", ALL_MS_LANGUAGES) LANGBUILTIN(_bittestandreset64, "UcWi*Wi", "n", ALL_MS_LANGUAGES) LANGBUILTIN(_bittestandset64, "UcWi*Wi", "n", ALL_MS_LANGUAGES) LIBBUILTIN(_byteswap_ushort, "UsUs", "fnc", "stdlib.h", ALL_MS_LANGUAGES) LIBBUILTIN(_byteswap_ulong, "UNiUNi", "fnc", "stdlib.h", ALL_MS_LANGUAGES) LIBBUILTIN(_byteswap_uint64, "ULLiULLi", "fnc", "stdlib.h", ALL_MS_LANGUAGES) LANGBUILTIN(__debugbreak, "v", "n", ALL_MS_LANGUAGES) LANGBUILTIN(__exception_code, "UNi", "n", ALL_MS_LANGUAGES) LANGBUILTIN(_exception_code, "UNi", "n", ALL_MS_LANGUAGES) LANGBUILTIN(__exception_info, "v*", "n", ALL_MS_LANGUAGES) LANGBUILTIN(_exception_info, "v*", "n", ALL_MS_LANGUAGES) LANGBUILTIN(__abnormal_termination, "i", "n", ALL_MS_LANGUAGES) LANGBUILTIN(_abnormal_termination, "i", "n", ALL_MS_LANGUAGES) LANGBUILTIN(__GetExceptionInfo, "v*.", "ntu", ALL_MS_LANGUAGES) LANGBUILTIN(_InterlockedAnd8, "ccD*c", "n", ALL_MS_LANGUAGES) LANGBUILTIN(_InterlockedAnd16, "ssD*s", "n", ALL_MS_LANGUAGES) LANGBUILTIN(_InterlockedAnd, "NiNiD*Ni", "n", ALL_MS_LANGUAGES) LANGBUILTIN(_InterlockedCompareExchange8, "ccD*cc", "n", ALL_MS_LANGUAGES) LANGBUILTIN(_InterlockedCompareExchange16, "ssD*ss", "n", ALL_MS_LANGUAGES) LANGBUILTIN(_InterlockedCompareExchange, "NiNiD*NiNi", "n", ALL_MS_LANGUAGES) LANGBUILTIN(_InterlockedCompareExchange64, "LLiLLiD*LLiLLi", "n", ALL_MS_LANGUAGES) LANGBUILTIN(_InterlockedCompareExchangePointer, "v*v*D*v*v*", "n", ALL_MS_LANGUAGES) LANGBUILTIN(_InterlockedDecrement16, "ssD*", "n", ALL_MS_LANGUAGES) LANGBUILTIN(_InterlockedDecrement, "NiNiD*", "n", ALL_MS_LANGUAGES) LANGBUILTIN(_InterlockedExchange, "NiNiD*Ni", "n", ALL_MS_LANGUAGES) LANGBUILTIN(_InterlockedExchange8, "ccD*c", "n", ALL_MS_LANGUAGES) LANGBUILTIN(_InterlockedExchange16, "ssD*s", "n", ALL_MS_LANGUAGES) LANGBUILTIN(_InterlockedExchangeAdd8, "ccD*c", "n", ALL_MS_LANGUAGES) LANGBUILTIN(_InterlockedExchangeAdd16, "ssD*s", "n", ALL_MS_LANGUAGES) LANGBUILTIN(_InterlockedExchangeAdd, "NiNiD*Ni", "n", ALL_MS_LANGUAGES) LANGBUILTIN(_InterlockedExchangePointer, "v*v*D*v*", "n", ALL_MS_LANGUAGES) LANGBUILTIN(_InterlockedExchangeSub8, "ccD*c", "n", ALL_MS_LANGUAGES) LANGBUILTIN(_InterlockedExchangeSub16, "ssD*s", "n", ALL_MS_LANGUAGES) LANGBUILTIN(_InterlockedExchangeSub, "NiNiD*Ni", "n", ALL_MS_LANGUAGES) LANGBUILTIN(_InterlockedIncrement16, "ssD*", "n", ALL_MS_LANGUAGES) LANGBUILTIN(_InterlockedIncrement, "NiNiD*", "n", ALL_MS_LANGUAGES) LANGBUILTIN(_InterlockedOr8, "ccD*c", "n", ALL_MS_LANGUAGES) LANGBUILTIN(_InterlockedOr16, "ssD*s", "n", ALL_MS_LANGUAGES) LANGBUILTIN(_InterlockedOr, "NiNiD*Ni", "n", ALL_MS_LANGUAGES) LANGBUILTIN(_InterlockedXor8, "ccD*c", "n", ALL_MS_LANGUAGES) LANGBUILTIN(_InterlockedXor16, "ssD*s", "n", ALL_MS_LANGUAGES) LANGBUILTIN(_InterlockedXor, "NiNiD*Ni", "n", ALL_MS_LANGUAGES) LANGBUILTIN(_interlockedbittestandreset, "UcNiD*Ni", "n", ALL_MS_LANGUAGES) LANGBUILTIN(_interlockedbittestandreset64, "UcWiD*Wi", "n", ALL_MS_LANGUAGES) LANGBUILTIN(_interlockedbittestandreset_acq, "UcNiD*Ni", "n", ALL_MS_LANGUAGES) LANGBUILTIN(_interlockedbittestandreset_nf, "UcNiD*Ni", "n", ALL_MS_LANGUAGES) LANGBUILTIN(_interlockedbittestandreset_rel, "UcNiD*Ni", "n", ALL_MS_LANGUAGES) LANGBUILTIN(_interlockedbittestandset, "UcNiD*Ni", "n", ALL_MS_LANGUAGES) LANGBUILTIN(_interlockedbittestandset64, "UcWiD*Wi", "n", ALL_MS_LANGUAGES) LANGBUILTIN(_interlockedbittestandset_acq, "UcNiD*Ni", "n", ALL_MS_LANGUAGES) LANGBUILTIN(_interlockedbittestandset_nf, "UcNiD*Ni", "n", ALL_MS_LANGUAGES) LANGBUILTIN(_interlockedbittestandset_rel, "UcNiD*Ni", "n", ALL_MS_LANGUAGES) LANGBUILTIN(__noop, "i.", "n", ALL_MS_LANGUAGES) LANGBUILTIN(__popcnt16, "UsUs", "nc", ALL_MS_LANGUAGES) LANGBUILTIN(__popcnt, "UiUi", "nc", ALL_MS_LANGUAGES) LANGBUILTIN(__popcnt64, "ULLiULLi", "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, "UNiUNii", "n", ALL_MS_LANGUAGES) LANGBUILTIN(_rotl64, "ULLiULLii", "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, "UNiUNii", "n", ALL_MS_LANGUAGES) LANGBUILTIN(_rotr64, "ULLiULLii", "n", ALL_MS_LANGUAGES) LANGBUILTIN(__va_start, "vc**.", "nt", ALL_MS_LANGUAGES) LANGBUILTIN(__fastfail, "vUi", "nr", ALL_MS_LANGUAGES) // Microsoft library builtins. LIBBUILTIN(_setjmpex, "iJ", "fj", "setjmpex.h", ALL_MS_LANGUAGES) // C99 library functions // C99 stdarg.h LIBBUILTIN(va_start, "vA.", "fn", "stdarg.h", ALL_LANGUAGES) LIBBUILTIN(va_end, "vA", "fn", "stdarg.h", ALL_LANGUAGES) LIBBUILTIN(va_copy, "vAA", "fn", "stdarg.h", ALL_LANGUAGES) // C99 stdlib.h LIBBUILTIN(abort, "v", "fr", "stdlib.h", ALL_LANGUAGES) LIBBUILTIN(calloc, "v*zz", "f", "stdlib.h", ALL_LANGUAGES) LIBBUILTIN(exit, "vi", "fr", "stdlib.h", ALL_LANGUAGES) LIBBUILTIN(_Exit, "vi", "fr", "stdlib.h", ALL_LANGUAGES) LIBBUILTIN(malloc, "v*z", "f", "stdlib.h", ALL_LANGUAGES) LIBBUILTIN(realloc, "v*v*z", "f", "stdlib.h", ALL_LANGUAGES) LIBBUILTIN(strtod, "dcC*c**", "f", "stdlib.h", ALL_LANGUAGES) LIBBUILTIN(strtof, "fcC*c**", "f", "stdlib.h", ALL_LANGUAGES) LIBBUILTIN(strtold, "LdcC*c**", "f", "stdlib.h", ALL_LANGUAGES) LIBBUILTIN(strtol, "LicC*c**i", "f", "stdlib.h", ALL_LANGUAGES) LIBBUILTIN(strtoll, "LLicC*c**i", "f", "stdlib.h", ALL_LANGUAGES) LIBBUILTIN(strtoul, "ULicC*c**i", "f", "stdlib.h", ALL_LANGUAGES) LIBBUILTIN(strtoull, "ULLicC*c**i", "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(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(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(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) LIBBUILTIN(strspn, "zcC*cC*", "f", "string.h", ALL_LANGUAGES) 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) // C99 stdio.h // FIXME: This list is incomplete. LIBBUILTIN(printf, "icC*.", "fp:0:", "stdio.h", ALL_LANGUAGES) LIBBUILTIN(fprintf, "iP*cC*.", "fp:1:", "stdio.h", ALL_LANGUAGES) LIBBUILTIN(snprintf, "ic*zcC*.", "fp:2:", "stdio.h", ALL_LANGUAGES) LIBBUILTIN(sprintf, "ic*cC*.", "fp:1:", "stdio.h", ALL_LANGUAGES) LIBBUILTIN(vprintf, "icC*a", "fP:0:", "stdio.h", ALL_LANGUAGES) LIBBUILTIN(vfprintf, "iP*cC*a", "fP:1:", "stdio.h", ALL_LANGUAGES) LIBBUILTIN(vsnprintf, "ic*zcC*a", "fP:2:", "stdio.h", ALL_LANGUAGES) LIBBUILTIN(vsprintf, "ic*cC*a", "fP:1:", "stdio.h", ALL_LANGUAGES) LIBBUILTIN(scanf, "icC*R.", "fs:0:", "stdio.h", ALL_LANGUAGES) LIBBUILTIN(fscanf, "iP*RcC*R.", "fs:1:", "stdio.h", ALL_LANGUAGES) LIBBUILTIN(sscanf, "icC*RcC*R.", "fs:1:", "stdio.h", ALL_LANGUAGES) LIBBUILTIN(vscanf, "icC*Ra", "fS:0:", "stdio.h", ALL_LANGUAGES) LIBBUILTIN(vfscanf, "iP*RcC*Ra", "fS:1:", "stdio.h", ALL_LANGUAGES) LIBBUILTIN(vsscanf, "icC*RcC*Ra", "fS:1:", "stdio.h", ALL_LANGUAGES) LIBBUILTIN(fopen, "P*cC*cC*", "f", "stdio.h", ALL_LANGUAGES) LIBBUILTIN(fread, "zv*zzP*", "f", "stdio.h", ALL_LANGUAGES) LIBBUILTIN(fwrite, "zvC*zzP*", "f", "stdio.h", ALL_LANGUAGES) // C99 ctype.h LIBBUILTIN(isalnum, "ii", "fnU", "ctype.h", ALL_LANGUAGES) LIBBUILTIN(isalpha, "ii", "fnU", "ctype.h", ALL_LANGUAGES) LIBBUILTIN(isblank, "ii", "fnU", "ctype.h", ALL_LANGUAGES) LIBBUILTIN(iscntrl, "ii", "fnU", "ctype.h", ALL_LANGUAGES) LIBBUILTIN(isdigit, "ii", "fnU", "ctype.h", ALL_LANGUAGES) LIBBUILTIN(isgraph, "ii", "fnU", "ctype.h", ALL_LANGUAGES) LIBBUILTIN(islower, "ii", "fnU", "ctype.h", ALL_LANGUAGES) LIBBUILTIN(isprint, "ii", "fnU", "ctype.h", ALL_LANGUAGES) LIBBUILTIN(ispunct, "ii", "fnU", "ctype.h", ALL_LANGUAGES) LIBBUILTIN(isspace, "ii", "fnU", "ctype.h", ALL_LANGUAGES) LIBBUILTIN(isupper, "ii", "fnU", "ctype.h", ALL_LANGUAGES) LIBBUILTIN(isxdigit, "ii", "fnU", "ctype.h", ALL_LANGUAGES) LIBBUILTIN(tolower, "ii", "fnU", "ctype.h", ALL_LANGUAGES) 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) // C99 // In some systems setjmp is a macro that expands to _setjmp. We undefine // it here to avoid having two identical LIBBUILTIN entries. #undef setjmp LIBBUILTIN(setjmp, "iJ", "fj", "setjmp.h", ALL_LANGUAGES) LIBBUILTIN(longjmp, "vJi", "fr", "setjmp.h", ALL_LANGUAGES) // Non-C library functions, active in GNU mode only. // Functions with (returns_twice) attribute (marked as "j") are still active in // all languages, because losing this attribute would result in miscompilation // when these functions are used in non-GNU mode. PR16138. LIBBUILTIN(alloca, "v*z", "f", "stdlib.h", ALL_GNU_LANGUAGES) // POSIX string.h LIBBUILTIN(stpcpy, "c*c*cC*", "f", "string.h", ALL_GNU_LANGUAGES) LIBBUILTIN(stpncpy, "c*c*cC*z", "f", "string.h", ALL_GNU_LANGUAGES) LIBBUILTIN(strdup, "c*cC*", "f", "string.h", ALL_GNU_LANGUAGES) LIBBUILTIN(strndup, "c*cC*z", "f", "string.h", ALL_GNU_LANGUAGES) // POSIX strings.h 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) // 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 #undef strncasecmp LIBBUILTIN(strcasecmp, "icC*cC*", "f", "strings.h", ALL_GNU_LANGUAGES) LIBBUILTIN(strncasecmp, "icC*cC*z", "f", "strings.h", ALL_GNU_LANGUAGES) // POSIX unistd.h LIBBUILTIN(_exit, "vi", "fr", "unistd.h", ALL_GNU_LANGUAGES) LIBBUILTIN(vfork, "p", "fj", "unistd.h", ALL_LANGUAGES) // POSIX setjmp.h LIBBUILTIN(_setjmp, "iJ", "fj", "setjmp.h", ALL_LANGUAGES) LIBBUILTIN(__sigsetjmp, "iSJi", "fj", "setjmp.h", ALL_LANGUAGES) LIBBUILTIN(sigsetjmp, "iSJi", "fj", "setjmp.h", ALL_LANGUAGES) LIBBUILTIN(setjmp_syscall, "iJ", "fj", "setjmp.h", ALL_LANGUAGES) LIBBUILTIN(savectx, "iJ", "fj", "setjmp.h", ALL_LANGUAGES) LIBBUILTIN(qsetjmp, "iJ", "fj", "setjmp.h", ALL_LANGUAGES) LIBBUILTIN(getcontext, "iK*", "fj", "setjmp.h", ALL_LANGUAGES) LIBBUILTIN(_longjmp, "vJi", "fr", "setjmp.h", ALL_GNU_LANGUAGES) LIBBUILTIN(siglongjmp, "vSJi", "fr", "setjmp.h", ALL_GNU_LANGUAGES) // non-standard but very common LIBBUILTIN(strlcpy, "zc*cC*z", "f", "string.h", ALL_GNU_LANGUAGES) LIBBUILTIN(strlcat, "zc*cC*z", "f", "string.h", ALL_GNU_LANGUAGES) // id objc_msgSend(id, SEL, ...) LIBBUILTIN(objc_msgSend, "GGH.", "f", "objc/message.h", OBJC_LANG) // long double objc_msgSend_fpret(id self, SEL op, ...) LIBBUILTIN(objc_msgSend_fpret, "LdGH.", "f", "objc/message.h", OBJC_LANG) // _Complex long double objc_msgSend_fp2ret(id self, SEL op, ...) LIBBUILTIN(objc_msgSend_fp2ret, "XLdGH.", "f", "objc/message.h", OBJC_LANG) // void objc_msgSend_stret (id, SEL, ...) LIBBUILTIN(objc_msgSend_stret, "vGH.", "f", "objc/message.h", OBJC_LANG) // id objc_msgSendSuper(struct objc_super *super, SEL op, ...) LIBBUILTIN(objc_msgSendSuper, "GM*H.", "f", "objc/message.h", OBJC_LANG) // void objc_msgSendSuper_stret(struct objc_super *super, SEL op, ...) LIBBUILTIN(objc_msgSendSuper_stret, "vM*H.", "f", "objc/message.h", OBJC_LANG) // id objc_getClass(const char *name) LIBBUILTIN(objc_getClass, "GcC*", "f", "objc/runtime.h", OBJC_LANG) // id objc_getMetaClass(const char *name) LIBBUILTIN(objc_getMetaClass, "GcC*", "f", "objc/runtime.h", OBJC_LANG) // void objc_enumerationMutation(id) LIBBUILTIN(objc_enumerationMutation, "vG", "f", "objc/runtime.h", OBJC_LANG) // id objc_read_weak(id *location) LIBBUILTIN(objc_read_weak, "GG*", "f", "objc/objc-auto.h", OBJC_LANG) // id objc_assign_weak(id value, id *location) LIBBUILTIN(objc_assign_weak, "GGG*", "f", "objc/objc-auto.h", OBJC_LANG) // id objc_assign_ivar(id value, id dest, ptrdiff_t offset) LIBBUILTIN(objc_assign_ivar, "GGGY", "f", "objc/objc-auto.h", OBJC_LANG) // id objc_assign_global(id val, id *dest) LIBBUILTIN(objc_assign_global, "GGG*", "f", "objc/objc-auto.h", OBJC_LANG) // id objc_assign_strongCast(id val, id *dest LIBBUILTIN(objc_assign_strongCast, "GGG*", "f", "objc/objc-auto.h", OBJC_LANG) // id objc_exception_extract(void *localExceptionData) LIBBUILTIN(objc_exception_extract, "Gv*", "f", "objc/objc-exception.h", OBJC_LANG) // void objc_exception_try_enter(void *localExceptionData) LIBBUILTIN(objc_exception_try_enter, "vv*", "f", "objc/objc-exception.h", OBJC_LANG) // void objc_exception_try_exit(void *localExceptionData) LIBBUILTIN(objc_exception_try_exit, "vv*", "f", "objc/objc-exception.h", OBJC_LANG) // int objc_exception_match(Class exceptionClass, id exception) LIBBUILTIN(objc_exception_match, "iGG", "f", "objc/objc-exception.h", OBJC_LANG) // void objc_exception_throw(id exception) LIBBUILTIN(objc_exception_throw, "vG", "f", "objc/objc-exception.h", OBJC_LANG) // int objc_sync_enter(id obj) LIBBUILTIN(objc_sync_enter, "iG", "f", "objc/objc-sync.h", OBJC_LANG) // int objc_sync_exit(id obj) LIBBUILTIN(objc_sync_exit, "iG", "f", "objc/objc-sync.h", OBJC_LANG) BUILTIN(__builtin_objc_memmove_collectable, "v*v*vC*z", "nF") // void NSLog(NSString *fmt, ...) LIBBUILTIN(NSLog, "vG.", "fp:0:", "Foundation/NSObjCRuntime.h", OBJC_LANG) // void NSLogv(NSString *fmt, va_list args) LIBBUILTIN(NSLogv, "vGa", "fP:0:", "Foundation/NSObjCRuntime.h", OBJC_LANG) // Builtin math library functions LIBBUILTIN(atan2, "ddd", "fne", "math.h", ALL_LANGUAGES) LIBBUILTIN(atan2f, "fff", "fne", "math.h", ALL_LANGUAGES) LIBBUILTIN(atan2l, "LdLdLd", "fne", "math.h", ALL_LANGUAGES) LIBBUILTIN(abs, "ii", "fnc", "stdlib.h", ALL_LANGUAGES) LIBBUILTIN(labs, "LiLi", "fnc", "stdlib.h", ALL_LANGUAGES) LIBBUILTIN(llabs, "LLiLLi", "fnc", "stdlib.h", ALL_LANGUAGES) LIBBUILTIN(copysign, "ddd", "fnc", "math.h", ALL_LANGUAGES) LIBBUILTIN(copysignf, "fff", "fnc", "math.h", ALL_LANGUAGES) LIBBUILTIN(copysignl, "LdLdLd", "fnc", "math.h", ALL_LANGUAGES) LIBBUILTIN(fabs, "dd", "fnc", "math.h", ALL_LANGUAGES) LIBBUILTIN(fabsf, "ff", "fnc", "math.h", ALL_LANGUAGES) LIBBUILTIN(fabsl, "LdLd", "fnc", "math.h", ALL_LANGUAGES) // Some systems define finitef as alias of _finitef. #if defined (finitef) #undef finitef #endif LIBBUILTIN(finite, "id", "fnc", "math.h", GNU_LANG) LIBBUILTIN(finitef, "if", "fnc", "math.h", GNU_LANG) LIBBUILTIN(finitel, "iLd", "fnc", "math.h", GNU_LANG) // glibc's math.h generates calls to __finite LIBBUILTIN(__finite, "id", "fnc", "math.h", ALL_LANGUAGES) LIBBUILTIN(__finitef, "if", "fnc", "math.h", ALL_LANGUAGES) LIBBUILTIN(__finitel, "iLd", "fnc", "math.h", ALL_LANGUAGES) LIBBUILTIN(fmod, "ddd", "fne", "math.h", ALL_LANGUAGES) LIBBUILTIN(fmodf, "fff", "fne", "math.h", ALL_LANGUAGES) LIBBUILTIN(fmodl, "LdLdLd", "fne", "math.h", ALL_LANGUAGES) LIBBUILTIN(frexp, "ddi*", "fn", "math.h", ALL_LANGUAGES) LIBBUILTIN(frexpf, "ffi*", "fn", "math.h", ALL_LANGUAGES) LIBBUILTIN(frexpl, "LdLdi*", "fn", "math.h", ALL_LANGUAGES) LIBBUILTIN(ldexp, "ddi", "fne", "math.h", ALL_LANGUAGES) LIBBUILTIN(ldexpf, "ffi", "fne", "math.h", ALL_LANGUAGES) LIBBUILTIN(ldexpl, "LdLdi", "fne", "math.h", ALL_LANGUAGES) LIBBUILTIN(modf, "ddd*", "fn", "math.h", ALL_LANGUAGES) LIBBUILTIN(modff, "fff*", "fn", "math.h", ALL_LANGUAGES) LIBBUILTIN(modfl, "LdLdLd*", "fn", "math.h", ALL_LANGUAGES) LIBBUILTIN(nan, "dcC*", "fUn", "math.h", ALL_LANGUAGES) LIBBUILTIN(nanf, "fcC*", "fUn", "math.h", ALL_LANGUAGES) LIBBUILTIN(nanl, "LdcC*", "fUn", "math.h", ALL_LANGUAGES) LIBBUILTIN(pow, "ddd", "fne", "math.h", ALL_LANGUAGES) LIBBUILTIN(powf, "fff", "fne", "math.h", ALL_LANGUAGES) LIBBUILTIN(powl, "LdLdLd", "fne", "math.h", ALL_LANGUAGES) LIBBUILTIN(acos, "dd", "fne", "math.h", ALL_LANGUAGES) LIBBUILTIN(acosf, "ff", "fne", "math.h", ALL_LANGUAGES) LIBBUILTIN(acosl, "LdLd", "fne", "math.h", ALL_LANGUAGES) LIBBUILTIN(acosh, "dd", "fne", "math.h", ALL_LANGUAGES) LIBBUILTIN(acoshf, "ff", "fne", "math.h", ALL_LANGUAGES) LIBBUILTIN(acoshl, "LdLd", "fne", "math.h", ALL_LANGUAGES) LIBBUILTIN(asin, "dd", "fne", "math.h", ALL_LANGUAGES) LIBBUILTIN(asinf, "ff", "fne", "math.h", ALL_LANGUAGES) LIBBUILTIN(asinl, "LdLd", "fne", "math.h", ALL_LANGUAGES) LIBBUILTIN(asinh, "dd", "fne", "math.h", ALL_LANGUAGES) LIBBUILTIN(asinhf, "ff", "fne", "math.h", ALL_LANGUAGES) LIBBUILTIN(asinhl, "LdLd", "fne", "math.h", ALL_LANGUAGES) LIBBUILTIN(atan, "dd", "fne", "math.h", ALL_LANGUAGES) LIBBUILTIN(atanf, "ff", "fne", "math.h", ALL_LANGUAGES) LIBBUILTIN(atanl, "LdLd", "fne", "math.h", ALL_LANGUAGES) LIBBUILTIN(atanh, "dd", "fne", "math.h", ALL_LANGUAGES) LIBBUILTIN(atanhf, "ff", "fne", "math.h", ALL_LANGUAGES) LIBBUILTIN(atanhl, "LdLd", "fne", "math.h", ALL_LANGUAGES) LIBBUILTIN(cbrt, "dd", "fnc", "math.h", ALL_LANGUAGES) LIBBUILTIN(cbrtf, "ff", "fnc", "math.h", ALL_LANGUAGES) LIBBUILTIN(cbrtl, "LdLd", "fnc", "math.h", ALL_LANGUAGES) LIBBUILTIN(ceil, "dd", "fnc", "math.h", ALL_LANGUAGES) LIBBUILTIN(ceilf, "ff", "fnc", "math.h", ALL_LANGUAGES) LIBBUILTIN(ceill, "LdLd", "fnc", "math.h", ALL_LANGUAGES) LIBBUILTIN(cos, "dd", "fne", "math.h", ALL_LANGUAGES) LIBBUILTIN(cosf, "ff", "fne", "math.h", ALL_LANGUAGES) LIBBUILTIN(cosl, "LdLd", "fne", "math.h", ALL_LANGUAGES) LIBBUILTIN(cosh, "dd", "fne", "math.h", ALL_LANGUAGES) LIBBUILTIN(coshf, "ff", "fne", "math.h", ALL_LANGUAGES) LIBBUILTIN(coshl, "LdLd", "fne", "math.h", ALL_LANGUAGES) LIBBUILTIN(erf, "dd", "fne", "math.h", ALL_LANGUAGES) LIBBUILTIN(erff, "ff", "fne", "math.h", ALL_LANGUAGES) LIBBUILTIN(erfl, "LdLd", "fne", "math.h", ALL_LANGUAGES) LIBBUILTIN(erfc, "dd", "fne", "math.h", ALL_LANGUAGES) LIBBUILTIN(erfcf, "ff", "fne", "math.h", ALL_LANGUAGES) LIBBUILTIN(erfcl, "LdLd", "fne", "math.h", ALL_LANGUAGES) LIBBUILTIN(exp, "dd", "fne", "math.h", ALL_LANGUAGES) LIBBUILTIN(expf, "ff", "fne", "math.h", ALL_LANGUAGES) LIBBUILTIN(expl, "LdLd", "fne", "math.h", ALL_LANGUAGES) LIBBUILTIN(exp2, "dd", "fne", "math.h", ALL_LANGUAGES) LIBBUILTIN(exp2f, "ff", "fne", "math.h", ALL_LANGUAGES) LIBBUILTIN(exp2l, "LdLd", "fne", "math.h", ALL_LANGUAGES) LIBBUILTIN(expm1, "dd", "fne", "math.h", ALL_LANGUAGES) LIBBUILTIN(expm1f, "ff", "fne", "math.h", ALL_LANGUAGES) LIBBUILTIN(expm1l, "LdLd", "fne", "math.h", ALL_LANGUAGES) LIBBUILTIN(fdim, "ddd", "fne", "math.h", ALL_LANGUAGES) LIBBUILTIN(fdimf, "fff", "fne", "math.h", ALL_LANGUAGES) LIBBUILTIN(fdiml, "LdLdLd", "fne", "math.h", ALL_LANGUAGES) LIBBUILTIN(floor, "dd", "fnc", "math.h", ALL_LANGUAGES) LIBBUILTIN(floorf, "ff", "fnc", "math.h", ALL_LANGUAGES) LIBBUILTIN(floorl, "LdLd", "fnc", "math.h", ALL_LANGUAGES) LIBBUILTIN(fma, "dddd", "fne", "math.h", ALL_LANGUAGES) LIBBUILTIN(fmaf, "ffff", "fne", "math.h", ALL_LANGUAGES) LIBBUILTIN(fmal, "LdLdLdLd", "fne", "math.h", ALL_LANGUAGES) LIBBUILTIN(fmax, "ddd", "fnc", "math.h", ALL_LANGUAGES) LIBBUILTIN(fmaxf, "fff", "fnc", "math.h", ALL_LANGUAGES) LIBBUILTIN(fmaxl, "LdLdLd", "fnc", "math.h", ALL_LANGUAGES) LIBBUILTIN(fmin, "ddd", "fnc", "math.h", ALL_LANGUAGES) LIBBUILTIN(fminf, "fff", "fnc", "math.h", ALL_LANGUAGES) LIBBUILTIN(fminl, "LdLdLd", "fnc", "math.h", ALL_LANGUAGES) LIBBUILTIN(hypot, "ddd", "fne", "math.h", ALL_LANGUAGES) LIBBUILTIN(hypotf, "fff", "fne", "math.h", ALL_LANGUAGES) LIBBUILTIN(hypotl, "LdLdLd", "fne", "math.h", ALL_LANGUAGES) LIBBUILTIN(ilogb, "id", "fne", "math.h", ALL_LANGUAGES) LIBBUILTIN(ilogbf, "if", "fne", "math.h", ALL_LANGUAGES) LIBBUILTIN(ilogbl, "iLd", "fne", "math.h", ALL_LANGUAGES) // POSIX math.h declares a global, signgam, that lgamma writes to, so these // shouldn't have "e" or "c" attributes LIBBUILTIN(lgamma, "dd", "fn", "math.h", ALL_LANGUAGES) LIBBUILTIN(lgammaf, "ff", "fn", "math.h", ALL_LANGUAGES) LIBBUILTIN(lgammal, "LdLd", "fn", "math.h", ALL_LANGUAGES) LIBBUILTIN(llrint, "LLid", "fne", "math.h", ALL_LANGUAGES) LIBBUILTIN(llrintf, "LLif", "fne", "math.h", ALL_LANGUAGES) LIBBUILTIN(llrintl, "LLiLd", "fne", "math.h", ALL_LANGUAGES) LIBBUILTIN(llround, "LLid", "fne", "math.h", ALL_LANGUAGES) LIBBUILTIN(llroundf, "LLif", "fne", "math.h", ALL_LANGUAGES) LIBBUILTIN(llroundl, "LLiLd", "fne", "math.h", ALL_LANGUAGES) LIBBUILTIN(log, "dd", "fne", "math.h", ALL_LANGUAGES) LIBBUILTIN(logf, "ff", "fne", "math.h", ALL_LANGUAGES) LIBBUILTIN(logl, "LdLd", "fne", "math.h", ALL_LANGUAGES) LIBBUILTIN(log10, "dd", "fne", "math.h", ALL_LANGUAGES) LIBBUILTIN(log10f, "ff", "fne", "math.h", ALL_LANGUAGES) LIBBUILTIN(log10l, "LdLd", "fne", "math.h", ALL_LANGUAGES) LIBBUILTIN(log1p, "dd", "fne", "math.h", ALL_LANGUAGES) LIBBUILTIN(log1pf, "ff", "fne", "math.h", ALL_LANGUAGES) LIBBUILTIN(log1pl, "LdLd", "fne", "math.h", ALL_LANGUAGES) LIBBUILTIN(log2, "dd", "fne", "math.h", ALL_LANGUAGES) LIBBUILTIN(log2f, "ff", "fne", "math.h", ALL_LANGUAGES) LIBBUILTIN(log2l, "LdLd", "fne", "math.h", ALL_LANGUAGES) LIBBUILTIN(logb, "dd", "fne", "math.h", ALL_LANGUAGES) LIBBUILTIN(logbf, "ff", "fne", "math.h", ALL_LANGUAGES) LIBBUILTIN(logbl, "LdLd", "fne", "math.h", ALL_LANGUAGES) LIBBUILTIN(lrint, "Lid", "fne", "math.h", ALL_LANGUAGES) LIBBUILTIN(lrintf, "Lif", "fne", "math.h", ALL_LANGUAGES) LIBBUILTIN(lrintl, "LiLd", "fne", "math.h", ALL_LANGUAGES) LIBBUILTIN(lround, "Lid", "fne", "math.h", ALL_LANGUAGES) LIBBUILTIN(lroundf, "Lif", "fne", "math.h", ALL_LANGUAGES) LIBBUILTIN(lroundl, "LiLd", "fne", "math.h", ALL_LANGUAGES) LIBBUILTIN(nearbyint, "dd", "fnc", "math.h", ALL_LANGUAGES) LIBBUILTIN(nearbyintf, "ff", "fnc", "math.h", ALL_LANGUAGES) LIBBUILTIN(nearbyintl, "LdLd", "fnc", "math.h", ALL_LANGUAGES) LIBBUILTIN(nextafter, "ddd", "fne", "math.h", ALL_LANGUAGES) LIBBUILTIN(nextafterf, "fff", "fne", "math.h", ALL_LANGUAGES) LIBBUILTIN(nextafterl, "LdLdLd", "fne", "math.h", ALL_LANGUAGES) LIBBUILTIN(nexttoward, "ddLd", "fne", "math.h", ALL_LANGUAGES) LIBBUILTIN(nexttowardf, "ffLd", "fne", "math.h", ALL_LANGUAGES) LIBBUILTIN(nexttowardl, "LdLdLd", "fne", "math.h", ALL_LANGUAGES) LIBBUILTIN(remainder, "ddd", "fne", "math.h", ALL_LANGUAGES) LIBBUILTIN(remainderf, "fff", "fne", "math.h", ALL_LANGUAGES) LIBBUILTIN(remainderl, "LdLdLd", "fne", "math.h", ALL_LANGUAGES) LIBBUILTIN(remquo, "dddi*", "fn", "math.h", ALL_LANGUAGES) LIBBUILTIN(remquof, "fffi*", "fn", "math.h", ALL_LANGUAGES) LIBBUILTIN(remquol, "LdLdLdi*", "fn", "math.h", ALL_LANGUAGES) LIBBUILTIN(rint, "dd", "fnc", "math.h", ALL_LANGUAGES) LIBBUILTIN(rintf, "ff", "fnc", "math.h", ALL_LANGUAGES) LIBBUILTIN(rintl, "LdLd", "fnc", "math.h", ALL_LANGUAGES) LIBBUILTIN(round, "dd", "fnc", "math.h", ALL_LANGUAGES) LIBBUILTIN(roundf, "ff", "fnc", "math.h", ALL_LANGUAGES) LIBBUILTIN(roundl, "LdLd", "fnc", "math.h", ALL_LANGUAGES) LIBBUILTIN(scalbln, "ddLi", "fne", "math.h", ALL_LANGUAGES) LIBBUILTIN(scalblnf, "ffLi", "fne", "math.h", ALL_LANGUAGES) LIBBUILTIN(scalblnl, "LdLdLi", "fne", "math.h", ALL_LANGUAGES) LIBBUILTIN(scalbn, "ddi", "fne", "math.h", ALL_LANGUAGES) LIBBUILTIN(scalbnf, "ffi", "fne", "math.h", ALL_LANGUAGES) LIBBUILTIN(scalbnl, "LdLdi", "fne", "math.h", ALL_LANGUAGES) LIBBUILTIN(sin, "dd", "fne", "math.h", ALL_LANGUAGES) LIBBUILTIN(sinf, "ff", "fne", "math.h", ALL_LANGUAGES) LIBBUILTIN(sinl, "LdLd", "fne", "math.h", ALL_LANGUAGES) LIBBUILTIN(sinh, "dd", "fne", "math.h", ALL_LANGUAGES) LIBBUILTIN(sinhf, "ff", "fne", "math.h", ALL_LANGUAGES) LIBBUILTIN(sinhl, "LdLd", "fne", "math.h", ALL_LANGUAGES) LIBBUILTIN(sqrt, "dd", "fne", "math.h", ALL_LANGUAGES) LIBBUILTIN(sqrtf, "ff", "fne", "math.h", ALL_LANGUAGES) LIBBUILTIN(sqrtl, "LdLd", "fne", "math.h", ALL_LANGUAGES) LIBBUILTIN(tan, "dd", "fne", "math.h", ALL_LANGUAGES) LIBBUILTIN(tanf, "ff", "fne", "math.h", ALL_LANGUAGES) LIBBUILTIN(tanl, "LdLd", "fne", "math.h", ALL_LANGUAGES) LIBBUILTIN(tanh, "dd", "fne", "math.h", ALL_LANGUAGES) LIBBUILTIN(tanhf, "ff", "fne", "math.h", ALL_LANGUAGES) LIBBUILTIN(tanhl, "LdLd", "fne", "math.h", ALL_LANGUAGES) LIBBUILTIN(tgamma, "dd", "fne", "math.h", ALL_LANGUAGES) LIBBUILTIN(tgammaf, "ff", "fne", "math.h", ALL_LANGUAGES) LIBBUILTIN(tgammal, "LdLd", "fne", "math.h", ALL_LANGUAGES) LIBBUILTIN(trunc, "dd", "fnc", "math.h", ALL_LANGUAGES) LIBBUILTIN(truncf, "ff", "fnc", "math.h", ALL_LANGUAGES) LIBBUILTIN(truncl, "LdLd", "fnc", "math.h", ALL_LANGUAGES) LIBBUILTIN(cabs, "dXd", "fne", "complex.h", ALL_LANGUAGES) LIBBUILTIN(cabsf, "fXf", "fne", "complex.h", ALL_LANGUAGES) LIBBUILTIN(cabsl, "LdXLd", "fne", "complex.h", ALL_LANGUAGES) LIBBUILTIN(cacos, "XdXd", "fne", "complex.h", ALL_LANGUAGES) LIBBUILTIN(cacosf, "XfXf", "fne", "complex.h", ALL_LANGUAGES) LIBBUILTIN(cacosl, "XLdXLd", "fne", "complex.h", ALL_LANGUAGES) LIBBUILTIN(cacosh, "XdXd", "fne", "complex.h", ALL_LANGUAGES) LIBBUILTIN(cacoshf, "XfXf", "fne", "complex.h", ALL_LANGUAGES) LIBBUILTIN(cacoshl, "XLdXLd", "fne", "complex.h", ALL_LANGUAGES) LIBBUILTIN(carg, "dXd", "fne", "complex.h", ALL_LANGUAGES) LIBBUILTIN(cargf, "fXf", "fne", "complex.h", ALL_LANGUAGES) LIBBUILTIN(cargl, "LdXLd", "fne", "complex.h", ALL_LANGUAGES) LIBBUILTIN(casin, "XdXd", "fne", "complex.h", ALL_LANGUAGES) LIBBUILTIN(casinf, "XfXf", "fne", "complex.h", ALL_LANGUAGES) LIBBUILTIN(casinl, "XLdXLd", "fne", "complex.h", ALL_LANGUAGES) LIBBUILTIN(casinh, "XdXd", "fne", "complex.h", ALL_LANGUAGES) LIBBUILTIN(casinhf, "XfXf", "fne", "complex.h", ALL_LANGUAGES) LIBBUILTIN(casinhl, "XLdXLd", "fne", "complex.h", ALL_LANGUAGES) LIBBUILTIN(catan, "XdXd", "fne", "complex.h", ALL_LANGUAGES) LIBBUILTIN(catanf, "XfXf", "fne", "complex.h", ALL_LANGUAGES) LIBBUILTIN(catanl, "XLdXLd", "fne", "complex.h", ALL_LANGUAGES) LIBBUILTIN(catanh, "XdXd", "fne", "complex.h", ALL_LANGUAGES) LIBBUILTIN(catanhf, "XfXf", "fne", "complex.h", ALL_LANGUAGES) LIBBUILTIN(catanhl, "XLdXLd", "fne", "complex.h", ALL_LANGUAGES) LIBBUILTIN(ccos, "XdXd", "fne", "complex.h", ALL_LANGUAGES) LIBBUILTIN(ccosf, "XfXf", "fne", "complex.h", ALL_LANGUAGES) LIBBUILTIN(ccosl, "XLdXLd", "fne", "complex.h", ALL_LANGUAGES) LIBBUILTIN(ccosh, "XdXd", "fne", "complex.h", ALL_LANGUAGES) LIBBUILTIN(ccoshf, "XfXf", "fne", "complex.h", ALL_LANGUAGES) LIBBUILTIN(ccoshl, "XLdXLd", "fne", "complex.h", ALL_LANGUAGES) LIBBUILTIN(cexp, "XdXd", "fne", "complex.h", ALL_LANGUAGES) LIBBUILTIN(cexpf, "XfXf", "fne", "complex.h", ALL_LANGUAGES) LIBBUILTIN(cexpl, "XLdXLd", "fne", "complex.h", ALL_LANGUAGES) LIBBUILTIN(cimag, "dXd", "fnc", "complex.h", ALL_LANGUAGES) LIBBUILTIN(cimagf, "fXf", "fnc", "complex.h", ALL_LANGUAGES) LIBBUILTIN(cimagl, "LdXLd", "fnc", "complex.h", ALL_LANGUAGES) LIBBUILTIN(conj, "XdXd", "fnc", "complex.h", ALL_LANGUAGES) LIBBUILTIN(conjf, "XfXf", "fnc", "complex.h", ALL_LANGUAGES) LIBBUILTIN(conjl, "XLdXLd", "fnc", "complex.h", ALL_LANGUAGES) LIBBUILTIN(clog, "XdXd", "fne", "complex.h", ALL_LANGUAGES) LIBBUILTIN(clogf, "XfXf", "fne", "complex.h", ALL_LANGUAGES) LIBBUILTIN(clogl, "XLdXLd", "fne", "complex.h", ALL_LANGUAGES) LIBBUILTIN(cproj, "XdXd", "fnc", "complex.h", ALL_LANGUAGES) LIBBUILTIN(cprojf, "XfXf", "fnc", "complex.h", ALL_LANGUAGES) LIBBUILTIN(cprojl, "XLdXLd", "fnc", "complex.h", ALL_LANGUAGES) LIBBUILTIN(cpow, "XdXdXd", "fne", "complex.h", ALL_LANGUAGES) LIBBUILTIN(cpowf, "XfXfXf", "fne", "complex.h", ALL_LANGUAGES) LIBBUILTIN(cpowl, "XLdXLdXLd", "fne", "complex.h", ALL_LANGUAGES) LIBBUILTIN(creal, "dXd", "fnc", "complex.h", ALL_LANGUAGES) LIBBUILTIN(crealf, "fXf", "fnc", "complex.h", ALL_LANGUAGES) LIBBUILTIN(creall, "LdXLd", "fnc", "complex.h", ALL_LANGUAGES) LIBBUILTIN(csin, "XdXd", "fne", "complex.h", ALL_LANGUAGES) LIBBUILTIN(csinf, "XfXf", "fne", "complex.h", ALL_LANGUAGES) LIBBUILTIN(csinl, "XLdXLd", "fne", "complex.h", ALL_LANGUAGES) LIBBUILTIN(csinh, "XdXd", "fne", "complex.h", ALL_LANGUAGES) LIBBUILTIN(csinhf, "XfXf", "fne", "complex.h", ALL_LANGUAGES) LIBBUILTIN(csinhl, "XLdXLd", "fne", "complex.h", ALL_LANGUAGES) LIBBUILTIN(csqrt, "XdXd", "fne", "complex.h", ALL_LANGUAGES) LIBBUILTIN(csqrtf, "XfXf", "fne", "complex.h", ALL_LANGUAGES) LIBBUILTIN(csqrtl, "XLdXLd", "fne", "complex.h", ALL_LANGUAGES) LIBBUILTIN(ctan, "XdXd", "fne", "complex.h", ALL_LANGUAGES) LIBBUILTIN(ctanf, "XfXf", "fne", "complex.h", ALL_LANGUAGES) LIBBUILTIN(ctanl, "XLdXLd", "fne", "complex.h", ALL_LANGUAGES) LIBBUILTIN(ctanh, "XdXd", "fne", "complex.h", ALL_LANGUAGES) LIBBUILTIN(ctanhf, "XfXf", "fne", "complex.h", ALL_LANGUAGES) LIBBUILTIN(ctanhl, "XLdXLd", "fne", "complex.h", ALL_LANGUAGES) // __sinpi and friends are OS X specific library functions, but otherwise much // like the standard (non-complex) sin (etc). LIBBUILTIN(__sinpi, "dd", "fne", "math.h", ALL_LANGUAGES) LIBBUILTIN(__sinpif, "ff", "fne", "math.h", ALL_LANGUAGES) LIBBUILTIN(__cospi, "dd", "fne", "math.h", ALL_LANGUAGES) LIBBUILTIN(__cospif, "ff", "fne", "math.h", ALL_LANGUAGES) LIBBUILTIN(__tanpi, "dd", "fne", "math.h", ALL_LANGUAGES) LIBBUILTIN(__tanpif, "ff", "fne", "math.h", ALL_LANGUAGES) // Similarly, __exp10 is OS X only LIBBUILTIN(__exp10, "dd", "fne", "math.h", ALL_LANGUAGES) LIBBUILTIN(__exp10f, "ff", "fne", "math.h", ALL_LANGUAGES) // Blocks runtime Builtin math library functions LIBBUILTIN(_Block_object_assign, "vv*vC*iC", "f", "Blocks.h", ALL_LANGUAGES) LIBBUILTIN(_Block_object_dispose, "vvC*iC", "f", "Blocks.h", ALL_LANGUAGES) // FIXME: Also declare NSConcreteGlobalBlock and NSConcreteStackBlock. // Annotation function BUILTIN(__builtin_annotation, "v.", "tn") // Invariants BUILTIN(__builtin_assume, "vb", "n") // Multiprecision Arithmetic Builtins. BUILTIN(__builtin_addcb, "UcUcCUcCUcCUc*", "n") BUILTIN(__builtin_addcs, "UsUsCUsCUsCUs*", "n") BUILTIN(__builtin_addc, "UiUiCUiCUiCUi*", "n") BUILTIN(__builtin_addcl, "ULiULiCULiCULiCULi*", "n") BUILTIN(__builtin_addcll, "ULLiULLiCULLiCULLiCULLi*", "n") BUILTIN(__builtin_subcb, "UcUcCUcCUcCUc*", "n") BUILTIN(__builtin_subcs, "UsUsCUsCUsCUs*", "n") BUILTIN(__builtin_subc, "UiUiCUiCUiCUi*", "n") BUILTIN(__builtin_subcl, "ULiULiCULiCULiCULi*", "n") BUILTIN(__builtin_subcll, "ULLiULLiCULLiCULLiCULLi*", "n") // Checked Arithmetic Builtins for Security. BUILTIN(__builtin_add_overflow, "v.", "nt") BUILTIN(__builtin_sub_overflow, "v.", "nt") BUILTIN(__builtin_mul_overflow, "v.", "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") // Clang builtins (not available in GCC). BUILTIN(__builtin_addressof, "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_dump_struct, "ivC*v*", "tn") // Safestack builtins BUILTIN(__builtin___get_unsafe_stack_start, "v*", "Fn") BUILTIN(__builtin___get_unsafe_stack_bottom, "v*", "Fn") BUILTIN(__builtin___get_unsafe_stack_top, "v*", "Fn") BUILTIN(__builtin___get_unsafe_stack_ptr, "v*", "Fn") // Nontemporal loads/stores builtins BUILTIN(__builtin_nontemporal_store, "v.", "t") BUILTIN(__builtin_nontemporal_load, "v.", "t") // Coroutine intrinsics. BUILTIN(__builtin_coro_resume, "vv*", "") BUILTIN(__builtin_coro_destroy, "vv*", "") BUILTIN(__builtin_coro_done, "bv*", "n") BUILTIN(__builtin_coro_promise, "v*v*IiIb", "n") BUILTIN(__builtin_coro_size, "z", "n") BUILTIN(__builtin_coro_frame, "v*", "n") BUILTIN(__builtin_coro_noop, "v*", "n") BUILTIN(__builtin_coro_free, "v*v*", "n") BUILTIN(__builtin_coro_id, "v*Iiv*v*v*", "n") BUILTIN(__builtin_coro_alloc, "b", "n") BUILTIN(__builtin_coro_begin, "v*v*", "n") BUILTIN(__builtin_coro_end, "bv*Ib", "n") BUILTIN(__builtin_coro_suspend, "cIb", "n") BUILTIN(__builtin_coro_param, "bv*v*", "n") // OpenCL v2.0 s6.13.16, s9.17.3.5 - Pipe functions. // We need the generic prototype, since the packet type could be anything. LANGBUILTIN(read_pipe, "i.", "tn", OCLC20_LANG) LANGBUILTIN(write_pipe, "i.", "tn", OCLC20_LANG) LANGBUILTIN(reserve_read_pipe, "i.", "tn", OCLC20_LANG) LANGBUILTIN(reserve_write_pipe, "i.", "tn", OCLC20_LANG) LANGBUILTIN(commit_write_pipe, "v.", "tn", OCLC20_LANG) LANGBUILTIN(commit_read_pipe, "v.", "tn", OCLC20_LANG) LANGBUILTIN(sub_group_reserve_read_pipe, "i.", "tn", OCLC20_LANG) LANGBUILTIN(sub_group_reserve_write_pipe, "i.", "tn", OCLC20_LANG) LANGBUILTIN(sub_group_commit_read_pipe, "v.", "tn", OCLC20_LANG) LANGBUILTIN(sub_group_commit_write_pipe, "v.", "tn", OCLC20_LANG) LANGBUILTIN(work_group_reserve_read_pipe, "i.", "tn", OCLC20_LANG) LANGBUILTIN(work_group_reserve_write_pipe, "i.", "tn", OCLC20_LANG) LANGBUILTIN(work_group_commit_read_pipe, "v.", "tn", OCLC20_LANG) LANGBUILTIN(work_group_commit_write_pipe, "v.", "tn", OCLC20_LANG) LANGBUILTIN(get_pipe_num_packets, "Ui.", "tn", OCLC20_LANG) LANGBUILTIN(get_pipe_max_packets, "Ui.", "tn", OCLC20_LANG) // OpenCL v2.0 s6.13.17 - Enqueue kernel functions. // Custom builtin check allows to perform special check of passed block arguments. LANGBUILTIN(enqueue_kernel, "i.", "tn", OCLC20_LANG) LANGBUILTIN(get_kernel_work_group_size, "Ui.", "tn", OCLC20_LANG) LANGBUILTIN(get_kernel_preferred_work_group_size_multiple, "Ui.", "tn", OCLC20_LANG) LANGBUILTIN(get_kernel_max_sub_group_size_for_ndrange, "Ui.", "tn", OCLC20_LANG) LANGBUILTIN(get_kernel_sub_group_count_for_ndrange, "Ui.", "tn", OCLC20_LANG) // OpenCL v2.0 s6.13.9 - Address space qualifier functions. LANGBUILTIN(to_global, "v*v*", "tn", OCLC20_LANG) LANGBUILTIN(to_local, "v*v*", "tn", OCLC20_LANG) LANGBUILTIN(to_private, "v*v*", "tn", OCLC20_LANG) // OpenCL half load/store builtin LANGBUILTIN(__builtin_store_half, "vdh*", "n", ALL_OCLC_LANGUAGES) LANGBUILTIN(__builtin_store_halff, "vfh*", "n", ALL_OCLC_LANGUAGES) LANGBUILTIN(__builtin_load_half, "dhC*", "nc", ALL_OCLC_LANGUAGES) LANGBUILTIN(__builtin_load_halff, "fhC*", "nc", ALL_OCLC_LANGUAGES) // Builtins for os_log/os_trace BUILTIN(__builtin_os_log_format_buffer_size, "zcC*.", "p:0:nut") BUILTIN(__builtin_os_log_format, "v*v*cC*.", "p:0:nt") // OpenMP 4.0 LANGBUILTIN(omp_is_initial_device, "i", "nc", OMP_LANG) // Builtins for XRay BUILTIN(__xray_customevent, "vcC*z", "") BUILTIN(__xray_typedevent, "vzcC*z", "") // Win64-compatible va_list functions BUILTIN(__builtin_ms_va_start, "vc*&.", "nt") BUILTIN(__builtin_ms_va_end, "vc*&", "n") BUILTIN(__builtin_ms_va_copy, "vc*&c*&", "n") #undef BUILTIN #undef LIBBUILTIN #undef LANGBUILTIN Index: projects/clang700-import/contrib/llvm/tools/clang/include/clang/Basic/DiagnosticASTKinds.td =================================================================== --- projects/clang700-import/contrib/llvm/tools/clang/include/clang/Basic/DiagnosticASTKinds.td (revision 337309) +++ projects/clang700-import/contrib/llvm/tools/clang/include/clang/Basic/DiagnosticASTKinds.td (revision 337310) @@ -1,308 +1,294 @@ //==--- DiagnosticASTKinds.td - libast diagnostics ------------------------===// // // The LLVM Compiler Infrastructure // // This file is distributed under the University of Illinois Open Source // License. See LICENSE.TXT for details. // //===----------------------------------------------------------------------===// let Component = "AST" in { // Constant expression diagnostics. These (and their users) belong in Sema. def note_expr_divide_by_zero : Note<"division by zero">; def note_constexpr_invalid_cast : Note< "%select{reinterpret_cast|dynamic_cast|cast that performs the conversions of" " a reinterpret_cast|cast from %1}0 is not allowed in a constant expression">; def note_constexpr_invalid_downcast : Note< "cannot cast object of dynamic type %0 to type %1">; def note_constexpr_overflow : Note< "value %0 is outside the range of representable values of type %1">; def note_constexpr_negative_shift : Note<"negative shift count %0">; def note_constexpr_large_shift : Note< "shift count %0 >= width of type %1 (%2 bit%s2)">; def note_constexpr_lshift_of_negative : Note<"left shift of negative value %0">; def note_constexpr_lshift_discards : Note<"signed left shift discards bits">; def note_constexpr_invalid_function : Note< "%select{non-constexpr|undefined}0 %select{function|constructor}1 %2 cannot " "be used in a constant expression">; def note_constexpr_invalid_inhctor : Note< "constructor inherited from base class %0 cannot be used in a " "constant expression; derived class cannot be implicitly initialized">; def note_constexpr_no_return : Note< "control reached end of constexpr function">; def note_constexpr_virtual_call : Note< "cannot evaluate virtual function call in a constant expression">; def note_constexpr_virtual_base : Note< "cannot construct object of type %0 with virtual base class " "in a constant expression">; def note_constexpr_nonliteral : Note< "non-literal type %0 cannot be used in a constant expression">; def note_constexpr_non_global : Note< "%select{pointer|reference}0 to %select{|subobject of }1" "%select{temporary|%3}2 is not a constant expression">; def note_constexpr_uninitialized : Note< "%select{|sub}0object of type %1 is not initialized">; def note_constexpr_array_index : Note<"cannot refer to element %0 of " "%select{array of %2 element%plural{1:|:s}2|non-array object}1 " "in a constant expression">; def note_constexpr_float_arithmetic : Note< "floating point arithmetic produces %select{an infinity|a NaN}0">; def note_constexpr_pointer_subtraction_not_same_array : Note< "subtracted pointers are not elements of the same array">; def note_constexpr_pointer_subtraction_zero_size : Note< "subtraction of pointers to type %0 of zero size">; def note_constexpr_pointer_comparison_base_classes : Note< "comparison of addresses of subobjects of different base classes " "has unspecified value">; def note_constexpr_pointer_comparison_base_field : Note< "comparison of address of base class subobject %0 of class %1 to field %2 " "has unspecified value">; def note_constexpr_pointer_comparison_differing_access : Note< "comparison of address of fields %0 and %2 of %4 with differing access " "specifiers (%1 vs %3) has unspecified value">; def note_constexpr_compare_virtual_mem_ptr : Note< "comparison of pointer to virtual member function %0 has unspecified value">; def note_constexpr_past_end : Note< "dereferenced pointer past the end of %select{|subobject of }0" "%select{temporary|%2}1 is not a constant expression">; def note_constexpr_past_end_subobject : Note< "cannot %select{access base class of|access derived class of|access field of|" "access array element of|ERROR|call member function on|" "access real component of|access imaginary component of}0 " "pointer past the end of object">; def note_constexpr_null_subobject : Note< "cannot %select{access base class of|access derived class of|access field of|" "access array element of|perform pointer arithmetic on|" "call member function on|access real component of|" "access imaginary component of}0 null pointer">; def note_constexpr_var_init_non_constant : Note< "initializer of %0 is not a constant expression">; def note_constexpr_typeid_polymorphic : Note< "typeid applied to expression of polymorphic type %0 is " "not allowed in a constant expression">; def note_constexpr_void_comparison : Note< "comparison between unequal pointers to void has unspecified result">; def note_constexpr_temporary_here : Note<"temporary created here">; def note_constexpr_conditional_never_const : Note< "both arms of conditional operator are unable to produce a " "constant expression">; def note_constexpr_depth_limit_exceeded : Note< "constexpr evaluation exceeded maximum depth of %0 calls">; def note_constexpr_call_limit_exceeded : Note< "constexpr evaluation hit maximum call limit">; def note_constexpr_step_limit_exceeded : Note< "constexpr evaluation hit maximum step limit; possible infinite loop?">; def note_constexpr_this : Note< "%select{|implicit }0use of 'this' pointer is only allowed within the " "evaluation of a call to a 'constexpr' member function">; def note_constexpr_lifetime_ended : Note< "%select{read of|assignment to|increment of|decrement of}0 " "%select{temporary|variable}1 whose lifetime has ended">; def note_constexpr_access_uninit : Note< "%select{read of|assignment to|increment of|decrement of}0 " "object outside its lifetime is not allowed in a constant expression">; def note_constexpr_use_uninit_reference : Note< "use of reference outside its lifetime " "is not allowed in a constant expression">; def note_constexpr_modify_const_type : Note< "modification of object of const-qualified type %0 is not allowed " "in a constant expression">; def note_constexpr_access_volatile_type : Note< "%select{read of|assignment to|increment of|decrement of}0 " "volatile-qualified type %1 is not allowed in a constant expression">; def note_constexpr_access_volatile_obj : Note< "%select{read of|assignment to|increment of|decrement of}0 volatile " "%select{temporary|object %2|member %2}1 is not allowed in " "a constant expression">; def note_constexpr_ltor_mutable : Note< "read of mutable member %0 is not allowed in a constant expression">; def note_constexpr_ltor_non_const_int : Note< "read of non-const variable %0 is not allowed in a constant expression">; def note_constexpr_ltor_non_constexpr : Note< "read of non-constexpr variable %0 is not allowed in a constant expression">; def note_constexpr_access_null : Note< "%select{read of|assignment to|increment of|decrement of}0 " "dereferenced null pointer is not allowed in a constant expression">; def note_constexpr_access_past_end : Note< "%select{read of|assignment to|increment of|decrement of}0 " "dereferenced one-past-the-end pointer is not allowed in a constant expression">; def note_constexpr_access_unsized_array : Note< "%select{read of|assignment to|increment of|decrement of}0 " "pointer to element of array without known bound " "is not allowed in a constant expression">; def note_constexpr_access_inactive_union_member : Note< "%select{read of|assignment to|increment of|decrement of}0 " "member %1 of union with %select{active member %3|no active member}2 " "is not allowed in a constant expression">; def note_constexpr_access_static_temporary : Note< "%select{read of|assignment to|increment of|decrement of}0 temporary " "is not allowed in a constant expression outside the expression that " "created the temporary">; def note_constexpr_modify_global : Note< "a constant expression cannot modify an object that is visible outside " "that expression">; def note_constexpr_stmt_expr_unsupported : Note< "this use of statement expressions is not supported in a " "constant expression">; def note_constexpr_calls_suppressed : Note< "(skipping %0 call%s0 in backtrace; use -fconstexpr-backtrace-limit=0 to " "see all)">; def note_constexpr_call_here : Note<"in call to '%0'">; def note_constexpr_inherited_ctor_call_here : Note< "in implicit initialization for inherited constructor of %0">; def note_constexpr_baa_insufficient_alignment : Note< "%select{alignment of|offset of the aligned pointer from}0 the base pointee " "object (%1 %plural{1:byte|:bytes}1) is %select{less than|not a multiple of}0 the " "asserted %2 %plural{1:byte|:bytes}2">; def note_constexpr_baa_value_insufficient_alignment : Note< "value of the aligned pointer (%0) is not a multiple of the asserted %1 " "%plural{1:byte|:bytes}1">; def note_constexpr_unsupported_unsized_array : Note< "array-to-pointer decay of array member without known bound is not supported">; def note_constexpr_unsized_array_indexed : Note< "indexing of array without known bound is not allowed " "in a constant expression">; -def note_constexpr_memcpy_type_pun : Note< - "cannot constant evaluate '%select{memcpy|memmove}0' from object of " - "type %1 to object of type %2">; -def note_constexpr_memcpy_nontrivial : Note< - "cannot constant evaluate '%select{memcpy|memmove}0' between objects of " - "non-trivially-copyable type %1">; -def note_constexpr_memcpy_overlap : Note< - "'%select{memcpy|wmemcpy}0' between overlapping memory regions">; -def note_constexpr_memcpy_unsupported : Note< - "'%select{%select{memcpy|wmemcpy}1|%select{memmove|wmemmove}1}0' " - "not supported: %select{" - "size to copy (%4) is not a multiple of size of element type %3 (%5)|" - "source is not a contiguous array of at least %4 elements of type %3|" - "destination is not a contiguous array of at least %4 elements of type %3}2">; def warn_integer_constant_overflow : Warning< "overflow in expression; result is %0 with type %1">, InGroup>; // This is a temporary diagnostic, and shall be removed once our // implementation is complete, and like the preceding constexpr notes belongs // in Sema. def note_unimplemented_constexpr_lambda_feature_ast : Note< "unimplemented constexpr lambda feature: %0 (coming soon!)">; // inline asm related. let CategoryName = "Inline Assembly Issue" in { def err_asm_invalid_escape : Error< "invalid %% escape in inline assembly string">; def err_asm_unknown_symbolic_operand_name : Error< "unknown symbolic operand name in inline assembly string">; def err_asm_unterminated_symbolic_operand_name : Error< "unterminated symbolic operand name in inline assembly string">; def err_asm_empty_symbolic_operand_name : Error< "empty symbolic operand name in inline assembly string">; def err_asm_invalid_operand_number : Error< "invalid operand number in inline asm string">; } // vtable related. let CategoryName = "VTable ABI Issue" in { def err_vftable_ambiguous_component : Error< "ambiguous vftable component for %0 introduced via covariant thunks; " "this is an inherent limitation of the ABI">; def note_covariant_thunk : Note< "covariant thunk required by %0">; } // Importing ASTs def err_odr_variable_type_inconsistent : Error< "external variable %0 declared with incompatible types in different " "translation units (%1 vs. %2)">; def err_odr_variable_multiple_def : Error< "external variable %0 defined in multiple translation units">; def note_odr_value_here : Note<"declared here with type %0">; def note_odr_defined_here : Note<"also defined here">; def err_odr_function_type_inconsistent : Error< "external function %0 declared with incompatible types in different " "translation units (%1 vs. %2)">; def warn_odr_tag_type_inconsistent : Warning<"type %0 has incompatible definitions in different translation " "units">, InGroup>; def err_odr_tag_type_inconsistent : Error<"type %0 has incompatible definitions in different translation " "units">; def note_odr_tag_kind_here: Note< "%0 is a %select{struct|interface|union|class|enum}1 here">; def note_odr_field : Note<"field %0 has type %1 here">; def note_odr_field_name : Note<"field has name %0 here">; def note_odr_missing_field : Note<"no corresponding field here">; def note_odr_bit_field : Note<"bit-field %0 with type %1 and length %2 here">; def note_odr_not_bit_field : Note<"field %0 is not a bit-field">; def note_odr_base : Note<"class has base type %0">; def note_odr_virtual_base : Note< "%select{non-virtual|virtual}0 derivation here">; def note_odr_missing_base : Note<"no corresponding base class here">; def note_odr_number_of_bases : Note< "class has %0 base %plural{1:class|:classes}0">; def note_odr_enumerator : Note<"enumerator %0 with value %1 here">; def note_odr_missing_enumerator : Note<"no corresponding enumerator here">; def err_odr_field_type_inconsistent : Error< "field %0 declared with incompatible types in different " "translation units (%1 vs. %2)">; // Importing Objective-C ASTs def err_odr_ivar_type_inconsistent : Error< "instance variable %0 declared with incompatible types in different " "translation units (%1 vs. %2)">; def err_odr_objc_superclass_inconsistent : Error< "class %0 has incompatible superclasses">; def note_odr_objc_superclass : Note<"inherits from superclass %0 here">; def note_odr_objc_missing_superclass : Note<"no corresponding superclass here">; def err_odr_objc_method_result_type_inconsistent : Error< "%select{class|instance}0 method %1 has incompatible result types in " "different translation units (%2 vs. %3)">; def err_odr_objc_method_num_params_inconsistent : Error< "%select{class|instance}0 method %1 has a different number of parameters in " "different translation units (%2 vs. %3)">; def err_odr_objc_method_param_type_inconsistent : Error< "%select{class|instance}0 method %1 has a parameter with a different types " "in different translation units (%2 vs. %3)">; def err_odr_objc_method_variadic_inconsistent : Error< "%select{class|instance}0 method %1 is variadic in one translation unit " "and not variadic in another">; def note_odr_objc_method_here : Note< "%select{class|instance}0 method %1 also declared here">; def err_odr_objc_property_type_inconsistent : Error< "property %0 declared with incompatible types in different " "translation units (%1 vs. %2)">; def err_odr_objc_property_impl_kind_inconsistent : Error< "property %0 is implemented with %select{@synthesize|@dynamic}1 in one " "translation but %select{@dynamic|@synthesize}1 in another translation unit">; def note_odr_objc_property_impl_kind : Note< "property %0 is implemented with %select{@synthesize|@dynamic}1 here">; def err_odr_objc_synthesize_ivar_inconsistent : Error< "property %0 is synthesized to different ivars in different translation " "units (%1 vs. %2)">; def note_odr_objc_synthesize_ivar_here : Note< "property is synthesized to ivar %0 here">; // Importing C++ ASTs def note_odr_friend : Note<"friend declared here">; def note_odr_missing_friend : Note<"no corresponding friend here">; def err_odr_different_num_template_parameters : Error< "template parameter lists have a different number of parameters (%0 vs %1)">; def note_odr_template_parameter_list : Note< "template parameter list also declared here">; def err_odr_different_template_parameter_kind : Error< "template parameter has different kinds in different translation units">; def note_odr_template_parameter_here : Note< "template parameter declared here">; def err_odr_parameter_pack_non_pack : Error< "parameter kind mismatch; parameter is %select{not a|a}0 parameter pack">; def note_odr_parameter_pack_non_pack : Note< "%select{parameter|parameter pack}0 declared here">; def err_odr_non_type_parameter_type_inconsistent : Error< "non-type template parameter declared with incompatible types in different " "translation units (%0 vs. %1)">; def err_unsupported_ast_node: Error<"cannot import unsupported AST node %0">; } Index: projects/clang700-import/contrib/llvm/tools/clang/lib/AST/ExprConstant.cpp =================================================================== --- projects/clang700-import/contrib/llvm/tools/clang/lib/AST/ExprConstant.cpp (revision 337309) +++ projects/clang700-import/contrib/llvm/tools/clang/lib/AST/ExprConstant.cpp (revision 337310) @@ -1,11483 +1,11333 @@ //===--- ExprConstant.cpp - Expression Constant Evaluator -----------------===// // // The LLVM Compiler Infrastructure // // This file is distributed under the University of Illinois Open Source // License. See LICENSE.TXT for details. // //===----------------------------------------------------------------------===// // // This file implements the Expr constant evaluator. // // Constant expression evaluation produces four main results: // // * A success/failure flag indicating whether constant folding was successful. // This is the 'bool' return value used by most of the code in this file. A // 'false' return value indicates that constant folding has failed, and any // appropriate diagnostic has already been produced. // // * An evaluated result, valid only if constant folding has not failed. // // * A flag indicating if evaluation encountered (unevaluated) side-effects. // These arise in cases such as (sideEffect(), 0) and (sideEffect() || 1), // where it is possible to determine the evaluated result regardless. // // * A set of notes indicating why the evaluation was not a constant expression // (under the C++11 / C++1y rules only, at the moment), or, if folding failed // too, why the expression could not be folded. // // If we are checking for a potential constant expression, failure to constant // fold a potential constant sub-expression will be indicated by a 'false' // return value (the expression could not be folded) and no diagnostic (the // expression is not necessarily non-constant). // //===----------------------------------------------------------------------===// #include "clang/AST/APValue.h" #include "clang/AST/ASTContext.h" #include "clang/AST/ASTDiagnostic.h" #include "clang/AST/ASTLambda.h" #include "clang/AST/CharUnits.h" #include "clang/AST/Expr.h" #include "clang/AST/RecordLayout.h" #include "clang/AST/StmtVisitor.h" #include "clang/AST/TypeLoc.h" #include "clang/Basic/Builtins.h" #include "clang/Basic/TargetInfo.h" #include "llvm/Support/raw_ostream.h" #include #include #define DEBUG_TYPE "exprconstant" using namespace clang; using llvm::APSInt; using llvm::APFloat; static bool IsGlobalLValue(APValue::LValueBase B); namespace { struct LValue; struct CallStackFrame; struct EvalInfo; static QualType getType(APValue::LValueBase B) { if (!B) return QualType(); if (const ValueDecl *D = B.dyn_cast()) { // FIXME: It's unclear where we're supposed to take the type from, and // this actually matters for arrays of unknown bound. Eg: // // extern int arr[]; void f() { extern int arr[3]; }; // constexpr int *p = &arr[1]; // valid? // // For now, we take the array bound from the most recent declaration. for (auto *Redecl = cast(D->getMostRecentDecl()); Redecl; Redecl = cast_or_null(Redecl->getPreviousDecl())) { QualType T = Redecl->getType(); if (!T->isIncompleteArrayType()) return T; } return D->getType(); } const Expr *Base = B.get(); // For a materialized temporary, the type of the temporary we materialized // may not be the type of the expression. if (const MaterializeTemporaryExpr *MTE = dyn_cast(Base)) { SmallVector CommaLHSs; SmallVector Adjustments; const Expr *Temp = MTE->GetTemporaryExpr(); const Expr *Inner = Temp->skipRValueSubobjectAdjustments(CommaLHSs, Adjustments); // Keep any cv-qualifiers from the reference if we generated a temporary // for it directly. Otherwise use the type after adjustment. if (!Adjustments.empty()) return Inner->getType(); } return Base->getType(); } /// Get an LValue path entry, which is known to not be an array index, as a /// field or base class. static APValue::BaseOrMemberType getAsBaseOrMember(APValue::LValuePathEntry E) { APValue::BaseOrMemberType Value; Value.setFromOpaqueValue(E.BaseOrMember); return Value; } /// Get an LValue path entry, which is known to not be an array index, as a /// field declaration. static const FieldDecl *getAsField(APValue::LValuePathEntry E) { return dyn_cast(getAsBaseOrMember(E).getPointer()); } /// Get an LValue path entry, which is known to not be an array index, as a /// base class declaration. static const CXXRecordDecl *getAsBaseClass(APValue::LValuePathEntry E) { return dyn_cast(getAsBaseOrMember(E).getPointer()); } /// Determine whether this LValue path entry for a base class names a virtual /// base class. static bool isVirtualBaseClass(APValue::LValuePathEntry E) { return getAsBaseOrMember(E).getInt(); } /// Given a CallExpr, try to get the alloc_size attribute. May return null. static const AllocSizeAttr *getAllocSizeAttr(const CallExpr *CE) { const FunctionDecl *Callee = CE->getDirectCallee(); return Callee ? Callee->getAttr() : nullptr; } /// Attempts to unwrap a CallExpr (with an alloc_size attribute) from an Expr. /// This will look through a single cast. /// /// Returns null if we couldn't unwrap a function with alloc_size. static const CallExpr *tryUnwrapAllocSizeCall(const Expr *E) { if (!E->getType()->isPointerType()) return nullptr; E = E->IgnoreParens(); // If we're doing a variable assignment from e.g. malloc(N), there will // probably be a cast of some kind. In exotic cases, we might also see a // top-level ExprWithCleanups. Ignore them either way. if (const auto *EC = dyn_cast(E)) E = EC->getSubExpr()->IgnoreParens(); if (const auto *Cast = dyn_cast(E)) E = Cast->getSubExpr()->IgnoreParens(); if (const auto *CE = dyn_cast(E)) return getAllocSizeAttr(CE) ? CE : nullptr; return nullptr; } /// Determines whether or not the given Base contains a call to a function /// with the alloc_size attribute. static bool isBaseAnAllocSizeCall(APValue::LValueBase Base) { const auto *E = Base.dyn_cast(); return E && E->getType()->isPointerType() && tryUnwrapAllocSizeCall(E); } /// The bound to claim that an array of unknown bound has. /// The value in MostDerivedArraySize is undefined in this case. So, set it /// to an arbitrary value that's likely to loudly break things if it's used. static const uint64_t AssumedSizeForUnsizedArray = std::numeric_limits::max() / 2; /// Determines if an LValue with the given LValueBase will have an unsized /// array in its designator. /// Find the path length and type of the most-derived subobject in the given /// path, and find the size of the containing array, if any. static unsigned findMostDerivedSubobject(ASTContext &Ctx, APValue::LValueBase Base, ArrayRef Path, uint64_t &ArraySize, QualType &Type, bool &IsArray, bool &FirstEntryIsUnsizedArray) { // This only accepts LValueBases from APValues, and APValues don't support // arrays that lack size info. assert(!isBaseAnAllocSizeCall(Base) && "Unsized arrays shouldn't appear here"); unsigned MostDerivedLength = 0; Type = getType(Base); for (unsigned I = 0, N = Path.size(); I != N; ++I) { if (Type->isArrayType()) { const ArrayType *AT = Ctx.getAsArrayType(Type); Type = AT->getElementType(); MostDerivedLength = I + 1; IsArray = true; if (auto *CAT = dyn_cast(AT)) { ArraySize = CAT->getSize().getZExtValue(); } else { assert(I == 0 && "unexpected unsized array designator"); FirstEntryIsUnsizedArray = true; ArraySize = AssumedSizeForUnsizedArray; } } else if (Type->isAnyComplexType()) { const ComplexType *CT = Type->castAs(); Type = CT->getElementType(); ArraySize = 2; MostDerivedLength = I + 1; IsArray = true; } else if (const FieldDecl *FD = getAsField(Path[I])) { Type = FD->getType(); ArraySize = 0; MostDerivedLength = I + 1; IsArray = false; } else { // Path[I] describes a base class. ArraySize = 0; IsArray = false; } } return MostDerivedLength; } // The order of this enum is important for diagnostics. enum CheckSubobjectKind { CSK_Base, CSK_Derived, CSK_Field, CSK_ArrayToPointer, CSK_ArrayIndex, CSK_This, CSK_Real, CSK_Imag }; /// A path from a glvalue to a subobject of that glvalue. struct SubobjectDesignator { /// True if the subobject was named in a manner not supported by C++11. Such /// lvalues can still be folded, but they are not core constant expressions /// and we cannot perform lvalue-to-rvalue conversions on them. unsigned Invalid : 1; /// Is this a pointer one past the end of an object? unsigned IsOnePastTheEnd : 1; /// Indicator of whether the first entry is an unsized array. unsigned FirstEntryIsAnUnsizedArray : 1; /// Indicator of whether the most-derived object is an array element. unsigned MostDerivedIsArrayElement : 1; /// The length of the path to the most-derived object of which this is a /// subobject. unsigned MostDerivedPathLength : 28; /// The size of the array of which the most-derived object is an element. /// This will always be 0 if the most-derived object is not an array /// element. 0 is not an indicator of whether or not the most-derived object /// is an array, however, because 0-length arrays are allowed. /// /// If the current array is an unsized array, the value of this is /// undefined. uint64_t MostDerivedArraySize; /// The type of the most derived object referred to by this address. QualType MostDerivedType; typedef APValue::LValuePathEntry PathEntry; /// The entries on the path from the glvalue to the designated subobject. SmallVector Entries; SubobjectDesignator() : Invalid(true) {} explicit SubobjectDesignator(QualType T) : Invalid(false), IsOnePastTheEnd(false), FirstEntryIsAnUnsizedArray(false), MostDerivedIsArrayElement(false), MostDerivedPathLength(0), MostDerivedArraySize(0), MostDerivedType(T) {} SubobjectDesignator(ASTContext &Ctx, const APValue &V) : Invalid(!V.isLValue() || !V.hasLValuePath()), IsOnePastTheEnd(false), FirstEntryIsAnUnsizedArray(false), MostDerivedIsArrayElement(false), MostDerivedPathLength(0), MostDerivedArraySize(0) { assert(V.isLValue() && "Non-LValue used to make an LValue designator?"); if (!Invalid) { IsOnePastTheEnd = V.isLValueOnePastTheEnd(); ArrayRef VEntries = V.getLValuePath(); Entries.insert(Entries.end(), VEntries.begin(), VEntries.end()); if (V.getLValueBase()) { bool IsArray = false; bool FirstIsUnsizedArray = false; MostDerivedPathLength = findMostDerivedSubobject( Ctx, V.getLValueBase(), V.getLValuePath(), MostDerivedArraySize, MostDerivedType, IsArray, FirstIsUnsizedArray); MostDerivedIsArrayElement = IsArray; FirstEntryIsAnUnsizedArray = FirstIsUnsizedArray; } } } void setInvalid() { Invalid = true; Entries.clear(); } /// Determine whether the most derived subobject is an array without a /// known bound. bool isMostDerivedAnUnsizedArray() const { assert(!Invalid && "Calling this makes no sense on invalid designators"); return Entries.size() == 1 && FirstEntryIsAnUnsizedArray; } /// Determine what the most derived array's size is. Results in an assertion /// failure if the most derived array lacks a size. uint64_t getMostDerivedArraySize() const { assert(!isMostDerivedAnUnsizedArray() && "Unsized array has no size"); return MostDerivedArraySize; } /// Determine whether this is a one-past-the-end pointer. bool isOnePastTheEnd() const { assert(!Invalid); if (IsOnePastTheEnd) return true; if (!isMostDerivedAnUnsizedArray() && MostDerivedIsArrayElement && Entries[MostDerivedPathLength - 1].ArrayIndex == MostDerivedArraySize) return true; return false; } - /// Get the range of valid index adjustments in the form - /// {maximum value that can be subtracted from this pointer, - /// maximum value that can be added to this pointer} - std::pair validIndexAdjustments() { - if (Invalid || isMostDerivedAnUnsizedArray()) - return {0, 0}; - - // [expr.add]p4: For the purposes of these operators, a pointer to a - // nonarray object behaves the same as a pointer to the first element of - // an array of length one with the type of the object as its element type. - bool IsArray = MostDerivedPathLength == Entries.size() && - MostDerivedIsArrayElement; - uint64_t ArrayIndex = - IsArray ? Entries.back().ArrayIndex : (uint64_t)IsOnePastTheEnd; - uint64_t ArraySize = - IsArray ? getMostDerivedArraySize() : (uint64_t)1; - return {ArrayIndex, ArraySize - ArrayIndex}; - } - /// Check that this refers to a valid subobject. bool isValidSubobject() const { if (Invalid) return false; return !isOnePastTheEnd(); } /// Check that this refers to a valid subobject, and if not, produce a /// relevant diagnostic and set the designator as invalid. bool checkSubobject(EvalInfo &Info, const Expr *E, CheckSubobjectKind CSK); - /// Get the type of the designated object. - QualType getType(ASTContext &Ctx) const { - return MostDerivedPathLength == Entries.size() - ? MostDerivedType - : Ctx.getRecordType(getAsBaseClass(Entries.back())); - } - /// Update this designator to refer to the first element within this array. void addArrayUnchecked(const ConstantArrayType *CAT) { PathEntry Entry; Entry.ArrayIndex = 0; Entries.push_back(Entry); // This is a most-derived object. MostDerivedType = CAT->getElementType(); MostDerivedIsArrayElement = true; MostDerivedArraySize = CAT->getSize().getZExtValue(); MostDerivedPathLength = Entries.size(); } /// Update this designator to refer to the first element within the array of /// elements of type T. This is an array of unknown size. void addUnsizedArrayUnchecked(QualType ElemTy) { PathEntry Entry; Entry.ArrayIndex = 0; Entries.push_back(Entry); MostDerivedType = ElemTy; MostDerivedIsArrayElement = true; // The value in MostDerivedArraySize is undefined in this case. So, set it // to an arbitrary value that's likely to loudly break things if it's // used. MostDerivedArraySize = AssumedSizeForUnsizedArray; MostDerivedPathLength = Entries.size(); } /// Update this designator to refer to the given base or member of this /// object. void addDeclUnchecked(const Decl *D, bool Virtual = false) { PathEntry Entry; APValue::BaseOrMemberType Value(D, Virtual); Entry.BaseOrMember = Value.getOpaqueValue(); Entries.push_back(Entry); // If this isn't a base class, it's a new most-derived object. if (const FieldDecl *FD = dyn_cast(D)) { MostDerivedType = FD->getType(); MostDerivedIsArrayElement = false; MostDerivedArraySize = 0; MostDerivedPathLength = Entries.size(); } } /// Update this designator to refer to the given complex component. void addComplexUnchecked(QualType EltTy, bool Imag) { PathEntry Entry; Entry.ArrayIndex = Imag; Entries.push_back(Entry); // This is technically a most-derived object, though in practice this // is unlikely to matter. MostDerivedType = EltTy; MostDerivedIsArrayElement = true; MostDerivedArraySize = 2; MostDerivedPathLength = Entries.size(); } void diagnoseUnsizedArrayPointerArithmetic(EvalInfo &Info, const Expr *E); void diagnosePointerArithmetic(EvalInfo &Info, const Expr *E, const APSInt &N); /// Add N to the address of this subobject. void adjustIndex(EvalInfo &Info, const Expr *E, APSInt N) { if (Invalid || !N) return; uint64_t TruncatedN = N.extOrTrunc(64).getZExtValue(); if (isMostDerivedAnUnsizedArray()) { diagnoseUnsizedArrayPointerArithmetic(Info, E); // Can't verify -- trust that the user is doing the right thing (or if // not, trust that the caller will catch the bad behavior). // FIXME: Should we reject if this overflows, at least? Entries.back().ArrayIndex += TruncatedN; return; } // [expr.add]p4: For the purposes of these operators, a pointer to a // nonarray object behaves the same as a pointer to the first element of // an array of length one with the type of the object as its element type. bool IsArray = MostDerivedPathLength == Entries.size() && MostDerivedIsArrayElement; uint64_t ArrayIndex = IsArray ? Entries.back().ArrayIndex : (uint64_t)IsOnePastTheEnd; uint64_t ArraySize = IsArray ? getMostDerivedArraySize() : (uint64_t)1; if (N < -(int64_t)ArrayIndex || N > ArraySize - ArrayIndex) { // Calculate the actual index in a wide enough type, so we can include // it in the note. N = N.extend(std::max(N.getBitWidth() + 1, 65)); (llvm::APInt&)N += ArrayIndex; assert(N.ugt(ArraySize) && "bounds check failed for in-bounds index"); diagnosePointerArithmetic(Info, E, N); setInvalid(); return; } ArrayIndex += TruncatedN; assert(ArrayIndex <= ArraySize && "bounds check succeeded for out-of-bounds index"); if (IsArray) Entries.back().ArrayIndex = ArrayIndex; else IsOnePastTheEnd = (ArrayIndex != 0); } }; /// A stack frame in the constexpr call stack. struct CallStackFrame { EvalInfo &Info; /// Parent - The caller of this stack frame. CallStackFrame *Caller; /// Callee - The function which was called. const FunctionDecl *Callee; /// This - The binding for the this pointer in this call, if any. const LValue *This; /// Arguments - Parameter bindings for this function call, indexed by /// parameters' function scope indices. APValue *Arguments; // Note that we intentionally use std::map here so that references to // values are stable. typedef std::pair MapKeyTy; typedef std::map MapTy; /// Temporaries - Temporary lvalues materialized within this stack frame. MapTy Temporaries; /// CallLoc - The location of the call expression for this call. SourceLocation CallLoc; /// Index - The call index of this call. unsigned Index; /// The stack of integers for tracking version numbers for temporaries. SmallVector TempVersionStack = {1}; unsigned CurTempVersion = TempVersionStack.back(); unsigned getTempVersion() const { return TempVersionStack.back(); } void pushTempVersion() { TempVersionStack.push_back(++CurTempVersion); } void popTempVersion() { TempVersionStack.pop_back(); } // FIXME: Adding this to every 'CallStackFrame' may have a nontrivial impact // on the overall stack usage of deeply-recursing constexpr evaluataions. // (We should cache this map rather than recomputing it repeatedly.) // But let's try this and see how it goes; we can look into caching the map // as a later change. /// LambdaCaptureFields - Mapping from captured variables/this to /// corresponding data members in the closure class. llvm::DenseMap LambdaCaptureFields; FieldDecl *LambdaThisCaptureField; CallStackFrame(EvalInfo &Info, SourceLocation CallLoc, const FunctionDecl *Callee, const LValue *This, APValue *Arguments); ~CallStackFrame(); // Return the temporary for Key whose version number is Version. APValue *getTemporary(const void *Key, unsigned Version) { MapKeyTy KV(Key, Version); auto LB = Temporaries.lower_bound(KV); if (LB != Temporaries.end() && LB->first == KV) return &LB->second; // Pair (Key,Version) wasn't found in the map. Check that no elements // in the map have 'Key' as their key. assert((LB == Temporaries.end() || LB->first.first != Key) && (LB == Temporaries.begin() || std::prev(LB)->first.first != Key) && "Element with key 'Key' found in map"); return nullptr; } // Return the current temporary for Key in the map. APValue *getCurrentTemporary(const void *Key) { auto UB = Temporaries.upper_bound(MapKeyTy(Key, UINT_MAX)); if (UB != Temporaries.begin() && std::prev(UB)->first.first == Key) return &std::prev(UB)->second; return nullptr; } // Return the version number of the current temporary for Key. unsigned getCurrentTemporaryVersion(const void *Key) const { auto UB = Temporaries.upper_bound(MapKeyTy(Key, UINT_MAX)); if (UB != Temporaries.begin() && std::prev(UB)->first.first == Key) return std::prev(UB)->first.second; return 0; } APValue &createTemporary(const void *Key, bool IsLifetimeExtended); }; /// Temporarily override 'this'. class ThisOverrideRAII { public: ThisOverrideRAII(CallStackFrame &Frame, const LValue *NewThis, bool Enable) : Frame(Frame), OldThis(Frame.This) { if (Enable) Frame.This = NewThis; } ~ThisOverrideRAII() { Frame.This = OldThis; } private: CallStackFrame &Frame; const LValue *OldThis; }; /// A partial diagnostic which we might know in advance that we are not going /// to emit. class OptionalDiagnostic { PartialDiagnostic *Diag; public: explicit OptionalDiagnostic(PartialDiagnostic *Diag = nullptr) : Diag(Diag) {} template OptionalDiagnostic &operator<<(const T &v) { if (Diag) *Diag << v; return *this; } OptionalDiagnostic &operator<<(const APSInt &I) { if (Diag) { SmallVector Buffer; I.toString(Buffer); *Diag << StringRef(Buffer.data(), Buffer.size()); } return *this; } OptionalDiagnostic &operator<<(const APFloat &F) { if (Diag) { // FIXME: Force the precision of the source value down so we don't // print digits which are usually useless (we don't really care here if // we truncate a digit by accident in edge cases). Ideally, // APFloat::toString would automatically print the shortest // representation which rounds to the correct value, but it's a bit // tricky to implement. unsigned precision = llvm::APFloat::semanticsPrecision(F.getSemantics()); precision = (precision * 59 + 195) / 196; SmallVector Buffer; F.toString(Buffer, precision); *Diag << StringRef(Buffer.data(), Buffer.size()); } return *this; } }; /// A cleanup, and a flag indicating whether it is lifetime-extended. class Cleanup { llvm::PointerIntPair Value; public: Cleanup(APValue *Val, bool IsLifetimeExtended) : Value(Val, IsLifetimeExtended) {} bool isLifetimeExtended() const { return Value.getInt(); } void endLifetime() { *Value.getPointer() = APValue(); } }; /// EvalInfo - This is a private struct used by the evaluator to capture /// information about a subexpression as it is folded. It retains information /// about the AST context, but also maintains information about the folded /// expression. /// /// If an expression could be evaluated, it is still possible it is not a C /// "integer constant expression" or constant expression. If not, this struct /// captures information about how and why not. /// /// One bit of information passed *into* the request for constant folding /// indicates whether the subexpression is "evaluated" or not according to C /// rules. For example, the RHS of (0 && foo()) is not evaluated. We can /// evaluate the expression regardless of what the RHS is, but C only allows /// certain things in certain situations. struct EvalInfo { ASTContext &Ctx; /// EvalStatus - Contains information about the evaluation. Expr::EvalStatus &EvalStatus; /// CurrentCall - The top of the constexpr call stack. CallStackFrame *CurrentCall; /// CallStackDepth - The number of calls in the call stack right now. unsigned CallStackDepth; /// NextCallIndex - The next call index to assign. unsigned NextCallIndex; /// StepsLeft - The remaining number of evaluation steps we're permitted /// to perform. This is essentially a limit for the number of statements /// we will evaluate. unsigned StepsLeft; /// BottomFrame - The frame in which evaluation started. This must be /// initialized after CurrentCall and CallStackDepth. CallStackFrame BottomFrame; /// A stack of values whose lifetimes end at the end of some surrounding /// evaluation frame. llvm::SmallVector CleanupStack; /// EvaluatingDecl - This is the declaration whose initializer is being /// evaluated, if any. APValue::LValueBase EvaluatingDecl; /// EvaluatingDeclValue - This is the value being constructed for the /// declaration whose initializer is being evaluated, if any. APValue *EvaluatingDeclValue; /// EvaluatingObject - Pair of the AST node that an lvalue represents and /// the call index that that lvalue was allocated in. typedef std::pair> EvaluatingObject; /// EvaluatingConstructors - Set of objects that are currently being /// constructed. llvm::DenseSet EvaluatingConstructors; struct EvaluatingConstructorRAII { EvalInfo &EI; EvaluatingObject Object; bool DidInsert; EvaluatingConstructorRAII(EvalInfo &EI, EvaluatingObject Object) : EI(EI), Object(Object) { DidInsert = EI.EvaluatingConstructors.insert(Object).second; } ~EvaluatingConstructorRAII() { if (DidInsert) EI.EvaluatingConstructors.erase(Object); } }; bool isEvaluatingConstructor(APValue::LValueBase Decl, unsigned CallIndex, unsigned Version) { return EvaluatingConstructors.count( EvaluatingObject(Decl, {CallIndex, Version})); } /// The current array initialization index, if we're performing array /// initialization. uint64_t ArrayInitIndex = -1; /// HasActiveDiagnostic - Was the previous diagnostic stored? If so, further /// notes attached to it will also be stored, otherwise they will not be. bool HasActiveDiagnostic; /// Have we emitted a diagnostic explaining why we couldn't constant /// fold (not just why it's not strictly a constant expression)? bool HasFoldFailureDiagnostic; /// Whether or not we're currently speculatively evaluating. bool IsSpeculativelyEvaluating; enum EvaluationMode { /// Evaluate as a constant expression. Stop if we find that the expression /// is not a constant expression. EM_ConstantExpression, /// Evaluate as a potential constant expression. Keep going if we hit a /// construct that we can't evaluate yet (because we don't yet know the /// value of something) but stop if we hit something that could never be /// a constant expression. EM_PotentialConstantExpression, /// Fold the expression to a constant. Stop if we hit a side-effect that /// we can't model. EM_ConstantFold, /// Evaluate the expression looking for integer overflow and similar /// issues. Don't worry about side-effects, and try to visit all /// subexpressions. EM_EvaluateForOverflow, /// Evaluate in any way we know how. Don't worry about side-effects that /// can't be modeled. EM_IgnoreSideEffects, /// Evaluate as a constant expression. Stop if we find that the expression /// is not a constant expression. Some expressions can be retried in the /// optimizer if we don't constant fold them here, but in an unevaluated /// context we try to fold them immediately since the optimizer never /// gets a chance to look at it. EM_ConstantExpressionUnevaluated, /// Evaluate as a potential constant expression. Keep going if we hit a /// construct that we can't evaluate yet (because we don't yet know the /// value of something) but stop if we hit something that could never be /// a constant expression. Some expressions can be retried in the /// optimizer if we don't constant fold them here, but in an unevaluated /// context we try to fold them immediately since the optimizer never /// gets a chance to look at it. EM_PotentialConstantExpressionUnevaluated, /// Evaluate as a constant expression. In certain scenarios, if: /// - we find a MemberExpr with a base that can't be evaluated, or /// - we find a variable initialized with a call to a function that has /// the alloc_size attribute on it /// then we may consider evaluation to have succeeded. /// /// In either case, the LValue returned shall have an invalid base; in the /// former, the base will be the invalid MemberExpr, in the latter, the /// base will be either the alloc_size CallExpr or a CastExpr wrapping /// said CallExpr. EM_OffsetFold, } EvalMode; /// Are we checking whether the expression is a potential constant /// expression? bool checkingPotentialConstantExpression() const { return EvalMode == EM_PotentialConstantExpression || EvalMode == EM_PotentialConstantExpressionUnevaluated; } /// Are we checking an expression for overflow? // FIXME: We should check for any kind of undefined or suspicious behavior // in such constructs, not just overflow. bool checkingForOverflow() { return EvalMode == EM_EvaluateForOverflow; } EvalInfo(const ASTContext &C, Expr::EvalStatus &S, EvaluationMode Mode) : Ctx(const_cast(C)), EvalStatus(S), CurrentCall(nullptr), CallStackDepth(0), NextCallIndex(1), StepsLeft(getLangOpts().ConstexprStepLimit), BottomFrame(*this, SourceLocation(), nullptr, nullptr, nullptr), EvaluatingDecl((const ValueDecl *)nullptr), EvaluatingDeclValue(nullptr), HasActiveDiagnostic(false), HasFoldFailureDiagnostic(false), IsSpeculativelyEvaluating(false), EvalMode(Mode) {} void setEvaluatingDecl(APValue::LValueBase Base, APValue &Value) { EvaluatingDecl = Base; EvaluatingDeclValue = &Value; EvaluatingConstructors.insert({Base, {0, 0}}); } const LangOptions &getLangOpts() const { return Ctx.getLangOpts(); } bool CheckCallLimit(SourceLocation Loc) { // Don't perform any constexpr calls (other than the call we're checking) // when checking a potential constant expression. if (checkingPotentialConstantExpression() && CallStackDepth > 1) return false; if (NextCallIndex == 0) { // NextCallIndex has wrapped around. FFDiag(Loc, diag::note_constexpr_call_limit_exceeded); return false; } if (CallStackDepth <= getLangOpts().ConstexprCallDepth) return true; FFDiag(Loc, diag::note_constexpr_depth_limit_exceeded) << getLangOpts().ConstexprCallDepth; return false; } CallStackFrame *getCallFrame(unsigned CallIndex) { assert(CallIndex && "no call index in getCallFrame"); // We will eventually hit BottomFrame, which has Index 1, so Frame can't // be null in this loop. CallStackFrame *Frame = CurrentCall; while (Frame->Index > CallIndex) Frame = Frame->Caller; return (Frame->Index == CallIndex) ? Frame : nullptr; } bool nextStep(const Stmt *S) { if (!StepsLeft) { FFDiag(S->getLocStart(), diag::note_constexpr_step_limit_exceeded); return false; } --StepsLeft; return true; } private: /// Add a diagnostic to the diagnostics list. PartialDiagnostic &addDiag(SourceLocation Loc, diag::kind DiagId) { PartialDiagnostic PD(DiagId, Ctx.getDiagAllocator()); EvalStatus.Diag->push_back(std::make_pair(Loc, PD)); return EvalStatus.Diag->back().second; } /// Add notes containing a call stack to the current point of evaluation. void addCallStack(unsigned Limit); private: OptionalDiagnostic Diag(SourceLocation Loc, diag::kind DiagId, unsigned ExtraNotes, bool IsCCEDiag) { if (EvalStatus.Diag) { // If we have a prior diagnostic, it will be noting that the expression // isn't a constant expression. This diagnostic is more important, // unless we require this evaluation to produce a constant expression. // // FIXME: We might want to show both diagnostics to the user in // EM_ConstantFold mode. if (!EvalStatus.Diag->empty()) { switch (EvalMode) { case EM_ConstantFold: case EM_IgnoreSideEffects: case EM_EvaluateForOverflow: if (!HasFoldFailureDiagnostic) break; // We've already failed to fold something. Keep that diagnostic. LLVM_FALLTHROUGH; case EM_ConstantExpression: case EM_PotentialConstantExpression: case EM_ConstantExpressionUnevaluated: case EM_PotentialConstantExpressionUnevaluated: case EM_OffsetFold: HasActiveDiagnostic = false; return OptionalDiagnostic(); } } unsigned CallStackNotes = CallStackDepth - 1; unsigned Limit = Ctx.getDiagnostics().getConstexprBacktraceLimit(); if (Limit) CallStackNotes = std::min(CallStackNotes, Limit + 1); if (checkingPotentialConstantExpression()) CallStackNotes = 0; HasActiveDiagnostic = true; HasFoldFailureDiagnostic = !IsCCEDiag; EvalStatus.Diag->clear(); EvalStatus.Diag->reserve(1 + ExtraNotes + CallStackNotes); addDiag(Loc, DiagId); if (!checkingPotentialConstantExpression()) addCallStack(Limit); return OptionalDiagnostic(&(*EvalStatus.Diag)[0].second); } HasActiveDiagnostic = false; return OptionalDiagnostic(); } public: // Diagnose that the evaluation could not be folded (FF => FoldFailure) OptionalDiagnostic FFDiag(SourceLocation Loc, diag::kind DiagId = diag::note_invalid_subexpr_in_const_expr, unsigned ExtraNotes = 0) { return Diag(Loc, DiagId, ExtraNotes, false); } OptionalDiagnostic FFDiag(const Expr *E, diag::kind DiagId = diag::note_invalid_subexpr_in_const_expr, unsigned ExtraNotes = 0) { if (EvalStatus.Diag) return Diag(E->getExprLoc(), DiagId, ExtraNotes, /*IsCCEDiag*/false); HasActiveDiagnostic = false; return OptionalDiagnostic(); } /// Diagnose that the evaluation does not produce a C++11 core constant /// expression. /// /// FIXME: Stop evaluating if we're in EM_ConstantExpression or /// EM_PotentialConstantExpression mode and we produce one of these. OptionalDiagnostic CCEDiag(SourceLocation Loc, diag::kind DiagId = diag::note_invalid_subexpr_in_const_expr, unsigned ExtraNotes = 0) { // Don't override a previous diagnostic. Don't bother collecting // diagnostics if we're evaluating for overflow. if (!EvalStatus.Diag || !EvalStatus.Diag->empty()) { HasActiveDiagnostic = false; return OptionalDiagnostic(); } return Diag(Loc, DiagId, ExtraNotes, true); } OptionalDiagnostic CCEDiag(const Expr *E, diag::kind DiagId = diag::note_invalid_subexpr_in_const_expr, unsigned ExtraNotes = 0) { return CCEDiag(E->getExprLoc(), DiagId, ExtraNotes); } /// Add a note to a prior diagnostic. OptionalDiagnostic Note(SourceLocation Loc, diag::kind DiagId) { if (!HasActiveDiagnostic) return OptionalDiagnostic(); return OptionalDiagnostic(&addDiag(Loc, DiagId)); } /// Add a stack of notes to a prior diagnostic. void addNotes(ArrayRef Diags) { if (HasActiveDiagnostic) { EvalStatus.Diag->insert(EvalStatus.Diag->end(), Diags.begin(), Diags.end()); } } /// Should we continue evaluation after encountering a side-effect that we /// couldn't model? bool keepEvaluatingAfterSideEffect() { switch (EvalMode) { case EM_PotentialConstantExpression: case EM_PotentialConstantExpressionUnevaluated: case EM_EvaluateForOverflow: case EM_IgnoreSideEffects: return true; case EM_ConstantExpression: case EM_ConstantExpressionUnevaluated: case EM_ConstantFold: case EM_OffsetFold: return false; } llvm_unreachable("Missed EvalMode case"); } /// Note that we have had a side-effect, and determine whether we should /// keep evaluating. bool noteSideEffect() { EvalStatus.HasSideEffects = true; return keepEvaluatingAfterSideEffect(); } /// Should we continue evaluation after encountering undefined behavior? bool keepEvaluatingAfterUndefinedBehavior() { switch (EvalMode) { case EM_EvaluateForOverflow: case EM_IgnoreSideEffects: case EM_ConstantFold: case EM_OffsetFold: return true; case EM_PotentialConstantExpression: case EM_PotentialConstantExpressionUnevaluated: case EM_ConstantExpression: case EM_ConstantExpressionUnevaluated: return false; } llvm_unreachable("Missed EvalMode case"); } /// Note that we hit something that was technically undefined behavior, but /// that we can evaluate past it (such as signed overflow or floating-point /// division by zero.) bool noteUndefinedBehavior() { EvalStatus.HasUndefinedBehavior = true; return keepEvaluatingAfterUndefinedBehavior(); } /// Should we continue evaluation as much as possible after encountering a /// construct which can't be reduced to a value? bool keepEvaluatingAfterFailure() { if (!StepsLeft) return false; switch (EvalMode) { case EM_PotentialConstantExpression: case EM_PotentialConstantExpressionUnevaluated: case EM_EvaluateForOverflow: return true; case EM_ConstantExpression: case EM_ConstantExpressionUnevaluated: case EM_ConstantFold: case EM_IgnoreSideEffects: case EM_OffsetFold: return false; } llvm_unreachable("Missed EvalMode case"); } /// Notes that we failed to evaluate an expression that other expressions /// directly depend on, and determine if we should keep evaluating. This /// should only be called if we actually intend to keep evaluating. /// /// Call noteSideEffect() instead if we may be able to ignore the value that /// we failed to evaluate, e.g. if we failed to evaluate Foo() in: /// /// (Foo(), 1) // use noteSideEffect /// (Foo() || true) // use noteSideEffect /// Foo() + 1 // use noteFailure LLVM_NODISCARD bool noteFailure() { // Failure when evaluating some expression often means there is some // subexpression whose evaluation was skipped. Therefore, (because we // don't track whether we skipped an expression when unwinding after an // evaluation failure) every evaluation failure that bubbles up from a // subexpression implies that a side-effect has potentially happened. We // skip setting the HasSideEffects flag to true until we decide to // continue evaluating after that point, which happens here. bool KeepGoing = keepEvaluatingAfterFailure(); EvalStatus.HasSideEffects |= KeepGoing; return KeepGoing; } class ArrayInitLoopIndex { EvalInfo &Info; uint64_t OuterIndex; public: ArrayInitLoopIndex(EvalInfo &Info) : Info(Info), OuterIndex(Info.ArrayInitIndex) { Info.ArrayInitIndex = 0; } ~ArrayInitLoopIndex() { Info.ArrayInitIndex = OuterIndex; } operator uint64_t&() { return Info.ArrayInitIndex; } }; }; /// Object used to treat all foldable expressions as constant expressions. struct FoldConstant { EvalInfo &Info; bool Enabled; bool HadNoPriorDiags; EvalInfo::EvaluationMode OldMode; explicit FoldConstant(EvalInfo &Info, bool Enabled) : Info(Info), Enabled(Enabled), HadNoPriorDiags(Info.EvalStatus.Diag && Info.EvalStatus.Diag->empty() && !Info.EvalStatus.HasSideEffects), OldMode(Info.EvalMode) { if (Enabled && (Info.EvalMode == EvalInfo::EM_ConstantExpression || Info.EvalMode == EvalInfo::EM_ConstantExpressionUnevaluated)) Info.EvalMode = EvalInfo::EM_ConstantFold; } void keepDiagnostics() { Enabled = false; } ~FoldConstant() { if (Enabled && HadNoPriorDiags && !Info.EvalStatus.Diag->empty() && !Info.EvalStatus.HasSideEffects) Info.EvalStatus.Diag->clear(); Info.EvalMode = OldMode; } }; /// RAII object used to treat the current evaluation as the correct pointer /// offset fold for the current EvalMode struct FoldOffsetRAII { EvalInfo &Info; EvalInfo::EvaluationMode OldMode; explicit FoldOffsetRAII(EvalInfo &Info) : Info(Info), OldMode(Info.EvalMode) { if (!Info.checkingPotentialConstantExpression()) Info.EvalMode = EvalInfo::EM_OffsetFold; } ~FoldOffsetRAII() { Info.EvalMode = OldMode; } }; /// RAII object used to optionally suppress diagnostics and side-effects from /// a speculative evaluation. class SpeculativeEvaluationRAII { EvalInfo *Info = nullptr; Expr::EvalStatus OldStatus; bool OldIsSpeculativelyEvaluating; void moveFromAndCancel(SpeculativeEvaluationRAII &&Other) { Info = Other.Info; OldStatus = Other.OldStatus; OldIsSpeculativelyEvaluating = Other.OldIsSpeculativelyEvaluating; Other.Info = nullptr; } void maybeRestoreState() { if (!Info) return; Info->EvalStatus = OldStatus; Info->IsSpeculativelyEvaluating = OldIsSpeculativelyEvaluating; } public: SpeculativeEvaluationRAII() = default; SpeculativeEvaluationRAII( EvalInfo &Info, SmallVectorImpl *NewDiag = nullptr) : Info(&Info), OldStatus(Info.EvalStatus), OldIsSpeculativelyEvaluating(Info.IsSpeculativelyEvaluating) { Info.EvalStatus.Diag = NewDiag; Info.IsSpeculativelyEvaluating = true; } SpeculativeEvaluationRAII(const SpeculativeEvaluationRAII &Other) = delete; SpeculativeEvaluationRAII(SpeculativeEvaluationRAII &&Other) { moveFromAndCancel(std::move(Other)); } SpeculativeEvaluationRAII &operator=(SpeculativeEvaluationRAII &&Other) { maybeRestoreState(); moveFromAndCancel(std::move(Other)); return *this; } ~SpeculativeEvaluationRAII() { maybeRestoreState(); } }; /// RAII object wrapping a full-expression or block scope, and handling /// the ending of the lifetime of temporaries created within it. template class ScopeRAII { EvalInfo &Info; unsigned OldStackSize; public: ScopeRAII(EvalInfo &Info) : Info(Info), OldStackSize(Info.CleanupStack.size()) { // Push a new temporary version. This is needed to distinguish between // temporaries created in different iterations of a loop. Info.CurrentCall->pushTempVersion(); } ~ScopeRAII() { // Body moved to a static method to encourage the compiler to inline away // instances of this class. cleanup(Info, OldStackSize); Info.CurrentCall->popTempVersion(); } private: static void cleanup(EvalInfo &Info, unsigned OldStackSize) { unsigned NewEnd = OldStackSize; for (unsigned I = OldStackSize, N = Info.CleanupStack.size(); I != N; ++I) { if (IsFullExpression && Info.CleanupStack[I].isLifetimeExtended()) { // Full-expression cleanup of a lifetime-extended temporary: nothing // to do, just move this cleanup to the right place in the stack. std::swap(Info.CleanupStack[I], Info.CleanupStack[NewEnd]); ++NewEnd; } else { // End the lifetime of the object. Info.CleanupStack[I].endLifetime(); } } Info.CleanupStack.erase(Info.CleanupStack.begin() + NewEnd, Info.CleanupStack.end()); } }; typedef ScopeRAII BlockScopeRAII; typedef ScopeRAII FullExpressionRAII; } bool SubobjectDesignator::checkSubobject(EvalInfo &Info, const Expr *E, CheckSubobjectKind CSK) { if (Invalid) return false; if (isOnePastTheEnd()) { Info.CCEDiag(E, diag::note_constexpr_past_end_subobject) << CSK; setInvalid(); return false; } // Note, we do not diagnose if isMostDerivedAnUnsizedArray(), because there // must actually be at least one array element; even a VLA cannot have a // bound of zero. And if our index is nonzero, we already had a CCEDiag. return true; } void SubobjectDesignator::diagnoseUnsizedArrayPointerArithmetic(EvalInfo &Info, const Expr *E) { Info.CCEDiag(E, diag::note_constexpr_unsized_array_indexed); // Do not set the designator as invalid: we can represent this situation, // and correct handling of __builtin_object_size requires us to do so. } void SubobjectDesignator::diagnosePointerArithmetic(EvalInfo &Info, const Expr *E, const APSInt &N) { // If we're complaining, we must be able to statically determine the size of // the most derived array. if (MostDerivedPathLength == Entries.size() && MostDerivedIsArrayElement) Info.CCEDiag(E, diag::note_constexpr_array_index) << N << /*array*/ 0 << static_cast(getMostDerivedArraySize()); else Info.CCEDiag(E, diag::note_constexpr_array_index) << N << /*non-array*/ 1; setInvalid(); } CallStackFrame::CallStackFrame(EvalInfo &Info, SourceLocation CallLoc, const FunctionDecl *Callee, const LValue *This, APValue *Arguments) : Info(Info), Caller(Info.CurrentCall), Callee(Callee), This(This), Arguments(Arguments), CallLoc(CallLoc), Index(Info.NextCallIndex++) { Info.CurrentCall = this; ++Info.CallStackDepth; } CallStackFrame::~CallStackFrame() { assert(Info.CurrentCall == this && "calls retired out of order"); --Info.CallStackDepth; Info.CurrentCall = Caller; } APValue &CallStackFrame::createTemporary(const void *Key, bool IsLifetimeExtended) { unsigned Version = Info.CurrentCall->getTempVersion(); APValue &Result = Temporaries[MapKeyTy(Key, Version)]; assert(Result.isUninit() && "temporary created multiple times"); Info.CleanupStack.push_back(Cleanup(&Result, IsLifetimeExtended)); return Result; } static void describeCall(CallStackFrame *Frame, raw_ostream &Out); void EvalInfo::addCallStack(unsigned Limit) { // Determine which calls to skip, if any. unsigned ActiveCalls = CallStackDepth - 1; unsigned SkipStart = ActiveCalls, SkipEnd = SkipStart; if (Limit && Limit < ActiveCalls) { SkipStart = Limit / 2 + Limit % 2; SkipEnd = ActiveCalls - Limit / 2; } // Walk the call stack and add the diagnostics. unsigned CallIdx = 0; for (CallStackFrame *Frame = CurrentCall; Frame != &BottomFrame; Frame = Frame->Caller, ++CallIdx) { // Skip this call? if (CallIdx >= SkipStart && CallIdx < SkipEnd) { if (CallIdx == SkipStart) { // Note that we're skipping calls. addDiag(Frame->CallLoc, diag::note_constexpr_calls_suppressed) << unsigned(ActiveCalls - Limit); } continue; } // Use a different note for an inheriting constructor, because from the // user's perspective it's not really a function at all. if (auto *CD = dyn_cast_or_null(Frame->Callee)) { if (CD->isInheritingConstructor()) { addDiag(Frame->CallLoc, diag::note_constexpr_inherited_ctor_call_here) << CD->getParent(); continue; } } SmallVector Buffer; llvm::raw_svector_ostream Out(Buffer); describeCall(Frame, Out); addDiag(Frame->CallLoc, diag::note_constexpr_call_here) << Out.str(); } } namespace { struct ComplexValue { private: bool IsInt; public: APSInt IntReal, IntImag; APFloat FloatReal, FloatImag; ComplexValue() : FloatReal(APFloat::Bogus()), FloatImag(APFloat::Bogus()) {} void makeComplexFloat() { IsInt = false; } bool isComplexFloat() const { return !IsInt; } APFloat &getComplexFloatReal() { return FloatReal; } APFloat &getComplexFloatImag() { return FloatImag; } void makeComplexInt() { IsInt = true; } bool isComplexInt() const { return IsInt; } APSInt &getComplexIntReal() { return IntReal; } APSInt &getComplexIntImag() { return IntImag; } void moveInto(APValue &v) const { if (isComplexFloat()) v = APValue(FloatReal, FloatImag); else v = APValue(IntReal, IntImag); } void setFrom(const APValue &v) { assert(v.isComplexFloat() || v.isComplexInt()); if (v.isComplexFloat()) { makeComplexFloat(); FloatReal = v.getComplexFloatReal(); FloatImag = v.getComplexFloatImag(); } else { makeComplexInt(); IntReal = v.getComplexIntReal(); IntImag = v.getComplexIntImag(); } } }; struct LValue { APValue::LValueBase Base; CharUnits Offset; SubobjectDesignator Designator; bool IsNullPtr : 1; bool InvalidBase : 1; const APValue::LValueBase getLValueBase() const { return Base; } CharUnits &getLValueOffset() { return Offset; } const CharUnits &getLValueOffset() const { return Offset; } SubobjectDesignator &getLValueDesignator() { return Designator; } const SubobjectDesignator &getLValueDesignator() const { return Designator;} bool isNullPointer() const { return IsNullPtr;} unsigned getLValueCallIndex() const { return Base.getCallIndex(); } unsigned getLValueVersion() const { return Base.getVersion(); } void moveInto(APValue &V) const { if (Designator.Invalid) V = APValue(Base, Offset, APValue::NoLValuePath(), IsNullPtr); else { assert(!InvalidBase && "APValues can't handle invalid LValue bases"); V = APValue(Base, Offset, Designator.Entries, Designator.IsOnePastTheEnd, IsNullPtr); } } void setFrom(ASTContext &Ctx, const APValue &V) { assert(V.isLValue() && "Setting LValue from a non-LValue?"); Base = V.getLValueBase(); Offset = V.getLValueOffset(); InvalidBase = false; Designator = SubobjectDesignator(Ctx, V); IsNullPtr = V.isNullPointer(); } void set(APValue::LValueBase B, bool BInvalid = false) { #ifndef NDEBUG // We only allow a few types of invalid bases. Enforce that here. if (BInvalid) { const auto *E = B.get(); assert((isa(E) || tryUnwrapAllocSizeCall(E)) && "Unexpected type of invalid base"); } #endif Base = B; Offset = CharUnits::fromQuantity(0); InvalidBase = BInvalid; Designator = SubobjectDesignator(getType(B)); IsNullPtr = false; } void setNull(QualType PointerTy, uint64_t TargetVal) { Base = (Expr *)nullptr; Offset = CharUnits::fromQuantity(TargetVal); InvalidBase = false; Designator = SubobjectDesignator(PointerTy->getPointeeType()); IsNullPtr = true; } void setInvalid(APValue::LValueBase B, unsigned I = 0) { set(B, true); } // Check that this LValue is not based on a null pointer. If it is, produce // a diagnostic and mark the designator as invalid. bool checkNullPointer(EvalInfo &Info, const Expr *E, CheckSubobjectKind CSK) { if (Designator.Invalid) return false; if (IsNullPtr) { Info.CCEDiag(E, diag::note_constexpr_null_subobject) << CSK; Designator.setInvalid(); return false; } return true; } // Check this LValue refers to an object. If not, set the designator to be // invalid and emit a diagnostic. bool checkSubobject(EvalInfo &Info, const Expr *E, CheckSubobjectKind CSK) { return (CSK == CSK_ArrayToPointer || checkNullPointer(Info, E, CSK)) && Designator.checkSubobject(Info, E, CSK); } void addDecl(EvalInfo &Info, const Expr *E, const Decl *D, bool Virtual = false) { if (checkSubobject(Info, E, isa(D) ? CSK_Field : CSK_Base)) Designator.addDeclUnchecked(D, Virtual); } void addUnsizedArray(EvalInfo &Info, const Expr *E, QualType ElemTy) { if (!Designator.Entries.empty()) { Info.CCEDiag(E, diag::note_constexpr_unsupported_unsized_array); Designator.setInvalid(); return; } if (checkSubobject(Info, E, CSK_ArrayToPointer)) { assert(getType(Base)->isPointerType() || getType(Base)->isArrayType()); Designator.FirstEntryIsAnUnsizedArray = true; Designator.addUnsizedArrayUnchecked(ElemTy); } } void addArray(EvalInfo &Info, const Expr *E, const ConstantArrayType *CAT) { if (checkSubobject(Info, E, CSK_ArrayToPointer)) Designator.addArrayUnchecked(CAT); } void addComplex(EvalInfo &Info, const Expr *E, QualType EltTy, bool Imag) { if (checkSubobject(Info, E, Imag ? CSK_Imag : CSK_Real)) Designator.addComplexUnchecked(EltTy, Imag); } void clearIsNullPointer() { IsNullPtr = false; } void adjustOffsetAndIndex(EvalInfo &Info, const Expr *E, const APSInt &Index, CharUnits ElementSize) { // An index of 0 has no effect. (In C, adding 0 to a null pointer is UB, // but we're not required to diagnose it and it's valid in C++.) if (!Index) return; // Compute the new offset in the appropriate width, wrapping at 64 bits. // FIXME: When compiling for a 32-bit target, we should use 32-bit // offsets. uint64_t Offset64 = Offset.getQuantity(); uint64_t ElemSize64 = ElementSize.getQuantity(); uint64_t Index64 = Index.extOrTrunc(64).getZExtValue(); Offset = CharUnits::fromQuantity(Offset64 + ElemSize64 * Index64); if (checkNullPointer(Info, E, CSK_ArrayIndex)) Designator.adjustIndex(Info, E, Index); clearIsNullPointer(); } void adjustOffset(CharUnits N) { Offset += N; if (N.getQuantity()) clearIsNullPointer(); } }; struct MemberPtr { MemberPtr() {} explicit MemberPtr(const ValueDecl *Decl) : DeclAndIsDerivedMember(Decl, false), Path() {} /// The member or (direct or indirect) field referred to by this member /// pointer, or 0 if this is a null member pointer. const ValueDecl *getDecl() const { return DeclAndIsDerivedMember.getPointer(); } /// Is this actually a member of some type derived from the relevant class? bool isDerivedMember() const { return DeclAndIsDerivedMember.getInt(); } /// Get the class which the declaration actually lives in. const CXXRecordDecl *getContainingRecord() const { return cast( DeclAndIsDerivedMember.getPointer()->getDeclContext()); } void moveInto(APValue &V) const { V = APValue(getDecl(), isDerivedMember(), Path); } void setFrom(const APValue &V) { assert(V.isMemberPointer()); DeclAndIsDerivedMember.setPointer(V.getMemberPointerDecl()); DeclAndIsDerivedMember.setInt(V.isMemberPointerToDerivedMember()); Path.clear(); ArrayRef P = V.getMemberPointerPath(); Path.insert(Path.end(), P.begin(), P.end()); } /// DeclAndIsDerivedMember - The member declaration, and a flag indicating /// whether the member is a member of some class derived from the class type /// of the member pointer. llvm::PointerIntPair DeclAndIsDerivedMember; /// Path - The path of base/derived classes from the member declaration's /// class (exclusive) to the class type of the member pointer (inclusive). SmallVector Path; /// Perform a cast towards the class of the Decl (either up or down the /// hierarchy). bool castBack(const CXXRecordDecl *Class) { assert(!Path.empty()); const CXXRecordDecl *Expected; if (Path.size() >= 2) Expected = Path[Path.size() - 2]; else Expected = getContainingRecord(); if (Expected->getCanonicalDecl() != Class->getCanonicalDecl()) { // C++11 [expr.static.cast]p12: In a conversion from (D::*) to (B::*), // if B does not contain the original member and is not a base or // derived class of the class containing the original member, the result // of the cast is undefined. // C++11 [conv.mem]p2 does not cover this case for a cast from (B::*) to // (D::*). We consider that to be a language defect. return false; } Path.pop_back(); return true; } /// Perform a base-to-derived member pointer cast. bool castToDerived(const CXXRecordDecl *Derived) { if (!getDecl()) return true; if (!isDerivedMember()) { Path.push_back(Derived); return true; } if (!castBack(Derived)) return false; if (Path.empty()) DeclAndIsDerivedMember.setInt(false); return true; } /// Perform a derived-to-base member pointer cast. bool castToBase(const CXXRecordDecl *Base) { if (!getDecl()) return true; if (Path.empty()) DeclAndIsDerivedMember.setInt(true); if (isDerivedMember()) { Path.push_back(Base); return true; } return castBack(Base); } }; /// Compare two member pointers, which are assumed to be of the same type. static bool operator==(const MemberPtr &LHS, const MemberPtr &RHS) { if (!LHS.getDecl() || !RHS.getDecl()) return !LHS.getDecl() && !RHS.getDecl(); if (LHS.getDecl()->getCanonicalDecl() != RHS.getDecl()->getCanonicalDecl()) return false; return LHS.Path == RHS.Path; } } static bool Evaluate(APValue &Result, EvalInfo &Info, const Expr *E); static bool EvaluateInPlace(APValue &Result, EvalInfo &Info, const LValue &This, const Expr *E, bool AllowNonLiteralTypes = false); static bool EvaluateLValue(const Expr *E, LValue &Result, EvalInfo &Info, bool InvalidBaseOK = false); static bool EvaluatePointer(const Expr *E, LValue &Result, EvalInfo &Info, bool InvalidBaseOK = false); static bool EvaluateMemberPointer(const Expr *E, MemberPtr &Result, EvalInfo &Info); static bool EvaluateTemporary(const Expr *E, LValue &Result, EvalInfo &Info); static bool EvaluateInteger(const Expr *E, APSInt &Result, EvalInfo &Info); static bool EvaluateIntegerOrLValue(const Expr *E, APValue &Result, EvalInfo &Info); static bool EvaluateFloat(const Expr *E, APFloat &Result, EvalInfo &Info); static bool EvaluateComplex(const Expr *E, ComplexValue &Res, EvalInfo &Info); static bool EvaluateAtomic(const Expr *E, const LValue *This, APValue &Result, EvalInfo &Info); static bool EvaluateAsRValue(EvalInfo &Info, const Expr *E, APValue &Result); //===----------------------------------------------------------------------===// // Misc utilities //===----------------------------------------------------------------------===// /// A helper function to create a temporary and set an LValue. template static APValue &createTemporary(const KeyTy *Key, bool IsLifetimeExtended, LValue &LV, CallStackFrame &Frame) { LV.set({Key, Frame.Info.CurrentCall->Index, Frame.Info.CurrentCall->getTempVersion()}); return Frame.createTemporary(Key, IsLifetimeExtended); } /// Negate an APSInt in place, converting it to a signed form if necessary, and /// preserving its value (by extending by up to one bit as needed). static void negateAsSigned(APSInt &Int) { if (Int.isUnsigned() || Int.isMinSignedValue()) { Int = Int.extend(Int.getBitWidth() + 1); Int.setIsSigned(true); } Int = -Int; } /// Produce a string describing the given constexpr call. static void describeCall(CallStackFrame *Frame, raw_ostream &Out) { unsigned ArgIndex = 0; bool IsMemberCall = isa(Frame->Callee) && !isa(Frame->Callee) && cast(Frame->Callee)->isInstance(); if (!IsMemberCall) Out << *Frame->Callee << '('; if (Frame->This && IsMemberCall) { APValue Val; Frame->This->moveInto(Val); Val.printPretty(Out, Frame->Info.Ctx, Frame->This->Designator.MostDerivedType); // FIXME: Add parens around Val if needed. Out << "->" << *Frame->Callee << '('; IsMemberCall = false; } for (FunctionDecl::param_const_iterator I = Frame->Callee->param_begin(), E = Frame->Callee->param_end(); I != E; ++I, ++ArgIndex) { if (ArgIndex > (unsigned)IsMemberCall) Out << ", "; const ParmVarDecl *Param = *I; const APValue &Arg = Frame->Arguments[ArgIndex]; Arg.printPretty(Out, Frame->Info.Ctx, Param->getType()); if (ArgIndex == 0 && IsMemberCall) Out << "->" << *Frame->Callee << '('; } Out << ')'; } /// Evaluate an expression to see if it had side-effects, and discard its /// result. /// \return \c true if the caller should keep evaluating. static bool EvaluateIgnoredValue(EvalInfo &Info, const Expr *E) { APValue Scratch; if (!Evaluate(Scratch, Info, E)) // We don't need the value, but we might have skipped a side effect here. return Info.noteSideEffect(); return true; } /// Should this call expression be treated as a string literal? static bool IsStringLiteralCall(const CallExpr *E) { unsigned Builtin = E->getBuiltinCallee(); return (Builtin == Builtin::BI__builtin___CFStringMakeConstantString || Builtin == Builtin::BI__builtin___NSStringMakeConstantString); } static bool IsGlobalLValue(APValue::LValueBase B) { // C++11 [expr.const]p3 An address constant expression is a prvalue core // constant expression of pointer type that evaluates to... // ... a null pointer value, or a prvalue core constant expression of type // std::nullptr_t. if (!B) return true; if (const ValueDecl *D = B.dyn_cast()) { // ... the address of an object with static storage duration, if (const VarDecl *VD = dyn_cast(D)) return VD->hasGlobalStorage(); // ... the address of a function, return isa(D); } const Expr *E = B.get(); switch (E->getStmtClass()) { default: return false; case Expr::CompoundLiteralExprClass: { const CompoundLiteralExpr *CLE = cast(E); return CLE->isFileScope() && CLE->isLValue(); } case Expr::MaterializeTemporaryExprClass: // A materialized temporary might have been lifetime-extended to static // storage duration. return cast(E)->getStorageDuration() == SD_Static; // A string literal has static storage duration. case Expr::StringLiteralClass: case Expr::PredefinedExprClass: case Expr::ObjCStringLiteralClass: case Expr::ObjCEncodeExprClass: case Expr::CXXTypeidExprClass: case Expr::CXXUuidofExprClass: return true; case Expr::CallExprClass: return IsStringLiteralCall(cast(E)); // For GCC compatibility, &&label has static storage duration. case Expr::AddrLabelExprClass: return true; // A Block literal expression may be used as the initialization value for // Block variables at global or local static scope. case Expr::BlockExprClass: return !cast(E)->getBlockDecl()->hasCaptures(); case Expr::ImplicitValueInitExprClass: // FIXME: // We can never form an lvalue with an implicit value initialization as its // base through expression evaluation, so these only appear in one case: the // implicit variable declaration we invent when checking whether a constexpr // constructor can produce a constant expression. We must assume that such // an expression might be a global lvalue. return true; } } -static const ValueDecl *GetLValueBaseDecl(const LValue &LVal) { - return LVal.Base.dyn_cast(); -} - -static bool IsLiteralLValue(const LValue &Value) { - if (Value.getLValueCallIndex()) - return false; - const Expr *E = Value.Base.dyn_cast(); - return E && !isa(E); -} - -static bool IsWeakLValue(const LValue &Value) { - const ValueDecl *Decl = GetLValueBaseDecl(Value); - return Decl && Decl->isWeak(); -} - -static bool isZeroSized(const LValue &Value) { - const ValueDecl *Decl = GetLValueBaseDecl(Value); - if (Decl && isa(Decl)) { - QualType Ty = Decl->getType(); - if (Ty->isArrayType()) - return Ty->isIncompleteType() || - Decl->getASTContext().getTypeSize(Ty) == 0; - } - return false; -} - -static bool HasSameBase(const LValue &A, const LValue &B) { - if (!A.getLValueBase()) - return !B.getLValueBase(); - if (!B.getLValueBase()) - return false; - - if (A.getLValueBase().getOpaqueValue() != - B.getLValueBase().getOpaqueValue()) { - const Decl *ADecl = GetLValueBaseDecl(A); - if (!ADecl) - return false; - const Decl *BDecl = GetLValueBaseDecl(B); - if (!BDecl || ADecl->getCanonicalDecl() != BDecl->getCanonicalDecl()) - return false; - } - - return IsGlobalLValue(A.getLValueBase()) || - (A.getLValueCallIndex() == B.getLValueCallIndex() && - A.getLValueVersion() == B.getLValueVersion()); -} - static void NoteLValueLocation(EvalInfo &Info, APValue::LValueBase Base) { assert(Base && "no location for a null lvalue"); const ValueDecl *VD = Base.dyn_cast(); if (VD) Info.Note(VD->getLocation(), diag::note_declared_at); else Info.Note(Base.get()->getExprLoc(), diag::note_constexpr_temporary_here); } /// Check that this reference or pointer core constant expression is a valid /// value for an address or reference constant expression. Return true if we /// can fold this expression, whether or not it's a constant expression. static bool CheckLValueConstantExpression(EvalInfo &Info, SourceLocation Loc, QualType Type, const LValue &LVal, Expr::ConstExprUsage Usage) { bool IsReferenceType = Type->isReferenceType(); APValue::LValueBase Base = LVal.getLValueBase(); const SubobjectDesignator &Designator = LVal.getLValueDesignator(); // Check that the object is a global. Note that the fake 'this' object we // manufacture when checking potential constant expressions is conservatively // assumed to be global here. if (!IsGlobalLValue(Base)) { if (Info.getLangOpts().CPlusPlus11) { const ValueDecl *VD = Base.dyn_cast(); Info.FFDiag(Loc, diag::note_constexpr_non_global, 1) << IsReferenceType << !Designator.Entries.empty() << !!VD << VD; NoteLValueLocation(Info, Base); } else { Info.FFDiag(Loc); } // Don't allow references to temporaries to escape. return false; } assert((Info.checkingPotentialConstantExpression() || LVal.getLValueCallIndex() == 0) && "have call index for global lvalue"); if (const ValueDecl *VD = Base.dyn_cast()) { if (const VarDecl *Var = dyn_cast(VD)) { // Check if this is a thread-local variable. if (Var->getTLSKind()) return false; // A dllimport variable never acts like a constant. if (Usage == Expr::EvaluateForCodeGen && Var->hasAttr()) return false; } if (const auto *FD = dyn_cast(VD)) { // __declspec(dllimport) must be handled very carefully: // We must never initialize an expression with the thunk in C++. // Doing otherwise would allow the same id-expression to yield // different addresses for the same function in different translation // units. However, this means that we must dynamically initialize the // expression with the contents of the import address table at runtime. // // The C language has no notion of ODR; furthermore, it has no notion of // dynamic initialization. This means that we are permitted to // perform initialization with the address of the thunk. if (Info.getLangOpts().CPlusPlus && Usage == Expr::EvaluateForCodeGen && FD->hasAttr()) return false; } } // Allow address constant expressions to be past-the-end pointers. This is // an extension: the standard requires them to point to an object. if (!IsReferenceType) return true; // A reference constant expression must refer to an object. if (!Base) { // FIXME: diagnostic Info.CCEDiag(Loc); return true; } // Does this refer one past the end of some object? if (!Designator.Invalid && Designator.isOnePastTheEnd()) { const ValueDecl *VD = Base.dyn_cast(); Info.FFDiag(Loc, diag::note_constexpr_past_end, 1) << !Designator.Entries.empty() << !!VD << VD; NoteLValueLocation(Info, Base); } return true; } /// Member pointers are constant expressions unless they point to a /// non-virtual dllimport member function. static bool CheckMemberPointerConstantExpression(EvalInfo &Info, SourceLocation Loc, QualType Type, const APValue &Value, Expr::ConstExprUsage Usage) { const ValueDecl *Member = Value.getMemberPointerDecl(); const auto *FD = dyn_cast_or_null(Member); if (!FD) return true; return Usage == Expr::EvaluateForMangling || FD->isVirtual() || !FD->hasAttr(); } /// Check that this core constant expression is of literal type, and if not, /// produce an appropriate diagnostic. static bool CheckLiteralType(EvalInfo &Info, const Expr *E, const LValue *This = nullptr) { if (!E->isRValue() || E->getType()->isLiteralType(Info.Ctx)) return true; // C++1y: A constant initializer for an object o [...] may also invoke // constexpr constructors for o and its subobjects even if those objects // are of non-literal class types. // // C++11 missed this detail for aggregates, so classes like this: // struct foo_t { union { int i; volatile int j; } u; }; // are not (obviously) initializable like so: // __attribute__((__require_constant_initialization__)) // static const foo_t x = {{0}}; // because "i" is a subobject with non-literal initialization (due to the // volatile member of the union). See: // http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#1677 // Therefore, we use the C++1y behavior. if (This && Info.EvaluatingDecl == This->getLValueBase()) return true; // Prvalue constant expressions must be of literal types. if (Info.getLangOpts().CPlusPlus11) Info.FFDiag(E, diag::note_constexpr_nonliteral) << E->getType(); else Info.FFDiag(E, diag::note_invalid_subexpr_in_const_expr); return false; } /// Check that this core constant expression value is a valid value for a /// constant expression. If not, report an appropriate diagnostic. Does not /// check that the expression is of literal type. static bool CheckConstantExpression(EvalInfo &Info, SourceLocation DiagLoc, QualType Type, const APValue &Value, Expr::ConstExprUsage Usage = Expr::EvaluateForCodeGen) { if (Value.isUninit()) { Info.FFDiag(DiagLoc, diag::note_constexpr_uninitialized) << true << Type; return false; } // We allow _Atomic(T) to be initialized from anything that T can be // initialized from. if (const AtomicType *AT = Type->getAs()) Type = AT->getValueType(); // Core issue 1454: For a literal constant expression of array or class type, // each subobject of its value shall have been initialized by a constant // expression. if (Value.isArray()) { QualType EltTy = Type->castAsArrayTypeUnsafe()->getElementType(); for (unsigned I = 0, N = Value.getArrayInitializedElts(); I != N; ++I) { if (!CheckConstantExpression(Info, DiagLoc, EltTy, Value.getArrayInitializedElt(I), Usage)) return false; } if (!Value.hasArrayFiller()) return true; return CheckConstantExpression(Info, DiagLoc, EltTy, Value.getArrayFiller(), Usage); } if (Value.isUnion() && Value.getUnionField()) { return CheckConstantExpression(Info, DiagLoc, Value.getUnionField()->getType(), Value.getUnionValue(), Usage); } if (Value.isStruct()) { RecordDecl *RD = Type->castAs()->getDecl(); if (const CXXRecordDecl *CD = dyn_cast(RD)) { unsigned BaseIndex = 0; for (const CXXBaseSpecifier &BS : CD->bases()) { if (!CheckConstantExpression(Info, DiagLoc, BS.getType(), Value.getStructBase(BaseIndex), Usage)) return false; ++BaseIndex; } } for (const auto *I : RD->fields()) { if (I->isUnnamedBitfield()) continue; if (!CheckConstantExpression(Info, DiagLoc, I->getType(), Value.getStructField(I->getFieldIndex()), Usage)) return false; } } if (Value.isLValue()) { LValue LVal; LVal.setFrom(Info.Ctx, Value); return CheckLValueConstantExpression(Info, DiagLoc, Type, LVal, Usage); } if (Value.isMemberPointer()) return CheckMemberPointerConstantExpression(Info, DiagLoc, Type, Value, Usage); // Everything else is fine. return true; } +static const ValueDecl *GetLValueBaseDecl(const LValue &LVal) { + return LVal.Base.dyn_cast(); +} + +static bool IsLiteralLValue(const LValue &Value) { + if (Value.getLValueCallIndex()) + return false; + const Expr *E = Value.Base.dyn_cast(); + return E && !isa(E); +} + +static bool IsWeakLValue(const LValue &Value) { + const ValueDecl *Decl = GetLValueBaseDecl(Value); + return Decl && Decl->isWeak(); +} + +static bool isZeroSized(const LValue &Value) { + const ValueDecl *Decl = GetLValueBaseDecl(Value); + if (Decl && isa(Decl)) { + QualType Ty = Decl->getType(); + if (Ty->isArrayType()) + return Ty->isIncompleteType() || + Decl->getASTContext().getTypeSize(Ty) == 0; + } + return false; +} + static bool EvalPointerValueAsBool(const APValue &Value, bool &Result) { // A null base expression indicates a null pointer. These are always // evaluatable, and they are false unless the offset is zero. if (!Value.getLValueBase()) { Result = !Value.getLValueOffset().isZero(); return true; } // We have a non-null base. These are generally known to be true, but if it's // a weak declaration it can be null at runtime. Result = true; const ValueDecl *Decl = Value.getLValueBase().dyn_cast(); return !Decl || !Decl->isWeak(); } static bool HandleConversionToBool(const APValue &Val, bool &Result) { switch (Val.getKind()) { case APValue::Uninitialized: return false; case APValue::Int: Result = Val.getInt().getBoolValue(); return true; case APValue::Float: Result = !Val.getFloat().isZero(); return true; case APValue::ComplexInt: Result = Val.getComplexIntReal().getBoolValue() || Val.getComplexIntImag().getBoolValue(); return true; case APValue::ComplexFloat: Result = !Val.getComplexFloatReal().isZero() || !Val.getComplexFloatImag().isZero(); return true; case APValue::LValue: return EvalPointerValueAsBool(Val, Result); case APValue::MemberPointer: Result = Val.getMemberPointerDecl(); return true; case APValue::Vector: case APValue::Array: case APValue::Struct: case APValue::Union: case APValue::AddrLabelDiff: return false; } llvm_unreachable("unknown APValue kind"); } static bool EvaluateAsBooleanCondition(const Expr *E, bool &Result, EvalInfo &Info) { assert(E->isRValue() && "missing lvalue-to-rvalue conv in bool condition"); APValue Val; if (!Evaluate(Val, Info, E)) return false; return HandleConversionToBool(Val, Result); } template static bool HandleOverflow(EvalInfo &Info, const Expr *E, const T &SrcValue, QualType DestType) { Info.CCEDiag(E, diag::note_constexpr_overflow) << SrcValue << DestType; return Info.noteUndefinedBehavior(); } static bool HandleFloatToIntCast(EvalInfo &Info, const Expr *E, QualType SrcType, const APFloat &Value, QualType DestType, APSInt &Result) { unsigned DestWidth = Info.Ctx.getIntWidth(DestType); // Determine whether we are converting to unsigned or signed. bool DestSigned = DestType->isSignedIntegerOrEnumerationType(); Result = APSInt(DestWidth, !DestSigned); bool ignored; if (Value.convertToInteger(Result, llvm::APFloat::rmTowardZero, &ignored) & APFloat::opInvalidOp) return HandleOverflow(Info, E, Value, DestType); return true; } static bool HandleFloatToFloatCast(EvalInfo &Info, const Expr *E, QualType SrcType, QualType DestType, APFloat &Result) { APFloat Value = Result; bool ignored; if (Result.convert(Info.Ctx.getFloatTypeSemantics(DestType), APFloat::rmNearestTiesToEven, &ignored) & APFloat::opOverflow) return HandleOverflow(Info, E, Value, DestType); return true; } static APSInt HandleIntToIntCast(EvalInfo &Info, const Expr *E, QualType DestType, QualType SrcType, const APSInt &Value) { unsigned DestWidth = Info.Ctx.getIntWidth(DestType); APSInt Result = Value; // Figure out if this is a truncate, extend or noop cast. // If the input is signed, do a sign extend, noop, or truncate. Result = Result.extOrTrunc(DestWidth); Result.setIsUnsigned(DestType->isUnsignedIntegerOrEnumerationType()); return Result; } static bool HandleIntToFloatCast(EvalInfo &Info, const Expr *E, QualType SrcType, const APSInt &Value, QualType DestType, APFloat &Result) { Result = APFloat(Info.Ctx.getFloatTypeSemantics(DestType), 1); if (Result.convertFromAPInt(Value, Value.isSigned(), APFloat::rmNearestTiesToEven) & APFloat::opOverflow) return HandleOverflow(Info, E, Value, DestType); return true; } static bool truncateBitfieldValue(EvalInfo &Info, const Expr *E, APValue &Value, const FieldDecl *FD) { assert(FD->isBitField() && "truncateBitfieldValue on non-bitfield"); if (!Value.isInt()) { // Trying to store a pointer-cast-to-integer into a bitfield. // FIXME: In this case, we should provide the diagnostic for casting // a pointer to an integer. assert(Value.isLValue() && "integral value neither int nor lvalue?"); Info.FFDiag(E); return false; } APSInt &Int = Value.getInt(); unsigned OldBitWidth = Int.getBitWidth(); unsigned NewBitWidth = FD->getBitWidthValue(Info.Ctx); if (NewBitWidth < OldBitWidth) Int = Int.trunc(NewBitWidth).extend(OldBitWidth); return true; } static bool EvalAndBitcastToAPInt(EvalInfo &Info, const Expr *E, llvm::APInt &Res) { APValue SVal; if (!Evaluate(SVal, Info, E)) return false; if (SVal.isInt()) { Res = SVal.getInt(); return true; } if (SVal.isFloat()) { Res = SVal.getFloat().bitcastToAPInt(); return true; } if (SVal.isVector()) { QualType VecTy = E->getType(); unsigned VecSize = Info.Ctx.getTypeSize(VecTy); QualType EltTy = VecTy->castAs()->getElementType(); unsigned EltSize = Info.Ctx.getTypeSize(EltTy); bool BigEndian = Info.Ctx.getTargetInfo().isBigEndian(); Res = llvm::APInt::getNullValue(VecSize); for (unsigned i = 0; i < SVal.getVectorLength(); i++) { APValue &Elt = SVal.getVectorElt(i); llvm::APInt EltAsInt; if (Elt.isInt()) { EltAsInt = Elt.getInt(); } else if (Elt.isFloat()) { EltAsInt = Elt.getFloat().bitcastToAPInt(); } else { // Don't try to handle vectors of anything other than int or float // (not sure if it's possible to hit this case). Info.FFDiag(E, diag::note_invalid_subexpr_in_const_expr); return false; } unsigned BaseEltSize = EltAsInt.getBitWidth(); if (BigEndian) Res |= EltAsInt.zextOrTrunc(VecSize).rotr(i*EltSize+BaseEltSize); else Res |= EltAsInt.zextOrTrunc(VecSize).rotl(i*EltSize); } return true; } // Give up if the input isn't an int, float, or vector. For example, we // reject "(v4i16)(intptr_t)&a". Info.FFDiag(E, diag::note_invalid_subexpr_in_const_expr); return false; } /// Perform the given integer operation, which is known to need at most BitWidth /// bits, and check for overflow in the original type (if that type was not an /// unsigned type). template static bool CheckedIntArithmetic(EvalInfo &Info, const Expr *E, const APSInt &LHS, const APSInt &RHS, unsigned BitWidth, Operation Op, APSInt &Result) { if (LHS.isUnsigned()) { Result = Op(LHS, RHS); return true; } APSInt Value(Op(LHS.extend(BitWidth), RHS.extend(BitWidth)), false); Result = Value.trunc(LHS.getBitWidth()); if (Result.extend(BitWidth) != Value) { if (Info.checkingForOverflow()) Info.Ctx.getDiagnostics().Report(E->getExprLoc(), diag::warn_integer_constant_overflow) << Result.toString(10) << E->getType(); else return HandleOverflow(Info, E, Value, E->getType()); } return true; } /// Perform the given binary integer operation. static bool handleIntIntBinOp(EvalInfo &Info, const Expr *E, const APSInt &LHS, BinaryOperatorKind Opcode, APSInt RHS, APSInt &Result) { switch (Opcode) { default: Info.FFDiag(E); return false; case BO_Mul: return CheckedIntArithmetic(Info, E, LHS, RHS, LHS.getBitWidth() * 2, std::multiplies(), Result); case BO_Add: return CheckedIntArithmetic(Info, E, LHS, RHS, LHS.getBitWidth() + 1, std::plus(), Result); case BO_Sub: return CheckedIntArithmetic(Info, E, LHS, RHS, LHS.getBitWidth() + 1, std::minus(), Result); case BO_And: Result = LHS & RHS; return true; case BO_Xor: Result = LHS ^ RHS; return true; case BO_Or: Result = LHS | RHS; return true; case BO_Div: case BO_Rem: if (RHS == 0) { Info.FFDiag(E, diag::note_expr_divide_by_zero); return false; } Result = (Opcode == BO_Rem ? LHS % RHS : LHS / RHS); // Check for overflow case: INT_MIN / -1 or INT_MIN % -1. APSInt supports // this operation and gives the two's complement result. if (RHS.isNegative() && RHS.isAllOnesValue() && LHS.isSigned() && LHS.isMinSignedValue()) return HandleOverflow(Info, E, -LHS.extend(LHS.getBitWidth() + 1), E->getType()); return true; case BO_Shl: { if (Info.getLangOpts().OpenCL) // OpenCL 6.3j: shift values are effectively % word size of LHS. RHS &= APSInt(llvm::APInt(RHS.getBitWidth(), static_cast(LHS.getBitWidth() - 1)), RHS.isUnsigned()); else if (RHS.isSigned() && RHS.isNegative()) { // During constant-folding, a negative shift is an opposite shift. Such // a shift is not a constant expression. Info.CCEDiag(E, diag::note_constexpr_negative_shift) << RHS; RHS = -RHS; goto shift_right; } shift_left: // C++11 [expr.shift]p1: Shift width must be less than the bit width of // the shifted type. unsigned SA = (unsigned) RHS.getLimitedValue(LHS.getBitWidth()-1); if (SA != RHS) { Info.CCEDiag(E, diag::note_constexpr_large_shift) << RHS << E->getType() << LHS.getBitWidth(); } else if (LHS.isSigned()) { // C++11 [expr.shift]p2: A signed left shift must have a non-negative // operand, and must not overflow the corresponding unsigned type. if (LHS.isNegative()) Info.CCEDiag(E, diag::note_constexpr_lshift_of_negative) << LHS; else if (LHS.countLeadingZeros() < SA) Info.CCEDiag(E, diag::note_constexpr_lshift_discards); } Result = LHS << SA; return true; } case BO_Shr: { if (Info.getLangOpts().OpenCL) // OpenCL 6.3j: shift values are effectively % word size of LHS. RHS &= APSInt(llvm::APInt(RHS.getBitWidth(), static_cast(LHS.getBitWidth() - 1)), RHS.isUnsigned()); else if (RHS.isSigned() && RHS.isNegative()) { // During constant-folding, a negative shift is an opposite shift. Such a // shift is not a constant expression. Info.CCEDiag(E, diag::note_constexpr_negative_shift) << RHS; RHS = -RHS; goto shift_left; } shift_right: // C++11 [expr.shift]p1: Shift width must be less than the bit width of the // shifted type. unsigned SA = (unsigned) RHS.getLimitedValue(LHS.getBitWidth()-1); if (SA != RHS) Info.CCEDiag(E, diag::note_constexpr_large_shift) << RHS << E->getType() << LHS.getBitWidth(); Result = LHS >> SA; return true; } case BO_LT: Result = LHS < RHS; return true; case BO_GT: Result = LHS > RHS; return true; case BO_LE: Result = LHS <= RHS; return true; case BO_GE: Result = LHS >= RHS; return true; case BO_EQ: Result = LHS == RHS; return true; case BO_NE: Result = LHS != RHS; return true; case BO_Cmp: llvm_unreachable("BO_Cmp should be handled elsewhere"); } } /// Perform the given binary floating-point operation, in-place, on LHS. static bool handleFloatFloatBinOp(EvalInfo &Info, const Expr *E, APFloat &LHS, BinaryOperatorKind Opcode, const APFloat &RHS) { switch (Opcode) { default: Info.FFDiag(E); return false; case BO_Mul: LHS.multiply(RHS, APFloat::rmNearestTiesToEven); break; case BO_Add: LHS.add(RHS, APFloat::rmNearestTiesToEven); break; case BO_Sub: LHS.subtract(RHS, APFloat::rmNearestTiesToEven); break; case BO_Div: LHS.divide(RHS, APFloat::rmNearestTiesToEven); break; } if (LHS.isInfinity() || LHS.isNaN()) { Info.CCEDiag(E, diag::note_constexpr_float_arithmetic) << LHS.isNaN(); return Info.noteUndefinedBehavior(); } return true; } /// Cast an lvalue referring to a base subobject to a derived class, by /// truncating the lvalue's path to the given length. static bool CastToDerivedClass(EvalInfo &Info, const Expr *E, LValue &Result, const RecordDecl *TruncatedType, unsigned TruncatedElements) { SubobjectDesignator &D = Result.Designator; // Check we actually point to a derived class object. if (TruncatedElements == D.Entries.size()) return true; assert(TruncatedElements >= D.MostDerivedPathLength && "not casting to a derived class"); if (!Result.checkSubobject(Info, E, CSK_Derived)) return false; // Truncate the path to the subobject, and remove any derived-to-base offsets. const RecordDecl *RD = TruncatedType; for (unsigned I = TruncatedElements, N = D.Entries.size(); I != N; ++I) { if (RD->isInvalidDecl()) return false; const ASTRecordLayout &Layout = Info.Ctx.getASTRecordLayout(RD); const CXXRecordDecl *Base = getAsBaseClass(D.Entries[I]); if (isVirtualBaseClass(D.Entries[I])) Result.Offset -= Layout.getVBaseClassOffset(Base); else Result.Offset -= Layout.getBaseClassOffset(Base); RD = Base; } D.Entries.resize(TruncatedElements); return true; } static bool HandleLValueDirectBase(EvalInfo &Info, const Expr *E, LValue &Obj, const CXXRecordDecl *Derived, const CXXRecordDecl *Base, const ASTRecordLayout *RL = nullptr) { if (!RL) { if (Derived->isInvalidDecl()) return false; RL = &Info.Ctx.getASTRecordLayout(Derived); } Obj.getLValueOffset() += RL->getBaseClassOffset(Base); Obj.addDecl(Info, E, Base, /*Virtual*/ false); return true; } static bool HandleLValueBase(EvalInfo &Info, const Expr *E, LValue &Obj, const CXXRecordDecl *DerivedDecl, const CXXBaseSpecifier *Base) { const CXXRecordDecl *BaseDecl = Base->getType()->getAsCXXRecordDecl(); if (!Base->isVirtual()) return HandleLValueDirectBase(Info, E, Obj, DerivedDecl, BaseDecl); SubobjectDesignator &D = Obj.Designator; if (D.Invalid) return false; // Extract most-derived object and corresponding type. DerivedDecl = D.MostDerivedType->getAsCXXRecordDecl(); if (!CastToDerivedClass(Info, E, Obj, DerivedDecl, D.MostDerivedPathLength)) return false; // Find the virtual base class. if (DerivedDecl->isInvalidDecl()) return false; const ASTRecordLayout &Layout = Info.Ctx.getASTRecordLayout(DerivedDecl); Obj.getLValueOffset() += Layout.getVBaseClassOffset(BaseDecl); Obj.addDecl(Info, E, BaseDecl, /*Virtual*/ true); return true; } static bool HandleLValueBasePath(EvalInfo &Info, const CastExpr *E, QualType Type, LValue &Result) { for (CastExpr::path_const_iterator PathI = E->path_begin(), PathE = E->path_end(); PathI != PathE; ++PathI) { if (!HandleLValueBase(Info, E, Result, Type->getAsCXXRecordDecl(), *PathI)) return false; Type = (*PathI)->getType(); } return true; } /// Update LVal to refer to the given field, which must be a member of the type /// currently described by LVal. static bool HandleLValueMember(EvalInfo &Info, const Expr *E, LValue &LVal, const FieldDecl *FD, const ASTRecordLayout *RL = nullptr) { if (!RL) { if (FD->getParent()->isInvalidDecl()) return false; RL = &Info.Ctx.getASTRecordLayout(FD->getParent()); } unsigned I = FD->getFieldIndex(); LVal.adjustOffset(Info.Ctx.toCharUnitsFromBits(RL->getFieldOffset(I))); LVal.addDecl(Info, E, FD); return true; } /// Update LVal to refer to the given indirect field. static bool HandleLValueIndirectMember(EvalInfo &Info, const Expr *E, LValue &LVal, const IndirectFieldDecl *IFD) { for (const auto *C : IFD->chain()) if (!HandleLValueMember(Info, E, LVal, cast(C))) return false; return true; } /// Get the size of the given type in char units. static bool HandleSizeof(EvalInfo &Info, SourceLocation Loc, QualType Type, CharUnits &Size) { // sizeof(void), __alignof__(void), sizeof(function) = 1 as a gcc // extension. if (Type->isVoidType() || Type->isFunctionType()) { Size = CharUnits::One(); return true; } if (Type->isDependentType()) { Info.FFDiag(Loc); return false; } if (!Type->isConstantSizeType()) { // sizeof(vla) is not a constantexpr: C99 6.5.3.4p2. // FIXME: Better diagnostic. Info.FFDiag(Loc); return false; } Size = Info.Ctx.getTypeSizeInChars(Type); return true; } /// Update a pointer value to model pointer arithmetic. /// \param Info - Information about the ongoing evaluation. /// \param E - The expression being evaluated, for diagnostic purposes. /// \param LVal - The pointer value to be updated. /// \param EltTy - The pointee type represented by LVal. /// \param Adjustment - The adjustment, in objects of type EltTy, to add. static bool HandleLValueArrayAdjustment(EvalInfo &Info, const Expr *E, LValue &LVal, QualType EltTy, APSInt Adjustment) { CharUnits SizeOfPointee; if (!HandleSizeof(Info, E->getExprLoc(), EltTy, SizeOfPointee)) return false; LVal.adjustOffsetAndIndex(Info, E, Adjustment, SizeOfPointee); return true; } static bool HandleLValueArrayAdjustment(EvalInfo &Info, const Expr *E, LValue &LVal, QualType EltTy, int64_t Adjustment) { return HandleLValueArrayAdjustment(Info, E, LVal, EltTy, APSInt::get(Adjustment)); } /// Update an lvalue to refer to a component of a complex number. /// \param Info - Information about the ongoing evaluation. /// \param LVal - The lvalue to be updated. /// \param EltTy - The complex number's component type. /// \param Imag - False for the real component, true for the imaginary. static bool HandleLValueComplexElement(EvalInfo &Info, const Expr *E, LValue &LVal, QualType EltTy, bool Imag) { if (Imag) { CharUnits SizeOfComponent; if (!HandleSizeof(Info, E->getExprLoc(), EltTy, SizeOfComponent)) return false; LVal.Offset += SizeOfComponent; } LVal.addComplex(Info, E, EltTy, Imag); return true; } static bool handleLValueToRValueConversion(EvalInfo &Info, const Expr *Conv, QualType Type, const LValue &LVal, APValue &RVal); /// Try to evaluate the initializer for a variable declaration. /// /// \param Info Information about the ongoing evaluation. /// \param E An expression to be used when printing diagnostics. /// \param VD The variable whose initializer should be obtained. /// \param Frame The frame in which the variable was created. Must be null /// if this variable is not local to the evaluation. /// \param Result Filled in with a pointer to the value of the variable. static bool evaluateVarDeclInit(EvalInfo &Info, const Expr *E, const VarDecl *VD, CallStackFrame *Frame, APValue *&Result, const LValue *LVal) { // If this is a parameter to an active constexpr function call, perform // argument substitution. if (const ParmVarDecl *PVD = dyn_cast(VD)) { // Assume arguments of a potential constant expression are unknown // constant expressions. if (Info.checkingPotentialConstantExpression()) return false; if (!Frame || !Frame->Arguments) { Info.FFDiag(E, diag::note_invalid_subexpr_in_const_expr); return false; } Result = &Frame->Arguments[PVD->getFunctionScopeIndex()]; return true; } // If this is a local variable, dig out its value. if (Frame) { Result = LVal ? Frame->getTemporary(VD, LVal->getLValueVersion()) : Frame->getCurrentTemporary(VD); if (!Result) { // Assume variables referenced within a lambda's call operator that were // not declared within the call operator are captures and during checking // of a potential constant expression, assume they are unknown constant // expressions. assert(isLambdaCallOperator(Frame->Callee) && (VD->getDeclContext() != Frame->Callee || VD->isInitCapture()) && "missing value for local variable"); if (Info.checkingPotentialConstantExpression()) return false; // FIXME: implement capture evaluation during constant expr evaluation. Info.FFDiag(E->getLocStart(), diag::note_unimplemented_constexpr_lambda_feature_ast) << "captures not currently allowed"; return false; } return true; } // Dig out the initializer, and use the declaration which it's attached to. const Expr *Init = VD->getAnyInitializer(VD); if (!Init || Init->isValueDependent()) { // If we're checking a potential constant expression, the variable could be // initialized later. if (!Info.checkingPotentialConstantExpression()) Info.FFDiag(E, diag::note_invalid_subexpr_in_const_expr); return false; } // If we're currently evaluating the initializer of this declaration, use that // in-flight value. if (Info.EvaluatingDecl.dyn_cast() == VD) { Result = Info.EvaluatingDeclValue; return true; } // Never evaluate the initializer of a weak variable. We can't be sure that // this is the definition which will be used. if (VD->isWeak()) { Info.FFDiag(E, diag::note_invalid_subexpr_in_const_expr); return false; } // Check that we can fold the initializer. In C++, we will have already done // this in the cases where it matters for conformance. SmallVector Notes; if (!VD->evaluateValue(Notes)) { Info.FFDiag(E, diag::note_constexpr_var_init_non_constant, Notes.size() + 1) << VD; Info.Note(VD->getLocation(), diag::note_declared_at); Info.addNotes(Notes); return false; } else if (!VD->checkInitIsICE()) { Info.CCEDiag(E, diag::note_constexpr_var_init_non_constant, Notes.size() + 1) << VD; Info.Note(VD->getLocation(), diag::note_declared_at); Info.addNotes(Notes); } Result = VD->getEvaluatedValue(); return true; } static bool IsConstNonVolatile(QualType T) { Qualifiers Quals = T.getQualifiers(); return Quals.hasConst() && !Quals.hasVolatile(); } /// Get the base index of the given base class within an APValue representing /// the given derived class. static unsigned getBaseIndex(const CXXRecordDecl *Derived, const CXXRecordDecl *Base) { Base = Base->getCanonicalDecl(); unsigned Index = 0; for (CXXRecordDecl::base_class_const_iterator I = Derived->bases_begin(), E = Derived->bases_end(); I != E; ++I, ++Index) { if (I->getType()->getAsCXXRecordDecl()->getCanonicalDecl() == Base) return Index; } llvm_unreachable("base class missing from derived class's bases list"); } /// Extract the value of a character from a string literal. static APSInt extractStringLiteralCharacter(EvalInfo &Info, const Expr *Lit, uint64_t Index) { // FIXME: Support MakeStringConstant if (const auto *ObjCEnc = dyn_cast(Lit)) { std::string Str; Info.Ctx.getObjCEncodingForType(ObjCEnc->getEncodedType(), Str); assert(Index <= Str.size() && "Index too large"); return APSInt::getUnsigned(Str.c_str()[Index]); } if (auto PE = dyn_cast(Lit)) Lit = PE->getFunctionName(); const StringLiteral *S = cast(Lit); const ConstantArrayType *CAT = Info.Ctx.getAsConstantArrayType(S->getType()); assert(CAT && "string literal isn't an array"); QualType CharType = CAT->getElementType(); assert(CharType->isIntegerType() && "unexpected character type"); APSInt Value(S->getCharByteWidth() * Info.Ctx.getCharWidth(), CharType->isUnsignedIntegerType()); if (Index < S->getLength()) Value = S->getCodeUnit(Index); return Value; } // Expand a string literal into an array of characters. static void expandStringLiteral(EvalInfo &Info, const Expr *Lit, APValue &Result) { const StringLiteral *S = cast(Lit); const ConstantArrayType *CAT = Info.Ctx.getAsConstantArrayType(S->getType()); assert(CAT && "string literal isn't an array"); QualType CharType = CAT->getElementType(); assert(CharType->isIntegerType() && "unexpected character type"); unsigned Elts = CAT->getSize().getZExtValue(); Result = APValue(APValue::UninitArray(), std::min(S->getLength(), Elts), Elts); APSInt Value(S->getCharByteWidth() * Info.Ctx.getCharWidth(), CharType->isUnsignedIntegerType()); if (Result.hasArrayFiller()) Result.getArrayFiller() = APValue(Value); for (unsigned I = 0, N = Result.getArrayInitializedElts(); I != N; ++I) { Value = S->getCodeUnit(I); Result.getArrayInitializedElt(I) = APValue(Value); } } // Expand an array so that it has more than Index filled elements. static void expandArray(APValue &Array, unsigned Index) { unsigned Size = Array.getArraySize(); assert(Index < Size); // Always at least double the number of elements for which we store a value. unsigned OldElts = Array.getArrayInitializedElts(); unsigned NewElts = std::max(Index+1, OldElts * 2); NewElts = std::min(Size, std::max(NewElts, 8u)); // Copy the data across. APValue NewValue(APValue::UninitArray(), NewElts, Size); for (unsigned I = 0; I != OldElts; ++I) NewValue.getArrayInitializedElt(I).swap(Array.getArrayInitializedElt(I)); for (unsigned I = OldElts; I != NewElts; ++I) NewValue.getArrayInitializedElt(I) = Array.getArrayFiller(); if (NewValue.hasArrayFiller()) NewValue.getArrayFiller() = Array.getArrayFiller(); Array.swap(NewValue); } /// Determine whether a type would actually be read by an lvalue-to-rvalue /// conversion. If it's of class type, we may assume that the copy operation /// is trivial. Note that this is never true for a union type with fields /// (because the copy always "reads" the active member) and always true for /// a non-class type. static bool isReadByLvalueToRvalueConversion(QualType T) { CXXRecordDecl *RD = T->getBaseElementTypeUnsafe()->getAsCXXRecordDecl(); if (!RD || (RD->isUnion() && !RD->field_empty())) return true; if (RD->isEmpty()) return false; for (auto *Field : RD->fields()) if (isReadByLvalueToRvalueConversion(Field->getType())) return true; for (auto &BaseSpec : RD->bases()) if (isReadByLvalueToRvalueConversion(BaseSpec.getType())) return true; return false; } /// Diagnose an attempt to read from any unreadable field within the specified /// type, which might be a class type. static bool diagnoseUnreadableFields(EvalInfo &Info, const Expr *E, QualType T) { CXXRecordDecl *RD = T->getBaseElementTypeUnsafe()->getAsCXXRecordDecl(); if (!RD) return false; if (!RD->hasMutableFields()) return false; for (auto *Field : RD->fields()) { // If we're actually going to read this field in some way, then it can't // be mutable. If we're in a union, then assigning to a mutable field // (even an empty one) can change the active member, so that's not OK. // FIXME: Add core issue number for the union case. if (Field->isMutable() && (RD->isUnion() || isReadByLvalueToRvalueConversion(Field->getType()))) { Info.FFDiag(E, diag::note_constexpr_ltor_mutable, 1) << Field; Info.Note(Field->getLocation(), diag::note_declared_at); return true; } if (diagnoseUnreadableFields(Info, E, Field->getType())) return true; } for (auto &BaseSpec : RD->bases()) if (diagnoseUnreadableFields(Info, E, BaseSpec.getType())) return true; // All mutable fields were empty, and thus not actually read. return false; } /// Kinds of access we can perform on an object, for diagnostics. enum AccessKinds { AK_Read, AK_Assign, AK_Increment, AK_Decrement }; namespace { /// A handle to a complete object (an object that is not a subobject of /// another object). struct CompleteObject { /// The value of the complete object. APValue *Value; /// The type of the complete object. QualType Type; bool LifetimeStartedInEvaluation; CompleteObject() : Value(nullptr) {} CompleteObject(APValue *Value, QualType Type, bool LifetimeStartedInEvaluation) : Value(Value), Type(Type), LifetimeStartedInEvaluation(LifetimeStartedInEvaluation) { assert(Value && "missing value for complete object"); } explicit operator bool() const { return Value; } }; } // end anonymous namespace /// Find the designated sub-object of an rvalue. template typename SubobjectHandler::result_type findSubobject(EvalInfo &Info, const Expr *E, const CompleteObject &Obj, const SubobjectDesignator &Sub, SubobjectHandler &handler) { if (Sub.Invalid) // A diagnostic will have already been produced. return handler.failed(); if (Sub.isOnePastTheEnd() || Sub.isMostDerivedAnUnsizedArray()) { if (Info.getLangOpts().CPlusPlus11) Info.FFDiag(E, Sub.isOnePastTheEnd() ? diag::note_constexpr_access_past_end : diag::note_constexpr_access_unsized_array) << handler.AccessKind; else Info.FFDiag(E); return handler.failed(); } APValue *O = Obj.Value; QualType ObjType = Obj.Type; const FieldDecl *LastField = nullptr; const bool MayReadMutableMembers = Obj.LifetimeStartedInEvaluation && Info.getLangOpts().CPlusPlus14; // Walk the designator's path to find the subobject. for (unsigned I = 0, N = Sub.Entries.size(); /**/; ++I) { if (O->isUninit()) { if (!Info.checkingPotentialConstantExpression()) Info.FFDiag(E, diag::note_constexpr_access_uninit) << handler.AccessKind; return handler.failed(); } if (I == N) { // If we are reading an object of class type, there may still be more // things we need to check: if there are any mutable subobjects, we // cannot perform this read. (This only happens when performing a trivial // copy or assignment.) if (ObjType->isRecordType() && handler.AccessKind == AK_Read && !MayReadMutableMembers && diagnoseUnreadableFields(Info, E, ObjType)) return handler.failed(); if (!handler.found(*O, ObjType)) return false; // If we modified a bit-field, truncate it to the right width. if (handler.AccessKind != AK_Read && LastField && LastField->isBitField() && !truncateBitfieldValue(Info, E, *O, LastField)) return false; return true; } LastField = nullptr; if (ObjType->isArrayType()) { // Next subobject is an array element. const ConstantArrayType *CAT = Info.Ctx.getAsConstantArrayType(ObjType); assert(CAT && "vla in literal type?"); uint64_t Index = Sub.Entries[I].ArrayIndex; if (CAT->getSize().ule(Index)) { // Note, it should not be possible to form a pointer with a valid // designator which points more than one past the end of the array. if (Info.getLangOpts().CPlusPlus11) Info.FFDiag(E, diag::note_constexpr_access_past_end) << handler.AccessKind; else Info.FFDiag(E); return handler.failed(); } ObjType = CAT->getElementType(); // An array object is represented as either an Array APValue or as an // LValue which refers to a string literal. if (O->isLValue()) { assert(I == N - 1 && "extracting subobject of character?"); assert(!O->hasLValuePath() || O->getLValuePath().empty()); if (handler.AccessKind != AK_Read) expandStringLiteral(Info, O->getLValueBase().get(), *O); else return handler.foundString(*O, ObjType, Index); } if (O->getArrayInitializedElts() > Index) O = &O->getArrayInitializedElt(Index); else if (handler.AccessKind != AK_Read) { expandArray(*O, Index); O = &O->getArrayInitializedElt(Index); } else O = &O->getArrayFiller(); } else if (ObjType->isAnyComplexType()) { // Next subobject is a complex number. uint64_t Index = Sub.Entries[I].ArrayIndex; if (Index > 1) { if (Info.getLangOpts().CPlusPlus11) Info.FFDiag(E, diag::note_constexpr_access_past_end) << handler.AccessKind; else Info.FFDiag(E); return handler.failed(); } bool WasConstQualified = ObjType.isConstQualified(); ObjType = ObjType->castAs()->getElementType(); if (WasConstQualified) ObjType.addConst(); assert(I == N - 1 && "extracting subobject of scalar?"); if (O->isComplexInt()) { return handler.found(Index ? O->getComplexIntImag() : O->getComplexIntReal(), ObjType); } else { assert(O->isComplexFloat()); return handler.found(Index ? O->getComplexFloatImag() : O->getComplexFloatReal(), ObjType); } } else if (const FieldDecl *Field = getAsField(Sub.Entries[I])) { // In C++14 onwards, it is permitted to read a mutable member whose // lifetime began within the evaluation. // FIXME: Should we also allow this in C++11? if (Field->isMutable() && handler.AccessKind == AK_Read && !MayReadMutableMembers) { Info.FFDiag(E, diag::note_constexpr_ltor_mutable, 1) << Field; Info.Note(Field->getLocation(), diag::note_declared_at); return handler.failed(); } // Next subobject is a class, struct or union field. RecordDecl *RD = ObjType->castAs()->getDecl(); if (RD->isUnion()) { const FieldDecl *UnionField = O->getUnionField(); if (!UnionField || UnionField->getCanonicalDecl() != Field->getCanonicalDecl()) { Info.FFDiag(E, diag::note_constexpr_access_inactive_union_member) << handler.AccessKind << Field << !UnionField << UnionField; return handler.failed(); } O = &O->getUnionValue(); } else O = &O->getStructField(Field->getFieldIndex()); bool WasConstQualified = ObjType.isConstQualified(); ObjType = Field->getType(); if (WasConstQualified && !Field->isMutable()) ObjType.addConst(); if (ObjType.isVolatileQualified()) { if (Info.getLangOpts().CPlusPlus) { // FIXME: Include a description of the path to the volatile subobject. Info.FFDiag(E, diag::note_constexpr_access_volatile_obj, 1) << handler.AccessKind << 2 << Field; Info.Note(Field->getLocation(), diag::note_declared_at); } else { Info.FFDiag(E, diag::note_invalid_subexpr_in_const_expr); } return handler.failed(); } LastField = Field; } else { // Next subobject is a base class. const CXXRecordDecl *Derived = ObjType->getAsCXXRecordDecl(); const CXXRecordDecl *Base = getAsBaseClass(Sub.Entries[I]); O = &O->getStructBase(getBaseIndex(Derived, Base)); bool WasConstQualified = ObjType.isConstQualified(); ObjType = Info.Ctx.getRecordType(Base); if (WasConstQualified) ObjType.addConst(); } } } namespace { struct ExtractSubobjectHandler { EvalInfo &Info; APValue &Result; static const AccessKinds AccessKind = AK_Read; typedef bool result_type; bool failed() { return false; } bool found(APValue &Subobj, QualType SubobjType) { Result = Subobj; return true; } bool found(APSInt &Value, QualType SubobjType) { Result = APValue(Value); return true; } bool found(APFloat &Value, QualType SubobjType) { Result = APValue(Value); return true; } bool foundString(APValue &Subobj, QualType SubobjType, uint64_t Character) { Result = APValue(extractStringLiteralCharacter( Info, Subobj.getLValueBase().get(), Character)); return true; } }; } // end anonymous namespace const AccessKinds ExtractSubobjectHandler::AccessKind; /// Extract the designated sub-object of an rvalue. static bool extractSubobject(EvalInfo &Info, const Expr *E, const CompleteObject &Obj, const SubobjectDesignator &Sub, APValue &Result) { ExtractSubobjectHandler Handler = { Info, Result }; return findSubobject(Info, E, Obj, Sub, Handler); } namespace { struct ModifySubobjectHandler { EvalInfo &Info; APValue &NewVal; const Expr *E; typedef bool result_type; static const AccessKinds AccessKind = AK_Assign; bool checkConst(QualType QT) { // Assigning to a const object has undefined behavior. if (QT.isConstQualified()) { Info.FFDiag(E, diag::note_constexpr_modify_const_type) << QT; return false; } return true; } bool failed() { return false; } bool found(APValue &Subobj, QualType SubobjType) { if (!checkConst(SubobjType)) return false; // We've been given ownership of NewVal, so just swap it in. Subobj.swap(NewVal); return true; } bool found(APSInt &Value, QualType SubobjType) { if (!checkConst(SubobjType)) return false; if (!NewVal.isInt()) { // Maybe trying to write a cast pointer value into a complex? Info.FFDiag(E); return false; } Value = NewVal.getInt(); return true; } bool found(APFloat &Value, QualType SubobjType) { if (!checkConst(SubobjType)) return false; Value = NewVal.getFloat(); return true; } bool foundString(APValue &Subobj, QualType SubobjType, uint64_t Character) { llvm_unreachable("shouldn't encounter string elements with ExpandArrays"); } }; } // end anonymous namespace const AccessKinds ModifySubobjectHandler::AccessKind; /// Update the designated sub-object of an rvalue to the given value. static bool modifySubobject(EvalInfo &Info, const Expr *E, const CompleteObject &Obj, const SubobjectDesignator &Sub, APValue &NewVal) { ModifySubobjectHandler Handler = { Info, NewVal, E }; return findSubobject(Info, E, Obj, Sub, Handler); } /// Find the position where two subobject designators diverge, or equivalently /// the length of the common initial subsequence. static unsigned FindDesignatorMismatch(QualType ObjType, const SubobjectDesignator &A, const SubobjectDesignator &B, bool &WasArrayIndex) { unsigned I = 0, N = std::min(A.Entries.size(), B.Entries.size()); for (/**/; I != N; ++I) { if (!ObjType.isNull() && (ObjType->isArrayType() || ObjType->isAnyComplexType())) { // Next subobject is an array element. if (A.Entries[I].ArrayIndex != B.Entries[I].ArrayIndex) { WasArrayIndex = true; return I; } if (ObjType->isAnyComplexType()) ObjType = ObjType->castAs()->getElementType(); else ObjType = ObjType->castAsArrayTypeUnsafe()->getElementType(); } else { if (A.Entries[I].BaseOrMember != B.Entries[I].BaseOrMember) { WasArrayIndex = false; return I; } if (const FieldDecl *FD = getAsField(A.Entries[I])) // Next subobject is a field. ObjType = FD->getType(); else // Next subobject is a base class. ObjType = QualType(); } } WasArrayIndex = false; return I; } /// Determine whether the given subobject designators refer to elements of the /// same array object. static bool AreElementsOfSameArray(QualType ObjType, const SubobjectDesignator &A, const SubobjectDesignator &B) { if (A.Entries.size() != B.Entries.size()) return false; bool IsArray = A.MostDerivedIsArrayElement; if (IsArray && A.MostDerivedPathLength != A.Entries.size()) // A is a subobject of the array element. return false; // If A (and B) designates an array element, the last entry will be the array // index. That doesn't have to match. Otherwise, we're in the 'implicit array // of length 1' case, and the entire path must match. bool WasArrayIndex; unsigned CommonLength = FindDesignatorMismatch(ObjType, A, B, WasArrayIndex); return CommonLength >= A.Entries.size() - IsArray; } /// Find the complete object to which an LValue refers. static CompleteObject findCompleteObject(EvalInfo &Info, const Expr *E, AccessKinds AK, const LValue &LVal, QualType LValType) { if (!LVal.Base) { Info.FFDiag(E, diag::note_constexpr_access_null) << AK; return CompleteObject(); } CallStackFrame *Frame = nullptr; if (LVal.getLValueCallIndex()) { Frame = Info.getCallFrame(LVal.getLValueCallIndex()); if (!Frame) { Info.FFDiag(E, diag::note_constexpr_lifetime_ended, 1) << AK << LVal.Base.is(); NoteLValueLocation(Info, LVal.Base); return CompleteObject(); } } // C++11 DR1311: An lvalue-to-rvalue conversion on a volatile-qualified type // is not a constant expression (even if the object is non-volatile). We also // apply this rule to C++98, in order to conform to the expected 'volatile' // semantics. if (LValType.isVolatileQualified()) { if (Info.getLangOpts().CPlusPlus) Info.FFDiag(E, diag::note_constexpr_access_volatile_type) << AK << LValType; else Info.FFDiag(E); return CompleteObject(); } // Compute value storage location and type of base object. APValue *BaseVal = nullptr; QualType BaseType = getType(LVal.Base); bool LifetimeStartedInEvaluation = Frame; if (const ValueDecl *D = LVal.Base.dyn_cast()) { // In C++98, const, non-volatile integers initialized with ICEs are ICEs. // In C++11, constexpr, non-volatile variables initialized with constant // expressions are constant expressions too. Inside constexpr functions, // parameters are constant expressions even if they're non-const. // In C++1y, objects local to a constant expression (those with a Frame) are // both readable and writable inside constant expressions. // In C, such things can also be folded, although they are not ICEs. const VarDecl *VD = dyn_cast(D); if (VD) { if (const VarDecl *VDef = VD->getDefinition(Info.Ctx)) VD = VDef; } if (!VD || VD->isInvalidDecl()) { Info.FFDiag(E); return CompleteObject(); } // Accesses of volatile-qualified objects are not allowed. if (BaseType.isVolatileQualified()) { if (Info.getLangOpts().CPlusPlus) { Info.FFDiag(E, diag::note_constexpr_access_volatile_obj, 1) << AK << 1 << VD; Info.Note(VD->getLocation(), diag::note_declared_at); } else { Info.FFDiag(E); } return CompleteObject(); } // Unless we're looking at a local variable or argument in a constexpr call, // the variable we're reading must be const. if (!Frame) { if (Info.getLangOpts().CPlusPlus14 && VD == Info.EvaluatingDecl.dyn_cast()) { // OK, we can read and modify an object if we're in the process of // evaluating its initializer, because its lifetime began in this // evaluation. } else if (AK != AK_Read) { // All the remaining cases only permit reading. Info.FFDiag(E, diag::note_constexpr_modify_global); return CompleteObject(); } else if (VD->isConstexpr()) { // OK, we can read this variable. } else if (BaseType->isIntegralOrEnumerationType()) { // In OpenCL if a variable is in constant address space it is a const value. if (!(BaseType.isConstQualified() || (Info.getLangOpts().OpenCL && BaseType.getAddressSpace() == LangAS::opencl_constant))) { if (Info.getLangOpts().CPlusPlus) { Info.FFDiag(E, diag::note_constexpr_ltor_non_const_int, 1) << VD; Info.Note(VD->getLocation(), diag::note_declared_at); } else { Info.FFDiag(E); } return CompleteObject(); } } else if (BaseType->isFloatingType() && BaseType.isConstQualified()) { // We support folding of const floating-point types, in order to make // static const data members of such types (supported as an extension) // more useful. if (Info.getLangOpts().CPlusPlus11) { Info.CCEDiag(E, diag::note_constexpr_ltor_non_constexpr, 1) << VD; Info.Note(VD->getLocation(), diag::note_declared_at); } else { Info.CCEDiag(E); } } else if (BaseType.isConstQualified() && VD->hasDefinition(Info.Ctx)) { Info.CCEDiag(E, diag::note_constexpr_ltor_non_constexpr) << VD; // Keep evaluating to see what we can do. } else { // FIXME: Allow folding of values of any literal type in all languages. if (Info.checkingPotentialConstantExpression() && VD->getType().isConstQualified() && !VD->hasDefinition(Info.Ctx)) { // The definition of this variable could be constexpr. We can't // access it right now, but may be able to in future. } else if (Info.getLangOpts().CPlusPlus11) { Info.FFDiag(E, diag::note_constexpr_ltor_non_constexpr, 1) << VD; Info.Note(VD->getLocation(), diag::note_declared_at); } else { Info.FFDiag(E); } return CompleteObject(); } } if (!evaluateVarDeclInit(Info, E, VD, Frame, BaseVal, &LVal)) return CompleteObject(); } else { const Expr *Base = LVal.Base.dyn_cast(); if (!Frame) { if (const MaterializeTemporaryExpr *MTE = dyn_cast(Base)) { assert(MTE->getStorageDuration() == SD_Static && "should have a frame for a non-global materialized temporary"); // Per C++1y [expr.const]p2: // an lvalue-to-rvalue conversion [is not allowed unless it applies to] // - a [...] glvalue of integral or enumeration type that refers to // a non-volatile const object [...] // [...] // - a [...] glvalue of literal type that refers to a non-volatile // object whose lifetime began within the evaluation of e. // // C++11 misses the 'began within the evaluation of e' check and // instead allows all temporaries, including things like: // int &&r = 1; // int x = ++r; // constexpr int k = r; // Therefore we use the C++14 rules in C++11 too. const ValueDecl *VD = Info.EvaluatingDecl.dyn_cast(); const ValueDecl *ED = MTE->getExtendingDecl(); if (!(BaseType.isConstQualified() && BaseType->isIntegralOrEnumerationType()) && !(VD && VD->getCanonicalDecl() == ED->getCanonicalDecl())) { Info.FFDiag(E, diag::note_constexpr_access_static_temporary, 1) << AK; Info.Note(MTE->getExprLoc(), diag::note_constexpr_temporary_here); return CompleteObject(); } BaseVal = Info.Ctx.getMaterializedTemporaryValue(MTE, false); assert(BaseVal && "got reference to unevaluated temporary"); LifetimeStartedInEvaluation = true; } else { Info.FFDiag(E); return CompleteObject(); } } else { BaseVal = Frame->getTemporary(Base, LVal.Base.getVersion()); assert(BaseVal && "missing value for temporary"); } // Volatile temporary objects cannot be accessed in constant expressions. if (BaseType.isVolatileQualified()) { if (Info.getLangOpts().CPlusPlus) { Info.FFDiag(E, diag::note_constexpr_access_volatile_obj, 1) << AK << 0; Info.Note(Base->getExprLoc(), diag::note_constexpr_temporary_here); } else { Info.FFDiag(E); } return CompleteObject(); } } // During the construction of an object, it is not yet 'const'. // FIXME: This doesn't do quite the right thing for const subobjects of the // object under construction. if (Info.isEvaluatingConstructor(LVal.getLValueBase(), LVal.getLValueCallIndex(), LVal.getLValueVersion())) { BaseType = Info.Ctx.getCanonicalType(BaseType); BaseType.removeLocalConst(); LifetimeStartedInEvaluation = true; } // In C++14, we can't safely access any mutable state when we might be // evaluating after an unmodeled side effect. // // FIXME: Not all local state is mutable. Allow local constant subobjects // to be read here (but take care with 'mutable' fields). if ((Frame && Info.getLangOpts().CPlusPlus14 && Info.EvalStatus.HasSideEffects) || (AK != AK_Read && Info.IsSpeculativelyEvaluating)) return CompleteObject(); return CompleteObject(BaseVal, BaseType, LifetimeStartedInEvaluation); } /// Perform an lvalue-to-rvalue conversion on the given glvalue. This /// can also be used for 'lvalue-to-lvalue' conversions for looking up the /// glvalue referred to by an entity of reference type. /// /// \param Info - Information about the ongoing evaluation. /// \param Conv - The expression for which we are performing the conversion. /// Used for diagnostics. /// \param Type - The type of the glvalue (before stripping cv-qualifiers in the /// case of a non-class type). /// \param LVal - The glvalue on which we are attempting to perform this action. /// \param RVal - The produced value will be placed here. static bool handleLValueToRValueConversion(EvalInfo &Info, const Expr *Conv, QualType Type, const LValue &LVal, APValue &RVal) { if (LVal.Designator.Invalid) return false; // Check for special cases where there is no existing APValue to look at. const Expr *Base = LVal.Base.dyn_cast(); if (Base && !LVal.getLValueCallIndex() && !Type.isVolatileQualified()) { if (const CompoundLiteralExpr *CLE = dyn_cast(Base)) { // In C99, a CompoundLiteralExpr is an lvalue, and we defer evaluating the // initializer until now for such expressions. Such an expression can't be // an ICE in C, so this only matters for fold. if (Type.isVolatileQualified()) { Info.FFDiag(Conv); return false; } APValue Lit; if (!Evaluate(Lit, Info, CLE->getInitializer())) return false; CompleteObject LitObj(&Lit, Base->getType(), false); return extractSubobject(Info, Conv, LitObj, LVal.Designator, RVal); } else if (isa(Base) || isa(Base)) { // We represent a string literal array as an lvalue pointing at the // corresponding expression, rather than building an array of chars. // FIXME: Support ObjCEncodeExpr, MakeStringConstant APValue Str(Base, CharUnits::Zero(), APValue::NoLValuePath(), 0); CompleteObject StrObj(&Str, Base->getType(), false); return extractSubobject(Info, Conv, StrObj, LVal.Designator, RVal); } } CompleteObject Obj = findCompleteObject(Info, Conv, AK_Read, LVal, Type); return Obj && extractSubobject(Info, Conv, Obj, LVal.Designator, RVal); } /// Perform an assignment of Val to LVal. Takes ownership of Val. static bool handleAssignment(EvalInfo &Info, const Expr *E, const LValue &LVal, QualType LValType, APValue &Val) { if (LVal.Designator.Invalid) return false; if (!Info.getLangOpts().CPlusPlus14) { Info.FFDiag(E); return false; } CompleteObject Obj = findCompleteObject(Info, E, AK_Assign, LVal, LValType); return Obj && modifySubobject(Info, E, Obj, LVal.Designator, Val); } namespace { struct CompoundAssignSubobjectHandler { EvalInfo &Info; const Expr *E; QualType PromotedLHSType; BinaryOperatorKind Opcode; const APValue &RHS; static const AccessKinds AccessKind = AK_Assign; typedef bool result_type; bool checkConst(QualType QT) { // Assigning to a const object has undefined behavior. if (QT.isConstQualified()) { Info.FFDiag(E, diag::note_constexpr_modify_const_type) << QT; return false; } return true; } bool failed() { return false; } bool found(APValue &Subobj, QualType SubobjType) { switch (Subobj.getKind()) { case APValue::Int: return found(Subobj.getInt(), SubobjType); case APValue::Float: return found(Subobj.getFloat(), SubobjType); case APValue::ComplexInt: case APValue::ComplexFloat: // FIXME: Implement complex compound assignment. Info.FFDiag(E); return false; case APValue::LValue: return foundPointer(Subobj, SubobjType); default: // FIXME: can this happen? Info.FFDiag(E); return false; } } bool found(APSInt &Value, QualType SubobjType) { if (!checkConst(SubobjType)) return false; if (!SubobjType->isIntegerType() || !RHS.isInt()) { // We don't support compound assignment on integer-cast-to-pointer // values. Info.FFDiag(E); return false; } APSInt LHS = HandleIntToIntCast(Info, E, PromotedLHSType, SubobjType, Value); if (!handleIntIntBinOp(Info, E, LHS, Opcode, RHS.getInt(), LHS)) return false; Value = HandleIntToIntCast(Info, E, SubobjType, PromotedLHSType, LHS); return true; } bool found(APFloat &Value, QualType SubobjType) { return checkConst(SubobjType) && HandleFloatToFloatCast(Info, E, SubobjType, PromotedLHSType, Value) && handleFloatFloatBinOp(Info, E, Value, Opcode, RHS.getFloat()) && HandleFloatToFloatCast(Info, E, PromotedLHSType, SubobjType, Value); } bool foundPointer(APValue &Subobj, QualType SubobjType) { if (!checkConst(SubobjType)) return false; QualType PointeeType; if (const PointerType *PT = SubobjType->getAs()) PointeeType = PT->getPointeeType(); if (PointeeType.isNull() || !RHS.isInt() || (Opcode != BO_Add && Opcode != BO_Sub)) { Info.FFDiag(E); return false; } APSInt Offset = RHS.getInt(); if (Opcode == BO_Sub) negateAsSigned(Offset); LValue LVal; LVal.setFrom(Info.Ctx, Subobj); if (!HandleLValueArrayAdjustment(Info, E, LVal, PointeeType, Offset)) return false; LVal.moveInto(Subobj); return true; } bool foundString(APValue &Subobj, QualType SubobjType, uint64_t Character) { llvm_unreachable("shouldn't encounter string elements here"); } }; } // end anonymous namespace const AccessKinds CompoundAssignSubobjectHandler::AccessKind; /// Perform a compound assignment of LVal = RVal. static bool handleCompoundAssignment( EvalInfo &Info, const Expr *E, const LValue &LVal, QualType LValType, QualType PromotedLValType, BinaryOperatorKind Opcode, const APValue &RVal) { if (LVal.Designator.Invalid) return false; if (!Info.getLangOpts().CPlusPlus14) { Info.FFDiag(E); return false; } CompleteObject Obj = findCompleteObject(Info, E, AK_Assign, LVal, LValType); CompoundAssignSubobjectHandler Handler = { Info, E, PromotedLValType, Opcode, RVal }; return Obj && findSubobject(Info, E, Obj, LVal.Designator, Handler); } namespace { struct IncDecSubobjectHandler { EvalInfo &Info; const UnaryOperator *E; AccessKinds AccessKind; APValue *Old; typedef bool result_type; bool checkConst(QualType QT) { // Assigning to a const object has undefined behavior. if (QT.isConstQualified()) { Info.FFDiag(E, diag::note_constexpr_modify_const_type) << QT; return false; } return true; } bool failed() { return false; } bool found(APValue &Subobj, QualType SubobjType) { // Stash the old value. Also clear Old, so we don't clobber it later // if we're post-incrementing a complex. if (Old) { *Old = Subobj; Old = nullptr; } switch (Subobj.getKind()) { case APValue::Int: return found(Subobj.getInt(), SubobjType); case APValue::Float: return found(Subobj.getFloat(), SubobjType); case APValue::ComplexInt: return found(Subobj.getComplexIntReal(), SubobjType->castAs()->getElementType() .withCVRQualifiers(SubobjType.getCVRQualifiers())); case APValue::ComplexFloat: return found(Subobj.getComplexFloatReal(), SubobjType->castAs()->getElementType() .withCVRQualifiers(SubobjType.getCVRQualifiers())); case APValue::LValue: return foundPointer(Subobj, SubobjType); default: // FIXME: can this happen? Info.FFDiag(E); return false; } } bool found(APSInt &Value, QualType SubobjType) { if (!checkConst(SubobjType)) return false; if (!SubobjType->isIntegerType()) { // We don't support increment / decrement on integer-cast-to-pointer // values. Info.FFDiag(E); return false; } if (Old) *Old = APValue(Value); // bool arithmetic promotes to int, and the conversion back to bool // doesn't reduce mod 2^n, so special-case it. if (SubobjType->isBooleanType()) { if (AccessKind == AK_Increment) Value = 1; else Value = !Value; return true; } bool WasNegative = Value.isNegative(); if (AccessKind == AK_Increment) { ++Value; if (!WasNegative && Value.isNegative() && E->canOverflow()) { APSInt ActualValue(Value, /*IsUnsigned*/true); return HandleOverflow(Info, E, ActualValue, SubobjType); } } else { --Value; if (WasNegative && !Value.isNegative() && E->canOverflow()) { unsigned BitWidth = Value.getBitWidth(); APSInt ActualValue(Value.sext(BitWidth + 1), /*IsUnsigned*/false); ActualValue.setBit(BitWidth); return HandleOverflow(Info, E, ActualValue, SubobjType); } } return true; } bool found(APFloat &Value, QualType SubobjType) { if (!checkConst(SubobjType)) return false; if (Old) *Old = APValue(Value); APFloat One(Value.getSemantics(), 1); if (AccessKind == AK_Increment) Value.add(One, APFloat::rmNearestTiesToEven); else Value.subtract(One, APFloat::rmNearestTiesToEven); return true; } bool foundPointer(APValue &Subobj, QualType SubobjType) { if (!checkConst(SubobjType)) return false; QualType PointeeType; if (const PointerType *PT = SubobjType->getAs()) PointeeType = PT->getPointeeType(); else { Info.FFDiag(E); return false; } LValue LVal; LVal.setFrom(Info.Ctx, Subobj); if (!HandleLValueArrayAdjustment(Info, E, LVal, PointeeType, AccessKind == AK_Increment ? 1 : -1)) return false; LVal.moveInto(Subobj); return true; } bool foundString(APValue &Subobj, QualType SubobjType, uint64_t Character) { llvm_unreachable("shouldn't encounter string elements here"); } }; } // end anonymous namespace /// Perform an increment or decrement on LVal. static bool handleIncDec(EvalInfo &Info, const Expr *E, const LValue &LVal, QualType LValType, bool IsIncrement, APValue *Old) { if (LVal.Designator.Invalid) return false; if (!Info.getLangOpts().CPlusPlus14) { Info.FFDiag(E); return false; } AccessKinds AK = IsIncrement ? AK_Increment : AK_Decrement; CompleteObject Obj = findCompleteObject(Info, E, AK, LVal, LValType); IncDecSubobjectHandler Handler = {Info, cast(E), AK, Old}; return Obj && findSubobject(Info, E, Obj, LVal.Designator, Handler); } /// Build an lvalue for the object argument of a member function call. static bool EvaluateObjectArgument(EvalInfo &Info, const Expr *Object, LValue &This) { if (Object->getType()->isPointerType()) return EvaluatePointer(Object, This, Info); if (Object->isGLValue()) return EvaluateLValue(Object, This, Info); if (Object->getType()->isLiteralType(Info.Ctx)) return EvaluateTemporary(Object, This, Info); Info.FFDiag(Object, diag::note_constexpr_nonliteral) << Object->getType(); return false; } /// HandleMemberPointerAccess - Evaluate a member access operation and build an /// lvalue referring to the result. /// /// \param Info - Information about the ongoing evaluation. /// \param LV - An lvalue referring to the base of the member pointer. /// \param RHS - The member pointer expression. /// \param IncludeMember - Specifies whether the member itself is included in /// the resulting LValue subobject designator. This is not possible when /// creating a bound member function. /// \return The field or method declaration to which the member pointer refers, /// or 0 if evaluation fails. static const ValueDecl *HandleMemberPointerAccess(EvalInfo &Info, QualType LVType, LValue &LV, const Expr *RHS, bool IncludeMember = true) { MemberPtr MemPtr; if (!EvaluateMemberPointer(RHS, MemPtr, Info)) return nullptr; // C++11 [expr.mptr.oper]p6: If the second operand is the null pointer to // member value, the behavior is undefined. if (!MemPtr.getDecl()) { // FIXME: Specific diagnostic. Info.FFDiag(RHS); return nullptr; } if (MemPtr.isDerivedMember()) { // This is a member of some derived class. Truncate LV appropriately. // The end of the derived-to-base path for the base object must match the // derived-to-base path for the member pointer. if (LV.Designator.MostDerivedPathLength + MemPtr.Path.size() > LV.Designator.Entries.size()) { Info.FFDiag(RHS); return nullptr; } unsigned PathLengthToMember = LV.Designator.Entries.size() - MemPtr.Path.size(); for (unsigned I = 0, N = MemPtr.Path.size(); I != N; ++I) { const CXXRecordDecl *LVDecl = getAsBaseClass( LV.Designator.Entries[PathLengthToMember + I]); const CXXRecordDecl *MPDecl = MemPtr.Path[I]; if (LVDecl->getCanonicalDecl() != MPDecl->getCanonicalDecl()) { Info.FFDiag(RHS); return nullptr; } } // Truncate the lvalue to the appropriate derived class. if (!CastToDerivedClass(Info, RHS, LV, MemPtr.getContainingRecord(), PathLengthToMember)) return nullptr; } else if (!MemPtr.Path.empty()) { // Extend the LValue path with the member pointer's path. LV.Designator.Entries.reserve(LV.Designator.Entries.size() + MemPtr.Path.size() + IncludeMember); // Walk down to the appropriate base class. if (const PointerType *PT = LVType->getAs()) LVType = PT->getPointeeType(); const CXXRecordDecl *RD = LVType->getAsCXXRecordDecl(); assert(RD && "member pointer access on non-class-type expression"); // The first class in the path is that of the lvalue. for (unsigned I = 1, N = MemPtr.Path.size(); I != N; ++I) { const CXXRecordDecl *Base = MemPtr.Path[N - I - 1]; if (!HandleLValueDirectBase(Info, RHS, LV, RD, Base)) return nullptr; RD = Base; } // Finally cast to the class containing the member. if (!HandleLValueDirectBase(Info, RHS, LV, RD, MemPtr.getContainingRecord())) return nullptr; } // Add the member. Note that we cannot build bound member functions here. if (IncludeMember) { if (const FieldDecl *FD = dyn_cast(MemPtr.getDecl())) { if (!HandleLValueMember(Info, RHS, LV, FD)) return nullptr; } else if (const IndirectFieldDecl *IFD = dyn_cast(MemPtr.getDecl())) { if (!HandleLValueIndirectMember(Info, RHS, LV, IFD)) return nullptr; } else { llvm_unreachable("can't construct reference to bound member function"); } } return MemPtr.getDecl(); } static const ValueDecl *HandleMemberPointerAccess(EvalInfo &Info, const BinaryOperator *BO, LValue &LV, bool IncludeMember = true) { assert(BO->getOpcode() == BO_PtrMemD || BO->getOpcode() == BO_PtrMemI); if (!EvaluateObjectArgument(Info, BO->getLHS(), LV)) { if (Info.noteFailure()) { MemberPtr MemPtr; EvaluateMemberPointer(BO->getRHS(), MemPtr, Info); } return nullptr; } return HandleMemberPointerAccess(Info, BO->getLHS()->getType(), LV, BO->getRHS(), IncludeMember); } /// HandleBaseToDerivedCast - Apply the given base-to-derived cast operation on /// the provided lvalue, which currently refers to the base object. static bool HandleBaseToDerivedCast(EvalInfo &Info, const CastExpr *E, LValue &Result) { SubobjectDesignator &D = Result.Designator; if (D.Invalid || !Result.checkNullPointer(Info, E, CSK_Derived)) return false; QualType TargetQT = E->getType(); if (const PointerType *PT = TargetQT->getAs()) TargetQT = PT->getPointeeType(); // Check this cast lands within the final derived-to-base subobject path. if (D.MostDerivedPathLength + E->path_size() > D.Entries.size()) { Info.CCEDiag(E, diag::note_constexpr_invalid_downcast) << D.MostDerivedType << TargetQT; return false; } // Check the type of the final cast. We don't need to check the path, // since a cast can only be formed if the path is unique. unsigned NewEntriesSize = D.Entries.size() - E->path_size(); const CXXRecordDecl *TargetType = TargetQT->getAsCXXRecordDecl(); const CXXRecordDecl *FinalType; if (NewEntriesSize == D.MostDerivedPathLength) FinalType = D.MostDerivedType->getAsCXXRecordDecl(); else FinalType = getAsBaseClass(D.Entries[NewEntriesSize - 1]); if (FinalType->getCanonicalDecl() != TargetType->getCanonicalDecl()) { Info.CCEDiag(E, diag::note_constexpr_invalid_downcast) << D.MostDerivedType << TargetQT; return false; } // Truncate the lvalue to the appropriate derived class. return CastToDerivedClass(Info, E, Result, TargetType, NewEntriesSize); } namespace { enum EvalStmtResult { /// Evaluation failed. ESR_Failed, /// Hit a 'return' statement. ESR_Returned, /// Evaluation succeeded. ESR_Succeeded, /// Hit a 'continue' statement. ESR_Continue, /// Hit a 'break' statement. ESR_Break, /// Still scanning for 'case' or 'default' statement. ESR_CaseNotFound }; } static bool EvaluateVarDecl(EvalInfo &Info, const VarDecl *VD) { // We don't need to evaluate the initializer for a static local. if (!VD->hasLocalStorage()) return true; LValue Result; APValue &Val = createTemporary(VD, true, Result, *Info.CurrentCall); const Expr *InitE = VD->getInit(); if (!InitE) { Info.FFDiag(VD->getLocStart(), diag::note_constexpr_uninitialized) << false << VD->getType(); Val = APValue(); return false; } if (InitE->isValueDependent()) return false; if (!EvaluateInPlace(Val, Info, Result, InitE)) { // Wipe out any partially-computed value, to allow tracking that this // evaluation failed. Val = APValue(); return false; } return true; } static bool EvaluateDecl(EvalInfo &Info, const Decl *D) { bool OK = true; if (const VarDecl *VD = dyn_cast(D)) OK &= EvaluateVarDecl(Info, VD); if (const DecompositionDecl *DD = dyn_cast(D)) for (auto *BD : DD->bindings()) if (auto *VD = BD->getHoldingVar()) OK &= EvaluateDecl(Info, VD); return OK; } /// Evaluate a condition (either a variable declaration or an expression). static bool EvaluateCond(EvalInfo &Info, const VarDecl *CondDecl, const Expr *Cond, bool &Result) { FullExpressionRAII Scope(Info); if (CondDecl && !EvaluateDecl(Info, CondDecl)) return false; return EvaluateAsBooleanCondition(Cond, Result, Info); } namespace { /// A location where the result (returned value) of evaluating a /// statement should be stored. struct StmtResult { /// The APValue that should be filled in with the returned value. APValue &Value; /// The location containing the result, if any (used to support RVO). const LValue *Slot; }; struct TempVersionRAII { CallStackFrame &Frame; TempVersionRAII(CallStackFrame &Frame) : Frame(Frame) { Frame.pushTempVersion(); } ~TempVersionRAII() { Frame.popTempVersion(); } }; } static EvalStmtResult EvaluateStmt(StmtResult &Result, EvalInfo &Info, const Stmt *S, const SwitchCase *SC = nullptr); /// Evaluate the body of a loop, and translate the result as appropriate. static EvalStmtResult EvaluateLoopBody(StmtResult &Result, EvalInfo &Info, const Stmt *Body, const SwitchCase *Case = nullptr) { BlockScopeRAII Scope(Info); switch (EvalStmtResult ESR = EvaluateStmt(Result, Info, Body, Case)) { case ESR_Break: return ESR_Succeeded; case ESR_Succeeded: case ESR_Continue: return ESR_Continue; case ESR_Failed: case ESR_Returned: case ESR_CaseNotFound: return ESR; } llvm_unreachable("Invalid EvalStmtResult!"); } /// Evaluate a switch statement. static EvalStmtResult EvaluateSwitch(StmtResult &Result, EvalInfo &Info, const SwitchStmt *SS) { BlockScopeRAII Scope(Info); // Evaluate the switch condition. APSInt Value; { FullExpressionRAII Scope(Info); if (const Stmt *Init = SS->getInit()) { EvalStmtResult ESR = EvaluateStmt(Result, Info, Init); if (ESR != ESR_Succeeded) return ESR; } if (SS->getConditionVariable() && !EvaluateDecl(Info, SS->getConditionVariable())) return ESR_Failed; if (!EvaluateInteger(SS->getCond(), Value, Info)) return ESR_Failed; } // Find the switch case corresponding to the value of the condition. // FIXME: Cache this lookup. const SwitchCase *Found = nullptr; for (const SwitchCase *SC = SS->getSwitchCaseList(); SC; SC = SC->getNextSwitchCase()) { if (isa(SC)) { Found = SC; continue; } const CaseStmt *CS = cast(SC); APSInt LHS = CS->getLHS()->EvaluateKnownConstInt(Info.Ctx); APSInt RHS = CS->getRHS() ? CS->getRHS()->EvaluateKnownConstInt(Info.Ctx) : LHS; if (LHS <= Value && Value <= RHS) { Found = SC; break; } } if (!Found) return ESR_Succeeded; // Search the switch body for the switch case and evaluate it from there. switch (EvalStmtResult ESR = EvaluateStmt(Result, Info, SS->getBody(), Found)) { case ESR_Break: return ESR_Succeeded; case ESR_Succeeded: case ESR_Continue: case ESR_Failed: case ESR_Returned: return ESR; case ESR_CaseNotFound: // This can only happen if the switch case is nested within a statement // expression. We have no intention of supporting that. Info.FFDiag(Found->getLocStart(), diag::note_constexpr_stmt_expr_unsupported); return ESR_Failed; } llvm_unreachable("Invalid EvalStmtResult!"); } // Evaluate a statement. static EvalStmtResult EvaluateStmt(StmtResult &Result, EvalInfo &Info, const Stmt *S, const SwitchCase *Case) { if (!Info.nextStep(S)) return ESR_Failed; // If we're hunting down a 'case' or 'default' label, recurse through // substatements until we hit the label. if (Case) { // FIXME: We don't start the lifetime of objects whose initialization we // jump over. However, such objects must be of class type with a trivial // default constructor that initialize all subobjects, so must be empty, // so this almost never matters. switch (S->getStmtClass()) { case Stmt::CompoundStmtClass: // FIXME: Precompute which substatement of a compound statement we // would jump to, and go straight there rather than performing a // linear scan each time. case Stmt::LabelStmtClass: case Stmt::AttributedStmtClass: case Stmt::DoStmtClass: break; case Stmt::CaseStmtClass: case Stmt::DefaultStmtClass: if (Case == S) Case = nullptr; break; case Stmt::IfStmtClass: { // FIXME: Precompute which side of an 'if' we would jump to, and go // straight there rather than scanning both sides. const IfStmt *IS = cast(S); // Wrap the evaluation in a block scope, in case it's a DeclStmt // preceded by our switch label. BlockScopeRAII Scope(Info); EvalStmtResult ESR = EvaluateStmt(Result, Info, IS->getThen(), Case); if (ESR != ESR_CaseNotFound || !IS->getElse()) return ESR; return EvaluateStmt(Result, Info, IS->getElse(), Case); } case Stmt::WhileStmtClass: { EvalStmtResult ESR = EvaluateLoopBody(Result, Info, cast(S)->getBody(), Case); if (ESR != ESR_Continue) return ESR; break; } case Stmt::ForStmtClass: { const ForStmt *FS = cast(S); EvalStmtResult ESR = EvaluateLoopBody(Result, Info, FS->getBody(), Case); if (ESR != ESR_Continue) return ESR; if (FS->getInc()) { FullExpressionRAII IncScope(Info); if (!EvaluateIgnoredValue(Info, FS->getInc())) return ESR_Failed; } break; } case Stmt::DeclStmtClass: // FIXME: If the variable has initialization that can't be jumped over, // bail out of any immediately-surrounding compound-statement too. default: return ESR_CaseNotFound; } } switch (S->getStmtClass()) { default: if (const Expr *E = dyn_cast(S)) { // Don't bother evaluating beyond an expression-statement which couldn't // be evaluated. FullExpressionRAII Scope(Info); if (!EvaluateIgnoredValue(Info, E)) return ESR_Failed; return ESR_Succeeded; } Info.FFDiag(S->getLocStart()); return ESR_Failed; case Stmt::NullStmtClass: return ESR_Succeeded; case Stmt::DeclStmtClass: { const DeclStmt *DS = cast(S); for (const auto *DclIt : DS->decls()) { // Each declaration initialization is its own full-expression. // FIXME: This isn't quite right; if we're performing aggregate // initialization, each braced subexpression is its own full-expression. FullExpressionRAII Scope(Info); if (!EvaluateDecl(Info, DclIt) && !Info.noteFailure()) return ESR_Failed; } return ESR_Succeeded; } case Stmt::ReturnStmtClass: { const Expr *RetExpr = cast(S)->getRetValue(); FullExpressionRAII Scope(Info); if (RetExpr && !(Result.Slot ? EvaluateInPlace(Result.Value, Info, *Result.Slot, RetExpr) : Evaluate(Result.Value, Info, RetExpr))) return ESR_Failed; return ESR_Returned; } case Stmt::CompoundStmtClass: { BlockScopeRAII Scope(Info); const CompoundStmt *CS = cast(S); for (const auto *BI : CS->body()) { EvalStmtResult ESR = EvaluateStmt(Result, Info, BI, Case); if (ESR == ESR_Succeeded) Case = nullptr; else if (ESR != ESR_CaseNotFound) return ESR; } return Case ? ESR_CaseNotFound : ESR_Succeeded; } case Stmt::IfStmtClass: { const IfStmt *IS = cast(S); // Evaluate the condition, as either a var decl or as an expression. BlockScopeRAII Scope(Info); if (const Stmt *Init = IS->getInit()) { EvalStmtResult ESR = EvaluateStmt(Result, Info, Init); if (ESR != ESR_Succeeded) return ESR; } bool Cond; if (!EvaluateCond(Info, IS->getConditionVariable(), IS->getCond(), Cond)) return ESR_Failed; if (const Stmt *SubStmt = Cond ? IS->getThen() : IS->getElse()) { EvalStmtResult ESR = EvaluateStmt(Result, Info, SubStmt); if (ESR != ESR_Succeeded) return ESR; } return ESR_Succeeded; } case Stmt::WhileStmtClass: { const WhileStmt *WS = cast(S); while (true) { BlockScopeRAII Scope(Info); bool Continue; if (!EvaluateCond(Info, WS->getConditionVariable(), WS->getCond(), Continue)) return ESR_Failed; if (!Continue) break; EvalStmtResult ESR = EvaluateLoopBody(Result, Info, WS->getBody()); if (ESR != ESR_Continue) return ESR; } return ESR_Succeeded; } case Stmt::DoStmtClass: { const DoStmt *DS = cast(S); bool Continue; do { EvalStmtResult ESR = EvaluateLoopBody(Result, Info, DS->getBody(), Case); if (ESR != ESR_Continue) return ESR; Case = nullptr; FullExpressionRAII CondScope(Info); if (!EvaluateAsBooleanCondition(DS->getCond(), Continue, Info)) return ESR_Failed; } while (Continue); return ESR_Succeeded; } case Stmt::ForStmtClass: { const ForStmt *FS = cast(S); BlockScopeRAII Scope(Info); if (FS->getInit()) { EvalStmtResult ESR = EvaluateStmt(Result, Info, FS->getInit()); if (ESR != ESR_Succeeded) return ESR; } while (true) { BlockScopeRAII Scope(Info); bool Continue = true; if (FS->getCond() && !EvaluateCond(Info, FS->getConditionVariable(), FS->getCond(), Continue)) return ESR_Failed; if (!Continue) break; EvalStmtResult ESR = EvaluateLoopBody(Result, Info, FS->getBody()); if (ESR != ESR_Continue) return ESR; if (FS->getInc()) { FullExpressionRAII IncScope(Info); if (!EvaluateIgnoredValue(Info, FS->getInc())) return ESR_Failed; } } return ESR_Succeeded; } case Stmt::CXXForRangeStmtClass: { const CXXForRangeStmt *FS = cast(S); BlockScopeRAII Scope(Info); // Initialize the __range variable. EvalStmtResult ESR = EvaluateStmt(Result, Info, FS->getRangeStmt()); if (ESR != ESR_Succeeded) return ESR; // Create the __begin and __end iterators. ESR = EvaluateStmt(Result, Info, FS->getBeginStmt()); if (ESR != ESR_Succeeded) return ESR; ESR = EvaluateStmt(Result, Info, FS->getEndStmt()); if (ESR != ESR_Succeeded) return ESR; while (true) { // Condition: __begin != __end. { bool Continue = true; FullExpressionRAII CondExpr(Info); if (!EvaluateAsBooleanCondition(FS->getCond(), Continue, Info)) return ESR_Failed; if (!Continue) break; } // User's variable declaration, initialized by *__begin. BlockScopeRAII InnerScope(Info); ESR = EvaluateStmt(Result, Info, FS->getLoopVarStmt()); if (ESR != ESR_Succeeded) return ESR; // Loop body. ESR = EvaluateLoopBody(Result, Info, FS->getBody()); if (ESR != ESR_Continue) return ESR; // Increment: ++__begin if (!EvaluateIgnoredValue(Info, FS->getInc())) return ESR_Failed; } return ESR_Succeeded; } case Stmt::SwitchStmtClass: return EvaluateSwitch(Result, Info, cast(S)); case Stmt::ContinueStmtClass: return ESR_Continue; case Stmt::BreakStmtClass: return ESR_Break; case Stmt::LabelStmtClass: return EvaluateStmt(Result, Info, cast(S)->getSubStmt(), Case); case Stmt::AttributedStmtClass: // As a general principle, C++11 attributes can be ignored without // any semantic impact. return EvaluateStmt(Result, Info, cast(S)->getSubStmt(), Case); case Stmt::CaseStmtClass: case Stmt::DefaultStmtClass: return EvaluateStmt(Result, Info, cast(S)->getSubStmt(), Case); } } /// CheckTrivialDefaultConstructor - Check whether a constructor is a trivial /// default constructor. If so, we'll fold it whether or not it's marked as /// constexpr. If it is marked as constexpr, we will never implicitly define it, /// so we need special handling. static bool CheckTrivialDefaultConstructor(EvalInfo &Info, SourceLocation Loc, const CXXConstructorDecl *CD, bool IsValueInitialization) { if (!CD->isTrivial() || !CD->isDefaultConstructor()) return false; // Value-initialization does not call a trivial default constructor, so such a // call is a core constant expression whether or not the constructor is // constexpr. if (!CD->isConstexpr() && !IsValueInitialization) { if (Info.getLangOpts().CPlusPlus11) { // FIXME: If DiagDecl is an implicitly-declared special member function, // we should be much more explicit about why it's not constexpr. Info.CCEDiag(Loc, diag::note_constexpr_invalid_function, 1) << /*IsConstexpr*/0 << /*IsConstructor*/1 << CD; Info.Note(CD->getLocation(), diag::note_declared_at); } else { Info.CCEDiag(Loc, diag::note_invalid_subexpr_in_const_expr); } } return true; } /// CheckConstexprFunction - Check that a function can be called in a constant /// expression. static bool CheckConstexprFunction(EvalInfo &Info, SourceLocation CallLoc, const FunctionDecl *Declaration, const FunctionDecl *Definition, const Stmt *Body) { // Potential constant expressions can contain calls to declared, but not yet // defined, constexpr functions. if (Info.checkingPotentialConstantExpression() && !Definition && Declaration->isConstexpr()) return false; // Bail out with no diagnostic if the function declaration itself is invalid. // We will have produced a relevant diagnostic while parsing it. if (Declaration->isInvalidDecl()) return false; // Can we evaluate this function call? if (Definition && Definition->isConstexpr() && !Definition->isInvalidDecl() && Body) return true; if (Info.getLangOpts().CPlusPlus11) { const FunctionDecl *DiagDecl = Definition ? Definition : Declaration; // If this function is not constexpr because it is an inherited // non-constexpr constructor, diagnose that directly. auto *CD = dyn_cast(DiagDecl); if (CD && CD->isInheritingConstructor()) { auto *Inherited = CD->getInheritedConstructor().getConstructor(); if (!Inherited->isConstexpr()) DiagDecl = CD = Inherited; } // FIXME: If DiagDecl is an implicitly-declared special member function // or an inheriting constructor, we should be much more explicit about why // it's not constexpr. if (CD && CD->isInheritingConstructor()) Info.FFDiag(CallLoc, diag::note_constexpr_invalid_inhctor, 1) << CD->getInheritedConstructor().getConstructor()->getParent(); else Info.FFDiag(CallLoc, diag::note_constexpr_invalid_function, 1) << DiagDecl->isConstexpr() << (bool)CD << DiagDecl; Info.Note(DiagDecl->getLocation(), diag::note_declared_at); } else { Info.FFDiag(CallLoc, diag::note_invalid_subexpr_in_const_expr); } return false; } /// Determine if a class has any fields that might need to be copied by a /// trivial copy or move operation. static bool hasFields(const CXXRecordDecl *RD) { if (!RD || RD->isEmpty()) return false; for (auto *FD : RD->fields()) { if (FD->isUnnamedBitfield()) continue; return true; } for (auto &Base : RD->bases()) if (hasFields(Base.getType()->getAsCXXRecordDecl())) return true; return false; } namespace { typedef SmallVector ArgVector; } /// EvaluateArgs - Evaluate the arguments to a function call. static bool EvaluateArgs(ArrayRef Args, ArgVector &ArgValues, EvalInfo &Info) { bool Success = true; for (ArrayRef::iterator I = Args.begin(), E = Args.end(); I != E; ++I) { if (!Evaluate(ArgValues[I - Args.begin()], Info, *I)) { // If we're checking for a potential constant expression, evaluate all // initializers even if some of them fail. if (!Info.noteFailure()) return false; Success = false; } } return Success; } /// Evaluate a function call. static bool HandleFunctionCall(SourceLocation CallLoc, const FunctionDecl *Callee, const LValue *This, ArrayRef Args, const Stmt *Body, EvalInfo &Info, APValue &Result, const LValue *ResultSlot) { ArgVector ArgValues(Args.size()); if (!EvaluateArgs(Args, ArgValues, Info)) return false; if (!Info.CheckCallLimit(CallLoc)) return false; CallStackFrame Frame(Info, CallLoc, Callee, This, ArgValues.data()); // For a trivial copy or move assignment, perform an APValue copy. This is // essential for unions, where the operations performed by the assignment // operator cannot be represented as statements. // // Skip this for non-union classes with no fields; in that case, the defaulted // copy/move does not actually read the object. const CXXMethodDecl *MD = dyn_cast(Callee); if (MD && MD->isDefaulted() && (MD->getParent()->isUnion() || (MD->isTrivial() && hasFields(MD->getParent())))) { assert(This && (MD->isCopyAssignmentOperator() || MD->isMoveAssignmentOperator())); LValue RHS; RHS.setFrom(Info.Ctx, ArgValues[0]); APValue RHSValue; if (!handleLValueToRValueConversion(Info, Args[0], Args[0]->getType(), RHS, RHSValue)) return false; if (!handleAssignment(Info, Args[0], *This, MD->getThisType(Info.Ctx), RHSValue)) return false; This->moveInto(Result); return true; } else if (MD && isLambdaCallOperator(MD)) { // We're in a lambda; determine the lambda capture field maps unless we're // just constexpr checking a lambda's call operator. constexpr checking is // done before the captures have been added to the closure object (unless // we're inferring constexpr-ness), so we don't have access to them in this // case. But since we don't need the captures to constexpr check, we can // just ignore them. if (!Info.checkingPotentialConstantExpression()) MD->getParent()->getCaptureFields(Frame.LambdaCaptureFields, Frame.LambdaThisCaptureField); } StmtResult Ret = {Result, ResultSlot}; EvalStmtResult ESR = EvaluateStmt(Ret, Info, Body); if (ESR == ESR_Succeeded) { if (Callee->getReturnType()->isVoidType()) return true; Info.FFDiag(Callee->getLocEnd(), diag::note_constexpr_no_return); } return ESR == ESR_Returned; } /// Evaluate a constructor call. static bool HandleConstructorCall(const Expr *E, const LValue &This, APValue *ArgValues, const CXXConstructorDecl *Definition, EvalInfo &Info, APValue &Result) { SourceLocation CallLoc = E->getExprLoc(); if (!Info.CheckCallLimit(CallLoc)) return false; const CXXRecordDecl *RD = Definition->getParent(); if (RD->getNumVBases()) { Info.FFDiag(CallLoc, diag::note_constexpr_virtual_base) << RD; return false; } EvalInfo::EvaluatingConstructorRAII EvalObj( Info, {This.getLValueBase(), {This.getLValueCallIndex(), This.getLValueVersion()}}); CallStackFrame Frame(Info, CallLoc, Definition, &This, ArgValues); // FIXME: Creating an APValue just to hold a nonexistent return value is // wasteful. APValue RetVal; StmtResult Ret = {RetVal, nullptr}; // If it's a delegating constructor, delegate. if (Definition->isDelegatingConstructor()) { CXXConstructorDecl::init_const_iterator I = Definition->init_begin(); { FullExpressionRAII InitScope(Info); if (!EvaluateInPlace(Result, Info, This, (*I)->getInit())) return false; } return EvaluateStmt(Ret, Info, Definition->getBody()) != ESR_Failed; } // For a trivial copy or move constructor, perform an APValue copy. This is // essential for unions (or classes with anonymous union members), where the // operations performed by the constructor cannot be represented by // ctor-initializers. // // Skip this for empty non-union classes; we should not perform an // lvalue-to-rvalue conversion on them because their copy constructor does not // actually read them. if (Definition->isDefaulted() && Definition->isCopyOrMoveConstructor() && (Definition->getParent()->isUnion() || (Definition->isTrivial() && hasFields(Definition->getParent())))) { LValue RHS; RHS.setFrom(Info.Ctx, ArgValues[0]); return handleLValueToRValueConversion( Info, E, Definition->getParamDecl(0)->getType().getNonReferenceType(), RHS, Result); } // Reserve space for the struct members. if (!RD->isUnion() && Result.isUninit()) Result = APValue(APValue::UninitStruct(), RD->getNumBases(), std::distance(RD->field_begin(), RD->field_end())); if (RD->isInvalidDecl()) return false; const ASTRecordLayout &Layout = Info.Ctx.getASTRecordLayout(RD); // A scope for temporaries lifetime-extended by reference members. BlockScopeRAII LifetimeExtendedScope(Info); bool Success = true; unsigned BasesSeen = 0; #ifndef NDEBUG CXXRecordDecl::base_class_const_iterator BaseIt = RD->bases_begin(); #endif for (const auto *I : Definition->inits()) { LValue Subobject = This; LValue SubobjectParent = This; APValue *Value = &Result; // Determine the subobject to initialize. FieldDecl *FD = nullptr; if (I->isBaseInitializer()) { QualType BaseType(I->getBaseClass(), 0); #ifndef NDEBUG // Non-virtual base classes are initialized in the order in the class // definition. We have already checked for virtual base classes. assert(!BaseIt->isVirtual() && "virtual base for literal type"); assert(Info.Ctx.hasSameType(BaseIt->getType(), BaseType) && "base class initializers not in expected order"); ++BaseIt; #endif if (!HandleLValueDirectBase(Info, I->getInit(), Subobject, RD, BaseType->getAsCXXRecordDecl(), &Layout)) return false; Value = &Result.getStructBase(BasesSeen++); } else if ((FD = I->getMember())) { if (!HandleLValueMember(Info, I->getInit(), Subobject, FD, &Layout)) return false; if (RD->isUnion()) { Result = APValue(FD); Value = &Result.getUnionValue(); } else { Value = &Result.getStructField(FD->getFieldIndex()); } } else if (IndirectFieldDecl *IFD = I->getIndirectMember()) { // Walk the indirect field decl's chain to find the object to initialize, // and make sure we've initialized every step along it. auto IndirectFieldChain = IFD->chain(); for (auto *C : IndirectFieldChain) { FD = cast(C); CXXRecordDecl *CD = cast(FD->getParent()); // Switch the union field if it differs. This happens if we had // preceding zero-initialization, and we're now initializing a union // subobject other than the first. // FIXME: In this case, the values of the other subobjects are // specified, since zero-initialization sets all padding bits to zero. if (Value->isUninit() || (Value->isUnion() && Value->getUnionField() != FD)) { if (CD->isUnion()) *Value = APValue(FD); else *Value = APValue(APValue::UninitStruct(), CD->getNumBases(), std::distance(CD->field_begin(), CD->field_end())); } // Store Subobject as its parent before updating it for the last element // in the chain. if (C == IndirectFieldChain.back()) SubobjectParent = Subobject; if (!HandleLValueMember(Info, I->getInit(), Subobject, FD)) return false; if (CD->isUnion()) Value = &Value->getUnionValue(); else Value = &Value->getStructField(FD->getFieldIndex()); } } else { llvm_unreachable("unknown base initializer kind"); } // Need to override This for implicit field initializers as in this case // This refers to innermost anonymous struct/union containing initializer, // not to currently constructed class. const Expr *Init = I->getInit(); ThisOverrideRAII ThisOverride(*Info.CurrentCall, &SubobjectParent, isa(Init)); FullExpressionRAII InitScope(Info); if (!EvaluateInPlace(*Value, Info, Subobject, Init) || (FD && FD->isBitField() && !truncateBitfieldValue(Info, Init, *Value, FD))) { // If we're checking for a potential constant expression, evaluate all // initializers even if some of them fail. if (!Info.noteFailure()) return false; Success = false; } } return Success && EvaluateStmt(Ret, Info, Definition->getBody()) != ESR_Failed; } static bool HandleConstructorCall(const Expr *E, const LValue &This, ArrayRef Args, const CXXConstructorDecl *Definition, EvalInfo &Info, APValue &Result) { ArgVector ArgValues(Args.size()); if (!EvaluateArgs(Args, ArgValues, Info)) return false; return HandleConstructorCall(E, This, ArgValues.data(), Definition, Info, Result); } //===----------------------------------------------------------------------===// // Generic Evaluation //===----------------------------------------------------------------------===// namespace { template class ExprEvaluatorBase : public ConstStmtVisitor { private: Derived &getDerived() { return static_cast(*this); } bool DerivedSuccess(const APValue &V, const Expr *E) { return getDerived().Success(V, E); } bool DerivedZeroInitialization(const Expr *E) { return getDerived().ZeroInitialization(E); } // Check whether a conditional operator with a non-constant condition is a // potential constant expression. If neither arm is a potential constant // expression, then the conditional operator is not either. template void CheckPotentialConstantConditional(const ConditionalOperator *E) { assert(Info.checkingPotentialConstantExpression()); // Speculatively evaluate both arms. SmallVector Diag; { SpeculativeEvaluationRAII Speculate(Info, &Diag); StmtVisitorTy::Visit(E->getFalseExpr()); if (Diag.empty()) return; } { SpeculativeEvaluationRAII Speculate(Info, &Diag); Diag.clear(); StmtVisitorTy::Visit(E->getTrueExpr()); if (Diag.empty()) return; } Error(E, diag::note_constexpr_conditional_never_const); } template bool HandleConditionalOperator(const ConditionalOperator *E) { bool BoolResult; if (!EvaluateAsBooleanCondition(E->getCond(), BoolResult, Info)) { if (Info.checkingPotentialConstantExpression() && Info.noteFailure()) { CheckPotentialConstantConditional(E); return false; } if (Info.noteFailure()) { StmtVisitorTy::Visit(E->getTrueExpr()); StmtVisitorTy::Visit(E->getFalseExpr()); } return false; } Expr *EvalExpr = BoolResult ? E->getTrueExpr() : E->getFalseExpr(); return StmtVisitorTy::Visit(EvalExpr); } protected: EvalInfo &Info; typedef ConstStmtVisitor StmtVisitorTy; typedef ExprEvaluatorBase ExprEvaluatorBaseTy; OptionalDiagnostic CCEDiag(const Expr *E, diag::kind D) { return Info.CCEDiag(E, D); } bool ZeroInitialization(const Expr *E) { return Error(E); } public: ExprEvaluatorBase(EvalInfo &Info) : Info(Info) {} EvalInfo &getEvalInfo() { return Info; } /// Report an evaluation error. This should only be called when an error is /// first discovered. When propagating an error, just return false. bool Error(const Expr *E, diag::kind D) { Info.FFDiag(E, D); return false; } bool Error(const Expr *E) { return Error(E, diag::note_invalid_subexpr_in_const_expr); } bool VisitStmt(const Stmt *) { llvm_unreachable("Expression evaluator should not be called on stmts"); } bool VisitExpr(const Expr *E) { return Error(E); } bool VisitParenExpr(const ParenExpr *E) { return StmtVisitorTy::Visit(E->getSubExpr()); } bool VisitUnaryExtension(const UnaryOperator *E) { return StmtVisitorTy::Visit(E->getSubExpr()); } bool VisitUnaryPlus(const UnaryOperator *E) { return StmtVisitorTy::Visit(E->getSubExpr()); } bool VisitChooseExpr(const ChooseExpr *E) { return StmtVisitorTy::Visit(E->getChosenSubExpr()); } bool VisitGenericSelectionExpr(const GenericSelectionExpr *E) { return StmtVisitorTy::Visit(E->getResultExpr()); } bool VisitSubstNonTypeTemplateParmExpr(const SubstNonTypeTemplateParmExpr *E) { return StmtVisitorTy::Visit(E->getReplacement()); } bool VisitCXXDefaultArgExpr(const CXXDefaultArgExpr *E) { TempVersionRAII RAII(*Info.CurrentCall); return StmtVisitorTy::Visit(E->getExpr()); } bool VisitCXXDefaultInitExpr(const CXXDefaultInitExpr *E) { TempVersionRAII RAII(*Info.CurrentCall); // The initializer may not have been parsed yet, or might be erroneous. if (!E->getExpr()) return Error(E); return StmtVisitorTy::Visit(E->getExpr()); } // We cannot create any objects for which cleanups are required, so there is // nothing to do here; all cleanups must come from unevaluated subexpressions. bool VisitExprWithCleanups(const ExprWithCleanups *E) { return StmtVisitorTy::Visit(E->getSubExpr()); } bool VisitCXXReinterpretCastExpr(const CXXReinterpretCastExpr *E) { CCEDiag(E, diag::note_constexpr_invalid_cast) << 0; return static_cast(this)->VisitCastExpr(E); } bool VisitCXXDynamicCastExpr(const CXXDynamicCastExpr *E) { CCEDiag(E, diag::note_constexpr_invalid_cast) << 1; return static_cast(this)->VisitCastExpr(E); } bool VisitBinaryOperator(const BinaryOperator *E) { switch (E->getOpcode()) { default: return Error(E); case BO_Comma: VisitIgnoredValue(E->getLHS()); return StmtVisitorTy::Visit(E->getRHS()); case BO_PtrMemD: case BO_PtrMemI: { LValue Obj; if (!HandleMemberPointerAccess(Info, E, Obj)) return false; APValue Result; if (!handleLValueToRValueConversion(Info, E, E->getType(), Obj, Result)) return false; return DerivedSuccess(Result, E); } } } bool VisitBinaryConditionalOperator(const BinaryConditionalOperator *E) { // Evaluate and cache the common expression. We treat it as a temporary, // even though it's not quite the same thing. if (!Evaluate(Info.CurrentCall->createTemporary(E->getOpaqueValue(), false), Info, E->getCommon())) return false; return HandleConditionalOperator(E); } bool VisitConditionalOperator(const ConditionalOperator *E) { bool IsBcpCall = false; // If the condition (ignoring parens) is a __builtin_constant_p call, // the result is a constant expression if it can be folded without // side-effects. This is an important GNU extension. See GCC PR38377 // for discussion. if (const CallExpr *CallCE = dyn_cast(E->getCond()->IgnoreParenCasts())) if (CallCE->getBuiltinCallee() == Builtin::BI__builtin_constant_p) IsBcpCall = true; // Always assume __builtin_constant_p(...) ? ... : ... is a potential // constant expression; we can't check whether it's potentially foldable. if (Info.checkingPotentialConstantExpression() && IsBcpCall) return false; FoldConstant Fold(Info, IsBcpCall); if (!HandleConditionalOperator(E)) { Fold.keepDiagnostics(); return false; } return true; } bool VisitOpaqueValueExpr(const OpaqueValueExpr *E) { if (APValue *Value = Info.CurrentCall->getCurrentTemporary(E)) return DerivedSuccess(*Value, E); const Expr *Source = E->getSourceExpr(); if (!Source) return Error(E); if (Source == E) { // sanity checking. assert(0 && "OpaqueValueExpr recursively refers to itself"); return Error(E); } return StmtVisitorTy::Visit(Source); } bool VisitCallExpr(const CallExpr *E) { APValue Result; if (!handleCallExpr(E, Result, nullptr)) return false; return DerivedSuccess(Result, E); } bool handleCallExpr(const CallExpr *E, APValue &Result, const LValue *ResultSlot) { const Expr *Callee = E->getCallee()->IgnoreParens(); QualType CalleeType = Callee->getType(); const FunctionDecl *FD = nullptr; LValue *This = nullptr, ThisVal; auto Args = llvm::makeArrayRef(E->getArgs(), E->getNumArgs()); bool HasQualifier = false; // Extract function decl and 'this' pointer from the callee. if (CalleeType->isSpecificBuiltinType(BuiltinType::BoundMember)) { const ValueDecl *Member = nullptr; if (const MemberExpr *ME = dyn_cast(Callee)) { // Explicit bound member calls, such as x.f() or p->g(); if (!EvaluateObjectArgument(Info, ME->getBase(), ThisVal)) return false; Member = ME->getMemberDecl(); This = &ThisVal; HasQualifier = ME->hasQualifier(); } else if (const BinaryOperator *BE = dyn_cast(Callee)) { // Indirect bound member calls ('.*' or '->*'). Member = HandleMemberPointerAccess(Info, BE, ThisVal, false); if (!Member) return false; This = &ThisVal; } else return Error(Callee); FD = dyn_cast(Member); if (!FD) return Error(Callee); } else if (CalleeType->isFunctionPointerType()) { LValue Call; if (!EvaluatePointer(Callee, Call, Info)) return false; if (!Call.getLValueOffset().isZero()) return Error(Callee); FD = dyn_cast_or_null( Call.getLValueBase().dyn_cast()); if (!FD) return Error(Callee); // Don't call function pointers which have been cast to some other type. // Per DR (no number yet), the caller and callee can differ in noexcept. if (!Info.Ctx.hasSameFunctionTypeIgnoringExceptionSpec( CalleeType->getPointeeType(), FD->getType())) { return Error(E); } // Overloaded operator calls to member functions are represented as normal // calls with '*this' as the first argument. const CXXMethodDecl *MD = dyn_cast(FD); if (MD && !MD->isStatic()) { // FIXME: When selecting an implicit conversion for an overloaded // operator delete, we sometimes try to evaluate calls to conversion // operators without a 'this' parameter! if (Args.empty()) return Error(E); if (!EvaluateObjectArgument(Info, Args[0], ThisVal)) return false; This = &ThisVal; Args = Args.slice(1); } else if (MD && MD->isLambdaStaticInvoker()) { // Map the static invoker for the lambda back to the call operator. // Conveniently, we don't have to slice out the 'this' argument (as is // being done for the non-static case), since a static member function // doesn't have an implicit argument passed in. const CXXRecordDecl *ClosureClass = MD->getParent(); assert( ClosureClass->captures_begin() == ClosureClass->captures_end() && "Number of captures must be zero for conversion to function-ptr"); const CXXMethodDecl *LambdaCallOp = ClosureClass->getLambdaCallOperator(); // Set 'FD', the function that will be called below, to the call // operator. If the closure object represents a generic lambda, find // the corresponding specialization of the call operator. if (ClosureClass->isGenericLambda()) { assert(MD->isFunctionTemplateSpecialization() && "A generic lambda's static-invoker function must be a " "template specialization"); const TemplateArgumentList *TAL = MD->getTemplateSpecializationArgs(); FunctionTemplateDecl *CallOpTemplate = LambdaCallOp->getDescribedFunctionTemplate(); void *InsertPos = nullptr; FunctionDecl *CorrespondingCallOpSpecialization = CallOpTemplate->findSpecialization(TAL->asArray(), InsertPos); assert(CorrespondingCallOpSpecialization && "We must always have a function call operator specialization " "that corresponds to our static invoker specialization"); FD = cast(CorrespondingCallOpSpecialization); } else FD = LambdaCallOp; } } else return Error(E); if (This && !This->checkSubobject(Info, E, CSK_This)) return false; // DR1358 allows virtual constexpr functions in some cases. Don't allow // calls to such functions in constant expressions. if (This && !HasQualifier && isa(FD) && cast(FD)->isVirtual()) return Error(E, diag::note_constexpr_virtual_call); const FunctionDecl *Definition = nullptr; Stmt *Body = FD->getBody(Definition); if (!CheckConstexprFunction(Info, E->getExprLoc(), FD, Definition, Body) || !HandleFunctionCall(E->getExprLoc(), Definition, This, Args, Body, Info, Result, ResultSlot)) return false; return true; } bool VisitCompoundLiteralExpr(const CompoundLiteralExpr *E) { return StmtVisitorTy::Visit(E->getInitializer()); } bool VisitInitListExpr(const InitListExpr *E) { if (E->getNumInits() == 0) return DerivedZeroInitialization(E); if (E->getNumInits() == 1) return StmtVisitorTy::Visit(E->getInit(0)); return Error(E); } bool VisitImplicitValueInitExpr(const ImplicitValueInitExpr *E) { return DerivedZeroInitialization(E); } bool VisitCXXScalarValueInitExpr(const CXXScalarValueInitExpr *E) { return DerivedZeroInitialization(E); } bool VisitCXXNullPtrLiteralExpr(const CXXNullPtrLiteralExpr *E) { return DerivedZeroInitialization(E); } /// A member expression where the object is a prvalue is itself a prvalue. bool VisitMemberExpr(const MemberExpr *E) { assert(!E->isArrow() && "missing call to bound member function?"); APValue Val; if (!Evaluate(Val, Info, E->getBase())) return false; QualType BaseTy = E->getBase()->getType(); const FieldDecl *FD = dyn_cast(E->getMemberDecl()); if (!FD) return Error(E); assert(!FD->getType()->isReferenceType() && "prvalue reference?"); assert(BaseTy->castAs()->getDecl()->getCanonicalDecl() == FD->getParent()->getCanonicalDecl() && "record / field mismatch"); CompleteObject Obj(&Val, BaseTy, true); SubobjectDesignator Designator(BaseTy); Designator.addDeclUnchecked(FD); APValue Result; return extractSubobject(Info, E, Obj, Designator, Result) && DerivedSuccess(Result, E); } bool VisitCastExpr(const CastExpr *E) { switch (E->getCastKind()) { default: break; case CK_AtomicToNonAtomic: { APValue AtomicVal; // This does not need to be done in place even for class/array types: // atomic-to-non-atomic conversion implies copying the object // representation. if (!Evaluate(AtomicVal, Info, E->getSubExpr())) return false; return DerivedSuccess(AtomicVal, E); } case CK_NoOp: case CK_UserDefinedConversion: return StmtVisitorTy::Visit(E->getSubExpr()); case CK_LValueToRValue: { LValue LVal; if (!EvaluateLValue(E->getSubExpr(), LVal, Info)) return false; APValue RVal; // Note, we use the subexpression's type in order to retain cv-qualifiers. if (!handleLValueToRValueConversion(Info, E, E->getSubExpr()->getType(), LVal, RVal)) return false; return DerivedSuccess(RVal, E); } } return Error(E); } bool VisitUnaryPostInc(const UnaryOperator *UO) { return VisitUnaryPostIncDec(UO); } bool VisitUnaryPostDec(const UnaryOperator *UO) { return VisitUnaryPostIncDec(UO); } bool VisitUnaryPostIncDec(const UnaryOperator *UO) { if (!Info.getLangOpts().CPlusPlus14 && !Info.keepEvaluatingAfterFailure()) return Error(UO); LValue LVal; if (!EvaluateLValue(UO->getSubExpr(), LVal, Info)) return false; APValue RVal; if (!handleIncDec(this->Info, UO, LVal, UO->getSubExpr()->getType(), UO->isIncrementOp(), &RVal)) return false; return DerivedSuccess(RVal, UO); } bool VisitStmtExpr(const StmtExpr *E) { // We will have checked the full-expressions inside the statement expression // when they were completed, and don't need to check them again now. if (Info.checkingForOverflow()) return Error(E); BlockScopeRAII Scope(Info); const CompoundStmt *CS = E->getSubStmt(); if (CS->body_empty()) return true; for (CompoundStmt::const_body_iterator BI = CS->body_begin(), BE = CS->body_end(); /**/; ++BI) { if (BI + 1 == BE) { const Expr *FinalExpr = dyn_cast(*BI); if (!FinalExpr) { Info.FFDiag((*BI)->getLocStart(), diag::note_constexpr_stmt_expr_unsupported); return false; } return this->Visit(FinalExpr); } APValue ReturnValue; StmtResult Result = { ReturnValue, nullptr }; EvalStmtResult ESR = EvaluateStmt(Result, Info, *BI); if (ESR != ESR_Succeeded) { // FIXME: If the statement-expression terminated due to 'return', // 'break', or 'continue', it would be nice to propagate that to // the outer statement evaluation rather than bailing out. if (ESR != ESR_Failed) Info.FFDiag((*BI)->getLocStart(), diag::note_constexpr_stmt_expr_unsupported); return false; } } llvm_unreachable("Return from function from the loop above."); } /// Visit a value which is evaluated, but whose value is ignored. void VisitIgnoredValue(const Expr *E) { EvaluateIgnoredValue(Info, E); } /// Potentially visit a MemberExpr's base expression. void VisitIgnoredBaseExpression(const Expr *E) { // While MSVC doesn't evaluate the base expression, it does diagnose the // presence of side-effecting behavior. if (Info.getLangOpts().MSVCCompat && !E->HasSideEffects(Info.Ctx)) return; VisitIgnoredValue(E); } }; } // namespace //===----------------------------------------------------------------------===// // Common base class for lvalue and temporary evaluation. //===----------------------------------------------------------------------===// namespace { template class LValueExprEvaluatorBase : public ExprEvaluatorBase { protected: LValue &Result; bool InvalidBaseOK; typedef LValueExprEvaluatorBase LValueExprEvaluatorBaseTy; typedef ExprEvaluatorBase ExprEvaluatorBaseTy; bool Success(APValue::LValueBase B) { Result.set(B); return true; } bool evaluatePointer(const Expr *E, LValue &Result) { return EvaluatePointer(E, Result, this->Info, InvalidBaseOK); } public: LValueExprEvaluatorBase(EvalInfo &Info, LValue &Result, bool InvalidBaseOK) : ExprEvaluatorBaseTy(Info), Result(Result), InvalidBaseOK(InvalidBaseOK) {} bool Success(const APValue &V, const Expr *E) { Result.setFrom(this->Info.Ctx, V); return true; } bool VisitMemberExpr(const MemberExpr *E) { // Handle non-static data members. QualType BaseTy; bool EvalOK; if (E->isArrow()) { EvalOK = evaluatePointer(E->getBase(), Result); BaseTy = E->getBase()->getType()->castAs()->getPointeeType(); } else if (E->getBase()->isRValue()) { assert(E->getBase()->getType()->isRecordType()); EvalOK = EvaluateTemporary(E->getBase(), Result, this->Info); BaseTy = E->getBase()->getType(); } else { EvalOK = this->Visit(E->getBase()); BaseTy = E->getBase()->getType(); } if (!EvalOK) { if (!InvalidBaseOK) return false; Result.setInvalid(E); return true; } const ValueDecl *MD = E->getMemberDecl(); if (const FieldDecl *FD = dyn_cast(E->getMemberDecl())) { assert(BaseTy->getAs()->getDecl()->getCanonicalDecl() == FD->getParent()->getCanonicalDecl() && "record / field mismatch"); (void)BaseTy; if (!HandleLValueMember(this->Info, E, Result, FD)) return false; } else if (const IndirectFieldDecl *IFD = dyn_cast(MD)) { if (!HandleLValueIndirectMember(this->Info, E, Result, IFD)) return false; } else return this->Error(E); if (MD->getType()->isReferenceType()) { APValue RefValue; if (!handleLValueToRValueConversion(this->Info, E, MD->getType(), Result, RefValue)) return false; return Success(RefValue, E); } return true; } bool VisitBinaryOperator(const BinaryOperator *E) { switch (E->getOpcode()) { default: return ExprEvaluatorBaseTy::VisitBinaryOperator(E); case BO_PtrMemD: case BO_PtrMemI: return HandleMemberPointerAccess(this->Info, E, Result); } } bool VisitCastExpr(const CastExpr *E) { switch (E->getCastKind()) { default: return ExprEvaluatorBaseTy::VisitCastExpr(E); case CK_DerivedToBase: case CK_UncheckedDerivedToBase: if (!this->Visit(E->getSubExpr())) return false; // Now figure out the necessary offset to add to the base LV to get from // the derived class to the base class. return HandleLValueBasePath(this->Info, E, E->getSubExpr()->getType(), Result); } } }; } //===----------------------------------------------------------------------===// // LValue Evaluation // // This is used for evaluating lvalues (in C and C++), xvalues (in C++11), // function designators (in C), decl references to void objects (in C), and // temporaries (if building with -Wno-address-of-temporary). // // LValue evaluation produces values comprising a base expression of one of the // following types: // - Declarations // * VarDecl // * FunctionDecl // - Literals // * CompoundLiteralExpr in C (and in global scope in C++) // * StringLiteral // * CXXTypeidExpr // * PredefinedExpr // * ObjCStringLiteralExpr // * ObjCEncodeExpr // * AddrLabelExpr // * BlockExpr // * CallExpr for a MakeStringConstant builtin // - Locals and temporaries // * MaterializeTemporaryExpr // * Any Expr, with a CallIndex indicating the function in which the temporary // was evaluated, for cases where the MaterializeTemporaryExpr is missing // from the AST (FIXME). // * A MaterializeTemporaryExpr that has static storage duration, with no // CallIndex, for a lifetime-extended temporary. // plus an offset in bytes. //===----------------------------------------------------------------------===// namespace { class LValueExprEvaluator : public LValueExprEvaluatorBase { public: LValueExprEvaluator(EvalInfo &Info, LValue &Result, bool InvalidBaseOK) : LValueExprEvaluatorBaseTy(Info, Result, InvalidBaseOK) {} bool VisitVarDecl(const Expr *E, const VarDecl *VD); bool VisitUnaryPreIncDec(const UnaryOperator *UO); bool VisitDeclRefExpr(const DeclRefExpr *E); bool VisitPredefinedExpr(const PredefinedExpr *E) { return Success(E); } bool VisitMaterializeTemporaryExpr(const MaterializeTemporaryExpr *E); bool VisitCompoundLiteralExpr(const CompoundLiteralExpr *E); bool VisitMemberExpr(const MemberExpr *E); bool VisitStringLiteral(const StringLiteral *E) { return Success(E); } bool VisitObjCEncodeExpr(const ObjCEncodeExpr *E) { return Success(E); } bool VisitCXXTypeidExpr(const CXXTypeidExpr *E); bool VisitCXXUuidofExpr(const CXXUuidofExpr *E); bool VisitArraySubscriptExpr(const ArraySubscriptExpr *E); bool VisitUnaryDeref(const UnaryOperator *E); bool VisitUnaryReal(const UnaryOperator *E); bool VisitUnaryImag(const UnaryOperator *E); bool VisitUnaryPreInc(const UnaryOperator *UO) { return VisitUnaryPreIncDec(UO); } bool VisitUnaryPreDec(const UnaryOperator *UO) { return VisitUnaryPreIncDec(UO); } bool VisitBinAssign(const BinaryOperator *BO); bool VisitCompoundAssignOperator(const CompoundAssignOperator *CAO); bool VisitCastExpr(const CastExpr *E) { switch (E->getCastKind()) { default: return LValueExprEvaluatorBaseTy::VisitCastExpr(E); case CK_LValueBitCast: this->CCEDiag(E, diag::note_constexpr_invalid_cast) << 2; if (!Visit(E->getSubExpr())) return false; Result.Designator.setInvalid(); return true; case CK_BaseToDerived: if (!Visit(E->getSubExpr())) return false; return HandleBaseToDerivedCast(Info, E, Result); } } }; } // end anonymous namespace /// Evaluate an expression as an lvalue. This can be legitimately called on /// expressions which are not glvalues, in three cases: /// * function designators in C, and /// * "extern void" objects /// * @selector() expressions in Objective-C static bool EvaluateLValue(const Expr *E, LValue &Result, EvalInfo &Info, bool InvalidBaseOK) { assert(E->isGLValue() || E->getType()->isFunctionType() || E->getType()->isVoidType() || isa(E)); return LValueExprEvaluator(Info, Result, InvalidBaseOK).Visit(E); } bool LValueExprEvaluator::VisitDeclRefExpr(const DeclRefExpr *E) { if (const FunctionDecl *FD = dyn_cast(E->getDecl())) return Success(FD); if (const VarDecl *VD = dyn_cast(E->getDecl())) return VisitVarDecl(E, VD); if (const BindingDecl *BD = dyn_cast(E->getDecl())) return Visit(BD->getBinding()); return Error(E); } bool LValueExprEvaluator::VisitVarDecl(const Expr *E, const VarDecl *VD) { // If we are within a lambda's call operator, check whether the 'VD' referred // to within 'E' actually represents a lambda-capture that maps to a // data-member/field within the closure object, and if so, evaluate to the // field or what the field refers to. if (Info.CurrentCall && isLambdaCallOperator(Info.CurrentCall->Callee) && isa(E) && cast(E)->refersToEnclosingVariableOrCapture()) { // We don't always have a complete capture-map when checking or inferring if // the function call operator meets the requirements of a constexpr function // - but we don't need to evaluate the captures to determine constexprness // (dcl.constexpr C++17). if (Info.checkingPotentialConstantExpression()) return false; if (auto *FD = Info.CurrentCall->LambdaCaptureFields.lookup(VD)) { // Start with 'Result' referring to the complete closure object... Result = *Info.CurrentCall->This; // ... then update it to refer to the field of the closure object // that represents the capture. if (!HandleLValueMember(Info, E, Result, FD)) return false; // And if the field is of reference type, update 'Result' to refer to what // the field refers to. if (FD->getType()->isReferenceType()) { APValue RVal; if (!handleLValueToRValueConversion(Info, E, FD->getType(), Result, RVal)) return false; Result.setFrom(Info.Ctx, RVal); } return true; } } CallStackFrame *Frame = nullptr; if (VD->hasLocalStorage() && Info.CurrentCall->Index > 1) { // Only if a local variable was declared in the function currently being // evaluated, do we expect to be able to find its value in the current // frame. (Otherwise it was likely declared in an enclosing context and // could either have a valid evaluatable value (for e.g. a constexpr // variable) or be ill-formed (and trigger an appropriate evaluation // diagnostic)). if (Info.CurrentCall->Callee && Info.CurrentCall->Callee->Equals(VD->getDeclContext())) { Frame = Info.CurrentCall; } } if (!VD->getType()->isReferenceType()) { if (Frame) { Result.set({VD, Frame->Index, Info.CurrentCall->getCurrentTemporaryVersion(VD)}); return true; } return Success(VD); } APValue *V; if (!evaluateVarDeclInit(Info, E, VD, Frame, V, nullptr)) return false; if (V->isUninit()) { if (!Info.checkingPotentialConstantExpression()) Info.FFDiag(E, diag::note_constexpr_use_uninit_reference); return false; } return Success(*V, E); } bool LValueExprEvaluator::VisitMaterializeTemporaryExpr( const MaterializeTemporaryExpr *E) { // Walk through the expression to find the materialized temporary itself. SmallVector CommaLHSs; SmallVector Adjustments; const Expr *Inner = E->GetTemporaryExpr()-> skipRValueSubobjectAdjustments(CommaLHSs, Adjustments); // If we passed any comma operators, evaluate their LHSs. for (unsigned I = 0, N = CommaLHSs.size(); I != N; ++I) if (!EvaluateIgnoredValue(Info, CommaLHSs[I])) return false; // A materialized temporary with static storage duration can appear within the // result of a constant expression evaluation, so we need to preserve its // value for use outside this evaluation. APValue *Value; if (E->getStorageDuration() == SD_Static) { Value = Info.Ctx.getMaterializedTemporaryValue(E, true); *Value = APValue(); Result.set(E); } else { Value = &createTemporary(E, E->getStorageDuration() == SD_Automatic, Result, *Info.CurrentCall); } QualType Type = Inner->getType(); // Materialize the temporary itself. if (!EvaluateInPlace(*Value, Info, Result, Inner) || (E->getStorageDuration() == SD_Static && !CheckConstantExpression(Info, E->getExprLoc(), Type, *Value))) { *Value = APValue(); return false; } // Adjust our lvalue to refer to the desired subobject. for (unsigned I = Adjustments.size(); I != 0; /**/) { --I; switch (Adjustments[I].Kind) { case SubobjectAdjustment::DerivedToBaseAdjustment: if (!HandleLValueBasePath(Info, Adjustments[I].DerivedToBase.BasePath, Type, Result)) return false; Type = Adjustments[I].DerivedToBase.BasePath->getType(); break; case SubobjectAdjustment::FieldAdjustment: if (!HandleLValueMember(Info, E, Result, Adjustments[I].Field)) return false; Type = Adjustments[I].Field->getType(); break; case SubobjectAdjustment::MemberPointerAdjustment: if (!HandleMemberPointerAccess(this->Info, Type, Result, Adjustments[I].Ptr.RHS)) return false; Type = Adjustments[I].Ptr.MPT->getPointeeType(); break; } } return true; } bool LValueExprEvaluator::VisitCompoundLiteralExpr(const CompoundLiteralExpr *E) { assert((!Info.getLangOpts().CPlusPlus || E->isFileScope()) && "lvalue compound literal in c++?"); // Defer visiting the literal until the lvalue-to-rvalue conversion. We can // only see this when folding in C, so there's no standard to follow here. return Success(E); } bool LValueExprEvaluator::VisitCXXTypeidExpr(const CXXTypeidExpr *E) { if (!E->isPotentiallyEvaluated()) return Success(E); Info.FFDiag(E, diag::note_constexpr_typeid_polymorphic) << E->getExprOperand()->getType() << E->getExprOperand()->getSourceRange(); return false; } bool LValueExprEvaluator::VisitCXXUuidofExpr(const CXXUuidofExpr *E) { return Success(E); } bool LValueExprEvaluator::VisitMemberExpr(const MemberExpr *E) { // Handle static data members. if (const VarDecl *VD = dyn_cast(E->getMemberDecl())) { VisitIgnoredBaseExpression(E->getBase()); return VisitVarDecl(E, VD); } // Handle static member functions. if (const CXXMethodDecl *MD = dyn_cast(E->getMemberDecl())) { if (MD->isStatic()) { VisitIgnoredBaseExpression(E->getBase()); return Success(MD); } } // Handle non-static data members. return LValueExprEvaluatorBaseTy::VisitMemberExpr(E); } bool LValueExprEvaluator::VisitArraySubscriptExpr(const ArraySubscriptExpr *E) { // FIXME: Deal with vectors as array subscript bases. if (E->getBase()->getType()->isVectorType()) return Error(E); bool Success = true; if (!evaluatePointer(E->getBase(), Result)) { if (!Info.noteFailure()) return false; Success = false; } APSInt Index; if (!EvaluateInteger(E->getIdx(), Index, Info)) return false; return Success && HandleLValueArrayAdjustment(Info, E, Result, E->getType(), Index); } bool LValueExprEvaluator::VisitUnaryDeref(const UnaryOperator *E) { return evaluatePointer(E->getSubExpr(), Result); } bool LValueExprEvaluator::VisitUnaryReal(const UnaryOperator *E) { if (!Visit(E->getSubExpr())) return false; // __real is a no-op on scalar lvalues. if (E->getSubExpr()->getType()->isAnyComplexType()) HandleLValueComplexElement(Info, E, Result, E->getType(), false); return true; } bool LValueExprEvaluator::VisitUnaryImag(const UnaryOperator *E) { assert(E->getSubExpr()->getType()->isAnyComplexType() && "lvalue __imag__ on scalar?"); if (!Visit(E->getSubExpr())) return false; HandleLValueComplexElement(Info, E, Result, E->getType(), true); return true; } bool LValueExprEvaluator::VisitUnaryPreIncDec(const UnaryOperator *UO) { if (!Info.getLangOpts().CPlusPlus14 && !Info.keepEvaluatingAfterFailure()) return Error(UO); if (!this->Visit(UO->getSubExpr())) return false; return handleIncDec( this->Info, UO, Result, UO->getSubExpr()->getType(), UO->isIncrementOp(), nullptr); } bool LValueExprEvaluator::VisitCompoundAssignOperator( const CompoundAssignOperator *CAO) { if (!Info.getLangOpts().CPlusPlus14 && !Info.keepEvaluatingAfterFailure()) return Error(CAO); APValue RHS; // The overall lvalue result is the result of evaluating the LHS. if (!this->Visit(CAO->getLHS())) { if (Info.noteFailure()) Evaluate(RHS, this->Info, CAO->getRHS()); return false; } if (!Evaluate(RHS, this->Info, CAO->getRHS())) return false; return handleCompoundAssignment( this->Info, CAO, Result, CAO->getLHS()->getType(), CAO->getComputationLHSType(), CAO->getOpForCompoundAssignment(CAO->getOpcode()), RHS); } bool LValueExprEvaluator::VisitBinAssign(const BinaryOperator *E) { if (!Info.getLangOpts().CPlusPlus14 && !Info.keepEvaluatingAfterFailure()) return Error(E); APValue NewVal; if (!this->Visit(E->getLHS())) { if (Info.noteFailure()) Evaluate(NewVal, this->Info, E->getRHS()); return false; } if (!Evaluate(NewVal, this->Info, E->getRHS())) return false; return handleAssignment(this->Info, E, Result, E->getLHS()->getType(), NewVal); } //===----------------------------------------------------------------------===// // Pointer Evaluation //===----------------------------------------------------------------------===// /// Attempts to compute the number of bytes available at the pointer /// returned by a function with the alloc_size attribute. Returns true if we /// were successful. Places an unsigned number into `Result`. /// /// This expects the given CallExpr to be a call to a function with an /// alloc_size attribute. static bool getBytesReturnedByAllocSizeCall(const ASTContext &Ctx, const CallExpr *Call, llvm::APInt &Result) { const AllocSizeAttr *AllocSize = getAllocSizeAttr(Call); assert(AllocSize && AllocSize->getElemSizeParam().isValid()); unsigned SizeArgNo = AllocSize->getElemSizeParam().getASTIndex(); unsigned BitsInSizeT = Ctx.getTypeSize(Ctx.getSizeType()); if (Call->getNumArgs() <= SizeArgNo) return false; auto EvaluateAsSizeT = [&](const Expr *E, APSInt &Into) { if (!E->EvaluateAsInt(Into, Ctx, Expr::SE_AllowSideEffects)) return false; if (Into.isNegative() || !Into.isIntN(BitsInSizeT)) return false; Into = Into.zextOrSelf(BitsInSizeT); return true; }; APSInt SizeOfElem; if (!EvaluateAsSizeT(Call->getArg(SizeArgNo), SizeOfElem)) return false; if (!AllocSize->getNumElemsParam().isValid()) { Result = std::move(SizeOfElem); return true; } APSInt NumberOfElems; unsigned NumArgNo = AllocSize->getNumElemsParam().getASTIndex(); if (!EvaluateAsSizeT(Call->getArg(NumArgNo), NumberOfElems)) return false; bool Overflow; llvm::APInt BytesAvailable = SizeOfElem.umul_ov(NumberOfElems, Overflow); if (Overflow) return false; Result = std::move(BytesAvailable); return true; } /// Convenience function. LVal's base must be a call to an alloc_size /// function. static bool getBytesReturnedByAllocSizeCall(const ASTContext &Ctx, const LValue &LVal, llvm::APInt &Result) { assert(isBaseAnAllocSizeCall(LVal.getLValueBase()) && "Can't get the size of a non alloc_size function"); const auto *Base = LVal.getLValueBase().get(); const CallExpr *CE = tryUnwrapAllocSizeCall(Base); return getBytesReturnedByAllocSizeCall(Ctx, CE, Result); } /// Attempts to evaluate the given LValueBase as the result of a call to /// a function with the alloc_size attribute. If it was possible to do so, this /// function will return true, make Result's Base point to said function call, /// and mark Result's Base as invalid. static bool evaluateLValueAsAllocSize(EvalInfo &Info, APValue::LValueBase Base, LValue &Result) { if (Base.isNull()) return false; // Because we do no form of static analysis, we only support const variables. // // Additionally, we can't support parameters, nor can we support static // variables (in the latter case, use-before-assign isn't UB; in the former, // we have no clue what they'll be assigned to). const auto *VD = dyn_cast_or_null(Base.dyn_cast()); if (!VD || !VD->isLocalVarDecl() || !VD->getType().isConstQualified()) return false; const Expr *Init = VD->getAnyInitializer(); if (!Init) return false; const Expr *E = Init->IgnoreParens(); if (!tryUnwrapAllocSizeCall(E)) return false; // Store E instead of E unwrapped so that the type of the LValue's base is // what the user wanted. Result.setInvalid(E); QualType Pointee = E->getType()->castAs()->getPointeeType(); Result.addUnsizedArray(Info, E, Pointee); return true; } namespace { class PointerExprEvaluator : public ExprEvaluatorBase { LValue &Result; bool InvalidBaseOK; bool Success(const Expr *E) { Result.set(E); return true; } bool evaluateLValue(const Expr *E, LValue &Result) { return EvaluateLValue(E, Result, Info, InvalidBaseOK); } bool evaluatePointer(const Expr *E, LValue &Result) { return EvaluatePointer(E, Result, Info, InvalidBaseOK); } bool visitNonBuiltinCallExpr(const CallExpr *E); public: PointerExprEvaluator(EvalInfo &info, LValue &Result, bool InvalidBaseOK) : ExprEvaluatorBaseTy(info), Result(Result), InvalidBaseOK(InvalidBaseOK) {} bool Success(const APValue &V, const Expr *E) { Result.setFrom(Info.Ctx, V); return true; } bool ZeroInitialization(const Expr *E) { auto TargetVal = Info.Ctx.getTargetNullPointerValue(E->getType()); Result.setNull(E->getType(), TargetVal); return true; } bool VisitBinaryOperator(const BinaryOperator *E); bool VisitCastExpr(const CastExpr* E); bool VisitUnaryAddrOf(const UnaryOperator *E); bool VisitObjCStringLiteral(const ObjCStringLiteral *E) { return Success(E); } bool VisitObjCBoxedExpr(const ObjCBoxedExpr *E) { if (Info.noteFailure()) EvaluateIgnoredValue(Info, E->getSubExpr()); return Error(E); } bool VisitAddrLabelExpr(const AddrLabelExpr *E) { return Success(E); } bool VisitCallExpr(const CallExpr *E); bool VisitBuiltinCallExpr(const CallExpr *E, unsigned BuiltinOp); bool VisitBlockExpr(const BlockExpr *E) { if (!E->getBlockDecl()->hasCaptures()) return Success(E); return Error(E); } bool VisitCXXThisExpr(const CXXThisExpr *E) { // Can't look at 'this' when checking a potential constant expression. if (Info.checkingPotentialConstantExpression()) return false; if (!Info.CurrentCall->This) { if (Info.getLangOpts().CPlusPlus11) Info.FFDiag(E, diag::note_constexpr_this) << E->isImplicit(); else Info.FFDiag(E); return false; } Result = *Info.CurrentCall->This; // If we are inside a lambda's call operator, the 'this' expression refers // to the enclosing '*this' object (either by value or reference) which is // either copied into the closure object's field that represents the '*this' // or refers to '*this'. if (isLambdaCallOperator(Info.CurrentCall->Callee)) { // Update 'Result' to refer to the data member/field of the closure object // that represents the '*this' capture. if (!HandleLValueMember(Info, E, Result, Info.CurrentCall->LambdaThisCaptureField)) return false; // If we captured '*this' by reference, replace the field with its referent. if (Info.CurrentCall->LambdaThisCaptureField->getType() ->isPointerType()) { APValue RVal; if (!handleLValueToRValueConversion(Info, E, E->getType(), Result, RVal)) return false; Result.setFrom(Info.Ctx, RVal); } } return true; } // FIXME: Missing: @protocol, @selector }; } // end anonymous namespace static bool EvaluatePointer(const Expr* E, LValue& Result, EvalInfo &Info, bool InvalidBaseOK) { assert(E->isRValue() && E->getType()->hasPointerRepresentation()); return PointerExprEvaluator(Info, Result, InvalidBaseOK).Visit(E); } bool PointerExprEvaluator::VisitBinaryOperator(const BinaryOperator *E) { if (E->getOpcode() != BO_Add && E->getOpcode() != BO_Sub) return ExprEvaluatorBaseTy::VisitBinaryOperator(E); const Expr *PExp = E->getLHS(); const Expr *IExp = E->getRHS(); if (IExp->getType()->isPointerType()) std::swap(PExp, IExp); bool EvalPtrOK = evaluatePointer(PExp, Result); if (!EvalPtrOK && !Info.noteFailure()) return false; llvm::APSInt Offset; if (!EvaluateInteger(IExp, Offset, Info) || !EvalPtrOK) return false; if (E->getOpcode() == BO_Sub) negateAsSigned(Offset); QualType Pointee = PExp->getType()->castAs()->getPointeeType(); return HandleLValueArrayAdjustment(Info, E, Result, Pointee, Offset); } bool PointerExprEvaluator::VisitUnaryAddrOf(const UnaryOperator *E) { return evaluateLValue(E->getSubExpr(), Result); } bool PointerExprEvaluator::VisitCastExpr(const CastExpr *E) { const Expr *SubExpr = E->getSubExpr(); switch (E->getCastKind()) { default: break; case CK_BitCast: case CK_CPointerToObjCPointerCast: case CK_BlockPointerToObjCPointerCast: case CK_AnyPointerToBlockPointerCast: case CK_AddressSpaceConversion: if (!Visit(SubExpr)) return false; // Bitcasts to cv void* are static_casts, not reinterpret_casts, so are // permitted in constant expressions in C++11. Bitcasts from cv void* are // also static_casts, but we disallow them as a resolution to DR1312. if (!E->getType()->isVoidPointerType()) { // If we changed anything other than cvr-qualifiers, we can't use this // value for constant folding. FIXME: Qualification conversions should // always be CK_NoOp, but we get this wrong in C. if (!Info.Ctx.hasCvrSimilarType(E->getType(), E->getSubExpr()->getType())) Result.Designator.setInvalid(); if (SubExpr->getType()->isVoidPointerType()) CCEDiag(E, diag::note_constexpr_invalid_cast) << 3 << SubExpr->getType(); else CCEDiag(E, diag::note_constexpr_invalid_cast) << 2; } if (E->getCastKind() == CK_AddressSpaceConversion && Result.IsNullPtr) ZeroInitialization(E); return true; case CK_DerivedToBase: case CK_UncheckedDerivedToBase: if (!evaluatePointer(E->getSubExpr(), Result)) return false; if (!Result.Base && Result.Offset.isZero()) return true; // Now figure out the necessary offset to add to the base LV to get from // the derived class to the base class. return HandleLValueBasePath(Info, E, E->getSubExpr()->getType()-> castAs()->getPointeeType(), Result); case CK_BaseToDerived: if (!Visit(E->getSubExpr())) return false; if (!Result.Base && Result.Offset.isZero()) return true; return HandleBaseToDerivedCast(Info, E, Result); case CK_NullToPointer: VisitIgnoredValue(E->getSubExpr()); return ZeroInitialization(E); case CK_IntegralToPointer: { CCEDiag(E, diag::note_constexpr_invalid_cast) << 2; APValue Value; if (!EvaluateIntegerOrLValue(SubExpr, Value, Info)) break; if (Value.isInt()) { unsigned Size = Info.Ctx.getTypeSize(E->getType()); uint64_t N = Value.getInt().extOrTrunc(Size).getZExtValue(); Result.Base = (Expr*)nullptr; Result.InvalidBase = false; Result.Offset = CharUnits::fromQuantity(N); Result.Designator.setInvalid(); Result.IsNullPtr = false; return true; } else { // Cast is of an lvalue, no need to change value. Result.setFrom(Info.Ctx, Value); return true; } } case CK_ArrayToPointerDecay: { if (SubExpr->isGLValue()) { if (!evaluateLValue(SubExpr, Result)) return false; } else { APValue &Value = createTemporary(SubExpr, false, Result, *Info.CurrentCall); if (!EvaluateInPlace(Value, Info, Result, SubExpr)) return false; } // The result is a pointer to the first element of the array. auto *AT = Info.Ctx.getAsArrayType(SubExpr->getType()); if (auto *CAT = dyn_cast(AT)) Result.addArray(Info, E, CAT); else Result.addUnsizedArray(Info, E, AT->getElementType()); return true; } case CK_FunctionToPointerDecay: return evaluateLValue(SubExpr, Result); case CK_LValueToRValue: { LValue LVal; if (!evaluateLValue(E->getSubExpr(), LVal)) return false; APValue RVal; // Note, we use the subexpression's type in order to retain cv-qualifiers. if (!handleLValueToRValueConversion(Info, E, E->getSubExpr()->getType(), LVal, RVal)) return InvalidBaseOK && evaluateLValueAsAllocSize(Info, LVal.Base, Result); return Success(RVal, E); } } return ExprEvaluatorBaseTy::VisitCastExpr(E); } static CharUnits GetAlignOfType(EvalInfo &Info, QualType T) { // C++ [expr.alignof]p3: // When alignof is applied to a reference type, the result is the // alignment of the referenced type. if (const ReferenceType *Ref = T->getAs()) T = Ref->getPointeeType(); // __alignof is defined to return the preferred alignment. if (T.getQualifiers().hasUnaligned()) return CharUnits::One(); return Info.Ctx.toCharUnitsFromBits( Info.Ctx.getPreferredTypeAlign(T.getTypePtr())); } static CharUnits GetAlignOfExpr(EvalInfo &Info, const Expr *E) { E = E->IgnoreParens(); // The kinds of expressions that we have special-case logic here for // should be kept up to date with the special checks for those // expressions in Sema. // alignof decl is always accepted, even if it doesn't make sense: we default // to 1 in those cases. if (const DeclRefExpr *DRE = dyn_cast(E)) return Info.Ctx.getDeclAlign(DRE->getDecl(), /*RefAsPointee*/true); if (const MemberExpr *ME = dyn_cast(E)) return Info.Ctx.getDeclAlign(ME->getMemberDecl(), /*RefAsPointee*/true); return GetAlignOfType(Info, E->getType()); } // To be clear: this happily visits unsupported builtins. Better name welcomed. bool PointerExprEvaluator::visitNonBuiltinCallExpr(const CallExpr *E) { if (ExprEvaluatorBaseTy::VisitCallExpr(E)) return true; if (!(InvalidBaseOK && getAllocSizeAttr(E))) return false; Result.setInvalid(E); QualType PointeeTy = E->getType()->castAs()->getPointeeType(); Result.addUnsizedArray(Info, E, PointeeTy); return true; } bool PointerExprEvaluator::VisitCallExpr(const CallExpr *E) { if (IsStringLiteralCall(E)) return Success(E); if (unsigned BuiltinOp = E->getBuiltinCallee()) return VisitBuiltinCallExpr(E, BuiltinOp); return visitNonBuiltinCallExpr(E); } bool PointerExprEvaluator::VisitBuiltinCallExpr(const CallExpr *E, unsigned BuiltinOp) { switch (BuiltinOp) { case Builtin::BI__builtin_addressof: return evaluateLValue(E->getArg(0), Result); case Builtin::BI__builtin_assume_aligned: { // We need to be very careful here because: if the pointer does not have the // asserted alignment, then the behavior is undefined, and undefined // behavior is non-constant. if (!evaluatePointer(E->getArg(0), Result)) return false; LValue OffsetResult(Result); APSInt Alignment; if (!EvaluateInteger(E->getArg(1), Alignment, Info)) return false; CharUnits Align = CharUnits::fromQuantity(Alignment.getZExtValue()); if (E->getNumArgs() > 2) { APSInt Offset; if (!EvaluateInteger(E->getArg(2), Offset, Info)) return false; int64_t AdditionalOffset = -Offset.getZExtValue(); OffsetResult.Offset += CharUnits::fromQuantity(AdditionalOffset); } // If there is a base object, then it must have the correct alignment. if (OffsetResult.Base) { CharUnits BaseAlignment; if (const ValueDecl *VD = OffsetResult.Base.dyn_cast()) { BaseAlignment = Info.Ctx.getDeclAlign(VD); } else { BaseAlignment = GetAlignOfExpr(Info, OffsetResult.Base.get()); } if (BaseAlignment < Align) { Result.Designator.setInvalid(); // FIXME: Add support to Diagnostic for long / long long. CCEDiag(E->getArg(0), diag::note_constexpr_baa_insufficient_alignment) << 0 << (unsigned)BaseAlignment.getQuantity() << (unsigned)Align.getQuantity(); return false; } } // The offset must also have the correct alignment. if (OffsetResult.Offset.alignTo(Align) != OffsetResult.Offset) { Result.Designator.setInvalid(); (OffsetResult.Base ? CCEDiag(E->getArg(0), diag::note_constexpr_baa_insufficient_alignment) << 1 : CCEDiag(E->getArg(0), diag::note_constexpr_baa_value_insufficient_alignment)) << (int)OffsetResult.Offset.getQuantity() << (unsigned)Align.getQuantity(); return false; } return true; } case Builtin::BIstrchr: case Builtin::BIwcschr: case Builtin::BImemchr: case Builtin::BIwmemchr: if (Info.getLangOpts().CPlusPlus11) Info.CCEDiag(E, diag::note_constexpr_invalid_function) << /*isConstexpr*/0 << /*isConstructor*/0 << (std::string("'") + Info.Ctx.BuiltinInfo.getName(BuiltinOp) + "'"); else Info.CCEDiag(E, diag::note_invalid_subexpr_in_const_expr); LLVM_FALLTHROUGH; case Builtin::BI__builtin_strchr: case Builtin::BI__builtin_wcschr: case Builtin::BI__builtin_memchr: case Builtin::BI__builtin_char_memchr: case Builtin::BI__builtin_wmemchr: { if (!Visit(E->getArg(0))) return false; APSInt Desired; if (!EvaluateInteger(E->getArg(1), Desired, Info)) return false; uint64_t MaxLength = uint64_t(-1); if (BuiltinOp != Builtin::BIstrchr && BuiltinOp != Builtin::BIwcschr && BuiltinOp != Builtin::BI__builtin_strchr && BuiltinOp != Builtin::BI__builtin_wcschr) { APSInt N; if (!EvaluateInteger(E->getArg(2), N, Info)) return false; MaxLength = N.getExtValue(); } QualType CharTy = E->getArg(0)->getType()->getPointeeType(); // Figure out what value we're actually looking for (after converting to // the corresponding unsigned type if necessary). uint64_t DesiredVal; bool StopAtNull = false; switch (BuiltinOp) { case Builtin::BIstrchr: case Builtin::BI__builtin_strchr: // strchr compares directly to the passed integer, and therefore // always fails if given an int that is not a char. if (!APSInt::isSameValue(HandleIntToIntCast(Info, E, CharTy, E->getArg(1)->getType(), Desired), Desired)) return ZeroInitialization(E); StopAtNull = true; LLVM_FALLTHROUGH; case Builtin::BImemchr: case Builtin::BI__builtin_memchr: case Builtin::BI__builtin_char_memchr: // memchr compares by converting both sides to unsigned char. That's also // correct for strchr if we get this far (to cope with plain char being // unsigned in the strchr case). DesiredVal = Desired.trunc(Info.Ctx.getCharWidth()).getZExtValue(); break; case Builtin::BIwcschr: case Builtin::BI__builtin_wcschr: StopAtNull = true; LLVM_FALLTHROUGH; case Builtin::BIwmemchr: case Builtin::BI__builtin_wmemchr: // wcschr and wmemchr are given a wchar_t to look for. Just use it. DesiredVal = Desired.getZExtValue(); break; } for (; MaxLength; --MaxLength) { APValue Char; if (!handleLValueToRValueConversion(Info, E, CharTy, Result, Char) || !Char.isInt()) return false; if (Char.getInt().getZExtValue() == DesiredVal) return true; if (StopAtNull && !Char.getInt()) break; if (!HandleLValueArrayAdjustment(Info, E, Result, CharTy, 1)) return false; } // Not found: return nullptr. return ZeroInitialization(E); } - case Builtin::BImemcpy: - case Builtin::BImemmove: - case Builtin::BIwmemcpy: - case Builtin::BIwmemmove: - if (Info.getLangOpts().CPlusPlus11) - Info.CCEDiag(E, diag::note_constexpr_invalid_function) - << /*isConstexpr*/0 << /*isConstructor*/0 - << (std::string("'") + Info.Ctx.BuiltinInfo.getName(BuiltinOp) + "'"); - else - Info.CCEDiag(E, diag::note_invalid_subexpr_in_const_expr); - LLVM_FALLTHROUGH; - case Builtin::BI__builtin_memcpy: - case Builtin::BI__builtin_memmove: - case Builtin::BI__builtin_wmemcpy: - case Builtin::BI__builtin_wmemmove: { - bool WChar = BuiltinOp == Builtin::BIwmemcpy || - BuiltinOp == Builtin::BIwmemmove || - BuiltinOp == Builtin::BI__builtin_wmemcpy || - BuiltinOp == Builtin::BI__builtin_wmemmove; - bool Move = BuiltinOp == Builtin::BImemmove || - BuiltinOp == Builtin::BIwmemmove || - BuiltinOp == Builtin::BI__builtin_memmove || - BuiltinOp == Builtin::BI__builtin_wmemmove; - - // The result of mem* is the first argument. - if (!Visit(E->getArg(0))) - return false; - LValue Dest = Result; - - LValue Src; - if (!EvaluatePointer(E->getArg(1), Src, Info)) - return false; - - APSInt N; - if (!EvaluateInteger(E->getArg(2), N, Info)) - return false; - assert(!N.isSigned() && "memcpy and friends take an unsigned size"); - - // If the size is zero, we treat this as always being a valid no-op. - // (Even if one of the src and dest pointers is null.) - if (!N) - return true; - - // We require that Src and Dest are both pointers to arrays of - // trivially-copyable type. (For the wide version, the designator will be - // invalid if the designated object is not a wchar_t.) - QualType T = Dest.Designator.getType(Info.Ctx); - QualType SrcT = Src.Designator.getType(Info.Ctx); - if (!Info.Ctx.hasSameUnqualifiedType(T, SrcT)) { - Info.FFDiag(E, diag::note_constexpr_memcpy_type_pun) << Move << SrcT << T; - return false; - } - if (!T.isTriviallyCopyableType(Info.Ctx)) { - Info.FFDiag(E, diag::note_constexpr_memcpy_nontrivial) << Move << T; - return false; - } - - // Figure out how many T's we're copying. - uint64_t TSize = Info.Ctx.getTypeSizeInChars(T).getQuantity(); - if (!WChar) { - uint64_t Remainder; - llvm::APInt OrigN = N; - llvm::APInt::udivrem(OrigN, TSize, N, Remainder); - if (Remainder) { - Info.FFDiag(E, diag::note_constexpr_memcpy_unsupported) - << Move << WChar << 0 << T << OrigN.toString(10, /*Signed*/false) - << (unsigned)TSize; - return false; - } - } - - // Check that the copying will remain within the arrays, just so that we - // can give a more meaningful diagnostic. This implicitly also checks that - // N fits into 64 bits. - uint64_t RemainingSrcSize = Src.Designator.validIndexAdjustments().second; - uint64_t RemainingDestSize = Dest.Designator.validIndexAdjustments().second; - if (N.ugt(RemainingSrcSize) || N.ugt(RemainingDestSize)) { - Info.FFDiag(E, diag::note_constexpr_memcpy_unsupported) - << Move << WChar << (N.ugt(RemainingSrcSize) ? 1 : 2) << T - << N.toString(10, /*Signed*/false); - return false; - } - uint64_t NElems = N.getZExtValue(); - uint64_t NBytes = NElems * TSize; - - // Check for overlap. - int Direction = 1; - if (HasSameBase(Src, Dest)) { - uint64_t SrcOffset = Src.getLValueOffset().getQuantity(); - uint64_t DestOffset = Dest.getLValueOffset().getQuantity(); - if (DestOffset >= SrcOffset && DestOffset - SrcOffset < NBytes) { - // Dest is inside the source region. - if (!Move) { - Info.FFDiag(E, diag::note_constexpr_memcpy_overlap) << WChar; - return false; - } - // For memmove and friends, copy backwards. - if (!HandleLValueArrayAdjustment(Info, E, Src, T, NElems - 1) || - !HandleLValueArrayAdjustment(Info, E, Dest, T, NElems - 1)) - return false; - Direction = -1; - } else if (!Move && SrcOffset >= DestOffset && - SrcOffset - DestOffset < NBytes) { - // Src is inside the destination region for memcpy: invalid. - Info.FFDiag(E, diag::note_constexpr_memcpy_overlap) << WChar; - return false; - } - } - - while (true) { - APValue Val; - if (!handleLValueToRValueConversion(Info, E, T, Src, Val) || - !handleAssignment(Info, E, Dest, T, Val)) - return false; - // Do not iterate past the last element; if we're copying backwards, that - // might take us off the start of the array. - if (--NElems == 0) - return true; - if (!HandleLValueArrayAdjustment(Info, E, Src, T, Direction) || - !HandleLValueArrayAdjustment(Info, E, Dest, T, Direction)) - return false; - } - } - default: return visitNonBuiltinCallExpr(E); } } //===----------------------------------------------------------------------===// // Member Pointer Evaluation //===----------------------------------------------------------------------===// namespace { class MemberPointerExprEvaluator : public ExprEvaluatorBase { MemberPtr &Result; bool Success(const ValueDecl *D) { Result = MemberPtr(D); return true; } public: MemberPointerExprEvaluator(EvalInfo &Info, MemberPtr &Result) : ExprEvaluatorBaseTy(Info), Result(Result) {} bool Success(const APValue &V, const Expr *E) { Result.setFrom(V); return true; } bool ZeroInitialization(const Expr *E) { return Success((const ValueDecl*)nullptr); } bool VisitCastExpr(const CastExpr *E); bool VisitUnaryAddrOf(const UnaryOperator *E); }; } // end anonymous namespace static bool EvaluateMemberPointer(const Expr *E, MemberPtr &Result, EvalInfo &Info) { assert(E->isRValue() && E->getType()->isMemberPointerType()); return MemberPointerExprEvaluator(Info, Result).Visit(E); } bool MemberPointerExprEvaluator::VisitCastExpr(const CastExpr *E) { switch (E->getCastKind()) { default: return ExprEvaluatorBaseTy::VisitCastExpr(E); case CK_NullToMemberPointer: VisitIgnoredValue(E->getSubExpr()); return ZeroInitialization(E); case CK_BaseToDerivedMemberPointer: { if (!Visit(E->getSubExpr())) return false; if (E->path_empty()) return true; // Base-to-derived member pointer casts store the path in derived-to-base // order, so iterate backwards. The CXXBaseSpecifier also provides us with // the wrong end of the derived->base arc, so stagger the path by one class. typedef std::reverse_iterator ReverseIter; for (ReverseIter PathI(E->path_end() - 1), PathE(E->path_begin()); PathI != PathE; ++PathI) { assert(!(*PathI)->isVirtual() && "memptr cast through vbase"); const CXXRecordDecl *Derived = (*PathI)->getType()->getAsCXXRecordDecl(); if (!Result.castToDerived(Derived)) return Error(E); } const Type *FinalTy = E->getType()->castAs()->getClass(); if (!Result.castToDerived(FinalTy->getAsCXXRecordDecl())) return Error(E); return true; } case CK_DerivedToBaseMemberPointer: if (!Visit(E->getSubExpr())) return false; for (CastExpr::path_const_iterator PathI = E->path_begin(), PathE = E->path_end(); PathI != PathE; ++PathI) { assert(!(*PathI)->isVirtual() && "memptr cast through vbase"); const CXXRecordDecl *Base = (*PathI)->getType()->getAsCXXRecordDecl(); if (!Result.castToBase(Base)) return Error(E); } return true; } } bool MemberPointerExprEvaluator::VisitUnaryAddrOf(const UnaryOperator *E) { // C++11 [expr.unary.op]p3 has very strict rules on how the address of a // member can be formed. return Success(cast(E->getSubExpr())->getDecl()); } //===----------------------------------------------------------------------===// // Record Evaluation //===----------------------------------------------------------------------===// namespace { class RecordExprEvaluator : public ExprEvaluatorBase { const LValue &This; APValue &Result; public: RecordExprEvaluator(EvalInfo &info, const LValue &This, APValue &Result) : ExprEvaluatorBaseTy(info), This(This), Result(Result) {} bool Success(const APValue &V, const Expr *E) { Result = V; return true; } bool ZeroInitialization(const Expr *E) { return ZeroInitialization(E, E->getType()); } bool ZeroInitialization(const Expr *E, QualType T); bool VisitCallExpr(const CallExpr *E) { return handleCallExpr(E, Result, &This); } bool VisitCastExpr(const CastExpr *E); bool VisitInitListExpr(const InitListExpr *E); bool VisitCXXConstructExpr(const CXXConstructExpr *E) { return VisitCXXConstructExpr(E, E->getType()); } bool VisitLambdaExpr(const LambdaExpr *E); bool VisitCXXInheritedCtorInitExpr(const CXXInheritedCtorInitExpr *E); bool VisitCXXConstructExpr(const CXXConstructExpr *E, QualType T); bool VisitCXXStdInitializerListExpr(const CXXStdInitializerListExpr *E); bool VisitBinCmp(const BinaryOperator *E); }; } /// Perform zero-initialization on an object of non-union class type. /// C++11 [dcl.init]p5: /// To zero-initialize an object or reference of type T means: /// [...] /// -- if T is a (possibly cv-qualified) non-union class type, /// each non-static data member and each base-class subobject is /// zero-initialized static bool HandleClassZeroInitialization(EvalInfo &Info, const Expr *E, const RecordDecl *RD, const LValue &This, APValue &Result) { assert(!RD->isUnion() && "Expected non-union class type"); const CXXRecordDecl *CD = dyn_cast(RD); Result = APValue(APValue::UninitStruct(), CD ? CD->getNumBases() : 0, std::distance(RD->field_begin(), RD->field_end())); if (RD->isInvalidDecl()) return false; const ASTRecordLayout &Layout = Info.Ctx.getASTRecordLayout(RD); if (CD) { unsigned Index = 0; for (CXXRecordDecl::base_class_const_iterator I = CD->bases_begin(), End = CD->bases_end(); I != End; ++I, ++Index) { const CXXRecordDecl *Base = I->getType()->getAsCXXRecordDecl(); LValue Subobject = This; if (!HandleLValueDirectBase(Info, E, Subobject, CD, Base, &Layout)) return false; if (!HandleClassZeroInitialization(Info, E, Base, Subobject, Result.getStructBase(Index))) return false; } } for (const auto *I : RD->fields()) { // -- if T is a reference type, no initialization is performed. if (I->getType()->isReferenceType()) continue; LValue Subobject = This; if (!HandleLValueMember(Info, E, Subobject, I, &Layout)) return false; ImplicitValueInitExpr VIE(I->getType()); if (!EvaluateInPlace( Result.getStructField(I->getFieldIndex()), Info, Subobject, &VIE)) return false; } return true; } bool RecordExprEvaluator::ZeroInitialization(const Expr *E, QualType T) { const RecordDecl *RD = T->castAs()->getDecl(); if (RD->isInvalidDecl()) return false; if (RD->isUnion()) { // C++11 [dcl.init]p5: If T is a (possibly cv-qualified) union type, the // object's first non-static named data member is zero-initialized RecordDecl::field_iterator I = RD->field_begin(); if (I == RD->field_end()) { Result = APValue((const FieldDecl*)nullptr); return true; } LValue Subobject = This; if (!HandleLValueMember(Info, E, Subobject, *I)) return false; Result = APValue(*I); ImplicitValueInitExpr VIE(I->getType()); return EvaluateInPlace(Result.getUnionValue(), Info, Subobject, &VIE); } if (isa(RD) && cast(RD)->getNumVBases()) { Info.FFDiag(E, diag::note_constexpr_virtual_base) << RD; return false; } return HandleClassZeroInitialization(Info, E, RD, This, Result); } bool RecordExprEvaluator::VisitCastExpr(const CastExpr *E) { switch (E->getCastKind()) { default: return ExprEvaluatorBaseTy::VisitCastExpr(E); case CK_ConstructorConversion: return Visit(E->getSubExpr()); case CK_DerivedToBase: case CK_UncheckedDerivedToBase: { APValue DerivedObject; if (!Evaluate(DerivedObject, Info, E->getSubExpr())) return false; if (!DerivedObject.isStruct()) return Error(E->getSubExpr()); // Derived-to-base rvalue conversion: just slice off the derived part. APValue *Value = &DerivedObject; const CXXRecordDecl *RD = E->getSubExpr()->getType()->getAsCXXRecordDecl(); for (CastExpr::path_const_iterator PathI = E->path_begin(), PathE = E->path_end(); PathI != PathE; ++PathI) { assert(!(*PathI)->isVirtual() && "record rvalue with virtual base"); const CXXRecordDecl *Base = (*PathI)->getType()->getAsCXXRecordDecl(); Value = &Value->getStructBase(getBaseIndex(RD, Base)); RD = Base; } Result = *Value; return true; } } } bool RecordExprEvaluator::VisitInitListExpr(const InitListExpr *E) { if (E->isTransparent()) return Visit(E->getInit(0)); const RecordDecl *RD = E->getType()->castAs()->getDecl(); if (RD->isInvalidDecl()) return false; const ASTRecordLayout &Layout = Info.Ctx.getASTRecordLayout(RD); if (RD->isUnion()) { const FieldDecl *Field = E->getInitializedFieldInUnion(); Result = APValue(Field); if (!Field) return true; // If the initializer list for a union does not contain any elements, the // first element of the union is value-initialized. // FIXME: The element should be initialized from an initializer list. // Is this difference ever observable for initializer lists which // we don't build? ImplicitValueInitExpr VIE(Field->getType()); const Expr *InitExpr = E->getNumInits() ? E->getInit(0) : &VIE; LValue Subobject = This; if (!HandleLValueMember(Info, InitExpr, Subobject, Field, &Layout)) return false; // Temporarily override This, in case there's a CXXDefaultInitExpr in here. ThisOverrideRAII ThisOverride(*Info.CurrentCall, &This, isa(InitExpr)); return EvaluateInPlace(Result.getUnionValue(), Info, Subobject, InitExpr); } auto *CXXRD = dyn_cast(RD); if (Result.isUninit()) Result = APValue(APValue::UninitStruct(), CXXRD ? CXXRD->getNumBases() : 0, std::distance(RD->field_begin(), RD->field_end())); unsigned ElementNo = 0; bool Success = true; // Initialize base classes. if (CXXRD) { for (const auto &Base : CXXRD->bases()) { assert(ElementNo < E->getNumInits() && "missing init for base class"); const Expr *Init = E->getInit(ElementNo); LValue Subobject = This; if (!HandleLValueBase(Info, Init, Subobject, CXXRD, &Base)) return false; APValue &FieldVal = Result.getStructBase(ElementNo); if (!EvaluateInPlace(FieldVal, Info, Subobject, Init)) { if (!Info.noteFailure()) return false; Success = false; } ++ElementNo; } } // Initialize members. for (const auto *Field : RD->fields()) { // Anonymous bit-fields are not considered members of the class for // purposes of aggregate initialization. if (Field->isUnnamedBitfield()) continue; LValue Subobject = This; bool HaveInit = ElementNo < E->getNumInits(); // FIXME: Diagnostics here should point to the end of the initializer // list, not the start. if (!HandleLValueMember(Info, HaveInit ? E->getInit(ElementNo) : E, Subobject, Field, &Layout)) return false; // Perform an implicit value-initialization for members beyond the end of // the initializer list. ImplicitValueInitExpr VIE(HaveInit ? Info.Ctx.IntTy : Field->getType()); const Expr *Init = HaveInit ? E->getInit(ElementNo++) : &VIE; // Temporarily override This, in case there's a CXXDefaultInitExpr in here. ThisOverrideRAII ThisOverride(*Info.CurrentCall, &This, isa(Init)); APValue &FieldVal = Result.getStructField(Field->getFieldIndex()); if (!EvaluateInPlace(FieldVal, Info, Subobject, Init) || (Field->isBitField() && !truncateBitfieldValue(Info, Init, FieldVal, Field))) { if (!Info.noteFailure()) return false; Success = false; } } return Success; } bool RecordExprEvaluator::VisitCXXConstructExpr(const CXXConstructExpr *E, QualType T) { // Note that E's type is not necessarily the type of our class here; we might // be initializing an array element instead. const CXXConstructorDecl *FD = E->getConstructor(); if (FD->isInvalidDecl() || FD->getParent()->isInvalidDecl()) return false; bool ZeroInit = E->requiresZeroInitialization(); if (CheckTrivialDefaultConstructor(Info, E->getExprLoc(), FD, ZeroInit)) { // If we've already performed zero-initialization, we're already done. if (!Result.isUninit()) return true; // We can get here in two different ways: // 1) We're performing value-initialization, and should zero-initialize // the object, or // 2) We're performing default-initialization of an object with a trivial // constexpr default constructor, in which case we should start the // lifetimes of all the base subobjects (there can be no data member // subobjects in this case) per [basic.life]p1. // Either way, ZeroInitialization is appropriate. return ZeroInitialization(E, T); } const FunctionDecl *Definition = nullptr; auto Body = FD->getBody(Definition); if (!CheckConstexprFunction(Info, E->getExprLoc(), FD, Definition, Body)) return false; // Avoid materializing a temporary for an elidable copy/move constructor. if (E->isElidable() && !ZeroInit) if (const MaterializeTemporaryExpr *ME = dyn_cast(E->getArg(0))) return Visit(ME->GetTemporaryExpr()); if (ZeroInit && !ZeroInitialization(E, T)) return false; auto Args = llvm::makeArrayRef(E->getArgs(), E->getNumArgs()); return HandleConstructorCall(E, This, Args, cast(Definition), Info, Result); } bool RecordExprEvaluator::VisitCXXInheritedCtorInitExpr( const CXXInheritedCtorInitExpr *E) { if (!Info.CurrentCall) { assert(Info.checkingPotentialConstantExpression()); return false; } const CXXConstructorDecl *FD = E->getConstructor(); if (FD->isInvalidDecl() || FD->getParent()->isInvalidDecl()) return false; const FunctionDecl *Definition = nullptr; auto Body = FD->getBody(Definition); if (!CheckConstexprFunction(Info, E->getExprLoc(), FD, Definition, Body)) return false; return HandleConstructorCall(E, This, Info.CurrentCall->Arguments, cast(Definition), Info, Result); } bool RecordExprEvaluator::VisitCXXStdInitializerListExpr( const CXXStdInitializerListExpr *E) { const ConstantArrayType *ArrayType = Info.Ctx.getAsConstantArrayType(E->getSubExpr()->getType()); LValue Array; if (!EvaluateLValue(E->getSubExpr(), Array, Info)) return false; // Get a pointer to the first element of the array. Array.addArray(Info, E, ArrayType); // FIXME: Perform the checks on the field types in SemaInit. RecordDecl *Record = E->getType()->castAs()->getDecl(); RecordDecl::field_iterator Field = Record->field_begin(); if (Field == Record->field_end()) return Error(E); // Start pointer. if (!Field->getType()->isPointerType() || !Info.Ctx.hasSameType(Field->getType()->getPointeeType(), ArrayType->getElementType())) return Error(E); // FIXME: What if the initializer_list type has base classes, etc? Result = APValue(APValue::UninitStruct(), 0, 2); Array.moveInto(Result.getStructField(0)); if (++Field == Record->field_end()) return Error(E); if (Field->getType()->isPointerType() && Info.Ctx.hasSameType(Field->getType()->getPointeeType(), ArrayType->getElementType())) { // End pointer. if (!HandleLValueArrayAdjustment(Info, E, Array, ArrayType->getElementType(), ArrayType->getSize().getZExtValue())) return false; Array.moveInto(Result.getStructField(1)); } else if (Info.Ctx.hasSameType(Field->getType(), Info.Ctx.getSizeType())) // Length. Result.getStructField(1) = APValue(APSInt(ArrayType->getSize())); else return Error(E); if (++Field != Record->field_end()) return Error(E); return true; } bool RecordExprEvaluator::VisitLambdaExpr(const LambdaExpr *E) { const CXXRecordDecl *ClosureClass = E->getLambdaClass(); if (ClosureClass->isInvalidDecl()) return false; if (Info.checkingPotentialConstantExpression()) return true; const size_t NumFields = std::distance(ClosureClass->field_begin(), ClosureClass->field_end()); assert(NumFields == (size_t)std::distance(E->capture_init_begin(), E->capture_init_end()) && "The number of lambda capture initializers should equal the number of " "fields within the closure type"); Result = APValue(APValue::UninitStruct(), /*NumBases*/0, NumFields); // Iterate through all the lambda's closure object's fields and initialize // them. auto *CaptureInitIt = E->capture_init_begin(); const LambdaCapture *CaptureIt = ClosureClass->captures_begin(); bool Success = true; for (const auto *Field : ClosureClass->fields()) { assert(CaptureInitIt != E->capture_init_end()); // Get the initializer for this field Expr *const CurFieldInit = *CaptureInitIt++; // If there is no initializer, either this is a VLA or an error has // occurred. if (!CurFieldInit) return Error(E); APValue &FieldVal = Result.getStructField(Field->getFieldIndex()); if (!EvaluateInPlace(FieldVal, Info, This, CurFieldInit)) { if (!Info.keepEvaluatingAfterFailure()) return false; Success = false; } ++CaptureIt; } return Success; } static bool EvaluateRecord(const Expr *E, const LValue &This, APValue &Result, EvalInfo &Info) { assert(E->isRValue() && E->getType()->isRecordType() && "can't evaluate expression as a record rvalue"); return RecordExprEvaluator(Info, This, Result).Visit(E); } //===----------------------------------------------------------------------===// // Temporary Evaluation // // Temporaries are represented in the AST as rvalues, but generally behave like // lvalues. The full-object of which the temporary is a subobject is implicitly // materialized so that a reference can bind to it. //===----------------------------------------------------------------------===// namespace { class TemporaryExprEvaluator : public LValueExprEvaluatorBase { public: TemporaryExprEvaluator(EvalInfo &Info, LValue &Result) : LValueExprEvaluatorBaseTy(Info, Result, false) {} /// Visit an expression which constructs the value of this temporary. bool VisitConstructExpr(const Expr *E) { APValue &Value = createTemporary(E, false, Result, *Info.CurrentCall); return EvaluateInPlace(Value, Info, Result, E); } bool VisitCastExpr(const CastExpr *E) { switch (E->getCastKind()) { default: return LValueExprEvaluatorBaseTy::VisitCastExpr(E); case CK_ConstructorConversion: return VisitConstructExpr(E->getSubExpr()); } } bool VisitInitListExpr(const InitListExpr *E) { return VisitConstructExpr(E); } bool VisitCXXConstructExpr(const CXXConstructExpr *E) { return VisitConstructExpr(E); } bool VisitCallExpr(const CallExpr *E) { return VisitConstructExpr(E); } bool VisitCXXStdInitializerListExpr(const CXXStdInitializerListExpr *E) { return VisitConstructExpr(E); } bool VisitLambdaExpr(const LambdaExpr *E) { return VisitConstructExpr(E); } }; } // end anonymous namespace /// Evaluate an expression of record type as a temporary. static bool EvaluateTemporary(const Expr *E, LValue &Result, EvalInfo &Info) { assert(E->isRValue() && E->getType()->isRecordType()); return TemporaryExprEvaluator(Info, Result).Visit(E); } //===----------------------------------------------------------------------===// // Vector Evaluation //===----------------------------------------------------------------------===// namespace { class VectorExprEvaluator : public ExprEvaluatorBase { APValue &Result; public: VectorExprEvaluator(EvalInfo &info, APValue &Result) : ExprEvaluatorBaseTy(info), Result(Result) {} bool Success(ArrayRef V, const Expr *E) { assert(V.size() == E->getType()->castAs()->getNumElements()); // FIXME: remove this APValue copy. Result = APValue(V.data(), V.size()); return true; } bool Success(const APValue &V, const Expr *E) { assert(V.isVector()); Result = V; return true; } bool ZeroInitialization(const Expr *E); bool VisitUnaryReal(const UnaryOperator *E) { return Visit(E->getSubExpr()); } bool VisitCastExpr(const CastExpr* E); bool VisitInitListExpr(const InitListExpr *E); bool VisitUnaryImag(const UnaryOperator *E); // FIXME: Missing: unary -, unary ~, binary add/sub/mul/div, // binary comparisons, binary and/or/xor, // shufflevector, ExtVectorElementExpr }; } // end anonymous namespace static bool EvaluateVector(const Expr* E, APValue& Result, EvalInfo &Info) { assert(E->isRValue() && E->getType()->isVectorType() &&"not a vector rvalue"); return VectorExprEvaluator(Info, Result).Visit(E); } bool VectorExprEvaluator::VisitCastExpr(const CastExpr *E) { const VectorType *VTy = E->getType()->castAs(); unsigned NElts = VTy->getNumElements(); const Expr *SE = E->getSubExpr(); QualType SETy = SE->getType(); switch (E->getCastKind()) { case CK_VectorSplat: { APValue Val = APValue(); if (SETy->isIntegerType()) { APSInt IntResult; if (!EvaluateInteger(SE, IntResult, Info)) return false; Val = APValue(std::move(IntResult)); } else if (SETy->isRealFloatingType()) { APFloat FloatResult(0.0); if (!EvaluateFloat(SE, FloatResult, Info)) return false; Val = APValue(std::move(FloatResult)); } else { return Error(E); } // Splat and create vector APValue. SmallVector Elts(NElts, Val); return Success(Elts, E); } case CK_BitCast: { // Evaluate the operand into an APInt we can extract from. llvm::APInt SValInt; if (!EvalAndBitcastToAPInt(Info, SE, SValInt)) return false; // Extract the elements QualType EltTy = VTy->getElementType(); unsigned EltSize = Info.Ctx.getTypeSize(EltTy); bool BigEndian = Info.Ctx.getTargetInfo().isBigEndian(); SmallVector Elts; if (EltTy->isRealFloatingType()) { const llvm::fltSemantics &Sem = Info.Ctx.getFloatTypeSemantics(EltTy); unsigned FloatEltSize = EltSize; if (&Sem == &APFloat::x87DoubleExtended()) FloatEltSize = 80; for (unsigned i = 0; i < NElts; i++) { llvm::APInt Elt; if (BigEndian) Elt = SValInt.rotl(i*EltSize+FloatEltSize).trunc(FloatEltSize); else Elt = SValInt.rotr(i*EltSize).trunc(FloatEltSize); Elts.push_back(APValue(APFloat(Sem, Elt))); } } else if (EltTy->isIntegerType()) { for (unsigned i = 0; i < NElts; i++) { llvm::APInt Elt; if (BigEndian) Elt = SValInt.rotl(i*EltSize+EltSize).zextOrTrunc(EltSize); else Elt = SValInt.rotr(i*EltSize).zextOrTrunc(EltSize); Elts.push_back(APValue(APSInt(Elt, EltTy->isSignedIntegerType()))); } } else { return Error(E); } return Success(Elts, E); } default: return ExprEvaluatorBaseTy::VisitCastExpr(E); } } bool VectorExprEvaluator::VisitInitListExpr(const InitListExpr *E) { const VectorType *VT = E->getType()->castAs(); unsigned NumInits = E->getNumInits(); unsigned NumElements = VT->getNumElements(); QualType EltTy = VT->getElementType(); SmallVector Elements; // The number of initializers can be less than the number of // vector elements. For OpenCL, this can be due to nested vector // initialization. For GCC compatibility, missing trailing elements // should be initialized with zeroes. unsigned CountInits = 0, CountElts = 0; while (CountElts < NumElements) { // Handle nested vector initialization. if (CountInits < NumInits && E->getInit(CountInits)->getType()->isVectorType()) { APValue v; if (!EvaluateVector(E->getInit(CountInits), v, Info)) return Error(E); unsigned vlen = v.getVectorLength(); for (unsigned j = 0; j < vlen; j++) Elements.push_back(v.getVectorElt(j)); CountElts += vlen; } else if (EltTy->isIntegerType()) { llvm::APSInt sInt(32); if (CountInits < NumInits) { if (!EvaluateInteger(E->getInit(CountInits), sInt, Info)) return false; } else // trailing integer zero. sInt = Info.Ctx.MakeIntValue(0, EltTy); Elements.push_back(APValue(sInt)); CountElts++; } else { llvm::APFloat f(0.0); if (CountInits < NumInits) { if (!EvaluateFloat(E->getInit(CountInits), f, Info)) return false; } else // trailing float zero. f = APFloat::getZero(Info.Ctx.getFloatTypeSemantics(EltTy)); Elements.push_back(APValue(f)); CountElts++; } CountInits++; } return Success(Elements, E); } bool VectorExprEvaluator::ZeroInitialization(const Expr *E) { const VectorType *VT = E->getType()->getAs(); QualType EltTy = VT->getElementType(); APValue ZeroElement; if (EltTy->isIntegerType()) ZeroElement = APValue(Info.Ctx.MakeIntValue(0, EltTy)); else ZeroElement = APValue(APFloat::getZero(Info.Ctx.getFloatTypeSemantics(EltTy))); SmallVector Elements(VT->getNumElements(), ZeroElement); return Success(Elements, E); } bool VectorExprEvaluator::VisitUnaryImag(const UnaryOperator *E) { VisitIgnoredValue(E->getSubExpr()); return ZeroInitialization(E); } //===----------------------------------------------------------------------===// // Array Evaluation //===----------------------------------------------------------------------===// namespace { class ArrayExprEvaluator : public ExprEvaluatorBase { const LValue &This; APValue &Result; public: ArrayExprEvaluator(EvalInfo &Info, const LValue &This, APValue &Result) : ExprEvaluatorBaseTy(Info), This(This), Result(Result) {} bool Success(const APValue &V, const Expr *E) { assert((V.isArray() || V.isLValue()) && "expected array or string literal"); Result = V; return true; } bool ZeroInitialization(const Expr *E) { const ConstantArrayType *CAT = Info.Ctx.getAsConstantArrayType(E->getType()); if (!CAT) return Error(E); Result = APValue(APValue::UninitArray(), 0, CAT->getSize().getZExtValue()); if (!Result.hasArrayFiller()) return true; // Zero-initialize all elements. LValue Subobject = This; Subobject.addArray(Info, E, CAT); ImplicitValueInitExpr VIE(CAT->getElementType()); return EvaluateInPlace(Result.getArrayFiller(), Info, Subobject, &VIE); } bool VisitCallExpr(const CallExpr *E) { return handleCallExpr(E, Result, &This); } bool VisitInitListExpr(const InitListExpr *E); bool VisitArrayInitLoopExpr(const ArrayInitLoopExpr *E); bool VisitCXXConstructExpr(const CXXConstructExpr *E); bool VisitCXXConstructExpr(const CXXConstructExpr *E, const LValue &Subobject, APValue *Value, QualType Type); }; } // end anonymous namespace static bool EvaluateArray(const Expr *E, const LValue &This, APValue &Result, EvalInfo &Info) { assert(E->isRValue() && E->getType()->isArrayType() && "not an array rvalue"); return ArrayExprEvaluator(Info, This, Result).Visit(E); } // Return true iff the given array filler may depend on the element index. static bool MaybeElementDependentArrayFiller(const Expr *FillerExpr) { // For now, just whitelist non-class value-initialization and initialization // lists comprised of them. if (isa(FillerExpr)) return false; if (const InitListExpr *ILE = dyn_cast(FillerExpr)) { for (unsigned I = 0, E = ILE->getNumInits(); I != E; ++I) { if (MaybeElementDependentArrayFiller(ILE->getInit(I))) return true; } return false; } return true; } bool ArrayExprEvaluator::VisitInitListExpr(const InitListExpr *E) { const ConstantArrayType *CAT = Info.Ctx.getAsConstantArrayType(E->getType()); if (!CAT) return Error(E); // C++11 [dcl.init.string]p1: A char array [...] can be initialized by [...] // an appropriately-typed string literal enclosed in braces. if (E->isStringLiteralInit()) { LValue LV; if (!EvaluateLValue(E->getInit(0), LV, Info)) return false; APValue Val; LV.moveInto(Val); return Success(Val, E); } bool Success = true; assert((!Result.isArray() || Result.getArrayInitializedElts() == 0) && "zero-initialized array shouldn't have any initialized elts"); APValue Filler; if (Result.isArray() && Result.hasArrayFiller()) Filler = Result.getArrayFiller(); unsigned NumEltsToInit = E->getNumInits(); unsigned NumElts = CAT->getSize().getZExtValue(); const Expr *FillerExpr = E->hasArrayFiller() ? E->getArrayFiller() : nullptr; // If the initializer might depend on the array index, run it for each // array element. if (NumEltsToInit != NumElts && MaybeElementDependentArrayFiller(FillerExpr)) NumEltsToInit = NumElts; LLVM_DEBUG(llvm::dbgs() << "The number of elements to initialize: " << NumEltsToInit << ".\n"); Result = APValue(APValue::UninitArray(), NumEltsToInit, NumElts); // If the array was previously zero-initialized, preserve the // zero-initialized values. if (!Filler.isUninit()) { for (unsigned I = 0, E = Result.getArrayInitializedElts(); I != E; ++I) Result.getArrayInitializedElt(I) = Filler; if (Result.hasArrayFiller()) Result.getArrayFiller() = Filler; } LValue Subobject = This; Subobject.addArray(Info, E, CAT); for (unsigned Index = 0; Index != NumEltsToInit; ++Index) { const Expr *Init = Index < E->getNumInits() ? E->getInit(Index) : FillerExpr; if (!EvaluateInPlace(Result.getArrayInitializedElt(Index), Info, Subobject, Init) || !HandleLValueArrayAdjustment(Info, Init, Subobject, CAT->getElementType(), 1)) { if (!Info.noteFailure()) return false; Success = false; } } if (!Result.hasArrayFiller()) return Success; // If we get here, we have a trivial filler, which we can just evaluate // once and splat over the rest of the array elements. assert(FillerExpr && "no array filler for incomplete init list"); return EvaluateInPlace(Result.getArrayFiller(), Info, Subobject, FillerExpr) && Success; } bool ArrayExprEvaluator::VisitArrayInitLoopExpr(const ArrayInitLoopExpr *E) { if (E->getCommonExpr() && !Evaluate(Info.CurrentCall->createTemporary(E->getCommonExpr(), false), Info, E->getCommonExpr()->getSourceExpr())) return false; auto *CAT = cast(E->getType()->castAsArrayTypeUnsafe()); uint64_t Elements = CAT->getSize().getZExtValue(); Result = APValue(APValue::UninitArray(), Elements, Elements); LValue Subobject = This; Subobject.addArray(Info, E, CAT); bool Success = true; for (EvalInfo::ArrayInitLoopIndex Index(Info); Index != Elements; ++Index) { if (!EvaluateInPlace(Result.getArrayInitializedElt(Index), Info, Subobject, E->getSubExpr()) || !HandleLValueArrayAdjustment(Info, E, Subobject, CAT->getElementType(), 1)) { if (!Info.noteFailure()) return false; Success = false; } } return Success; } bool ArrayExprEvaluator::VisitCXXConstructExpr(const CXXConstructExpr *E) { return VisitCXXConstructExpr(E, This, &Result, E->getType()); } bool ArrayExprEvaluator::VisitCXXConstructExpr(const CXXConstructExpr *E, const LValue &Subobject, APValue *Value, QualType Type) { bool HadZeroInit = !Value->isUninit(); if (const ConstantArrayType *CAT = Info.Ctx.getAsConstantArrayType(Type)) { unsigned N = CAT->getSize().getZExtValue(); // Preserve the array filler if we had prior zero-initialization. APValue Filler = HadZeroInit && Value->hasArrayFiller() ? Value->getArrayFiller() : APValue(); *Value = APValue(APValue::UninitArray(), N, N); if (HadZeroInit) for (unsigned I = 0; I != N; ++I) Value->getArrayInitializedElt(I) = Filler; // Initialize the elements. LValue ArrayElt = Subobject; ArrayElt.addArray(Info, E, CAT); for (unsigned I = 0; I != N; ++I) if (!VisitCXXConstructExpr(E, ArrayElt, &Value->getArrayInitializedElt(I), CAT->getElementType()) || !HandleLValueArrayAdjustment(Info, E, ArrayElt, CAT->getElementType(), 1)) return false; return true; } if (!Type->isRecordType()) return Error(E); return RecordExprEvaluator(Info, Subobject, *Value) .VisitCXXConstructExpr(E, Type); } //===----------------------------------------------------------------------===// // Integer Evaluation // // As a GNU extension, we support casting pointers to sufficiently-wide integer // types and back in constant folding. Integer values are thus represented // either as an integer-valued APValue, or as an lvalue-valued APValue. //===----------------------------------------------------------------------===// namespace { class IntExprEvaluator : public ExprEvaluatorBase { APValue &Result; public: IntExprEvaluator(EvalInfo &info, APValue &result) : ExprEvaluatorBaseTy(info), Result(result) {} bool Success(const llvm::APSInt &SI, const Expr *E, APValue &Result) { assert(E->getType()->isIntegralOrEnumerationType() && "Invalid evaluation result."); assert(SI.isSigned() == E->getType()->isSignedIntegerOrEnumerationType() && "Invalid evaluation result."); assert(SI.getBitWidth() == Info.Ctx.getIntWidth(E->getType()) && "Invalid evaluation result."); Result = APValue(SI); return true; } bool Success(const llvm::APSInt &SI, const Expr *E) { return Success(SI, E, Result); } bool Success(const llvm::APInt &I, const Expr *E, APValue &Result) { assert(E->getType()->isIntegralOrEnumerationType() && "Invalid evaluation result."); assert(I.getBitWidth() == Info.Ctx.getIntWidth(E->getType()) && "Invalid evaluation result."); Result = APValue(APSInt(I)); Result.getInt().setIsUnsigned( E->getType()->isUnsignedIntegerOrEnumerationType()); return true; } bool Success(const llvm::APInt &I, const Expr *E) { return Success(I, E, Result); } bool Success(uint64_t Value, const Expr *E, APValue &Result) { assert(E->getType()->isIntegralOrEnumerationType() && "Invalid evaluation result."); Result = APValue(Info.Ctx.MakeIntValue(Value, E->getType())); return true; } bool Success(uint64_t Value, const Expr *E) { return Success(Value, E, Result); } bool Success(CharUnits Size, const Expr *E) { return Success(Size.getQuantity(), E); } bool Success(const APValue &V, const Expr *E) { if (V.isLValue() || V.isAddrLabelDiff()) { Result = V; return true; } return Success(V.getInt(), E); } bool ZeroInitialization(const Expr *E) { return Success(0, E); } //===--------------------------------------------------------------------===// // Visitor Methods //===--------------------------------------------------------------------===// bool VisitIntegerLiteral(const IntegerLiteral *E) { return Success(E->getValue(), E); } bool VisitCharacterLiteral(const CharacterLiteral *E) { return Success(E->getValue(), E); } bool CheckReferencedDecl(const Expr *E, const Decl *D); bool VisitDeclRefExpr(const DeclRefExpr *E) { if (CheckReferencedDecl(E, E->getDecl())) return true; return ExprEvaluatorBaseTy::VisitDeclRefExpr(E); } bool VisitMemberExpr(const MemberExpr *E) { if (CheckReferencedDecl(E, E->getMemberDecl())) { VisitIgnoredBaseExpression(E->getBase()); return true; } return ExprEvaluatorBaseTy::VisitMemberExpr(E); } bool VisitCallExpr(const CallExpr *E); bool VisitBuiltinCallExpr(const CallExpr *E, unsigned BuiltinOp); bool VisitBinaryOperator(const BinaryOperator *E); bool VisitOffsetOfExpr(const OffsetOfExpr *E); bool VisitUnaryOperator(const UnaryOperator *E); bool VisitCastExpr(const CastExpr* E); bool VisitUnaryExprOrTypeTraitExpr(const UnaryExprOrTypeTraitExpr *E); bool VisitCXXBoolLiteralExpr(const CXXBoolLiteralExpr *E) { return Success(E->getValue(), E); } bool VisitObjCBoolLiteralExpr(const ObjCBoolLiteralExpr *E) { return Success(E->getValue(), E); } bool VisitArrayInitIndexExpr(const ArrayInitIndexExpr *E) { if (Info.ArrayInitIndex == uint64_t(-1)) { // We were asked to evaluate this subexpression independent of the // enclosing ArrayInitLoopExpr. We can't do that. Info.FFDiag(E); return false; } return Success(Info.ArrayInitIndex, E); } // Note, GNU defines __null as an integer, not a pointer. bool VisitGNUNullExpr(const GNUNullExpr *E) { return ZeroInitialization(E); } bool VisitTypeTraitExpr(const TypeTraitExpr *E) { return Success(E->getValue(), E); } bool VisitArrayTypeTraitExpr(const ArrayTypeTraitExpr *E) { return Success(E->getValue(), E); } bool VisitExpressionTraitExpr(const ExpressionTraitExpr *E) { return Success(E->getValue(), E); } bool VisitUnaryReal(const UnaryOperator *E); bool VisitUnaryImag(const UnaryOperator *E); bool VisitCXXNoexceptExpr(const CXXNoexceptExpr *E); bool VisitSizeOfPackExpr(const SizeOfPackExpr *E); // FIXME: Missing: array subscript of vector, member of vector }; class FixedPointExprEvaluator : public ExprEvaluatorBase { APValue &Result; public: FixedPointExprEvaluator(EvalInfo &info, APValue &result) : ExprEvaluatorBaseTy(info), Result(result) {} bool Success(const llvm::APSInt &SI, const Expr *E, APValue &Result) { assert(E->getType()->isFixedPointType() && "Invalid evaluation result."); assert(SI.isSigned() == E->getType()->isSignedFixedPointType() && "Invalid evaluation result."); assert(SI.getBitWidth() == Info.Ctx.getIntWidth(E->getType()) && "Invalid evaluation result."); Result = APValue(SI); return true; } bool Success(const llvm::APSInt &SI, const Expr *E) { return Success(SI, E, Result); } bool Success(const llvm::APInt &I, const Expr *E, APValue &Result) { assert(E->getType()->isFixedPointType() && "Invalid evaluation result."); assert(I.getBitWidth() == Info.Ctx.getIntWidth(E->getType()) && "Invalid evaluation result."); Result = APValue(APSInt(I)); Result.getInt().setIsUnsigned(E->getType()->isUnsignedFixedPointType()); return true; } bool Success(const llvm::APInt &I, const Expr *E) { return Success(I, E, Result); } bool Success(uint64_t Value, const Expr *E, APValue &Result) { assert(E->getType()->isFixedPointType() && "Invalid evaluation result."); Result = APValue(Info.Ctx.MakeIntValue(Value, E->getType())); return true; } bool Success(uint64_t Value, const Expr *E) { return Success(Value, E, Result); } bool Success(CharUnits Size, const Expr *E) { return Success(Size.getQuantity(), E); } bool Success(const APValue &V, const Expr *E) { if (V.isLValue() || V.isAddrLabelDiff()) { Result = V; return true; } return Success(V.getInt(), E); } bool ZeroInitialization(const Expr *E) { return Success(0, E); } //===--------------------------------------------------------------------===// // Visitor Methods //===--------------------------------------------------------------------===// bool VisitFixedPointLiteral(const FixedPointLiteral *E) { return Success(E->getValue(), E); } bool VisitUnaryOperator(const UnaryOperator *E); }; } // end anonymous namespace /// EvaluateIntegerOrLValue - Evaluate an rvalue integral-typed expression, and /// produce either the integer value or a pointer. /// /// GCC has a heinous extension which folds casts between pointer types and /// pointer-sized integral types. We support this by allowing the evaluation of /// an integer rvalue to produce a pointer (represented as an lvalue) instead. /// Some simple arithmetic on such values is supported (they are treated much /// like char*). static bool EvaluateIntegerOrLValue(const Expr *E, APValue &Result, EvalInfo &Info) { assert(E->isRValue() && E->getType()->isIntegralOrEnumerationType()); return IntExprEvaluator(Info, Result).Visit(E); } static bool EvaluateInteger(const Expr *E, APSInt &Result, EvalInfo &Info) { APValue Val; if (!EvaluateIntegerOrLValue(E, Val, Info)) return false; if (!Val.isInt()) { // FIXME: It would be better to produce the diagnostic for casting // a pointer to an integer. Info.FFDiag(E, diag::note_invalid_subexpr_in_const_expr); return false; } Result = Val.getInt(); return true; } /// Check whether the given declaration can be directly converted to an integral /// rvalue. If not, no diagnostic is produced; there are other things we can /// try. bool IntExprEvaluator::CheckReferencedDecl(const Expr* E, const Decl* D) { // Enums are integer constant exprs. if (const EnumConstantDecl *ECD = dyn_cast(D)) { // Check for signedness/width mismatches between E type and ECD value. bool SameSign = (ECD->getInitVal().isSigned() == E->getType()->isSignedIntegerOrEnumerationType()); bool SameWidth = (ECD->getInitVal().getBitWidth() == Info.Ctx.getIntWidth(E->getType())); if (SameSign && SameWidth) return Success(ECD->getInitVal(), E); else { // Get rid of mismatch (otherwise Success assertions will fail) // by computing a new value matching the type of E. llvm::APSInt Val = ECD->getInitVal(); if (!SameSign) Val.setIsSigned(!ECD->getInitVal().isSigned()); if (!SameWidth) Val = Val.extOrTrunc(Info.Ctx.getIntWidth(E->getType())); return Success(Val, E); } } return false; } /// Values returned by __builtin_classify_type, chosen to match the values /// produced by GCC's builtin. enum class GCCTypeClass { None = -1, Void = 0, Integer = 1, // GCC reserves 2 for character types, but instead classifies them as // integers. Enum = 3, Bool = 4, Pointer = 5, // GCC reserves 6 for references, but appears to never use it (because // expressions never have reference type, presumably). PointerToDataMember = 7, RealFloat = 8, Complex = 9, // GCC reserves 10 for functions, but does not use it since GCC version 6 due // to decay to pointer. (Prior to version 6 it was only used in C++ mode). // GCC claims to reserve 11 for pointers to member functions, but *actually* // uses 12 for that purpose, same as for a class or struct. Maybe it // internally implements a pointer to member as a struct? Who knows. PointerToMemberFunction = 12, // Not a bug, see above. ClassOrStruct = 12, Union = 13, // GCC reserves 14 for arrays, but does not use it since GCC version 6 due to // decay to pointer. (Prior to version 6 it was only used in C++ mode). // GCC reserves 15 for strings, but actually uses 5 (pointer) for string // literals. }; /// EvaluateBuiltinClassifyType - Evaluate __builtin_classify_type the same way /// as GCC. static GCCTypeClass EvaluateBuiltinClassifyType(QualType T, const LangOptions &LangOpts) { assert(!T->isDependentType() && "unexpected dependent type"); QualType CanTy = T.getCanonicalType(); const BuiltinType *BT = dyn_cast(CanTy); switch (CanTy->getTypeClass()) { #define TYPE(ID, BASE) #define DEPENDENT_TYPE(ID, BASE) case Type::ID: #define NON_CANONICAL_TYPE(ID, BASE) case Type::ID: #define NON_CANONICAL_UNLESS_DEPENDENT_TYPE(ID, BASE) case Type::ID: #include "clang/AST/TypeNodes.def" case Type::Auto: case Type::DeducedTemplateSpecialization: llvm_unreachable("unexpected non-canonical or dependent type"); case Type::Builtin: switch (BT->getKind()) { #define BUILTIN_TYPE(ID, SINGLETON_ID) #define SIGNED_TYPE(ID, SINGLETON_ID) \ case BuiltinType::ID: return GCCTypeClass::Integer; #define FLOATING_TYPE(ID, SINGLETON_ID) \ case BuiltinType::ID: return GCCTypeClass::RealFloat; #define PLACEHOLDER_TYPE(ID, SINGLETON_ID) \ case BuiltinType::ID: break; #include "clang/AST/BuiltinTypes.def" case BuiltinType::Void: return GCCTypeClass::Void; case BuiltinType::Bool: return GCCTypeClass::Bool; case BuiltinType::Char_U: case BuiltinType::UChar: case BuiltinType::WChar_U: case BuiltinType::Char8: case BuiltinType::Char16: case BuiltinType::Char32: case BuiltinType::UShort: case BuiltinType::UInt: case BuiltinType::ULong: case BuiltinType::ULongLong: case BuiltinType::UInt128: return GCCTypeClass::Integer; case BuiltinType::UShortAccum: case BuiltinType::UAccum: case BuiltinType::ULongAccum: case BuiltinType::UShortFract: case BuiltinType::UFract: case BuiltinType::ULongFract: case BuiltinType::SatUShortAccum: case BuiltinType::SatUAccum: case BuiltinType::SatULongAccum: case BuiltinType::SatUShortFract: case BuiltinType::SatUFract: case BuiltinType::SatULongFract: return GCCTypeClass::None; case BuiltinType::NullPtr: case BuiltinType::ObjCId: case BuiltinType::ObjCClass: case BuiltinType::ObjCSel: #define IMAGE_TYPE(ImgType, Id, SingletonId, Access, Suffix) \ case BuiltinType::Id: #include "clang/Basic/OpenCLImageTypes.def" case BuiltinType::OCLSampler: case BuiltinType::OCLEvent: case BuiltinType::OCLClkEvent: case BuiltinType::OCLQueue: case BuiltinType::OCLReserveID: return GCCTypeClass::None; case BuiltinType::Dependent: llvm_unreachable("unexpected dependent type"); }; llvm_unreachable("unexpected placeholder type"); case Type::Enum: return LangOpts.CPlusPlus ? GCCTypeClass::Enum : GCCTypeClass::Integer; case Type::Pointer: case Type::ConstantArray: case Type::VariableArray: case Type::IncompleteArray: case Type::FunctionNoProto: case Type::FunctionProto: return GCCTypeClass::Pointer; case Type::MemberPointer: return CanTy->isMemberDataPointerType() ? GCCTypeClass::PointerToDataMember : GCCTypeClass::PointerToMemberFunction; case Type::Complex: return GCCTypeClass::Complex; case Type::Record: return CanTy->isUnionType() ? GCCTypeClass::Union : GCCTypeClass::ClassOrStruct; case Type::Atomic: // GCC classifies _Atomic T the same as T. return EvaluateBuiltinClassifyType( CanTy->castAs()->getValueType(), LangOpts); case Type::BlockPointer: case Type::Vector: case Type::ExtVector: case Type::ObjCObject: case Type::ObjCInterface: case Type::ObjCObjectPointer: case Type::Pipe: // GCC classifies vectors as None. We follow its lead and classify all // other types that don't fit into the regular classification the same way. return GCCTypeClass::None; case Type::LValueReference: case Type::RValueReference: llvm_unreachable("invalid type for expression"); } llvm_unreachable("unexpected type class"); } /// EvaluateBuiltinClassifyType - Evaluate __builtin_classify_type the same way /// as GCC. static GCCTypeClass EvaluateBuiltinClassifyType(const CallExpr *E, const LangOptions &LangOpts) { // If no argument was supplied, default to None. This isn't // ideal, however it is what gcc does. if (E->getNumArgs() == 0) return GCCTypeClass::None; // FIXME: Bizarrely, GCC treats a call with more than one argument as not // being an ICE, but still folds it to a constant using the type of the first // argument. return EvaluateBuiltinClassifyType(E->getArg(0)->getType(), LangOpts); } /// EvaluateBuiltinConstantPForLValue - Determine the result of /// __builtin_constant_p when applied to the given lvalue. /// /// An lvalue is only "constant" if it is a pointer or reference to the first /// character of a string literal. template static bool EvaluateBuiltinConstantPForLValue(const LValue &LV) { const Expr *E = LV.getLValueBase().template dyn_cast(); return E && isa(E) && LV.getLValueOffset().isZero(); } /// EvaluateBuiltinConstantP - Evaluate __builtin_constant_p as similarly to /// GCC as we can manage. static bool EvaluateBuiltinConstantP(ASTContext &Ctx, const Expr *Arg) { QualType ArgType = Arg->getType(); // __builtin_constant_p always has one operand. The rules which gcc follows // are not precisely documented, but are as follows: // // - If the operand is of integral, floating, complex or enumeration type, // and can be folded to a known value of that type, it returns 1. // - If the operand and can be folded to a pointer to the first character // of a string literal (or such a pointer cast to an integral type), it // returns 1. // // Otherwise, it returns 0. // // FIXME: GCC also intends to return 1 for literals of aggregate types, but // its support for this does not currently work. if (ArgType->isIntegralOrEnumerationType()) { Expr::EvalResult Result; if (!Arg->EvaluateAsRValue(Result, Ctx) || Result.HasSideEffects) return false; APValue &V = Result.Val; if (V.getKind() == APValue::Int) return true; if (V.getKind() == APValue::LValue) return EvaluateBuiltinConstantPForLValue(V); } else if (ArgType->isFloatingType() || ArgType->isAnyComplexType()) { return Arg->isEvaluatable(Ctx); } else if (ArgType->isPointerType() || Arg->isGLValue()) { LValue LV; Expr::EvalStatus Status; EvalInfo Info(Ctx, Status, EvalInfo::EM_ConstantFold); if ((Arg->isGLValue() ? EvaluateLValue(Arg, LV, Info) : EvaluatePointer(Arg, LV, Info)) && !Status.HasSideEffects) return EvaluateBuiltinConstantPForLValue(LV); } // Anything else isn't considered to be sufficiently constant. return false; } /// Retrieves the "underlying object type" of the given expression, /// as used by __builtin_object_size. static QualType getObjectType(APValue::LValueBase B) { if (const ValueDecl *D = B.dyn_cast()) { if (const VarDecl *VD = dyn_cast(D)) return VD->getType(); } else if (const Expr *E = B.get()) { if (isa(E)) return E->getType(); } return QualType(); } /// A more selective version of E->IgnoreParenCasts for /// tryEvaluateBuiltinObjectSize. This ignores some casts/parens that serve only /// to change the type of E. /// Ex. For E = `(short*)((char*)(&foo))`, returns `&foo` /// /// Always returns an RValue with a pointer representation. static const Expr *ignorePointerCastsAndParens(const Expr *E) { assert(E->isRValue() && E->getType()->hasPointerRepresentation()); auto *NoParens = E->IgnoreParens(); auto *Cast = dyn_cast(NoParens); if (Cast == nullptr) return NoParens; // We only conservatively allow a few kinds of casts, because this code is // inherently a simple solution that seeks to support the common case. auto CastKind = Cast->getCastKind(); if (CastKind != CK_NoOp && CastKind != CK_BitCast && CastKind != CK_AddressSpaceConversion) return NoParens; auto *SubExpr = Cast->getSubExpr(); if (!SubExpr->getType()->hasPointerRepresentation() || !SubExpr->isRValue()) return NoParens; return ignorePointerCastsAndParens(SubExpr); } /// Checks to see if the given LValue's Designator is at the end of the LValue's /// record layout. e.g. /// struct { struct { int a, b; } fst, snd; } obj; /// obj.fst // no /// obj.snd // yes /// obj.fst.a // no /// obj.fst.b // no /// obj.snd.a // no /// obj.snd.b // yes /// /// Please note: this function is specialized for how __builtin_object_size /// views "objects". /// /// If this encounters an invalid RecordDecl or otherwise cannot determine the /// correct result, it will always return true. static bool isDesignatorAtObjectEnd(const ASTContext &Ctx, const LValue &LVal) { assert(!LVal.Designator.Invalid); auto IsLastOrInvalidFieldDecl = [&Ctx](const FieldDecl *FD, bool &Invalid) { const RecordDecl *Parent = FD->getParent(); Invalid = Parent->isInvalidDecl(); if (Invalid || Parent->isUnion()) return true; const ASTRecordLayout &Layout = Ctx.getASTRecordLayout(Parent); return FD->getFieldIndex() + 1 == Layout.getFieldCount(); }; auto &Base = LVal.getLValueBase(); if (auto *ME = dyn_cast_or_null(Base.dyn_cast())) { if (auto *FD = dyn_cast(ME->getMemberDecl())) { bool Invalid; if (!IsLastOrInvalidFieldDecl(FD, Invalid)) return Invalid; } else if (auto *IFD = dyn_cast(ME->getMemberDecl())) { for (auto *FD : IFD->chain()) { bool Invalid; if (!IsLastOrInvalidFieldDecl(cast(FD), Invalid)) return Invalid; } } } unsigned I = 0; QualType BaseType = getType(Base); if (LVal.Designator.FirstEntryIsAnUnsizedArray) { // If we don't know the array bound, conservatively assume we're looking at // the final array element. ++I; if (BaseType->isIncompleteArrayType()) BaseType = Ctx.getAsArrayType(BaseType)->getElementType(); else BaseType = BaseType->castAs()->getPointeeType(); } for (unsigned E = LVal.Designator.Entries.size(); I != E; ++I) { const auto &Entry = LVal.Designator.Entries[I]; if (BaseType->isArrayType()) { // Because __builtin_object_size treats arrays as objects, we can ignore // the index iff this is the last array in the Designator. if (I + 1 == E) return true; const auto *CAT = cast(Ctx.getAsArrayType(BaseType)); uint64_t Index = Entry.ArrayIndex; if (Index + 1 != CAT->getSize()) return false; BaseType = CAT->getElementType(); } else if (BaseType->isAnyComplexType()) { const auto *CT = BaseType->castAs(); uint64_t Index = Entry.ArrayIndex; if (Index != 1) return false; BaseType = CT->getElementType(); } else if (auto *FD = getAsField(Entry)) { bool Invalid; if (!IsLastOrInvalidFieldDecl(FD, Invalid)) return Invalid; BaseType = FD->getType(); } else { assert(getAsBaseClass(Entry) && "Expecting cast to a base class"); return false; } } return true; } /// Tests to see if the LValue has a user-specified designator (that isn't /// necessarily valid). Note that this always returns 'true' if the LValue has /// an unsized array as its first designator entry, because there's currently no /// way to tell if the user typed *foo or foo[0]. static bool refersToCompleteObject(const LValue &LVal) { if (LVal.Designator.Invalid) return false; if (!LVal.Designator.Entries.empty()) return LVal.Designator.isMostDerivedAnUnsizedArray(); if (!LVal.InvalidBase) return true; // If `E` is a MemberExpr, then the first part of the designator is hiding in // the LValueBase. const auto *E = LVal.Base.dyn_cast(); return !E || !isa(E); } /// Attempts to detect a user writing into a piece of memory that's impossible /// to figure out the size of by just using types. static bool isUserWritingOffTheEnd(const ASTContext &Ctx, const LValue &LVal) { const SubobjectDesignator &Designator = LVal.Designator; // Notes: // - Users can only write off of the end when we have an invalid base. Invalid // bases imply we don't know where the memory came from. // - We used to be a bit more aggressive here; we'd only be conservative if // the array at the end was flexible, or if it had 0 or 1 elements. This // broke some common standard library extensions (PR30346), but was // otherwise seemingly fine. It may be useful to reintroduce this behavior // with some sort of whitelist. OTOH, it seems that GCC is always // conservative with the last element in structs (if it's an array), so our // current behavior is more compatible than a whitelisting approach would // be. return LVal.InvalidBase && Designator.Entries.size() == Designator.MostDerivedPathLength && Designator.MostDerivedIsArrayElement && isDesignatorAtObjectEnd(Ctx, LVal); } /// Converts the given APInt to CharUnits, assuming the APInt is unsigned. /// Fails if the conversion would cause loss of precision. static bool convertUnsignedAPIntToCharUnits(const llvm::APInt &Int, CharUnits &Result) { auto CharUnitsMax = std::numeric_limits::max(); if (Int.ugt(CharUnitsMax)) return false; Result = CharUnits::fromQuantity(Int.getZExtValue()); return true; } /// Helper for tryEvaluateBuiltinObjectSize -- Given an LValue, this will /// determine how many bytes exist from the beginning of the object to either /// the end of the current subobject, or the end of the object itself, depending /// on what the LValue looks like + the value of Type. /// /// If this returns false, the value of Result is undefined. static bool determineEndOffset(EvalInfo &Info, SourceLocation ExprLoc, unsigned Type, const LValue &LVal, CharUnits &EndOffset) { bool DetermineForCompleteObject = refersToCompleteObject(LVal); auto CheckedHandleSizeof = [&](QualType Ty, CharUnits &Result) { if (Ty.isNull() || Ty->isIncompleteType() || Ty->isFunctionType()) return false; return HandleSizeof(Info, ExprLoc, Ty, Result); }; // We want to evaluate the size of the entire object. This is a valid fallback // for when Type=1 and the designator is invalid, because we're asked for an // upper-bound. if (!(Type & 1) || LVal.Designator.Invalid || DetermineForCompleteObject) { // Type=3 wants a lower bound, so we can't fall back to this. if (Type == 3 && !DetermineForCompleteObject) return false; llvm::APInt APEndOffset; if (isBaseAnAllocSizeCall(LVal.getLValueBase()) && getBytesReturnedByAllocSizeCall(Info.Ctx, LVal, APEndOffset)) return convertUnsignedAPIntToCharUnits(APEndOffset, EndOffset); if (LVal.InvalidBase) return false; QualType BaseTy = getObjectType(LVal.getLValueBase()); return CheckedHandleSizeof(BaseTy, EndOffset); } // We want to evaluate the size of a subobject. const SubobjectDesignator &Designator = LVal.Designator; // The following is a moderately common idiom in C: // // struct Foo { int a; char c[1]; }; // struct Foo *F = (struct Foo *)malloc(sizeof(struct Foo) + strlen(Bar)); // strcpy(&F->c[0], Bar); // // In order to not break too much legacy code, we need to support it. if (isUserWritingOffTheEnd(Info.Ctx, LVal)) { // If we can resolve this to an alloc_size call, we can hand that back, // because we know for certain how many bytes there are to write to. llvm::APInt APEndOffset; if (isBaseAnAllocSizeCall(LVal.getLValueBase()) && getBytesReturnedByAllocSizeCall(Info.Ctx, LVal, APEndOffset)) return convertUnsignedAPIntToCharUnits(APEndOffset, EndOffset); // If we cannot determine the size of the initial allocation, then we can't // given an accurate upper-bound. However, we are still able to give // conservative lower-bounds for Type=3. if (Type == 1) return false; } CharUnits BytesPerElem; if (!CheckedHandleSizeof(Designator.MostDerivedType, BytesPerElem)) return false; // According to the GCC documentation, we want the size of the subobject // denoted by the pointer. But that's not quite right -- what we actually // want is the size of the immediately-enclosing array, if there is one. int64_t ElemsRemaining; if (Designator.MostDerivedIsArrayElement && Designator.Entries.size() == Designator.MostDerivedPathLength) { uint64_t ArraySize = Designator.getMostDerivedArraySize(); uint64_t ArrayIndex = Designator.Entries.back().ArrayIndex; ElemsRemaining = ArraySize <= ArrayIndex ? 0 : ArraySize - ArrayIndex; } else { ElemsRemaining = Designator.isOnePastTheEnd() ? 0 : 1; } EndOffset = LVal.getLValueOffset() + BytesPerElem * ElemsRemaining; return true; } /// Tries to evaluate the __builtin_object_size for @p E. If successful, /// returns true and stores the result in @p Size. /// /// If @p WasError is non-null, this will report whether the failure to evaluate /// is to be treated as an Error in IntExprEvaluator. static bool tryEvaluateBuiltinObjectSize(const Expr *E, unsigned Type, EvalInfo &Info, uint64_t &Size) { // Determine the denoted object. LValue LVal; { // The operand of __builtin_object_size is never evaluated for side-effects. // If there are any, but we can determine the pointed-to object anyway, then // ignore the side-effects. SpeculativeEvaluationRAII SpeculativeEval(Info); FoldOffsetRAII Fold(Info); if (E->isGLValue()) { // It's possible for us to be given GLValues if we're called via // Expr::tryEvaluateObjectSize. APValue RVal; if (!EvaluateAsRValue(Info, E, RVal)) return false; LVal.setFrom(Info.Ctx, RVal); } else if (!EvaluatePointer(ignorePointerCastsAndParens(E), LVal, Info, /*InvalidBaseOK=*/true)) return false; } // If we point to before the start of the object, there are no accessible // bytes. if (LVal.getLValueOffset().isNegative()) { Size = 0; return true; } CharUnits EndOffset; if (!determineEndOffset(Info, E->getExprLoc(), Type, LVal, EndOffset)) return false; // If we've fallen outside of the end offset, just pretend there's nothing to // write to/read from. if (EndOffset <= LVal.getLValueOffset()) Size = 0; else Size = (EndOffset - LVal.getLValueOffset()).getQuantity(); return true; } bool IntExprEvaluator::VisitCallExpr(const CallExpr *E) { if (unsigned BuiltinOp = E->getBuiltinCallee()) return VisitBuiltinCallExpr(E, BuiltinOp); return ExprEvaluatorBaseTy::VisitCallExpr(E); } bool IntExprEvaluator::VisitBuiltinCallExpr(const CallExpr *E, unsigned BuiltinOp) { switch (unsigned BuiltinOp = E->getBuiltinCallee()) { default: return ExprEvaluatorBaseTy::VisitCallExpr(E); case Builtin::BI__builtin_object_size: { // The type was checked when we built the expression. unsigned Type = E->getArg(1)->EvaluateKnownConstInt(Info.Ctx).getZExtValue(); assert(Type <= 3 && "unexpected type"); uint64_t Size; if (tryEvaluateBuiltinObjectSize(E->getArg(0), Type, Info, Size)) return Success(Size, E); if (E->getArg(0)->HasSideEffects(Info.Ctx)) return Success((Type & 2) ? 0 : -1, E); // Expression had no side effects, but we couldn't statically determine the // size of the referenced object. switch (Info.EvalMode) { case EvalInfo::EM_ConstantExpression: case EvalInfo::EM_PotentialConstantExpression: case EvalInfo::EM_ConstantFold: case EvalInfo::EM_EvaluateForOverflow: case EvalInfo::EM_IgnoreSideEffects: case EvalInfo::EM_OffsetFold: // Leave it to IR generation. return Error(E); case EvalInfo::EM_ConstantExpressionUnevaluated: case EvalInfo::EM_PotentialConstantExpressionUnevaluated: // Reduce it to a constant now. return Success((Type & 2) ? 0 : -1, E); } llvm_unreachable("unexpected EvalMode"); } case Builtin::BI__builtin_bswap16: case Builtin::BI__builtin_bswap32: case Builtin::BI__builtin_bswap64: { APSInt Val; if (!EvaluateInteger(E->getArg(0), Val, Info)) return false; return Success(Val.byteSwap(), E); } case Builtin::BI__builtin_classify_type: return Success((int)EvaluateBuiltinClassifyType(E, Info.getLangOpts()), E); // FIXME: BI__builtin_clrsb // FIXME: BI__builtin_clrsbl // FIXME: BI__builtin_clrsbll case Builtin::BI__builtin_clz: case Builtin::BI__builtin_clzl: case Builtin::BI__builtin_clzll: case Builtin::BI__builtin_clzs: { APSInt Val; if (!EvaluateInteger(E->getArg(0), Val, Info)) return false; if (!Val) return Error(E); return Success(Val.countLeadingZeros(), E); } case Builtin::BI__builtin_constant_p: return Success(EvaluateBuiltinConstantP(Info.Ctx, E->getArg(0)), E); case Builtin::BI__builtin_ctz: case Builtin::BI__builtin_ctzl: case Builtin::BI__builtin_ctzll: case Builtin::BI__builtin_ctzs: { APSInt Val; if (!EvaluateInteger(E->getArg(0), Val, Info)) return false; if (!Val) return Error(E); return Success(Val.countTrailingZeros(), E); } case Builtin::BI__builtin_eh_return_data_regno: { int Operand = E->getArg(0)->EvaluateKnownConstInt(Info.Ctx).getZExtValue(); Operand = Info.Ctx.getTargetInfo().getEHDataRegisterNumber(Operand); return Success(Operand, E); } case Builtin::BI__builtin_expect: return Visit(E->getArg(0)); case Builtin::BI__builtin_ffs: case Builtin::BI__builtin_ffsl: case Builtin::BI__builtin_ffsll: { APSInt Val; if (!EvaluateInteger(E->getArg(0), Val, Info)) return false; unsigned N = Val.countTrailingZeros(); return Success(N == Val.getBitWidth() ? 0 : N + 1, E); } case Builtin::BI__builtin_fpclassify: { APFloat Val(0.0); if (!EvaluateFloat(E->getArg(5), Val, Info)) return false; unsigned Arg; switch (Val.getCategory()) { case APFloat::fcNaN: Arg = 0; break; case APFloat::fcInfinity: Arg = 1; break; case APFloat::fcNormal: Arg = Val.isDenormal() ? 3 : 2; break; case APFloat::fcZero: Arg = 4; break; } return Visit(E->getArg(Arg)); } case Builtin::BI__builtin_isinf_sign: { APFloat Val(0.0); return EvaluateFloat(E->getArg(0), Val, Info) && Success(Val.isInfinity() ? (Val.isNegative() ? -1 : 1) : 0, E); } case Builtin::BI__builtin_isinf: { APFloat Val(0.0); return EvaluateFloat(E->getArg(0), Val, Info) && Success(Val.isInfinity() ? 1 : 0, E); } case Builtin::BI__builtin_isfinite: { APFloat Val(0.0); return EvaluateFloat(E->getArg(0), Val, Info) && Success(Val.isFinite() ? 1 : 0, E); } case Builtin::BI__builtin_isnan: { APFloat Val(0.0); return EvaluateFloat(E->getArg(0), Val, Info) && Success(Val.isNaN() ? 1 : 0, E); } case Builtin::BI__builtin_isnormal: { APFloat Val(0.0); return EvaluateFloat(E->getArg(0), Val, Info) && Success(Val.isNormal() ? 1 : 0, E); } case Builtin::BI__builtin_parity: case Builtin::BI__builtin_parityl: case Builtin::BI__builtin_parityll: { APSInt Val; if (!EvaluateInteger(E->getArg(0), Val, Info)) return false; return Success(Val.countPopulation() % 2, E); } case Builtin::BI__builtin_popcount: case Builtin::BI__builtin_popcountl: case Builtin::BI__builtin_popcountll: { APSInt Val; if (!EvaluateInteger(E->getArg(0), Val, Info)) return false; return Success(Val.countPopulation(), E); } case Builtin::BIstrlen: case Builtin::BIwcslen: // A call to strlen is not a constant expression. if (Info.getLangOpts().CPlusPlus11) Info.CCEDiag(E, diag::note_constexpr_invalid_function) << /*isConstexpr*/0 << /*isConstructor*/0 << (std::string("'") + Info.Ctx.BuiltinInfo.getName(BuiltinOp) + "'"); else Info.CCEDiag(E, diag::note_invalid_subexpr_in_const_expr); LLVM_FALLTHROUGH; case Builtin::BI__builtin_strlen: case Builtin::BI__builtin_wcslen: { // As an extension, we support __builtin_strlen() as a constant expression, // and support folding strlen() to a constant. LValue String; if (!EvaluatePointer(E->getArg(0), String, Info)) return false; QualType CharTy = E->getArg(0)->getType()->getPointeeType(); // Fast path: if it's a string literal, search the string value. if (const StringLiteral *S = dyn_cast_or_null( String.getLValueBase().dyn_cast())) { // The string literal may have embedded null characters. Find the first // one and truncate there. StringRef Str = S->getBytes(); int64_t Off = String.Offset.getQuantity(); if (Off >= 0 && (uint64_t)Off <= (uint64_t)Str.size() && S->getCharByteWidth() == 1 && // FIXME: Add fast-path for wchar_t too. Info.Ctx.hasSameUnqualifiedType(CharTy, Info.Ctx.CharTy)) { Str = Str.substr(Off); StringRef::size_type Pos = Str.find(0); if (Pos != StringRef::npos) Str = Str.substr(0, Pos); return Success(Str.size(), E); } // Fall through to slow path to issue appropriate diagnostic. } // Slow path: scan the bytes of the string looking for the terminating 0. for (uint64_t Strlen = 0; /**/; ++Strlen) { APValue Char; if (!handleLValueToRValueConversion(Info, E, CharTy, String, Char) || !Char.isInt()) return false; if (!Char.getInt()) return Success(Strlen, E); if (!HandleLValueArrayAdjustment(Info, E, String, CharTy, 1)) return false; } } case Builtin::BIstrcmp: case Builtin::BIwcscmp: case Builtin::BIstrncmp: case Builtin::BIwcsncmp: case Builtin::BImemcmp: case Builtin::BIwmemcmp: // A call to strlen is not a constant expression. if (Info.getLangOpts().CPlusPlus11) Info.CCEDiag(E, diag::note_constexpr_invalid_function) << /*isConstexpr*/0 << /*isConstructor*/0 << (std::string("'") + Info.Ctx.BuiltinInfo.getName(BuiltinOp) + "'"); else Info.CCEDiag(E, diag::note_invalid_subexpr_in_const_expr); LLVM_FALLTHROUGH; case Builtin::BI__builtin_strcmp: case Builtin::BI__builtin_wcscmp: case Builtin::BI__builtin_strncmp: case Builtin::BI__builtin_wcsncmp: case Builtin::BI__builtin_memcmp: case Builtin::BI__builtin_wmemcmp: { LValue String1, String2; if (!EvaluatePointer(E->getArg(0), String1, Info) || !EvaluatePointer(E->getArg(1), String2, Info)) return false; QualType CharTy = E->getArg(0)->getType()->getPointeeType(); uint64_t MaxLength = uint64_t(-1); if (BuiltinOp != Builtin::BIstrcmp && BuiltinOp != Builtin::BIwcscmp && BuiltinOp != Builtin::BI__builtin_strcmp && BuiltinOp != Builtin::BI__builtin_wcscmp) { APSInt N; if (!EvaluateInteger(E->getArg(2), N, Info)) return false; MaxLength = N.getExtValue(); } bool StopAtNull = (BuiltinOp != Builtin::BImemcmp && BuiltinOp != Builtin::BIwmemcmp && BuiltinOp != Builtin::BI__builtin_memcmp && BuiltinOp != Builtin::BI__builtin_wmemcmp); bool IsWide = BuiltinOp == Builtin::BIwcscmp || BuiltinOp == Builtin::BIwcsncmp || BuiltinOp == Builtin::BIwmemcmp || BuiltinOp == Builtin::BI__builtin_wcscmp || BuiltinOp == Builtin::BI__builtin_wcsncmp || BuiltinOp == Builtin::BI__builtin_wmemcmp; for (; MaxLength; --MaxLength) { APValue Char1, Char2; if (!handleLValueToRValueConversion(Info, E, CharTy, String1, Char1) || !handleLValueToRValueConversion(Info, E, CharTy, String2, Char2) || !Char1.isInt() || !Char2.isInt()) return false; if (Char1.getInt() != Char2.getInt()) { if (IsWide) // wmemcmp compares with wchar_t signedness. return Success(Char1.getInt() < Char2.getInt() ? -1 : 1, E); // memcmp always compares unsigned chars. return Success(Char1.getInt().ult(Char2.getInt()) ? -1 : 1, E); } if (StopAtNull && !Char1.getInt()) return Success(0, E); assert(!(StopAtNull && !Char2.getInt())); if (!HandleLValueArrayAdjustment(Info, E, String1, CharTy, 1) || !HandleLValueArrayAdjustment(Info, E, String2, CharTy, 1)) return false; } // We hit the strncmp / memcmp limit. return Success(0, E); } case Builtin::BI__atomic_always_lock_free: case Builtin::BI__atomic_is_lock_free: case Builtin::BI__c11_atomic_is_lock_free: { APSInt SizeVal; if (!EvaluateInteger(E->getArg(0), SizeVal, Info)) return false; // For __atomic_is_lock_free(sizeof(_Atomic(T))), if the size is a power // of two less than the maximum inline atomic width, we know it is // lock-free. If the size isn't a power of two, or greater than the // maximum alignment where we promote atomics, we know it is not lock-free // (at least not in the sense of atomic_is_lock_free). Otherwise, // the answer can only be determined at runtime; for example, 16-byte // atomics have lock-free implementations on some, but not all, // x86-64 processors. // Check power-of-two. CharUnits Size = CharUnits::fromQuantity(SizeVal.getZExtValue()); if (Size.isPowerOfTwo()) { // Check against inlining width. unsigned InlineWidthBits = Info.Ctx.getTargetInfo().getMaxAtomicInlineWidth(); if (Size <= Info.Ctx.toCharUnitsFromBits(InlineWidthBits)) { if (BuiltinOp == Builtin::BI__c11_atomic_is_lock_free || Size == CharUnits::One() || E->getArg(1)->isNullPointerConstant(Info.Ctx, Expr::NPC_NeverValueDependent)) // OK, we will inline appropriately-aligned operations of this size, // and _Atomic(T) is appropriately-aligned. return Success(1, E); QualType PointeeType = E->getArg(1)->IgnoreImpCasts()->getType()-> castAs()->getPointeeType(); if (!PointeeType->isIncompleteType() && Info.Ctx.getTypeAlignInChars(PointeeType) >= Size) { // OK, we will inline operations on this object. return Success(1, E); } } } return BuiltinOp == Builtin::BI__atomic_always_lock_free ? Success(0, E) : Error(E); } case Builtin::BIomp_is_initial_device: // We can decide statically which value the runtime would return if called. return Success(Info.getLangOpts().OpenMPIsDevice ? 0 : 1, E); case Builtin::BI__builtin_add_overflow: case Builtin::BI__builtin_sub_overflow: case Builtin::BI__builtin_mul_overflow: case Builtin::BI__builtin_sadd_overflow: case Builtin::BI__builtin_uadd_overflow: case Builtin::BI__builtin_uaddl_overflow: case Builtin::BI__builtin_uaddll_overflow: case Builtin::BI__builtin_usub_overflow: case Builtin::BI__builtin_usubl_overflow: case Builtin::BI__builtin_usubll_overflow: case Builtin::BI__builtin_umul_overflow: case Builtin::BI__builtin_umull_overflow: case Builtin::BI__builtin_umulll_overflow: case Builtin::BI__builtin_saddl_overflow: case Builtin::BI__builtin_saddll_overflow: case Builtin::BI__builtin_ssub_overflow: case Builtin::BI__builtin_ssubl_overflow: case Builtin::BI__builtin_ssubll_overflow: case Builtin::BI__builtin_smul_overflow: case Builtin::BI__builtin_smull_overflow: case Builtin::BI__builtin_smulll_overflow: { LValue ResultLValue; APSInt LHS, RHS; QualType ResultType = E->getArg(2)->getType()->getPointeeType(); if (!EvaluateInteger(E->getArg(0), LHS, Info) || !EvaluateInteger(E->getArg(1), RHS, Info) || !EvaluatePointer(E->getArg(2), ResultLValue, Info)) return false; APSInt Result; bool DidOverflow = false; // If the types don't have to match, enlarge all 3 to the largest of them. if (BuiltinOp == Builtin::BI__builtin_add_overflow || BuiltinOp == Builtin::BI__builtin_sub_overflow || BuiltinOp == Builtin::BI__builtin_mul_overflow) { bool IsSigned = LHS.isSigned() || RHS.isSigned() || ResultType->isSignedIntegerOrEnumerationType(); bool AllSigned = LHS.isSigned() && RHS.isSigned() && ResultType->isSignedIntegerOrEnumerationType(); uint64_t LHSSize = LHS.getBitWidth(); uint64_t RHSSize = RHS.getBitWidth(); uint64_t ResultSize = Info.Ctx.getTypeSize(ResultType); uint64_t MaxBits = std::max(std::max(LHSSize, RHSSize), ResultSize); // Add an additional bit if the signedness isn't uniformly agreed to. We // could do this ONLY if there is a signed and an unsigned that both have // MaxBits, but the code to check that is pretty nasty. The issue will be // caught in the shrink-to-result later anyway. if (IsSigned && !AllSigned) ++MaxBits; LHS = APSInt(IsSigned ? LHS.sextOrSelf(MaxBits) : LHS.zextOrSelf(MaxBits), !IsSigned); RHS = APSInt(IsSigned ? RHS.sextOrSelf(MaxBits) : RHS.zextOrSelf(MaxBits), !IsSigned); Result = APSInt(MaxBits, !IsSigned); } // Find largest int. switch (BuiltinOp) { default: llvm_unreachable("Invalid value for BuiltinOp"); case Builtin::BI__builtin_add_overflow: case Builtin::BI__builtin_sadd_overflow: case Builtin::BI__builtin_saddl_overflow: case Builtin::BI__builtin_saddll_overflow: case Builtin::BI__builtin_uadd_overflow: case Builtin::BI__builtin_uaddl_overflow: case Builtin::BI__builtin_uaddll_overflow: Result = LHS.isSigned() ? LHS.sadd_ov(RHS, DidOverflow) : LHS.uadd_ov(RHS, DidOverflow); break; case Builtin::BI__builtin_sub_overflow: case Builtin::BI__builtin_ssub_overflow: case Builtin::BI__builtin_ssubl_overflow: case Builtin::BI__builtin_ssubll_overflow: case Builtin::BI__builtin_usub_overflow: case Builtin::BI__builtin_usubl_overflow: case Builtin::BI__builtin_usubll_overflow: Result = LHS.isSigned() ? LHS.ssub_ov(RHS, DidOverflow) : LHS.usub_ov(RHS, DidOverflow); break; case Builtin::BI__builtin_mul_overflow: case Builtin::BI__builtin_smul_overflow: case Builtin::BI__builtin_smull_overflow: case Builtin::BI__builtin_smulll_overflow: case Builtin::BI__builtin_umul_overflow: case Builtin::BI__builtin_umull_overflow: case Builtin::BI__builtin_umulll_overflow: Result = LHS.isSigned() ? LHS.smul_ov(RHS, DidOverflow) : LHS.umul_ov(RHS, DidOverflow); break; } // In the case where multiple sizes are allowed, truncate and see if // the values are the same. if (BuiltinOp == Builtin::BI__builtin_add_overflow || BuiltinOp == Builtin::BI__builtin_sub_overflow || BuiltinOp == Builtin::BI__builtin_mul_overflow) { // APSInt doesn't have a TruncOrSelf, so we use extOrTrunc instead, // since it will give us the behavior of a TruncOrSelf in the case where // its parameter <= its size. We previously set Result to be at least the // type-size of the result, so getTypeSize(ResultType) <= Result.BitWidth // will work exactly like TruncOrSelf. APSInt Temp = Result.extOrTrunc(Info.Ctx.getTypeSize(ResultType)); Temp.setIsSigned(ResultType->isSignedIntegerOrEnumerationType()); if (!APSInt::isSameValue(Temp, Result)) DidOverflow = true; Result = Temp; } APValue APV{Result}; if (!handleAssignment(Info, E, ResultLValue, ResultType, APV)) return false; return Success(DidOverflow, E); } } +} + +static bool HasSameBase(const LValue &A, const LValue &B) { + if (!A.getLValueBase()) + return !B.getLValueBase(); + if (!B.getLValueBase()) + return false; + + if (A.getLValueBase().getOpaqueValue() != + B.getLValueBase().getOpaqueValue()) { + const Decl *ADecl = GetLValueBaseDecl(A); + if (!ADecl) + return false; + const Decl *BDecl = GetLValueBaseDecl(B); + if (!BDecl || ADecl->getCanonicalDecl() != BDecl->getCanonicalDecl()) + return false; + } + + return IsGlobalLValue(A.getLValueBase()) || + (A.getLValueCallIndex() == B.getLValueCallIndex() && + A.getLValueVersion() == B.getLValueVersion()); } /// Determine whether this is a pointer past the end of the complete /// object referred to by the lvalue. static bool isOnePastTheEndOfCompleteObject(const ASTContext &Ctx, const LValue &LV) { // A null pointer can be viewed as being "past the end" but we don't // choose to look at it that way here. if (!LV.getLValueBase()) return false; // If the designator is valid and refers to a subobject, we're not pointing // past the end. if (!LV.getLValueDesignator().Invalid && !LV.getLValueDesignator().isOnePastTheEnd()) return false; // A pointer to an incomplete type might be past-the-end if the type's size is // zero. We cannot tell because the type is incomplete. QualType Ty = getType(LV.getLValueBase()); if (Ty->isIncompleteType()) return true; // We're a past-the-end pointer if we point to the byte after the object, // no matter what our type or path is. auto Size = Ctx.getTypeSizeInChars(Ty); return LV.getLValueOffset() == Size; } namespace { /// Data recursive integer evaluator of certain binary operators. /// /// We use a data recursive algorithm for binary operators so that we are able /// to handle extreme cases of chained binary operators without causing stack /// overflow. class DataRecursiveIntBinOpEvaluator { struct EvalResult { APValue Val; bool Failed; EvalResult() : Failed(false) { } void swap(EvalResult &RHS) { Val.swap(RHS.Val); Failed = RHS.Failed; RHS.Failed = false; } }; struct Job { const Expr *E; EvalResult LHSResult; // meaningful only for binary operator expression. enum { AnyExprKind, BinOpKind, BinOpVisitedLHSKind } Kind; Job() = default; Job(Job &&) = default; void startSpeculativeEval(EvalInfo &Info) { SpecEvalRAII = SpeculativeEvaluationRAII(Info); } private: SpeculativeEvaluationRAII SpecEvalRAII; }; SmallVector Queue; IntExprEvaluator &IntEval; EvalInfo &Info; APValue &FinalResult; public: DataRecursiveIntBinOpEvaluator(IntExprEvaluator &IntEval, APValue &Result) : IntEval(IntEval), Info(IntEval.getEvalInfo()), FinalResult(Result) { } /// True if \param E is a binary operator that we are going to handle /// data recursively. /// We handle binary operators that are comma, logical, or that have operands /// with integral or enumeration type. static bool shouldEnqueue(const BinaryOperator *E) { return E->getOpcode() == BO_Comma || E->isLogicalOp() || (E->isRValue() && E->getType()->isIntegralOrEnumerationType() && E->getLHS()->getType()->isIntegralOrEnumerationType() && E->getRHS()->getType()->isIntegralOrEnumerationType()); } bool Traverse(const BinaryOperator *E) { enqueue(E); EvalResult PrevResult; while (!Queue.empty()) process(PrevResult); if (PrevResult.Failed) return false; FinalResult.swap(PrevResult.Val); return true; } private: bool Success(uint64_t Value, const Expr *E, APValue &Result) { return IntEval.Success(Value, E, Result); } bool Success(const APSInt &Value, const Expr *E, APValue &Result) { return IntEval.Success(Value, E, Result); } bool Error(const Expr *E) { return IntEval.Error(E); } bool Error(const Expr *E, diag::kind D) { return IntEval.Error(E, D); } OptionalDiagnostic CCEDiag(const Expr *E, diag::kind D) { return Info.CCEDiag(E, D); } // Returns true if visiting the RHS is necessary, false otherwise. bool VisitBinOpLHSOnly(EvalResult &LHSResult, const BinaryOperator *E, bool &SuppressRHSDiags); bool VisitBinOp(const EvalResult &LHSResult, const EvalResult &RHSResult, const BinaryOperator *E, APValue &Result); void EvaluateExpr(const Expr *E, EvalResult &Result) { Result.Failed = !Evaluate(Result.Val, Info, E); if (Result.Failed) Result.Val = APValue(); } void process(EvalResult &Result); void enqueue(const Expr *E) { E = E->IgnoreParens(); Queue.resize(Queue.size()+1); Queue.back().E = E; Queue.back().Kind = Job::AnyExprKind; } }; } bool DataRecursiveIntBinOpEvaluator:: VisitBinOpLHSOnly(EvalResult &LHSResult, const BinaryOperator *E, bool &SuppressRHSDiags) { if (E->getOpcode() == BO_Comma) { // Ignore LHS but note if we could not evaluate it. if (LHSResult.Failed) return Info.noteSideEffect(); return true; } if (E->isLogicalOp()) { bool LHSAsBool; if (!LHSResult.Failed && HandleConversionToBool(LHSResult.Val, LHSAsBool)) { // We were able to evaluate the LHS, see if we can get away with not // evaluating the RHS: 0 && X -> 0, 1 || X -> 1 if (LHSAsBool == (E->getOpcode() == BO_LOr)) { Success(LHSAsBool, E, LHSResult.Val); return false; // Ignore RHS } } else { LHSResult.Failed = true; // Since we weren't able to evaluate the left hand side, it // might have had side effects. if (!Info.noteSideEffect()) return false; // We can't evaluate the LHS; however, sometimes the result // is determined by the RHS: X && 0 -> 0, X || 1 -> 1. // Don't ignore RHS and suppress diagnostics from this arm. SuppressRHSDiags = true; } return true; } assert(E->getLHS()->getType()->isIntegralOrEnumerationType() && E->getRHS()->getType()->isIntegralOrEnumerationType()); if (LHSResult.Failed && !Info.noteFailure()) return false; // Ignore RHS; return true; } static void addOrSubLValueAsInteger(APValue &LVal, const APSInt &Index, bool IsSub) { // Compute the new offset in the appropriate width, wrapping at 64 bits. // FIXME: When compiling for a 32-bit target, we should use 32-bit // offsets. assert(!LVal.hasLValuePath() && "have designator for integer lvalue"); CharUnits &Offset = LVal.getLValueOffset(); uint64_t Offset64 = Offset.getQuantity(); uint64_t Index64 = Index.extOrTrunc(64).getZExtValue(); Offset = CharUnits::fromQuantity(IsSub ? Offset64 - Index64 : Offset64 + Index64); } bool DataRecursiveIntBinOpEvaluator:: VisitBinOp(const EvalResult &LHSResult, const EvalResult &RHSResult, const BinaryOperator *E, APValue &Result) { if (E->getOpcode() == BO_Comma) { if (RHSResult.Failed) return false; Result = RHSResult.Val; return true; } if (E->isLogicalOp()) { bool lhsResult, rhsResult; bool LHSIsOK = HandleConversionToBool(LHSResult.Val, lhsResult); bool RHSIsOK = HandleConversionToBool(RHSResult.Val, rhsResult); if (LHSIsOK) { if (RHSIsOK) { if (E->getOpcode() == BO_LOr) return Success(lhsResult || rhsResult, E, Result); else return Success(lhsResult && rhsResult, E, Result); } } else { if (RHSIsOK) { // We can't evaluate the LHS; however, sometimes the result // is determined by the RHS: X && 0 -> 0, X || 1 -> 1. if (rhsResult == (E->getOpcode() == BO_LOr)) return Success(rhsResult, E, Result); } } return false; } assert(E->getLHS()->getType()->isIntegralOrEnumerationType() && E->getRHS()->getType()->isIntegralOrEnumerationType()); if (LHSResult.Failed || RHSResult.Failed) return false; const APValue &LHSVal = LHSResult.Val; const APValue &RHSVal = RHSResult.Val; // Handle cases like (unsigned long)&a + 4. if (E->isAdditiveOp() && LHSVal.isLValue() && RHSVal.isInt()) { Result = LHSVal; addOrSubLValueAsInteger(Result, RHSVal.getInt(), E->getOpcode() == BO_Sub); return true; } // Handle cases like 4 + (unsigned long)&a if (E->getOpcode() == BO_Add && RHSVal.isLValue() && LHSVal.isInt()) { Result = RHSVal; addOrSubLValueAsInteger(Result, LHSVal.getInt(), /*IsSub*/false); return true; } if (E->getOpcode() == BO_Sub && LHSVal.isLValue() && RHSVal.isLValue()) { // Handle (intptr_t)&&A - (intptr_t)&&B. if (!LHSVal.getLValueOffset().isZero() || !RHSVal.getLValueOffset().isZero()) return false; const Expr *LHSExpr = LHSVal.getLValueBase().dyn_cast(); const Expr *RHSExpr = RHSVal.getLValueBase().dyn_cast(); if (!LHSExpr || !RHSExpr) return false; const AddrLabelExpr *LHSAddrExpr = dyn_cast(LHSExpr); const AddrLabelExpr *RHSAddrExpr = dyn_cast(RHSExpr); if (!LHSAddrExpr || !RHSAddrExpr) return false; // Make sure both labels come from the same function. if (LHSAddrExpr->getLabel()->getDeclContext() != RHSAddrExpr->getLabel()->getDeclContext()) return false; Result = APValue(LHSAddrExpr, RHSAddrExpr); return true; } // All the remaining cases expect both operands to be an integer if (!LHSVal.isInt() || !RHSVal.isInt()) return Error(E); // Set up the width and signedness manually, in case it can't be deduced // from the operation we're performing. // FIXME: Don't do this in the cases where we can deduce it. APSInt Value(Info.Ctx.getIntWidth(E->getType()), E->getType()->isUnsignedIntegerOrEnumerationType()); if (!handleIntIntBinOp(Info, E, LHSVal.getInt(), E->getOpcode(), RHSVal.getInt(), Value)) return false; return Success(Value, E, Result); } void DataRecursiveIntBinOpEvaluator::process(EvalResult &Result) { Job &job = Queue.back(); switch (job.Kind) { case Job::AnyExprKind: { if (const BinaryOperator *Bop = dyn_cast(job.E)) { if (shouldEnqueue(Bop)) { job.Kind = Job::BinOpKind; enqueue(Bop->getLHS()); return; } } EvaluateExpr(job.E, Result); Queue.pop_back(); return; } case Job::BinOpKind: { const BinaryOperator *Bop = cast(job.E); bool SuppressRHSDiags = false; if (!VisitBinOpLHSOnly(Result, Bop, SuppressRHSDiags)) { Queue.pop_back(); return; } if (SuppressRHSDiags) job.startSpeculativeEval(Info); job.LHSResult.swap(Result); job.Kind = Job::BinOpVisitedLHSKind; enqueue(Bop->getRHS()); return; } case Job::BinOpVisitedLHSKind: { const BinaryOperator *Bop = cast(job.E); EvalResult RHS; RHS.swap(Result); Result.Failed = !VisitBinOp(job.LHSResult, RHS, Bop, Result.Val); Queue.pop_back(); return; } } llvm_unreachable("Invalid Job::Kind!"); } namespace { /// Used when we determine that we should fail, but can keep evaluating prior to /// noting that we had a failure. class DelayedNoteFailureRAII { EvalInfo &Info; bool NoteFailure; public: DelayedNoteFailureRAII(EvalInfo &Info, bool NoteFailure = true) : Info(Info), NoteFailure(NoteFailure) {} ~DelayedNoteFailureRAII() { if (NoteFailure) { bool ContinueAfterFailure = Info.noteFailure(); (void)ContinueAfterFailure; assert(ContinueAfterFailure && "Shouldn't have kept evaluating on failure."); } } }; } template static bool EvaluateComparisonBinaryOperator(EvalInfo &Info, const BinaryOperator *E, SuccessCB &&Success, AfterCB &&DoAfter) { assert(E->isComparisonOp() && "expected comparison operator"); assert((E->getOpcode() == BO_Cmp || E->getType()->isIntegralOrEnumerationType()) && "unsupported binary expression evaluation"); auto Error = [&](const Expr *E) { Info.FFDiag(E, diag::note_invalid_subexpr_in_const_expr); return false; }; using CCR = ComparisonCategoryResult; bool IsRelational = E->isRelationalOp(); bool IsEquality = E->isEqualityOp(); if (E->getOpcode() == BO_Cmp) { const ComparisonCategoryInfo &CmpInfo = Info.Ctx.CompCategories.getInfoForType(E->getType()); IsRelational = CmpInfo.isOrdered(); IsEquality = CmpInfo.isEquality(); } QualType LHSTy = E->getLHS()->getType(); QualType RHSTy = E->getRHS()->getType(); if (LHSTy->isIntegralOrEnumerationType() && RHSTy->isIntegralOrEnumerationType()) { APSInt LHS, RHS; bool LHSOK = EvaluateInteger(E->getLHS(), LHS, Info); if (!LHSOK && !Info.noteFailure()) return false; if (!EvaluateInteger(E->getRHS(), RHS, Info) || !LHSOK) return false; if (LHS < RHS) return Success(CCR::Less, E); if (LHS > RHS) return Success(CCR::Greater, E); return Success(CCR::Equal, E); } if (LHSTy->isAnyComplexType() || RHSTy->isAnyComplexType()) { ComplexValue LHS, RHS; bool LHSOK; if (E->isAssignmentOp()) { LValue LV; EvaluateLValue(E->getLHS(), LV, Info); LHSOK = false; } else if (LHSTy->isRealFloatingType()) { LHSOK = EvaluateFloat(E->getLHS(), LHS.FloatReal, Info); if (LHSOK) { LHS.makeComplexFloat(); LHS.FloatImag = APFloat(LHS.FloatReal.getSemantics()); } } else { LHSOK = EvaluateComplex(E->getLHS(), LHS, Info); } if (!LHSOK && !Info.noteFailure()) return false; if (E->getRHS()->getType()->isRealFloatingType()) { if (!EvaluateFloat(E->getRHS(), RHS.FloatReal, Info) || !LHSOK) return false; RHS.makeComplexFloat(); RHS.FloatImag = APFloat(RHS.FloatReal.getSemantics()); } else if (!EvaluateComplex(E->getRHS(), RHS, Info) || !LHSOK) return false; if (LHS.isComplexFloat()) { APFloat::cmpResult CR_r = LHS.getComplexFloatReal().compare(RHS.getComplexFloatReal()); APFloat::cmpResult CR_i = LHS.getComplexFloatImag().compare(RHS.getComplexFloatImag()); bool IsEqual = CR_r == APFloat::cmpEqual && CR_i == APFloat::cmpEqual; return Success(IsEqual ? CCR::Equal : CCR::Nonequal, E); } else { assert(IsEquality && "invalid complex comparison"); bool IsEqual = LHS.getComplexIntReal() == RHS.getComplexIntReal() && LHS.getComplexIntImag() == RHS.getComplexIntImag(); return Success(IsEqual ? CCR::Equal : CCR::Nonequal, E); } } if (LHSTy->isRealFloatingType() && RHSTy->isRealFloatingType()) { APFloat RHS(0.0), LHS(0.0); bool LHSOK = EvaluateFloat(E->getRHS(), RHS, Info); if (!LHSOK && !Info.noteFailure()) return false; if (!EvaluateFloat(E->getLHS(), LHS, Info) || !LHSOK) return false; assert(E->isComparisonOp() && "Invalid binary operator!"); auto GetCmpRes = [&]() { switch (LHS.compare(RHS)) { case APFloat::cmpEqual: return CCR::Equal; case APFloat::cmpLessThan: return CCR::Less; case APFloat::cmpGreaterThan: return CCR::Greater; case APFloat::cmpUnordered: return CCR::Unordered; } llvm_unreachable("Unrecognised APFloat::cmpResult enum"); }; return Success(GetCmpRes(), E); } if (LHSTy->isPointerType() && RHSTy->isPointerType()) { LValue LHSValue, RHSValue; bool LHSOK = EvaluatePointer(E->getLHS(), LHSValue, Info); if (!LHSOK && !Info.noteFailure()) return false; if (!EvaluatePointer(E->getRHS(), RHSValue, Info) || !LHSOK) return false; // Reject differing bases from the normal codepath; we special-case // comparisons to null. if (!HasSameBase(LHSValue, RHSValue)) { // Inequalities and subtractions between unrelated pointers have // unspecified or undefined behavior. if (!IsEquality) return Error(E); // A constant address may compare equal to the address of a symbol. // The one exception is that address of an object cannot compare equal // to a null pointer constant. if ((!LHSValue.Base && !LHSValue.Offset.isZero()) || (!RHSValue.Base && !RHSValue.Offset.isZero())) return Error(E); // It's implementation-defined whether distinct literals will have // distinct addresses. In clang, the result of such a comparison is // unspecified, so it is not a constant expression. However, we do know // that the address of a literal will be non-null. if ((IsLiteralLValue(LHSValue) || IsLiteralLValue(RHSValue)) && LHSValue.Base && RHSValue.Base) return Error(E); // We can't tell whether weak symbols will end up pointing to the same // object. if (IsWeakLValue(LHSValue) || IsWeakLValue(RHSValue)) return Error(E); // We can't compare the address of the start of one object with the // past-the-end address of another object, per C++ DR1652. if ((LHSValue.Base && LHSValue.Offset.isZero() && isOnePastTheEndOfCompleteObject(Info.Ctx, RHSValue)) || (RHSValue.Base && RHSValue.Offset.isZero() && isOnePastTheEndOfCompleteObject(Info.Ctx, LHSValue))) return Error(E); // We can't tell whether an object is at the same address as another // zero sized object. if ((RHSValue.Base && isZeroSized(LHSValue)) || (LHSValue.Base && isZeroSized(RHSValue))) return Error(E); return Success(CCR::Nonequal, E); } const CharUnits &LHSOffset = LHSValue.getLValueOffset(); const CharUnits &RHSOffset = RHSValue.getLValueOffset(); SubobjectDesignator &LHSDesignator = LHSValue.getLValueDesignator(); SubobjectDesignator &RHSDesignator = RHSValue.getLValueDesignator(); // C++11 [expr.rel]p3: // Pointers to void (after pointer conversions) can be compared, with a // result defined as follows: If both pointers represent the same // address or are both the null pointer value, the result is true if the // operator is <= or >= and false otherwise; otherwise the result is // unspecified. // We interpret this as applying to pointers to *cv* void. if (LHSTy->isVoidPointerType() && LHSOffset != RHSOffset && IsRelational) Info.CCEDiag(E, diag::note_constexpr_void_comparison); // C++11 [expr.rel]p2: // - If two pointers point to non-static data members of the same object, // or to subobjects or array elements fo such members, recursively, the // pointer to the later declared member compares greater provided the // two members have the same access control and provided their class is // not a union. // [...] // - Otherwise pointer comparisons are unspecified. if (!LHSDesignator.Invalid && !RHSDesignator.Invalid && IsRelational) { bool WasArrayIndex; unsigned Mismatch = FindDesignatorMismatch( getType(LHSValue.Base), LHSDesignator, RHSDesignator, WasArrayIndex); // At the point where the designators diverge, the comparison has a // specified value if: // - we are comparing array indices // - we are comparing fields of a union, or fields with the same access // Otherwise, the result is unspecified and thus the comparison is not a // constant expression. if (!WasArrayIndex && Mismatch < LHSDesignator.Entries.size() && Mismatch < RHSDesignator.Entries.size()) { const FieldDecl *LF = getAsField(LHSDesignator.Entries[Mismatch]); const FieldDecl *RF = getAsField(RHSDesignator.Entries[Mismatch]); if (!LF && !RF) Info.CCEDiag(E, diag::note_constexpr_pointer_comparison_base_classes); else if (!LF) Info.CCEDiag(E, diag::note_constexpr_pointer_comparison_base_field) << getAsBaseClass(LHSDesignator.Entries[Mismatch]) << RF->getParent() << RF; else if (!RF) Info.CCEDiag(E, diag::note_constexpr_pointer_comparison_base_field) << getAsBaseClass(RHSDesignator.Entries[Mismatch]) << LF->getParent() << LF; else if (!LF->getParent()->isUnion() && LF->getAccess() != RF->getAccess()) Info.CCEDiag(E, diag::note_constexpr_pointer_comparison_differing_access) << LF << LF->getAccess() << RF << RF->getAccess() << LF->getParent(); } } // The comparison here must be unsigned, and performed with the same // width as the pointer. unsigned PtrSize = Info.Ctx.getTypeSize(LHSTy); uint64_t CompareLHS = LHSOffset.getQuantity(); uint64_t CompareRHS = RHSOffset.getQuantity(); assert(PtrSize <= 64 && "Unexpected pointer width"); uint64_t Mask = ~0ULL >> (64 - PtrSize); CompareLHS &= Mask; CompareRHS &= Mask; // If there is a base and this is a relational operator, we can only // compare pointers within the object in question; otherwise, the result // depends on where the object is located in memory. if (!LHSValue.Base.isNull() && IsRelational) { QualType BaseTy = getType(LHSValue.Base); if (BaseTy->isIncompleteType()) return Error(E); CharUnits Size = Info.Ctx.getTypeSizeInChars(BaseTy); uint64_t OffsetLimit = Size.getQuantity(); if (CompareLHS > OffsetLimit || CompareRHS > OffsetLimit) return Error(E); } if (CompareLHS < CompareRHS) return Success(CCR::Less, E); if (CompareLHS > CompareRHS) return Success(CCR::Greater, E); return Success(CCR::Equal, E); } if (LHSTy->isMemberPointerType()) { assert(IsEquality && "unexpected member pointer operation"); assert(RHSTy->isMemberPointerType() && "invalid comparison"); MemberPtr LHSValue, RHSValue; bool LHSOK = EvaluateMemberPointer(E->getLHS(), LHSValue, Info); if (!LHSOK && !Info.noteFailure()) return false; if (!EvaluateMemberPointer(E->getRHS(), RHSValue, Info) || !LHSOK) return false; // C++11 [expr.eq]p2: // If both operands are null, they compare equal. Otherwise if only one is // null, they compare unequal. if (!LHSValue.getDecl() || !RHSValue.getDecl()) { bool Equal = !LHSValue.getDecl() && !RHSValue.getDecl(); return Success(Equal ? CCR::Equal : CCR::Nonequal, E); } // Otherwise if either is a pointer to a virtual member function, the // result is unspecified. if (const CXXMethodDecl *MD = dyn_cast(LHSValue.getDecl())) if (MD->isVirtual()) Info.CCEDiag(E, diag::note_constexpr_compare_virtual_mem_ptr) << MD; if (const CXXMethodDecl *MD = dyn_cast(RHSValue.getDecl())) if (MD->isVirtual()) Info.CCEDiag(E, diag::note_constexpr_compare_virtual_mem_ptr) << MD; // Otherwise they compare equal if and only if they would refer to the // same member of the same most derived object or the same subobject if // they were dereferenced with a hypothetical object of the associated // class type. bool Equal = LHSValue == RHSValue; return Success(Equal ? CCR::Equal : CCR::Nonequal, E); } if (LHSTy->isNullPtrType()) { assert(E->isComparisonOp() && "unexpected nullptr operation"); assert(RHSTy->isNullPtrType() && "missing pointer conversion"); // C++11 [expr.rel]p4, [expr.eq]p3: If two operands of type std::nullptr_t // are compared, the result is true of the operator is <=, >= or ==, and // false otherwise. return Success(CCR::Equal, E); } return DoAfter(); } bool RecordExprEvaluator::VisitBinCmp(const BinaryOperator *E) { if (!CheckLiteralType(Info, E)) return false; auto OnSuccess = [&](ComparisonCategoryResult ResKind, const BinaryOperator *E) { // Evaluation succeeded. Lookup the information for the comparison category // type and fetch the VarDecl for the result. const ComparisonCategoryInfo &CmpInfo = Info.Ctx.CompCategories.getInfoForType(E->getType()); const VarDecl *VD = CmpInfo.getValueInfo(CmpInfo.makeWeakResult(ResKind))->VD; // Check and evaluate the result as a constant expression. LValue LV; LV.set(VD); if (!handleLValueToRValueConversion(Info, E, E->getType(), LV, Result)) return false; return CheckConstantExpression(Info, E->getExprLoc(), E->getType(), Result); }; return EvaluateComparisonBinaryOperator(Info, E, OnSuccess, [&]() { return ExprEvaluatorBaseTy::VisitBinCmp(E); }); } bool IntExprEvaluator::VisitBinaryOperator(const BinaryOperator *E) { // We don't call noteFailure immediately because the assignment happens after // we evaluate LHS and RHS. if (!Info.keepEvaluatingAfterFailure() && E->isAssignmentOp()) return Error(E); DelayedNoteFailureRAII MaybeNoteFailureLater(Info, E->isAssignmentOp()); if (DataRecursiveIntBinOpEvaluator::shouldEnqueue(E)) return DataRecursiveIntBinOpEvaluator(*this, Result).Traverse(E); assert((!E->getLHS()->getType()->isIntegralOrEnumerationType() || !E->getRHS()->getType()->isIntegralOrEnumerationType()) && "DataRecursiveIntBinOpEvaluator should have handled integral types"); if (E->isComparisonOp()) { // Evaluate builtin binary comparisons by evaluating them as C++2a three-way // comparisons and then translating the result. auto OnSuccess = [&](ComparisonCategoryResult ResKind, const BinaryOperator *E) { using CCR = ComparisonCategoryResult; bool IsEqual = ResKind == CCR::Equal, IsLess = ResKind == CCR::Less, IsGreater = ResKind == CCR::Greater; auto Op = E->getOpcode(); switch (Op) { default: llvm_unreachable("unsupported binary operator"); case BO_EQ: case BO_NE: return Success(IsEqual == (Op == BO_EQ), E); case BO_LT: return Success(IsLess, E); case BO_GT: return Success(IsGreater, E); case BO_LE: return Success(IsEqual || IsLess, E); case BO_GE: return Success(IsEqual || IsGreater, E); } }; return EvaluateComparisonBinaryOperator(Info, E, OnSuccess, [&]() { return ExprEvaluatorBaseTy::VisitBinaryOperator(E); }); } QualType LHSTy = E->getLHS()->getType(); QualType RHSTy = E->getRHS()->getType(); if (LHSTy->isPointerType() && RHSTy->isPointerType() && E->getOpcode() == BO_Sub) { LValue LHSValue, RHSValue; bool LHSOK = EvaluatePointer(E->getLHS(), LHSValue, Info); if (!LHSOK && !Info.noteFailure()) return false; if (!EvaluatePointer(E->getRHS(), RHSValue, Info) || !LHSOK) return false; // Reject differing bases from the normal codepath; we special-case // comparisons to null. if (!HasSameBase(LHSValue, RHSValue)) { // Handle &&A - &&B. if (!LHSValue.Offset.isZero() || !RHSValue.Offset.isZero()) return Error(E); const Expr *LHSExpr = LHSValue.Base.dyn_cast(); const Expr *RHSExpr = RHSValue.Base.dyn_cast(); if (!LHSExpr || !RHSExpr) return Error(E); const AddrLabelExpr *LHSAddrExpr = dyn_cast(LHSExpr); const AddrLabelExpr *RHSAddrExpr = dyn_cast(RHSExpr); if (!LHSAddrExpr || !RHSAddrExpr) return Error(E); // Make sure both labels come from the same function. if (LHSAddrExpr->getLabel()->getDeclContext() != RHSAddrExpr->getLabel()->getDeclContext()) return Error(E); return Success(APValue(LHSAddrExpr, RHSAddrExpr), E); } const CharUnits &LHSOffset = LHSValue.getLValueOffset(); const CharUnits &RHSOffset = RHSValue.getLValueOffset(); SubobjectDesignator &LHSDesignator = LHSValue.getLValueDesignator(); SubobjectDesignator &RHSDesignator = RHSValue.getLValueDesignator(); // C++11 [expr.add]p6: // Unless both pointers point to elements of the same array object, or // one past the last element of the array object, the behavior is // undefined. if (!LHSDesignator.Invalid && !RHSDesignator.Invalid && !AreElementsOfSameArray(getType(LHSValue.Base), LHSDesignator, RHSDesignator)) Info.CCEDiag(E, diag::note_constexpr_pointer_subtraction_not_same_array); QualType Type = E->getLHS()->getType(); QualType ElementType = Type->getAs()->getPointeeType(); CharUnits ElementSize; if (!HandleSizeof(Info, E->getExprLoc(), ElementType, ElementSize)) return false; // As an extension, a type may have zero size (empty struct or union in // C, array of zero length). Pointer subtraction in such cases has // undefined behavior, so is not constant. if (ElementSize.isZero()) { Info.FFDiag(E, diag::note_constexpr_pointer_subtraction_zero_size) << ElementType; return false; } // FIXME: LLVM and GCC both compute LHSOffset - RHSOffset at runtime, // and produce incorrect results when it overflows. Such behavior // appears to be non-conforming, but is common, so perhaps we should // assume the standard intended for such cases to be undefined behavior // and check for them. // Compute (LHSOffset - RHSOffset) / Size carefully, checking for // overflow in the final conversion to ptrdiff_t. APSInt LHS(llvm::APInt(65, (int64_t)LHSOffset.getQuantity(), true), false); APSInt RHS(llvm::APInt(65, (int64_t)RHSOffset.getQuantity(), true), false); APSInt ElemSize(llvm::APInt(65, (int64_t)ElementSize.getQuantity(), true), false); APSInt TrueResult = (LHS - RHS) / ElemSize; APSInt Result = TrueResult.trunc(Info.Ctx.getIntWidth(E->getType())); if (Result.extend(65) != TrueResult && !HandleOverflow(Info, E, TrueResult, E->getType())) return false; return Success(Result, E); } return ExprEvaluatorBaseTy::VisitBinaryOperator(E); } /// VisitUnaryExprOrTypeTraitExpr - Evaluate a sizeof, alignof or vec_step with /// a result as the expression's type. bool IntExprEvaluator::VisitUnaryExprOrTypeTraitExpr( const UnaryExprOrTypeTraitExpr *E) { switch(E->getKind()) { case UETT_AlignOf: { if (E->isArgumentType()) return Success(GetAlignOfType(Info, E->getArgumentType()), E); else return Success(GetAlignOfExpr(Info, E->getArgumentExpr()), E); } case UETT_VecStep: { QualType Ty = E->getTypeOfArgument(); if (Ty->isVectorType()) { unsigned n = Ty->castAs()->getNumElements(); // The vec_step built-in functions that take a 3-component // vector return 4. (OpenCL 1.1 spec 6.11.12) if (n == 3) n = 4; return Success(n, E); } else return Success(1, E); } case UETT_SizeOf: { QualType SrcTy = E->getTypeOfArgument(); // C++ [expr.sizeof]p2: "When applied to a reference or a reference type, // the result is the size of the referenced type." if (const ReferenceType *Ref = SrcTy->getAs()) SrcTy = Ref->getPointeeType(); CharUnits Sizeof; if (!HandleSizeof(Info, E->getExprLoc(), SrcTy, Sizeof)) return false; return Success(Sizeof, E); } case UETT_OpenMPRequiredSimdAlign: assert(E->isArgumentType()); return Success( Info.Ctx.toCharUnitsFromBits( Info.Ctx.getOpenMPDefaultSimdAlign(E->getArgumentType())) .getQuantity(), E); } llvm_unreachable("unknown expr/type trait"); } bool IntExprEvaluator::VisitOffsetOfExpr(const OffsetOfExpr *OOE) { CharUnits Result; unsigned n = OOE->getNumComponents(); if (n == 0) return Error(OOE); QualType CurrentType = OOE->getTypeSourceInfo()->getType(); for (unsigned i = 0; i != n; ++i) { OffsetOfNode ON = OOE->getComponent(i); switch (ON.getKind()) { case OffsetOfNode::Array: { const Expr *Idx = OOE->getIndexExpr(ON.getArrayExprIndex()); APSInt IdxResult; if (!EvaluateInteger(Idx, IdxResult, Info)) return false; const ArrayType *AT = Info.Ctx.getAsArrayType(CurrentType); if (!AT) return Error(OOE); CurrentType = AT->getElementType(); CharUnits ElementSize = Info.Ctx.getTypeSizeInChars(CurrentType); Result += IdxResult.getSExtValue() * ElementSize; break; } case OffsetOfNode::Field: { FieldDecl *MemberDecl = ON.getField(); const RecordType *RT = CurrentType->getAs(); if (!RT) return Error(OOE); RecordDecl *RD = RT->getDecl(); if (RD->isInvalidDecl()) return false; const ASTRecordLayout &RL = Info.Ctx.getASTRecordLayout(RD); unsigned i = MemberDecl->getFieldIndex(); assert(i < RL.getFieldCount() && "offsetof field in wrong type"); Result += Info.Ctx.toCharUnitsFromBits(RL.getFieldOffset(i)); CurrentType = MemberDecl->getType().getNonReferenceType(); break; } case OffsetOfNode::Identifier: llvm_unreachable("dependent __builtin_offsetof"); case OffsetOfNode::Base: { CXXBaseSpecifier *BaseSpec = ON.getBase(); if (BaseSpec->isVirtual()) return Error(OOE); // Find the layout of the class whose base we are looking into. const RecordType *RT = CurrentType->getAs(); if (!RT) return Error(OOE); RecordDecl *RD = RT->getDecl(); if (RD->isInvalidDecl()) return false; const ASTRecordLayout &RL = Info.Ctx.getASTRecordLayout(RD); // Find the base class itself. CurrentType = BaseSpec->getType(); const RecordType *BaseRT = CurrentType->getAs(); if (!BaseRT) return Error(OOE); // Add the offset to the base. Result += RL.getBaseClassOffset(cast(BaseRT->getDecl())); break; } } } return Success(Result, OOE); } bool IntExprEvaluator::VisitUnaryOperator(const UnaryOperator *E) { switch (E->getOpcode()) { default: // Address, indirect, pre/post inc/dec, etc are not valid constant exprs. // See C99 6.6p3. return Error(E); case UO_Extension: // FIXME: Should extension allow i-c-e extension expressions in its scope? // If so, we could clear the diagnostic ID. return Visit(E->getSubExpr()); case UO_Plus: // The result is just the value. return Visit(E->getSubExpr()); case UO_Minus: { if (!Visit(E->getSubExpr())) return false; if (!Result.isInt()) return Error(E); const APSInt &Value = Result.getInt(); if (Value.isSigned() && Value.isMinSignedValue() && E->canOverflow() && !HandleOverflow(Info, E, -Value.extend(Value.getBitWidth() + 1), E->getType())) return false; return Success(-Value, E); } case UO_Not: { if (!Visit(E->getSubExpr())) return false; if (!Result.isInt()) return Error(E); return Success(~Result.getInt(), E); } case UO_LNot: { bool bres; if (!EvaluateAsBooleanCondition(E->getSubExpr(), bres, Info)) return false; return Success(!bres, E); } } } /// HandleCast - This is used to evaluate implicit or explicit casts where the /// result type is integer. bool IntExprEvaluator::VisitCastExpr(const CastExpr *E) { const Expr *SubExpr = E->getSubExpr(); QualType DestType = E->getType(); QualType SrcType = SubExpr->getType(); switch (E->getCastKind()) { case CK_BaseToDerived: case CK_DerivedToBase: case CK_UncheckedDerivedToBase: case CK_Dynamic: case CK_ToUnion: case CK_ArrayToPointerDecay: case CK_FunctionToPointerDecay: case CK_NullToPointer: case CK_NullToMemberPointer: case CK_BaseToDerivedMemberPointer: case CK_DerivedToBaseMemberPointer: case CK_ReinterpretMemberPointer: case CK_ConstructorConversion: case CK_IntegralToPointer: case CK_ToVoid: case CK_VectorSplat: case CK_IntegralToFloating: case CK_FloatingCast: case CK_CPointerToObjCPointerCast: case CK_BlockPointerToObjCPointerCast: case CK_AnyPointerToBlockPointerCast: case CK_ObjCObjectLValueCast: case CK_FloatingRealToComplex: case CK_FloatingComplexToReal: case CK_FloatingComplexCast: case CK_FloatingComplexToIntegralComplex: case CK_IntegralRealToComplex: case CK_IntegralComplexCast: case CK_IntegralComplexToFloatingComplex: case CK_BuiltinFnToFnPtr: case CK_ZeroToOCLEvent: case CK_ZeroToOCLQueue: case CK_NonAtomicToAtomic: case CK_AddressSpaceConversion: case CK_IntToOCLSampler: llvm_unreachable("invalid cast kind for integral value"); case CK_BitCast: case CK_Dependent: case CK_LValueBitCast: case CK_ARCProduceObject: case CK_ARCConsumeObject: case CK_ARCReclaimReturnedObject: case CK_ARCExtendBlockObject: case CK_CopyAndAutoreleaseBlockObject: return Error(E); case CK_UserDefinedConversion: case CK_LValueToRValue: case CK_AtomicToNonAtomic: case CK_NoOp: return ExprEvaluatorBaseTy::VisitCastExpr(E); case CK_MemberPointerToBoolean: case CK_PointerToBoolean: case CK_IntegralToBoolean: case CK_FloatingToBoolean: case CK_BooleanToSignedIntegral: case CK_FloatingComplexToBoolean: case CK_IntegralComplexToBoolean: { bool BoolResult; if (!EvaluateAsBooleanCondition(SubExpr, BoolResult, Info)) return false; uint64_t IntResult = BoolResult; if (BoolResult && E->getCastKind() == CK_BooleanToSignedIntegral) IntResult = (uint64_t)-1; return Success(IntResult, E); } case CK_IntegralCast: { if (!Visit(SubExpr)) return false; if (!Result.isInt()) { // Allow casts of address-of-label differences if they are no-ops // or narrowing. (The narrowing case isn't actually guaranteed to // be constant-evaluatable except in some narrow cases which are hard // to detect here. We let it through on the assumption the user knows // what they are doing.) if (Result.isAddrLabelDiff()) return Info.Ctx.getTypeSize(DestType) <= Info.Ctx.getTypeSize(SrcType); // Only allow casts of lvalues if they are lossless. return Info.Ctx.getTypeSize(DestType) == Info.Ctx.getTypeSize(SrcType); } return Success(HandleIntToIntCast(Info, E, DestType, SrcType, Result.getInt()), E); } case CK_PointerToIntegral: { CCEDiag(E, diag::note_constexpr_invalid_cast) << 2; LValue LV; if (!EvaluatePointer(SubExpr, LV, Info)) return false; if (LV.getLValueBase()) { // Only allow based lvalue casts if they are lossless. // FIXME: Allow a larger integer size than the pointer size, and allow // narrowing back down to pointer width in subsequent integral casts. // FIXME: Check integer type's active bits, not its type size. if (Info.Ctx.getTypeSize(DestType) != Info.Ctx.getTypeSize(SrcType)) return Error(E); LV.Designator.setInvalid(); LV.moveInto(Result); return true; } uint64_t V; if (LV.isNullPointer()) V = Info.Ctx.getTargetNullPointerValue(SrcType); else V = LV.getLValueOffset().getQuantity(); APSInt AsInt = Info.Ctx.MakeIntValue(V, SrcType); return Success(HandleIntToIntCast(Info, E, DestType, SrcType, AsInt), E); } case CK_IntegralComplexToReal: { ComplexValue C; if (!EvaluateComplex(SubExpr, C, Info)) return false; return Success(C.getComplexIntReal(), E); } case CK_FloatingToIntegral: { APFloat F(0.0); if (!EvaluateFloat(SubExpr, F, Info)) return false; APSInt Value; if (!HandleFloatToIntCast(Info, E, SrcType, F, DestType, Value)) return false; return Success(Value, E); } } llvm_unreachable("unknown cast resulting in integral value"); } bool IntExprEvaluator::VisitUnaryReal(const UnaryOperator *E) { if (E->getSubExpr()->getType()->isAnyComplexType()) { ComplexValue LV; if (!EvaluateComplex(E->getSubExpr(), LV, Info)) return false; if (!LV.isComplexInt()) return Error(E); return Success(LV.getComplexIntReal(), E); } return Visit(E->getSubExpr()); } bool IntExprEvaluator::VisitUnaryImag(const UnaryOperator *E) { if (E->getSubExpr()->getType()->isComplexIntegerType()) { ComplexValue LV; if (!EvaluateComplex(E->getSubExpr(), LV, Info)) return false; if (!LV.isComplexInt()) return Error(E); return Success(LV.getComplexIntImag(), E); } VisitIgnoredValue(E->getSubExpr()); return Success(0, E); } bool IntExprEvaluator::VisitSizeOfPackExpr(const SizeOfPackExpr *E) { return Success(E->getPackLength(), E); } bool IntExprEvaluator::VisitCXXNoexceptExpr(const CXXNoexceptExpr *E) { return Success(E->getValue(), E); } bool FixedPointExprEvaluator::VisitUnaryOperator(const UnaryOperator *E) { switch (E->getOpcode()) { default: // Invalid unary operators return Error(E); case UO_Plus: // The result is just the value. return Visit(E->getSubExpr()); case UO_Minus: { if (!Visit(E->getSubExpr())) return false; if (!Result.isInt()) return Error(E); const APSInt &Value = Result.getInt(); if (Value.isSigned() && Value.isMinSignedValue() && E->canOverflow()) { SmallString<64> S; FixedPointValueToString(S, Value, Info.Ctx.getTypeInfo(E->getType()).Width, /*Radix=*/10); Info.CCEDiag(E, diag::note_constexpr_overflow) << S << E->getType(); if (Info.noteUndefinedBehavior()) return false; } return Success(-Value, E); } case UO_LNot: { bool bres; if (!EvaluateAsBooleanCondition(E->getSubExpr(), bres, Info)) return false; return Success(!bres, E); } } } //===----------------------------------------------------------------------===// // Float Evaluation //===----------------------------------------------------------------------===// namespace { class FloatExprEvaluator : public ExprEvaluatorBase { APFloat &Result; public: FloatExprEvaluator(EvalInfo &info, APFloat &result) : ExprEvaluatorBaseTy(info), Result(result) {} bool Success(const APValue &V, const Expr *e) { Result = V.getFloat(); return true; } bool ZeroInitialization(const Expr *E) { Result = APFloat::getZero(Info.Ctx.getFloatTypeSemantics(E->getType())); return true; } bool VisitCallExpr(const CallExpr *E); bool VisitUnaryOperator(const UnaryOperator *E); bool VisitBinaryOperator(const BinaryOperator *E); bool VisitFloatingLiteral(const FloatingLiteral *E); bool VisitCastExpr(const CastExpr *E); bool VisitUnaryReal(const UnaryOperator *E); bool VisitUnaryImag(const UnaryOperator *E); // FIXME: Missing: array subscript of vector, member of vector }; } // end anonymous namespace static bool EvaluateFloat(const Expr* E, APFloat& Result, EvalInfo &Info) { assert(E->isRValue() && E->getType()->isRealFloatingType()); return FloatExprEvaluator(Info, Result).Visit(E); } static bool TryEvaluateBuiltinNaN(const ASTContext &Context, QualType ResultTy, const Expr *Arg, bool SNaN, llvm::APFloat &Result) { const StringLiteral *S = dyn_cast(Arg->IgnoreParenCasts()); if (!S) return false; const llvm::fltSemantics &Sem = Context.getFloatTypeSemantics(ResultTy); llvm::APInt fill; // Treat empty strings as if they were zero. if (S->getString().empty()) fill = llvm::APInt(32, 0); else if (S->getString().getAsInteger(0, fill)) return false; if (Context.getTargetInfo().isNan2008()) { if (SNaN) Result = llvm::APFloat::getSNaN(Sem, false, &fill); else Result = llvm::APFloat::getQNaN(Sem, false, &fill); } else { // Prior to IEEE 754-2008, architectures were allowed to choose whether // the first bit of their significand was set for qNaN or sNaN. MIPS chose // a different encoding to what became a standard in 2008, and for pre- // 2008 revisions, MIPS interpreted sNaN-2008 as qNan and qNaN-2008 as // sNaN. This is now known as "legacy NaN" encoding. if (SNaN) Result = llvm::APFloat::getQNaN(Sem, false, &fill); else Result = llvm::APFloat::getSNaN(Sem, false, &fill); } return true; } bool FloatExprEvaluator::VisitCallExpr(const CallExpr *E) { switch (E->getBuiltinCallee()) { default: return ExprEvaluatorBaseTy::VisitCallExpr(E); case Builtin::BI__builtin_huge_val: case Builtin::BI__builtin_huge_valf: case Builtin::BI__builtin_huge_vall: case Builtin::BI__builtin_huge_valf128: case Builtin::BI__builtin_inf: case Builtin::BI__builtin_inff: case Builtin::BI__builtin_infl: case Builtin::BI__builtin_inff128: { const llvm::fltSemantics &Sem = Info.Ctx.getFloatTypeSemantics(E->getType()); Result = llvm::APFloat::getInf(Sem); return true; } case Builtin::BI__builtin_nans: case Builtin::BI__builtin_nansf: case Builtin::BI__builtin_nansl: case Builtin::BI__builtin_nansf128: if (!TryEvaluateBuiltinNaN(Info.Ctx, E->getType(), E->getArg(0), true, Result)) return Error(E); return true; case Builtin::BI__builtin_nan: case Builtin::BI__builtin_nanf: case Builtin::BI__builtin_nanl: case Builtin::BI__builtin_nanf128: // If this is __builtin_nan() turn this into a nan, otherwise we // can't constant fold it. if (!TryEvaluateBuiltinNaN(Info.Ctx, E->getType(), E->getArg(0), false, Result)) return Error(E); return true; case Builtin::BI__builtin_fabs: case Builtin::BI__builtin_fabsf: case Builtin::BI__builtin_fabsl: case Builtin::BI__builtin_fabsf128: if (!EvaluateFloat(E->getArg(0), Result, Info)) return false; if (Result.isNegative()) Result.changeSign(); return true; // FIXME: Builtin::BI__builtin_powi // FIXME: Builtin::BI__builtin_powif // FIXME: Builtin::BI__builtin_powil case Builtin::BI__builtin_copysign: case Builtin::BI__builtin_copysignf: case Builtin::BI__builtin_copysignl: case Builtin::BI__builtin_copysignf128: { APFloat RHS(0.); if (!EvaluateFloat(E->getArg(0), Result, Info) || !EvaluateFloat(E->getArg(1), RHS, Info)) return false; Result.copySign(RHS); return true; } } } bool FloatExprEvaluator::VisitUnaryReal(const UnaryOperator *E) { if (E->getSubExpr()->getType()->isAnyComplexType()) { ComplexValue CV; if (!EvaluateComplex(E->getSubExpr(), CV, Info)) return false; Result = CV.FloatReal; return true; } return Visit(E->getSubExpr()); } bool FloatExprEvaluator::VisitUnaryImag(const UnaryOperator *E) { if (E->getSubExpr()->getType()->isAnyComplexType()) { ComplexValue CV; if (!EvaluateComplex(E->getSubExpr(), CV, Info)) return false; Result = CV.FloatImag; return true; } VisitIgnoredValue(E->getSubExpr()); const llvm::fltSemantics &Sem = Info.Ctx.getFloatTypeSemantics(E->getType()); Result = llvm::APFloat::getZero(Sem); return true; } bool FloatExprEvaluator::VisitUnaryOperator(const UnaryOperator *E) { switch (E->getOpcode()) { default: return Error(E); case UO_Plus: return EvaluateFloat(E->getSubExpr(), Result, Info); case UO_Minus: if (!EvaluateFloat(E->getSubExpr(), Result, Info)) return false; Result.changeSign(); return true; } } bool FloatExprEvaluator::VisitBinaryOperator(const BinaryOperator *E) { if (E->isPtrMemOp() || E->isAssignmentOp() || E->getOpcode() == BO_Comma) return ExprEvaluatorBaseTy::VisitBinaryOperator(E); APFloat RHS(0.0); bool LHSOK = EvaluateFloat(E->getLHS(), Result, Info); if (!LHSOK && !Info.noteFailure()) return false; return EvaluateFloat(E->getRHS(), RHS, Info) && LHSOK && handleFloatFloatBinOp(Info, E, Result, E->getOpcode(), RHS); } bool FloatExprEvaluator::VisitFloatingLiteral(const FloatingLiteral *E) { Result = E->getValue(); return true; } bool FloatExprEvaluator::VisitCastExpr(const CastExpr *E) { const Expr* SubExpr = E->getSubExpr(); switch (E->getCastKind()) { default: return ExprEvaluatorBaseTy::VisitCastExpr(E); case CK_IntegralToFloating: { APSInt IntResult; return EvaluateInteger(SubExpr, IntResult, Info) && HandleIntToFloatCast(Info, E, SubExpr->getType(), IntResult, E->getType(), Result); } case CK_FloatingCast: { if (!Visit(SubExpr)) return false; return HandleFloatToFloatCast(Info, E, SubExpr->getType(), E->getType(), Result); } case CK_FloatingComplexToReal: { ComplexValue V; if (!EvaluateComplex(SubExpr, V, Info)) return false; Result = V.getComplexFloatReal(); return true; } } } //===----------------------------------------------------------------------===// // Complex Evaluation (for float and integer) //===----------------------------------------------------------------------===// namespace { class ComplexExprEvaluator : public ExprEvaluatorBase { ComplexValue &Result; public: ComplexExprEvaluator(EvalInfo &info, ComplexValue &Result) : ExprEvaluatorBaseTy(info), Result(Result) {} bool Success(const APValue &V, const Expr *e) { Result.setFrom(V); return true; } bool ZeroInitialization(const Expr *E); //===--------------------------------------------------------------------===// // Visitor Methods //===--------------------------------------------------------------------===// bool VisitImaginaryLiteral(const ImaginaryLiteral *E); bool VisitCastExpr(const CastExpr *E); bool VisitBinaryOperator(const BinaryOperator *E); bool VisitUnaryOperator(const UnaryOperator *E); bool VisitInitListExpr(const InitListExpr *E); }; } // end anonymous namespace static bool EvaluateComplex(const Expr *E, ComplexValue &Result, EvalInfo &Info) { assert(E->isRValue() && E->getType()->isAnyComplexType()); return ComplexExprEvaluator(Info, Result).Visit(E); } bool ComplexExprEvaluator::ZeroInitialization(const Expr *E) { QualType ElemTy = E->getType()->castAs()->getElementType(); if (ElemTy->isRealFloatingType()) { Result.makeComplexFloat(); APFloat Zero = APFloat::getZero(Info.Ctx.getFloatTypeSemantics(ElemTy)); Result.FloatReal = Zero; Result.FloatImag = Zero; } else { Result.makeComplexInt(); APSInt Zero = Info.Ctx.MakeIntValue(0, ElemTy); Result.IntReal = Zero; Result.IntImag = Zero; } return true; } bool ComplexExprEvaluator::VisitImaginaryLiteral(const ImaginaryLiteral *E) { const Expr* SubExpr = E->getSubExpr(); if (SubExpr->getType()->isRealFloatingType()) { Result.makeComplexFloat(); APFloat &Imag = Result.FloatImag; if (!EvaluateFloat(SubExpr, Imag, Info)) return false; Result.FloatReal = APFloat(Imag.getSemantics()); return true; } else { assert(SubExpr->getType()->isIntegerType() && "Unexpected imaginary literal."); Result.makeComplexInt(); APSInt &Imag = Result.IntImag; if (!EvaluateInteger(SubExpr, Imag, Info)) return false; Result.IntReal = APSInt(Imag.getBitWidth(), !Imag.isSigned()); return true; } } bool ComplexExprEvaluator::VisitCastExpr(const CastExpr *E) { switch (E->getCastKind()) { case CK_BitCast: case CK_BaseToDerived: case CK_DerivedToBase: case CK_UncheckedDerivedToBase: case CK_Dynamic: case CK_ToUnion: case CK_ArrayToPointerDecay: case CK_FunctionToPointerDecay: case CK_NullToPointer: case CK_NullToMemberPointer: case CK_BaseToDerivedMemberPointer: case CK_DerivedToBaseMemberPointer: case CK_MemberPointerToBoolean: case CK_ReinterpretMemberPointer: case CK_ConstructorConversion: case CK_IntegralToPointer: case CK_PointerToIntegral: case CK_PointerToBoolean: case CK_ToVoid: case CK_VectorSplat: case CK_IntegralCast: case CK_BooleanToSignedIntegral: case CK_IntegralToBoolean: case CK_IntegralToFloating: case CK_FloatingToIntegral: case CK_FloatingToBoolean: case CK_FloatingCast: case CK_CPointerToObjCPointerCast: case CK_BlockPointerToObjCPointerCast: case CK_AnyPointerToBlockPointerCast: case CK_ObjCObjectLValueCast: case CK_FloatingComplexToReal: case CK_FloatingComplexToBoolean: case CK_IntegralComplexToReal: case CK_IntegralComplexToBoolean: case CK_ARCProduceObject: case CK_ARCConsumeObject: case CK_ARCReclaimReturnedObject: case CK_ARCExtendBlockObject: case CK_CopyAndAutoreleaseBlockObject: case CK_BuiltinFnToFnPtr: case CK_ZeroToOCLEvent: case CK_ZeroToOCLQueue: case CK_NonAtomicToAtomic: case CK_AddressSpaceConversion: case CK_IntToOCLSampler: llvm_unreachable("invalid cast kind for complex value"); case CK_LValueToRValue: case CK_AtomicToNonAtomic: case CK_NoOp: return ExprEvaluatorBaseTy::VisitCastExpr(E); case CK_Dependent: case CK_LValueBitCast: case CK_UserDefinedConversion: return Error(E); case CK_FloatingRealToComplex: { APFloat &Real = Result.FloatReal; if (!EvaluateFloat(E->getSubExpr(), Real, Info)) return false; Result.makeComplexFloat(); Result.FloatImag = APFloat(Real.getSemantics()); return true; } case CK_FloatingComplexCast: { if (!Visit(E->getSubExpr())) return false; QualType To = E->getType()->getAs()->getElementType(); QualType From = E->getSubExpr()->getType()->getAs()->getElementType(); return HandleFloatToFloatCast(Info, E, From, To, Result.FloatReal) && HandleFloatToFloatCast(Info, E, From, To, Result.FloatImag); } case CK_FloatingComplexToIntegralComplex: { if (!Visit(E->getSubExpr())) return false; QualType To = E->getType()->getAs()->getElementType(); QualType From = E->getSubExpr()->getType()->getAs()->getElementType(); Result.makeComplexInt(); return HandleFloatToIntCast(Info, E, From, Result.FloatReal, To, Result.IntReal) && HandleFloatToIntCast(Info, E, From, Result.FloatImag, To, Result.IntImag); } case CK_IntegralRealToComplex: { APSInt &Real = Result.IntReal; if (!EvaluateInteger(E->getSubExpr(), Real, Info)) return false; Result.makeComplexInt(); Result.IntImag = APSInt(Real.getBitWidth(), !Real.isSigned()); return true; } case CK_IntegralComplexCast: { if (!Visit(E->getSubExpr())) return false; QualType To = E->getType()->getAs()->getElementType(); QualType From = E->getSubExpr()->getType()->getAs()->getElementType(); Result.IntReal = HandleIntToIntCast(Info, E, To, From, Result.IntReal); Result.IntImag = HandleIntToIntCast(Info, E, To, From, Result.IntImag); return true; } case CK_IntegralComplexToFloatingComplex: { if (!Visit(E->getSubExpr())) return false; QualType To = E->getType()->castAs()->getElementType(); QualType From = E->getSubExpr()->getType()->castAs()->getElementType(); Result.makeComplexFloat(); return HandleIntToFloatCast(Info, E, From, Result.IntReal, To, Result.FloatReal) && HandleIntToFloatCast(Info, E, From, Result.IntImag, To, Result.FloatImag); } } llvm_unreachable("unknown cast resulting in complex value"); } bool ComplexExprEvaluator::VisitBinaryOperator(const BinaryOperator *E) { if (E->isPtrMemOp() || E->isAssignmentOp() || E->getOpcode() == BO_Comma) return ExprEvaluatorBaseTy::VisitBinaryOperator(E); // Track whether the LHS or RHS is real at the type system level. When this is // the case we can simplify our evaluation strategy. bool LHSReal = false, RHSReal = false; bool LHSOK; if (E->getLHS()->getType()->isRealFloatingType()) { LHSReal = true; APFloat &Real = Result.FloatReal; LHSOK = EvaluateFloat(E->getLHS(), Real, Info); if (LHSOK) { Result.makeComplexFloat(); Result.FloatImag = APFloat(Real.getSemantics()); } } else { LHSOK = Visit(E->getLHS()); } if (!LHSOK && !Info.noteFailure()) return false; ComplexValue RHS; if (E->getRHS()->getType()->isRealFloatingType()) { RHSReal = true; APFloat &Real = RHS.FloatReal; if (!EvaluateFloat(E->getRHS(), Real, Info) || !LHSOK) return false; RHS.makeComplexFloat(); RHS.FloatImag = APFloat(Real.getSemantics()); } else if (!EvaluateComplex(E->getRHS(), RHS, Info) || !LHSOK) return false; assert(!(LHSReal && RHSReal) && "Cannot have both operands of a complex operation be real."); switch (E->getOpcode()) { default: return Error(E); case BO_Add: if (Result.isComplexFloat()) { Result.getComplexFloatReal().add(RHS.getComplexFloatReal(), APFloat::rmNearestTiesToEven); if (LHSReal) Result.getComplexFloatImag() = RHS.getComplexFloatImag(); else if (!RHSReal) Result.getComplexFloatImag().add(RHS.getComplexFloatImag(), APFloat::rmNearestTiesToEven); } else { Result.getComplexIntReal() += RHS.getComplexIntReal(); Result.getComplexIntImag() += RHS.getComplexIntImag(); } break; case BO_Sub: if (Result.isComplexFloat()) { Result.getComplexFloatReal().subtract(RHS.getComplexFloatReal(), APFloat::rmNearestTiesToEven); if (LHSReal) { Result.getComplexFloatImag() = RHS.getComplexFloatImag(); Result.getComplexFloatImag().changeSign(); } else if (!RHSReal) { Result.getComplexFloatImag().subtract(RHS.getComplexFloatImag(), APFloat::rmNearestTiesToEven); } } else { Result.getComplexIntReal() -= RHS.getComplexIntReal(); Result.getComplexIntImag() -= RHS.getComplexIntImag(); } break; case BO_Mul: if (Result.isComplexFloat()) { // This is an implementation of complex multiplication according to the // constraints laid out in C11 Annex G. The implemention uses the // following naming scheme: // (a + ib) * (c + id) ComplexValue LHS = Result; APFloat &A = LHS.getComplexFloatReal(); APFloat &B = LHS.getComplexFloatImag(); APFloat &C = RHS.getComplexFloatReal(); APFloat &D = RHS.getComplexFloatImag(); APFloat &ResR = Result.getComplexFloatReal(); APFloat &ResI = Result.getComplexFloatImag(); if (LHSReal) { assert(!RHSReal && "Cannot have two real operands for a complex op!"); ResR = A * C; ResI = A * D; } else if (RHSReal) { ResR = C * A; ResI = C * B; } else { // In the fully general case, we need to handle NaNs and infinities // robustly. APFloat AC = A * C; APFloat BD = B * D; APFloat AD = A * D; APFloat BC = B * C; ResR = AC - BD; ResI = AD + BC; if (ResR.isNaN() && ResI.isNaN()) { bool Recalc = false; if (A.isInfinity() || B.isInfinity()) { A = APFloat::copySign( APFloat(A.getSemantics(), A.isInfinity() ? 1 : 0), A); B = APFloat::copySign( APFloat(B.getSemantics(), B.isInfinity() ? 1 : 0), B); if (C.isNaN()) C = APFloat::copySign(APFloat(C.getSemantics()), C); if (D.isNaN()) D = APFloat::copySign(APFloat(D.getSemantics()), D); Recalc = true; } if (C.isInfinity() || D.isInfinity()) { C = APFloat::copySign( APFloat(C.getSemantics(), C.isInfinity() ? 1 : 0), C); D = APFloat::copySign( APFloat(D.getSemantics(), D.isInfinity() ? 1 : 0), D); if (A.isNaN()) A = APFloat::copySign(APFloat(A.getSemantics()), A); if (B.isNaN()) B = APFloat::copySign(APFloat(B.getSemantics()), B); Recalc = true; } if (!Recalc && (AC.isInfinity() || BD.isInfinity() || AD.isInfinity() || BC.isInfinity())) { if (A.isNaN()) A = APFloat::copySign(APFloat(A.getSemantics()), A); if (B.isNaN()) B = APFloat::copySign(APFloat(B.getSemantics()), B); if (C.isNaN()) C = APFloat::copySign(APFloat(C.getSemantics()), C); if (D.isNaN()) D = APFloat::copySign(APFloat(D.getSemantics()), D); Recalc = true; } if (Recalc) { ResR = APFloat::getInf(A.getSemantics()) * (A * C - B * D); ResI = APFloat::getInf(A.getSemantics()) * (A * D + B * C); } } } } else { ComplexValue LHS = Result; Result.getComplexIntReal() = (LHS.getComplexIntReal() * RHS.getComplexIntReal() - LHS.getComplexIntImag() * RHS.getComplexIntImag()); Result.getComplexIntImag() = (LHS.getComplexIntReal() * RHS.getComplexIntImag() + LHS.getComplexIntImag() * RHS.getComplexIntReal()); } break; case BO_Div: if (Result.isComplexFloat()) { // This is an implementation of complex division according to the // constraints laid out in C11 Annex G. The implemention uses the // following naming scheme: // (a + ib) / (c + id) ComplexValue LHS = Result; APFloat &A = LHS.getComplexFloatReal(); APFloat &B = LHS.getComplexFloatImag(); APFloat &C = RHS.getComplexFloatReal(); APFloat &D = RHS.getComplexFloatImag(); APFloat &ResR = Result.getComplexFloatReal(); APFloat &ResI = Result.getComplexFloatImag(); if (RHSReal) { ResR = A / C; ResI = B / C; } else { if (LHSReal) { // No real optimizations we can do here, stub out with zero. B = APFloat::getZero(A.getSemantics()); } int DenomLogB = 0; APFloat MaxCD = maxnum(abs(C), abs(D)); if (MaxCD.isFinite()) { DenomLogB = ilogb(MaxCD); C = scalbn(C, -DenomLogB, APFloat::rmNearestTiesToEven); D = scalbn(D, -DenomLogB, APFloat::rmNearestTiesToEven); } APFloat Denom = C * C + D * D; ResR = scalbn((A * C + B * D) / Denom, -DenomLogB, APFloat::rmNearestTiesToEven); ResI = scalbn((B * C - A * D) / Denom, -DenomLogB, APFloat::rmNearestTiesToEven); if (ResR.isNaN() && ResI.isNaN()) { if (Denom.isPosZero() && (!A.isNaN() || !B.isNaN())) { ResR = APFloat::getInf(ResR.getSemantics(), C.isNegative()) * A; ResI = APFloat::getInf(ResR.getSemantics(), C.isNegative()) * B; } else if ((A.isInfinity() || B.isInfinity()) && C.isFinite() && D.isFinite()) { A = APFloat::copySign( APFloat(A.getSemantics(), A.isInfinity() ? 1 : 0), A); B = APFloat::copySign( APFloat(B.getSemantics(), B.isInfinity() ? 1 : 0), B); ResR = APFloat::getInf(ResR.getSemantics()) * (A * C + B * D); ResI = APFloat::getInf(ResI.getSemantics()) * (B * C - A * D); } else if (MaxCD.isInfinity() && A.isFinite() && B.isFinite()) { C = APFloat::copySign( APFloat(C.getSemantics(), C.isInfinity() ? 1 : 0), C); D = APFloat::copySign( APFloat(D.getSemantics(), D.isInfinity() ? 1 : 0), D); ResR = APFloat::getZero(ResR.getSemantics()) * (A * C + B * D); ResI = APFloat::getZero(ResI.getSemantics()) * (B * C - A * D); } } } } else { if (RHS.getComplexIntReal() == 0 && RHS.getComplexIntImag() == 0) return Error(E, diag::note_expr_divide_by_zero); ComplexValue LHS = Result; APSInt Den = RHS.getComplexIntReal() * RHS.getComplexIntReal() + RHS.getComplexIntImag() * RHS.getComplexIntImag(); Result.getComplexIntReal() = (LHS.getComplexIntReal() * RHS.getComplexIntReal() + LHS.getComplexIntImag() * RHS.getComplexIntImag()) / Den; Result.getComplexIntImag() = (LHS.getComplexIntImag() * RHS.getComplexIntReal() - LHS.getComplexIntReal() * RHS.getComplexIntImag()) / Den; } break; } return true; } bool ComplexExprEvaluator::VisitUnaryOperator(const UnaryOperator *E) { // Get the operand value into 'Result'. if (!Visit(E->getSubExpr())) return false; switch (E->getOpcode()) { default: return Error(E); case UO_Extension: return true; case UO_Plus: // The result is always just the subexpr. return true; case UO_Minus: if (Result.isComplexFloat()) { Result.getComplexFloatReal().changeSign(); Result.getComplexFloatImag().changeSign(); } else { Result.getComplexIntReal() = -Result.getComplexIntReal(); Result.getComplexIntImag() = -Result.getComplexIntImag(); } return true; case UO_Not: if (Result.isComplexFloat()) Result.getComplexFloatImag().changeSign(); else Result.getComplexIntImag() = -Result.getComplexIntImag(); return true; } } bool ComplexExprEvaluator::VisitInitListExpr(const InitListExpr *E) { if (E->getNumInits() == 2) { if (E->getType()->isComplexType()) { Result.makeComplexFloat(); if (!EvaluateFloat(E->getInit(0), Result.FloatReal, Info)) return false; if (!EvaluateFloat(E->getInit(1), Result.FloatImag, Info)) return false; } else { Result.makeComplexInt(); if (!EvaluateInteger(E->getInit(0), Result.IntReal, Info)) return false; if (!EvaluateInteger(E->getInit(1), Result.IntImag, Info)) return false; } return true; } return ExprEvaluatorBaseTy::VisitInitListExpr(E); } //===----------------------------------------------------------------------===// // Atomic expression evaluation, essentially just handling the NonAtomicToAtomic // implicit conversion. //===----------------------------------------------------------------------===// namespace { class AtomicExprEvaluator : public ExprEvaluatorBase { const LValue *This; APValue &Result; public: AtomicExprEvaluator(EvalInfo &Info, const LValue *This, APValue &Result) : ExprEvaluatorBaseTy(Info), This(This), Result(Result) {} bool Success(const APValue &V, const Expr *E) { Result = V; return true; } bool ZeroInitialization(const Expr *E) { ImplicitValueInitExpr VIE( E->getType()->castAs()->getValueType()); // For atomic-qualified class (and array) types in C++, initialize the // _Atomic-wrapped subobject directly, in-place. return This ? EvaluateInPlace(Result, Info, *This, &VIE) : Evaluate(Result, Info, &VIE); } bool VisitCastExpr(const CastExpr *E) { switch (E->getCastKind()) { default: return ExprEvaluatorBaseTy::VisitCastExpr(E); case CK_NonAtomicToAtomic: return This ? EvaluateInPlace(Result, Info, *This, E->getSubExpr()) : Evaluate(Result, Info, E->getSubExpr()); } } }; } // end anonymous namespace static bool EvaluateAtomic(const Expr *E, const LValue *This, APValue &Result, EvalInfo &Info) { assert(E->isRValue() && E->getType()->isAtomicType()); return AtomicExprEvaluator(Info, This, Result).Visit(E); } //===----------------------------------------------------------------------===// // Void expression evaluation, primarily for a cast to void on the LHS of a // comma operator //===----------------------------------------------------------------------===// namespace { class VoidExprEvaluator : public ExprEvaluatorBase { public: VoidExprEvaluator(EvalInfo &Info) : ExprEvaluatorBaseTy(Info) {} bool Success(const APValue &V, const Expr *e) { return true; } bool ZeroInitialization(const Expr *E) { return true; } bool VisitCastExpr(const CastExpr *E) { switch (E->getCastKind()) { default: return ExprEvaluatorBaseTy::VisitCastExpr(E); case CK_ToVoid: VisitIgnoredValue(E->getSubExpr()); return true; } } bool VisitCallExpr(const CallExpr *E) { switch (E->getBuiltinCallee()) { default: return ExprEvaluatorBaseTy::VisitCallExpr(E); case Builtin::BI__assume: case Builtin::BI__builtin_assume: // The argument is not evaluated! return true; } } }; } // end anonymous namespace static bool EvaluateVoid(const Expr *E, EvalInfo &Info) { assert(E->isRValue() && E->getType()->isVoidType()); return VoidExprEvaluator(Info).Visit(E); } //===----------------------------------------------------------------------===// // Top level Expr::EvaluateAsRValue method. //===----------------------------------------------------------------------===// static bool Evaluate(APValue &Result, EvalInfo &Info, const Expr *E) { // In C, function designators are not lvalues, but we evaluate them as if they // are. QualType T = E->getType(); if (E->isGLValue() || T->isFunctionType()) { LValue LV; if (!EvaluateLValue(E, LV, Info)) return false; LV.moveInto(Result); } else if (T->isVectorType()) { if (!EvaluateVector(E, Result, Info)) return false; } else if (T->isIntegralOrEnumerationType()) { if (!IntExprEvaluator(Info, Result).Visit(E)) return false; } else if (T->hasPointerRepresentation()) { LValue LV; if (!EvaluatePointer(E, LV, Info)) return false; LV.moveInto(Result); } else if (T->isRealFloatingType()) { llvm::APFloat F(0.0); if (!EvaluateFloat(E, F, Info)) return false; Result = APValue(F); } else if (T->isAnyComplexType()) { ComplexValue C; if (!EvaluateComplex(E, C, Info)) return false; C.moveInto(Result); } else if (T->isFixedPointType()) { if (!FixedPointExprEvaluator(Info, Result).Visit(E)) return false; } else if (T->isMemberPointerType()) { MemberPtr P; if (!EvaluateMemberPointer(E, P, Info)) return false; P.moveInto(Result); return true; } else if (T->isArrayType()) { LValue LV; APValue &Value = createTemporary(E, false, LV, *Info.CurrentCall); if (!EvaluateArray(E, LV, Value, Info)) return false; Result = Value; } else if (T->isRecordType()) { LValue LV; APValue &Value = createTemporary(E, false, LV, *Info.CurrentCall); if (!EvaluateRecord(E, LV, Value, Info)) return false; Result = Value; } else if (T->isVoidType()) { if (!Info.getLangOpts().CPlusPlus11) Info.CCEDiag(E, diag::note_constexpr_nonliteral) << E->getType(); if (!EvaluateVoid(E, Info)) return false; } else if (T->isAtomicType()) { QualType Unqual = T.getAtomicUnqualifiedType(); if (Unqual->isArrayType() || Unqual->isRecordType()) { LValue LV; APValue &Value = createTemporary(E, false, LV, *Info.CurrentCall); if (!EvaluateAtomic(E, &LV, Value, Info)) return false; } else { if (!EvaluateAtomic(E, nullptr, Result, Info)) return false; } } else if (Info.getLangOpts().CPlusPlus11) { Info.FFDiag(E, diag::note_constexpr_nonliteral) << E->getType(); return false; } else { Info.FFDiag(E, diag::note_invalid_subexpr_in_const_expr); return false; } return true; } /// EvaluateInPlace - Evaluate an expression in-place in an APValue. In some /// cases, the in-place evaluation is essential, since later initializers for /// an object can indirectly refer to subobjects which were initialized earlier. static bool EvaluateInPlace(APValue &Result, EvalInfo &Info, const LValue &This, const Expr *E, bool AllowNonLiteralTypes) { assert(!E->isValueDependent()); if (!AllowNonLiteralTypes && !CheckLiteralType(Info, E, &This)) return false; if (E->isRValue()) { // Evaluate arrays and record types in-place, so that later initializers can // refer to earlier-initialized members of the object. QualType T = E->getType(); if (T->isArrayType()) return EvaluateArray(E, This, Result, Info); else if (T->isRecordType()) return EvaluateRecord(E, This, Result, Info); else if (T->isAtomicType()) { QualType Unqual = T.getAtomicUnqualifiedType(); if (Unqual->isArrayType() || Unqual->isRecordType()) return EvaluateAtomic(E, &This, Result, Info); } } // For any other type, in-place evaluation is unimportant. return Evaluate(Result, Info, E); } /// EvaluateAsRValue - Try to evaluate this expression, performing an implicit /// lvalue-to-rvalue cast if it is an lvalue. static bool EvaluateAsRValue(EvalInfo &Info, const Expr *E, APValue &Result) { if (E->getType().isNull()) return false; if (!CheckLiteralType(Info, E)) return false; if (!::Evaluate(Result, Info, E)) return false; if (E->isGLValue()) { LValue LV; LV.setFrom(Info.Ctx, Result); if (!handleLValueToRValueConversion(Info, E, E->getType(), LV, Result)) return false; } // Check this core constant expression is a constant expression. return CheckConstantExpression(Info, E->getExprLoc(), E->getType(), Result); } static bool FastEvaluateAsRValue(const Expr *Exp, Expr::EvalResult &Result, const ASTContext &Ctx, bool &IsConst) { // Fast-path evaluations of integer literals, since we sometimes see files // containing vast quantities of these. if (const IntegerLiteral *L = dyn_cast(Exp)) { Result.Val = APValue(APSInt(L->getValue(), L->getType()->isUnsignedIntegerType())); IsConst = true; return true; } // This case should be rare, but we need to check it before we check on // the type below. if (Exp->getType().isNull()) { IsConst = false; return true; } // FIXME: Evaluating values of large array and record types can cause // performance problems. Only do so in C++11 for now. if (Exp->isRValue() && (Exp->getType()->isArrayType() || Exp->getType()->isRecordType()) && !Ctx.getLangOpts().CPlusPlus11) { IsConst = false; return true; } return false; } /// EvaluateAsRValue - Return true if this is a constant which we can fold using /// any crazy technique (that has nothing to do with language standards) that /// we want to. If this function returns true, it returns the folded constant /// in Result. If this expression is a glvalue, an lvalue-to-rvalue conversion /// will be applied to the result. bool Expr::EvaluateAsRValue(EvalResult &Result, const ASTContext &Ctx) const { bool IsConst; if (FastEvaluateAsRValue(this, Result, Ctx, IsConst)) return IsConst; EvalInfo Info(Ctx, Result, EvalInfo::EM_IgnoreSideEffects); return ::EvaluateAsRValue(Info, this, Result.Val); } bool Expr::EvaluateAsBooleanCondition(bool &Result, const ASTContext &Ctx) const { EvalResult Scratch; return EvaluateAsRValue(Scratch, Ctx) && HandleConversionToBool(Scratch.Val, Result); } static bool hasUnacceptableSideEffect(Expr::EvalStatus &Result, Expr::SideEffectsKind SEK) { return (SEK < Expr::SE_AllowSideEffects && Result.HasSideEffects) || (SEK < Expr::SE_AllowUndefinedBehavior && Result.HasUndefinedBehavior); } bool Expr::EvaluateAsInt(APSInt &Result, const ASTContext &Ctx, SideEffectsKind AllowSideEffects) const { if (!getType()->isIntegralOrEnumerationType()) return false; EvalResult ExprResult; if (!EvaluateAsRValue(ExprResult, Ctx) || !ExprResult.Val.isInt() || hasUnacceptableSideEffect(ExprResult, AllowSideEffects)) return false; Result = ExprResult.Val.getInt(); return true; } bool Expr::EvaluateAsFloat(APFloat &Result, const ASTContext &Ctx, SideEffectsKind AllowSideEffects) const { if (!getType()->isRealFloatingType()) return false; EvalResult ExprResult; if (!EvaluateAsRValue(ExprResult, Ctx) || !ExprResult.Val.isFloat() || hasUnacceptableSideEffect(ExprResult, AllowSideEffects)) return false; Result = ExprResult.Val.getFloat(); return true; } bool Expr::EvaluateAsLValue(EvalResult &Result, const ASTContext &Ctx) const { EvalInfo Info(Ctx, Result, EvalInfo::EM_ConstantFold); LValue LV; if (!EvaluateLValue(this, LV, Info) || Result.HasSideEffects || !CheckLValueConstantExpression(Info, getExprLoc(), Ctx.getLValueReferenceType(getType()), LV, Expr::EvaluateForCodeGen)) return false; LV.moveInto(Result.Val); return true; } bool Expr::EvaluateAsConstantExpr(EvalResult &Result, ConstExprUsage Usage, const ASTContext &Ctx) const { EvalInfo::EvaluationMode EM = EvalInfo::EM_ConstantExpression; EvalInfo Info(Ctx, Result, EM); if (!::Evaluate(Result.Val, Info, this)) return false; return CheckConstantExpression(Info, getExprLoc(), getType(), Result.Val, Usage); } bool Expr::EvaluateAsInitializer(APValue &Value, const ASTContext &Ctx, const VarDecl *VD, SmallVectorImpl &Notes) const { // FIXME: Evaluating initializers for large array and record types can cause // performance problems. Only do so in C++11 for now. if (isRValue() && (getType()->isArrayType() || getType()->isRecordType()) && !Ctx.getLangOpts().CPlusPlus11) return false; Expr::EvalStatus EStatus; EStatus.Diag = &Notes; EvalInfo InitInfo(Ctx, EStatus, VD->isConstexpr() ? EvalInfo::EM_ConstantExpression : EvalInfo::EM_ConstantFold); InitInfo.setEvaluatingDecl(VD, Value); LValue LVal; LVal.set(VD); // C++11 [basic.start.init]p2: // Variables with static storage duration or thread storage duration shall be // zero-initialized before any other initialization takes place. // This behavior is not present in C. if (Ctx.getLangOpts().CPlusPlus && !VD->hasLocalStorage() && !VD->getType()->isReferenceType()) { ImplicitValueInitExpr VIE(VD->getType()); if (!EvaluateInPlace(Value, InitInfo, LVal, &VIE, /*AllowNonLiteralTypes=*/true)) return false; } if (!EvaluateInPlace(Value, InitInfo, LVal, this, /*AllowNonLiteralTypes=*/true) || EStatus.HasSideEffects) return false; return CheckConstantExpression(InitInfo, VD->getLocation(), VD->getType(), Value); } /// isEvaluatable - Call EvaluateAsRValue to see if this expression can be /// constant folded, but discard the result. bool Expr::isEvaluatable(const ASTContext &Ctx, SideEffectsKind SEK) const { EvalResult Result; return EvaluateAsRValue(Result, Ctx) && !hasUnacceptableSideEffect(Result, SEK); } APSInt Expr::EvaluateKnownConstInt(const ASTContext &Ctx, SmallVectorImpl *Diag) const { EvalResult EvalResult; EvalResult.Diag = Diag; bool Result = EvaluateAsRValue(EvalResult, Ctx); (void)Result; assert(Result && "Could not evaluate expression"); assert(EvalResult.Val.isInt() && "Expression did not evaluate to integer"); return EvalResult.Val.getInt(); } void Expr::EvaluateForOverflow(const ASTContext &Ctx) const { bool IsConst; EvalResult EvalResult; if (!FastEvaluateAsRValue(this, EvalResult, Ctx, IsConst)) { EvalInfo Info(Ctx, EvalResult, EvalInfo::EM_EvaluateForOverflow); (void)::EvaluateAsRValue(Info, this, EvalResult.Val); } } bool Expr::EvalResult::isGlobalLValue() const { assert(Val.isLValue()); return IsGlobalLValue(Val.getLValueBase()); } /// isIntegerConstantExpr - this recursive routine will test if an expression is /// an integer constant expression. /// FIXME: Pass up a reason why! Invalid operation in i-c-e, division by zero, /// comma, etc // CheckICE - This function does the fundamental ICE checking: the returned // ICEDiag contains an ICEKind indicating whether the expression is an ICE, // and a (possibly null) SourceLocation indicating the location of the problem. // // Note that to reduce code duplication, this helper does no evaluation // itself; the caller checks whether the expression is evaluatable, and // in the rare cases where CheckICE actually cares about the evaluated // value, it calls into Evaluate. namespace { enum ICEKind { /// This expression is an ICE. IK_ICE, /// This expression is not an ICE, but if it isn't evaluated, it's /// a legal subexpression for an ICE. This return value is used to handle /// the comma operator in C99 mode, and non-constant subexpressions. IK_ICEIfUnevaluated, /// This expression is not an ICE, and is not a legal subexpression for one. IK_NotICE }; struct ICEDiag { ICEKind Kind; SourceLocation Loc; ICEDiag(ICEKind IK, SourceLocation l) : Kind(IK), Loc(l) {} }; } static ICEDiag NoDiag() { return ICEDiag(IK_ICE, SourceLocation()); } static ICEDiag Worst(ICEDiag A, ICEDiag B) { return A.Kind >= B.Kind ? A : B; } static ICEDiag CheckEvalInICE(const Expr* E, const ASTContext &Ctx) { Expr::EvalResult EVResult; if (!E->EvaluateAsRValue(EVResult, Ctx) || EVResult.HasSideEffects || !EVResult.Val.isInt()) return ICEDiag(IK_NotICE, E->getLocStart()); return NoDiag(); } static ICEDiag CheckICE(const Expr* E, const ASTContext &Ctx) { assert(!E->isValueDependent() && "Should not see value dependent exprs!"); if (!E->getType()->isIntegralOrEnumerationType()) return ICEDiag(IK_NotICE, E->getLocStart()); switch (E->getStmtClass()) { #define ABSTRACT_STMT(Node) #define STMT(Node, Base) case Expr::Node##Class: #define EXPR(Node, Base) #include "clang/AST/StmtNodes.inc" case Expr::PredefinedExprClass: case Expr::FloatingLiteralClass: case Expr::ImaginaryLiteralClass: case Expr::StringLiteralClass: case Expr::ArraySubscriptExprClass: case Expr::OMPArraySectionExprClass: case Expr::MemberExprClass: case Expr::CompoundAssignOperatorClass: case Expr::CompoundLiteralExprClass: case Expr::ExtVectorElementExprClass: case Expr::DesignatedInitExprClass: case Expr::ArrayInitLoopExprClass: case Expr::ArrayInitIndexExprClass: case Expr::NoInitExprClass: case Expr::DesignatedInitUpdateExprClass: case Expr::ImplicitValueInitExprClass: case Expr::ParenListExprClass: case Expr::VAArgExprClass: case Expr::AddrLabelExprClass: case Expr::StmtExprClass: case Expr::CXXMemberCallExprClass: case Expr::CUDAKernelCallExprClass: case Expr::CXXDynamicCastExprClass: case Expr::CXXTypeidExprClass: case Expr::CXXUuidofExprClass: case Expr::MSPropertyRefExprClass: case Expr::MSPropertySubscriptExprClass: case Expr::CXXNullPtrLiteralExprClass: case Expr::UserDefinedLiteralClass: case Expr::CXXThisExprClass: case Expr::CXXThrowExprClass: case Expr::CXXNewExprClass: case Expr::CXXDeleteExprClass: case Expr::CXXPseudoDestructorExprClass: case Expr::UnresolvedLookupExprClass: case Expr::TypoExprClass: case Expr::DependentScopeDeclRefExprClass: case Expr::CXXConstructExprClass: case Expr::CXXInheritedCtorInitExprClass: case Expr::CXXStdInitializerListExprClass: case Expr::CXXBindTemporaryExprClass: case Expr::ExprWithCleanupsClass: case Expr::CXXTemporaryObjectExprClass: case Expr::CXXUnresolvedConstructExprClass: case Expr::CXXDependentScopeMemberExprClass: case Expr::UnresolvedMemberExprClass: case Expr::ObjCStringLiteralClass: case Expr::ObjCBoxedExprClass: case Expr::ObjCArrayLiteralClass: case Expr::ObjCDictionaryLiteralClass: case Expr::ObjCEncodeExprClass: case Expr::ObjCMessageExprClass: case Expr::ObjCSelectorExprClass: case Expr::ObjCProtocolExprClass: case Expr::ObjCIvarRefExprClass: case Expr::ObjCPropertyRefExprClass: case Expr::ObjCSubscriptRefExprClass: case Expr::ObjCIsaExprClass: case Expr::ObjCAvailabilityCheckExprClass: case Expr::ShuffleVectorExprClass: case Expr::ConvertVectorExprClass: case Expr::BlockExprClass: case Expr::NoStmtClass: case Expr::OpaqueValueExprClass: case Expr::PackExpansionExprClass: case Expr::SubstNonTypeTemplateParmPackExprClass: case Expr::FunctionParmPackExprClass: case Expr::AsTypeExprClass: case Expr::ObjCIndirectCopyRestoreExprClass: case Expr::MaterializeTemporaryExprClass: case Expr::PseudoObjectExprClass: case Expr::AtomicExprClass: case Expr::LambdaExprClass: case Expr::CXXFoldExprClass: case Expr::CoawaitExprClass: case Expr::DependentCoawaitExprClass: case Expr::CoyieldExprClass: return ICEDiag(IK_NotICE, E->getLocStart()); case Expr::InitListExprClass: { // C++03 [dcl.init]p13: If T is a scalar type, then a declaration of the // form "T x = { a };" is equivalent to "T x = a;". // Unless we're initializing a reference, T is a scalar as it is known to be // of integral or enumeration type. if (E->isRValue()) if (cast(E)->getNumInits() == 1) return CheckICE(cast(E)->getInit(0), Ctx); return ICEDiag(IK_NotICE, E->getLocStart()); } case Expr::SizeOfPackExprClass: case Expr::GNUNullExprClass: // GCC considers the GNU __null value to be an integral constant expression. return NoDiag(); case Expr::SubstNonTypeTemplateParmExprClass: return CheckICE(cast(E)->getReplacement(), Ctx); case Expr::ParenExprClass: return CheckICE(cast(E)->getSubExpr(), Ctx); case Expr::GenericSelectionExprClass: return CheckICE(cast(E)->getResultExpr(), Ctx); case Expr::IntegerLiteralClass: case Expr::FixedPointLiteralClass: case Expr::CharacterLiteralClass: case Expr::ObjCBoolLiteralExprClass: case Expr::CXXBoolLiteralExprClass: case Expr::CXXScalarValueInitExprClass: case Expr::TypeTraitExprClass: case Expr::ArrayTypeTraitExprClass: case Expr::ExpressionTraitExprClass: case Expr::CXXNoexceptExprClass: return NoDiag(); case Expr::CallExprClass: case Expr::CXXOperatorCallExprClass: { // C99 6.6/3 allows function calls within unevaluated subexpressions of // constant expressions, but they can never be ICEs because an ICE cannot // contain an operand of (pointer to) function type. const CallExpr *CE = cast(E); if (CE->getBuiltinCallee()) return CheckEvalInICE(E, Ctx); return ICEDiag(IK_NotICE, E->getLocStart()); } case Expr::DeclRefExprClass: { if (isa(cast(E)->getDecl())) return NoDiag(); const ValueDecl *D = cast(E)->getDecl(); if (Ctx.getLangOpts().CPlusPlus && D && IsConstNonVolatile(D->getType())) { // Parameter variables are never constants. Without this check, // getAnyInitializer() can find a default argument, which leads // to chaos. if (isa(D)) return ICEDiag(IK_NotICE, cast(E)->getLocation()); // C++ 7.1.5.1p2 // A variable of non-volatile const-qualified integral or enumeration // type initialized by an ICE can be used in ICEs. if (const VarDecl *Dcl = dyn_cast(D)) { if (!Dcl->getType()->isIntegralOrEnumerationType()) return ICEDiag(IK_NotICE, cast(E)->getLocation()); const VarDecl *VD; // Look for a declaration of this variable that has an initializer, and // check whether it is an ICE. if (Dcl->getAnyInitializer(VD) && VD->checkInitIsICE()) return NoDiag(); else return ICEDiag(IK_NotICE, cast(E)->getLocation()); } } return ICEDiag(IK_NotICE, E->getLocStart()); } case Expr::UnaryOperatorClass: { const UnaryOperator *Exp = cast(E); switch (Exp->getOpcode()) { case UO_PostInc: case UO_PostDec: case UO_PreInc: case UO_PreDec: case UO_AddrOf: case UO_Deref: case UO_Coawait: // C99 6.6/3 allows increment and decrement within unevaluated // subexpressions of constant expressions, but they can never be ICEs // because an ICE cannot contain an lvalue operand. return ICEDiag(IK_NotICE, E->getLocStart()); case UO_Extension: case UO_LNot: case UO_Plus: case UO_Minus: case UO_Not: case UO_Real: case UO_Imag: return CheckICE(Exp->getSubExpr(), Ctx); } // OffsetOf falls through here. LLVM_FALLTHROUGH; } case Expr::OffsetOfExprClass: { // Note that per C99, offsetof must be an ICE. And AFAIK, using // EvaluateAsRValue matches the proposed gcc behavior for cases like // "offsetof(struct s{int x[4];}, x[1.0])". This doesn't affect // compliance: we should warn earlier for offsetof expressions with // array subscripts that aren't ICEs, and if the array subscripts // are ICEs, the value of the offsetof must be an integer constant. return CheckEvalInICE(E, Ctx); } case Expr::UnaryExprOrTypeTraitExprClass: { const UnaryExprOrTypeTraitExpr *Exp = cast(E); if ((Exp->getKind() == UETT_SizeOf) && Exp->getTypeOfArgument()->isVariableArrayType()) return ICEDiag(IK_NotICE, E->getLocStart()); return NoDiag(); } case Expr::BinaryOperatorClass: { const BinaryOperator *Exp = cast(E); switch (Exp->getOpcode()) { case BO_PtrMemD: case BO_PtrMemI: case BO_Assign: case BO_MulAssign: case BO_DivAssign: case BO_RemAssign: case BO_AddAssign: case BO_SubAssign: case BO_ShlAssign: case BO_ShrAssign: case BO_AndAssign: case BO_XorAssign: case BO_OrAssign: // C99 6.6/3 allows assignments within unevaluated subexpressions of // constant expressions, but they can never be ICEs because an ICE cannot // contain an lvalue operand. return ICEDiag(IK_NotICE, E->getLocStart()); case BO_Mul: case BO_Div: case BO_Rem: case BO_Add: case BO_Sub: case BO_Shl: case BO_Shr: case BO_LT: case BO_GT: case BO_LE: case BO_GE: case BO_EQ: case BO_NE: case BO_And: case BO_Xor: case BO_Or: case BO_Comma: case BO_Cmp: { ICEDiag LHSResult = CheckICE(Exp->getLHS(), Ctx); ICEDiag RHSResult = CheckICE(Exp->getRHS(), Ctx); if (Exp->getOpcode() == BO_Div || Exp->getOpcode() == BO_Rem) { // EvaluateAsRValue gives an error for undefined Div/Rem, so make sure // we don't evaluate one. if (LHSResult.Kind == IK_ICE && RHSResult.Kind == IK_ICE) { llvm::APSInt REval = Exp->getRHS()->EvaluateKnownConstInt(Ctx); if (REval == 0) return ICEDiag(IK_ICEIfUnevaluated, E->getLocStart()); if (REval.isSigned() && REval.isAllOnesValue()) { llvm::APSInt LEval = Exp->getLHS()->EvaluateKnownConstInt(Ctx); if (LEval.isMinSignedValue()) return ICEDiag(IK_ICEIfUnevaluated, E->getLocStart()); } } } if (Exp->getOpcode() == BO_Comma) { if (Ctx.getLangOpts().C99) { // C99 6.6p3 introduces a strange edge case: comma can be in an ICE // if it isn't evaluated. if (LHSResult.Kind == IK_ICE && RHSResult.Kind == IK_ICE) return ICEDiag(IK_ICEIfUnevaluated, E->getLocStart()); } else { // In both C89 and C++, commas in ICEs are illegal. return ICEDiag(IK_NotICE, E->getLocStart()); } } return Worst(LHSResult, RHSResult); } case BO_LAnd: case BO_LOr: { ICEDiag LHSResult = CheckICE(Exp->getLHS(), Ctx); ICEDiag RHSResult = CheckICE(Exp->getRHS(), Ctx); if (LHSResult.Kind == IK_ICE && RHSResult.Kind == IK_ICEIfUnevaluated) { // Rare case where the RHS has a comma "side-effect"; we need // to actually check the condition to see whether the side // with the comma is evaluated. if ((Exp->getOpcode() == BO_LAnd) != (Exp->getLHS()->EvaluateKnownConstInt(Ctx) == 0)) return RHSResult; return NoDiag(); } return Worst(LHSResult, RHSResult); } } LLVM_FALLTHROUGH; } case Expr::ImplicitCastExprClass: case Expr::CStyleCastExprClass: case Expr::CXXFunctionalCastExprClass: case Expr::CXXStaticCastExprClass: case Expr::CXXReinterpretCastExprClass: case Expr::CXXConstCastExprClass: case Expr::ObjCBridgedCastExprClass: { const Expr *SubExpr = cast(E)->getSubExpr(); if (isa(E)) { if (const FloatingLiteral *FL = dyn_cast(SubExpr->IgnoreParenImpCasts())) { unsigned DestWidth = Ctx.getIntWidth(E->getType()); bool DestSigned = E->getType()->isSignedIntegerOrEnumerationType(); APSInt IgnoredVal(DestWidth, !DestSigned); bool Ignored; // If the value does not fit in the destination type, the behavior is // undefined, so we are not required to treat it as a constant // expression. if (FL->getValue().convertToInteger(IgnoredVal, llvm::APFloat::rmTowardZero, &Ignored) & APFloat::opInvalidOp) return ICEDiag(IK_NotICE, E->getLocStart()); return NoDiag(); } } switch (cast(E)->getCastKind()) { case CK_LValueToRValue: case CK_AtomicToNonAtomic: case CK_NonAtomicToAtomic: case CK_NoOp: case CK_IntegralToBoolean: case CK_IntegralCast: return CheckICE(SubExpr, Ctx); default: return ICEDiag(IK_NotICE, E->getLocStart()); } } case Expr::BinaryConditionalOperatorClass: { const BinaryConditionalOperator *Exp = cast(E); ICEDiag CommonResult = CheckICE(Exp->getCommon(), Ctx); if (CommonResult.Kind == IK_NotICE) return CommonResult; ICEDiag FalseResult = CheckICE(Exp->getFalseExpr(), Ctx); if (FalseResult.Kind == IK_NotICE) return FalseResult; if (CommonResult.Kind == IK_ICEIfUnevaluated) return CommonResult; if (FalseResult.Kind == IK_ICEIfUnevaluated && Exp->getCommon()->EvaluateKnownConstInt(Ctx) != 0) return NoDiag(); return FalseResult; } case Expr::ConditionalOperatorClass: { const ConditionalOperator *Exp = cast(E); // If the condition (ignoring parens) is a __builtin_constant_p call, // then only the true side is actually considered in an integer constant // expression, and it is fully evaluated. This is an important GNU // extension. See GCC PR38377 for discussion. if (const CallExpr *CallCE = dyn_cast(Exp->getCond()->IgnoreParenCasts())) if (CallCE->getBuiltinCallee() == Builtin::BI__builtin_constant_p) return CheckEvalInICE(E, Ctx); ICEDiag CondResult = CheckICE(Exp->getCond(), Ctx); if (CondResult.Kind == IK_NotICE) return CondResult; ICEDiag TrueResult = CheckICE(Exp->getTrueExpr(), Ctx); ICEDiag FalseResult = CheckICE(Exp->getFalseExpr(), Ctx); if (TrueResult.Kind == IK_NotICE) return TrueResult; if (FalseResult.Kind == IK_NotICE) return FalseResult; if (CondResult.Kind == IK_ICEIfUnevaluated) return CondResult; if (TrueResult.Kind == IK_ICE && FalseResult.Kind == IK_ICE) return NoDiag(); // Rare case where the diagnostics depend on which side is evaluated // Note that if we get here, CondResult is 0, and at least one of // TrueResult and FalseResult is non-zero. if (Exp->getCond()->EvaluateKnownConstInt(Ctx) == 0) return FalseResult; return TrueResult; } case Expr::CXXDefaultArgExprClass: return CheckICE(cast(E)->getExpr(), Ctx); case Expr::CXXDefaultInitExprClass: return CheckICE(cast(E)->getExpr(), Ctx); case Expr::ChooseExprClass: { return CheckICE(cast(E)->getChosenSubExpr(), Ctx); } } llvm_unreachable("Invalid StmtClass!"); } /// Evaluate an expression as a C++11 integral constant expression. static bool EvaluateCPlusPlus11IntegralConstantExpr(const ASTContext &Ctx, const Expr *E, llvm::APSInt *Value, SourceLocation *Loc) { if (!E->getType()->isIntegralOrUnscopedEnumerationType()) { if (Loc) *Loc = E->getExprLoc(); return false; } APValue Result; if (!E->isCXX11ConstantExpr(Ctx, &Result, Loc)) return false; if (!Result.isInt()) { if (Loc) *Loc = E->getExprLoc(); return false; } if (Value) *Value = Result.getInt(); return true; } bool Expr::isIntegerConstantExpr(const ASTContext &Ctx, SourceLocation *Loc) const { if (Ctx.getLangOpts().CPlusPlus11) return EvaluateCPlusPlus11IntegralConstantExpr(Ctx, this, nullptr, Loc); ICEDiag D = CheckICE(this, Ctx); if (D.Kind != IK_ICE) { if (Loc) *Loc = D.Loc; return false; } return true; } bool Expr::isIntegerConstantExpr(llvm::APSInt &Value, const ASTContext &Ctx, SourceLocation *Loc, bool isEvaluated) const { if (Ctx.getLangOpts().CPlusPlus11) return EvaluateCPlusPlus11IntegralConstantExpr(Ctx, this, &Value, Loc); if (!isIntegerConstantExpr(Ctx, Loc)) return false; // The only possible side-effects here are due to UB discovered in the // evaluation (for instance, INT_MAX + 1). In such a case, we are still // required to treat the expression as an ICE, so we produce the folded // value. if (!EvaluateAsInt(Value, Ctx, SE_AllowSideEffects)) llvm_unreachable("ICE cannot be evaluated!"); return true; } bool Expr::isCXX98IntegralConstantExpr(const ASTContext &Ctx) const { return CheckICE(this, Ctx).Kind == IK_ICE; } bool Expr::isCXX11ConstantExpr(const ASTContext &Ctx, APValue *Result, SourceLocation *Loc) const { // We support this checking in C++98 mode in order to diagnose compatibility // issues. assert(Ctx.getLangOpts().CPlusPlus); // Build evaluation settings. Expr::EvalStatus Status; SmallVector Diags; Status.Diag = &Diags; EvalInfo Info(Ctx, Status, EvalInfo::EM_ConstantExpression); APValue Scratch; bool IsConstExpr = ::EvaluateAsRValue(Info, this, Result ? *Result : Scratch); if (!Diags.empty()) { IsConstExpr = false; if (Loc) *Loc = Diags[0].first; } else if (!IsConstExpr) { // FIXME: This shouldn't happen. if (Loc) *Loc = getExprLoc(); } return IsConstExpr; } bool Expr::EvaluateWithSubstitution(APValue &Value, ASTContext &Ctx, const FunctionDecl *Callee, ArrayRef Args, const Expr *This) const { Expr::EvalStatus Status; EvalInfo Info(Ctx, Status, EvalInfo::EM_ConstantExpressionUnevaluated); LValue ThisVal; const LValue *ThisPtr = nullptr; if (This) { #ifndef NDEBUG auto *MD = dyn_cast(Callee); assert(MD && "Don't provide `this` for non-methods."); assert(!MD->isStatic() && "Don't provide `this` for static methods."); #endif if (EvaluateObjectArgument(Info, This, ThisVal)) ThisPtr = &ThisVal; if (Info.EvalStatus.HasSideEffects) return false; } ArgVector ArgValues(Args.size()); for (ArrayRef::iterator I = Args.begin(), E = Args.end(); I != E; ++I) { if ((*I)->isValueDependent() || !Evaluate(ArgValues[I - Args.begin()], Info, *I)) // If evaluation fails, throw away the argument entirely. ArgValues[I - Args.begin()] = APValue(); if (Info.EvalStatus.HasSideEffects) return false; } // Build fake call to Callee. CallStackFrame Frame(Info, Callee->getLocation(), Callee, ThisPtr, ArgValues.data()); return Evaluate(Value, Info, this) && !Info.EvalStatus.HasSideEffects; } bool Expr::isPotentialConstantExpr(const FunctionDecl *FD, SmallVectorImpl< PartialDiagnosticAt> &Diags) { // FIXME: It would be useful to check constexpr function templates, but at the // moment the constant expression evaluator cannot cope with the non-rigorous // ASTs which we build for dependent expressions. if (FD->isDependentContext()) return true; Expr::EvalStatus Status; Status.Diag = &Diags; EvalInfo Info(FD->getASTContext(), Status, EvalInfo::EM_PotentialConstantExpression); const CXXMethodDecl *MD = dyn_cast(FD); const CXXRecordDecl *RD = MD ? MD->getParent()->getCanonicalDecl() : nullptr; // Fabricate an arbitrary expression on the stack and pretend that it // is a temporary being used as the 'this' pointer. LValue This; ImplicitValueInitExpr VIE(RD ? Info.Ctx.getRecordType(RD) : Info.Ctx.IntTy); This.set({&VIE, Info.CurrentCall->Index}); ArrayRef Args; APValue Scratch; if (const CXXConstructorDecl *CD = dyn_cast(FD)) { // Evaluate the call as a constant initializer, to allow the construction // of objects of non-literal types. Info.setEvaluatingDecl(This.getLValueBase(), Scratch); HandleConstructorCall(&VIE, This, Args, CD, Info, Scratch); } else { SourceLocation Loc = FD->getLocation(); HandleFunctionCall(Loc, FD, (MD && MD->isInstance()) ? &This : nullptr, Args, FD->getBody(), Info, Scratch, nullptr); } return Diags.empty(); } bool Expr::isPotentialConstantExprUnevaluated(Expr *E, const FunctionDecl *FD, SmallVectorImpl< PartialDiagnosticAt> &Diags) { Expr::EvalStatus Status; Status.Diag = &Diags; EvalInfo Info(FD->getASTContext(), Status, EvalInfo::EM_PotentialConstantExpressionUnevaluated); // Fabricate a call stack frame to give the arguments a plausible cover story. ArrayRef Args; ArgVector ArgValues(0); bool Success = EvaluateArgs(Args, ArgValues, Info); (void)Success; assert(Success && "Failed to set up arguments for potential constant evaluation"); CallStackFrame Frame(Info, SourceLocation(), FD, nullptr, ArgValues.data()); APValue ResultScratch; Evaluate(ResultScratch, Info, E); return Diags.empty(); } bool Expr::tryEvaluateObjectSize(uint64_t &Result, ASTContext &Ctx, unsigned Type) const { if (!getType()->isPointerType()) return false; Expr::EvalStatus Status; EvalInfo Info(Ctx, Status, EvalInfo::EM_ConstantFold); return tryEvaluateBuiltinObjectSize(this, Type, Info, Result); } Index: projects/clang700-import/contrib/llvm/tools/clang/lib/Basic/Version.cpp =================================================================== --- projects/clang700-import/contrib/llvm/tools/clang/lib/Basic/Version.cpp (revision 337309) +++ projects/clang700-import/contrib/llvm/tools/clang/lib/Basic/Version.cpp (revision 337310) @@ -1,151 +1,151 @@ //===- Version.cpp - Clang Version Number -----------------------*- C++ -*-===// // // The LLVM Compiler Infrastructure // // This file is distributed under the University of Illinois Open Source // License. See LICENSE.TXT for details. // //===----------------------------------------------------------------------===// // // This file defines several version-related utility functions for Clang. // //===----------------------------------------------------------------------===// #include "clang/Basic/Version.h" #include "clang/Basic/LLVM.h" #include "clang/Config/config.h" #include "llvm/Support/raw_ostream.h" #include #include #ifdef HAVE_SVN_VERSION_INC # include "SVNVersion.inc" #endif namespace clang { std::string getClangRepositoryPath() { #if defined(CLANG_REPOSITORY_STRING) return CLANG_REPOSITORY_STRING; #else #ifdef SVN_REPOSITORY StringRef URL(SVN_REPOSITORY); #else StringRef URL(""); #endif // If the SVN_REPOSITORY is empty, try to use the SVN keyword. This helps us // pick up a tag in an SVN export, for example. - StringRef SVNRepository("$URL: https://llvm.org/svn/llvm-project/cfe/trunk/lib/Basic/Version.cpp $"); + StringRef SVNRepository("$URL: https://llvm.org/svn/llvm-project/cfe/branches/release_70/lib/Basic/Version.cpp $"); if (URL.empty()) { URL = SVNRepository.slice(SVNRepository.find(':'), SVNRepository.find("/lib/Basic")); } // Strip off version from a build from an integration branch. URL = URL.slice(0, URL.find("/src/tools/clang")); // Trim path prefix off, assuming path came from standard cfe path. size_t Start = URL.find("cfe/"); if (Start != StringRef::npos) URL = URL.substr(Start + 4); return URL; #endif } std::string getLLVMRepositoryPath() { #ifdef LLVM_REPOSITORY StringRef URL(LLVM_REPOSITORY); #else StringRef URL(""); #endif // Trim path prefix off, assuming path came from standard llvm path. // Leave "llvm/" prefix to distinguish the following llvm revision from the // clang revision. size_t Start = URL.find("llvm/"); if (Start != StringRef::npos) URL = URL.substr(Start); return URL; } std::string getClangRevision() { #ifdef SVN_REVISION return SVN_REVISION; #else return ""; #endif } std::string getLLVMRevision() { #ifdef LLVM_REVISION return LLVM_REVISION; #else return ""; #endif } std::string getClangFullRepositoryVersion() { std::string buf; llvm::raw_string_ostream OS(buf); std::string Path = getClangRepositoryPath(); std::string Revision = getClangRevision(); if (!Path.empty() || !Revision.empty()) { OS << '('; if (!Path.empty()) OS << Path; if (!Revision.empty()) { if (!Path.empty()) OS << ' '; OS << Revision; } OS << ')'; } // Support LLVM in a separate repository. std::string LLVMRev = getLLVMRevision(); if (!LLVMRev.empty() && LLVMRev != Revision) { OS << " ("; std::string LLVMRepo = getLLVMRepositoryPath(); if (!LLVMRepo.empty()) OS << LLVMRepo << ' '; OS << LLVMRev << ')'; } return OS.str(); } std::string getClangFullVersion() { return getClangToolFullVersion("clang"); } std::string getClangToolFullVersion(StringRef ToolName) { std::string buf; llvm::raw_string_ostream OS(buf); #ifdef CLANG_VENDOR OS << CLANG_VENDOR; #endif OS << ToolName << " version " CLANG_VERSION_STRING " " << getClangFullRepositoryVersion(); // If vendor supplied, include the base LLVM version as well. #ifdef CLANG_VENDOR OS << " (based on " << BACKEND_PACKAGE_STRING << ")"; #endif return OS.str(); } std::string getClangFullCPPVersion() { // The version string we report in __VERSION__ is just a compacted version of // the one we report on the command line. std::string buf; llvm::raw_string_ostream OS(buf); #ifdef CLANG_VENDOR OS << CLANG_VENDOR; #endif OS << "Clang " CLANG_VERSION_STRING " " << getClangFullRepositoryVersion(); return OS.str(); } } // end namespace clang Index: projects/clang700-import/contrib/llvm/tools/clang/lib/Sema/SemaInit.cpp =================================================================== --- projects/clang700-import/contrib/llvm/tools/clang/lib/Sema/SemaInit.cpp (revision 337309) +++ projects/clang700-import/contrib/llvm/tools/clang/lib/Sema/SemaInit.cpp (revision 337310) @@ -1,9282 +1,9286 @@ //===--- SemaInit.cpp - Semantic Analysis for Initializers ----------------===// // // The LLVM Compiler Infrastructure // // This file is distributed under the University of Illinois Open Source // License. See LICENSE.TXT for details. // //===----------------------------------------------------------------------===// // // This file implements semantic analysis for initializers. // //===----------------------------------------------------------------------===// #include "clang/AST/ASTContext.h" #include "clang/AST/DeclObjC.h" #include "clang/AST/ExprCXX.h" #include "clang/AST/ExprObjC.h" #include "clang/AST/ExprOpenMP.h" #include "clang/AST/TypeLoc.h" #include "clang/Basic/TargetInfo.h" #include "clang/Sema/Designator.h" #include "clang/Sema/Initialization.h" #include "clang/Sema/Lookup.h" #include "clang/Sema/SemaInternal.h" #include "llvm/ADT/APInt.h" #include "llvm/ADT/SmallString.h" #include "llvm/Support/ErrorHandling.h" #include "llvm/Support/raw_ostream.h" using namespace clang; //===----------------------------------------------------------------------===// // Sema Initialization Checking //===----------------------------------------------------------------------===// /// Check whether T is compatible with a wide character type (wchar_t, /// char16_t or char32_t). static bool IsWideCharCompatible(QualType T, ASTContext &Context) { if (Context.typesAreCompatible(Context.getWideCharType(), T)) return true; if (Context.getLangOpts().CPlusPlus || Context.getLangOpts().C11) { return Context.typesAreCompatible(Context.Char16Ty, T) || Context.typesAreCompatible(Context.Char32Ty, T); } return false; } enum StringInitFailureKind { SIF_None, SIF_NarrowStringIntoWideChar, SIF_WideStringIntoChar, SIF_IncompatWideStringIntoWideChar, SIF_UTF8StringIntoPlainChar, SIF_PlainStringIntoUTF8Char, SIF_Other }; /// Check whether the array of type AT can be initialized by the Init /// expression by means of string initialization. Returns SIF_None if so, /// otherwise returns a StringInitFailureKind that describes why the /// initialization would not work. static StringInitFailureKind IsStringInit(Expr *Init, const ArrayType *AT, ASTContext &Context) { if (!isa(AT) && !isa(AT)) return SIF_Other; // See if this is a string literal or @encode. Init = Init->IgnoreParens(); // Handle @encode, which is a narrow string. if (isa(Init) && AT->getElementType()->isCharType()) return SIF_None; // Otherwise we can only handle string literals. StringLiteral *SL = dyn_cast(Init); if (!SL) return SIF_Other; const QualType ElemTy = Context.getCanonicalType(AT->getElementType()).getUnqualifiedType(); switch (SL->getKind()) { case StringLiteral::UTF8: // char8_t array can be initialized with a UTF-8 string. if (ElemTy->isChar8Type()) return SIF_None; LLVM_FALLTHROUGH; case StringLiteral::Ascii: // char array can be initialized with a narrow string. // Only allow char x[] = "foo"; not char x[] = L"foo"; if (ElemTy->isCharType()) return (SL->getKind() == StringLiteral::UTF8 && Context.getLangOpts().Char8) ? SIF_UTF8StringIntoPlainChar : SIF_None; if (ElemTy->isChar8Type()) return SIF_PlainStringIntoUTF8Char; if (IsWideCharCompatible(ElemTy, Context)) return SIF_NarrowStringIntoWideChar; return SIF_Other; // C99 6.7.8p15 (with correction from DR343), or C11 6.7.9p15: // "An array with element type compatible with a qualified or unqualified // version of wchar_t, char16_t, or char32_t may be initialized by a wide // string literal with the corresponding encoding prefix (L, u, or U, // respectively), optionally enclosed in braces. case StringLiteral::UTF16: if (Context.typesAreCompatible(Context.Char16Ty, ElemTy)) return SIF_None; if (ElemTy->isCharType() || ElemTy->isChar8Type()) return SIF_WideStringIntoChar; if (IsWideCharCompatible(ElemTy, Context)) return SIF_IncompatWideStringIntoWideChar; return SIF_Other; case StringLiteral::UTF32: if (Context.typesAreCompatible(Context.Char32Ty, ElemTy)) return SIF_None; if (ElemTy->isCharType() || ElemTy->isChar8Type()) return SIF_WideStringIntoChar; if (IsWideCharCompatible(ElemTy, Context)) return SIF_IncompatWideStringIntoWideChar; return SIF_Other; case StringLiteral::Wide: if (Context.typesAreCompatible(Context.getWideCharType(), ElemTy)) return SIF_None; if (ElemTy->isCharType() || ElemTy->isChar8Type()) return SIF_WideStringIntoChar; if (IsWideCharCompatible(ElemTy, Context)) return SIF_IncompatWideStringIntoWideChar; return SIF_Other; } llvm_unreachable("missed a StringLiteral kind?"); } static StringInitFailureKind IsStringInit(Expr *init, QualType declType, ASTContext &Context) { const ArrayType *arrayType = Context.getAsArrayType(declType); if (!arrayType) return SIF_Other; return IsStringInit(init, arrayType, Context); } /// Update the type of a string literal, including any surrounding parentheses, /// to match the type of the object which it is initializing. static void updateStringLiteralType(Expr *E, QualType Ty) { while (true) { E->setType(Ty); if (isa(E) || isa(E)) break; else if (ParenExpr *PE = dyn_cast(E)) E = PE->getSubExpr(); else if (UnaryOperator *UO = dyn_cast(E)) E = UO->getSubExpr(); else if (GenericSelectionExpr *GSE = dyn_cast(E)) E = GSE->getResultExpr(); else llvm_unreachable("unexpected expr in string literal init"); } } static void CheckStringInit(Expr *Str, QualType &DeclT, const ArrayType *AT, Sema &S) { // Get the length of the string as parsed. auto *ConstantArrayTy = cast(Str->getType()->getAsArrayTypeUnsafe()); uint64_t StrLength = ConstantArrayTy->getSize().getZExtValue(); if (const IncompleteArrayType *IAT = dyn_cast(AT)) { // C99 6.7.8p14. We have an array of character type with unknown size // being initialized to a string literal. llvm::APInt ConstVal(32, StrLength); // Return a new array type (C99 6.7.8p22). DeclT = S.Context.getConstantArrayType(IAT->getElementType(), ConstVal, ArrayType::Normal, 0); updateStringLiteralType(Str, DeclT); return; } const ConstantArrayType *CAT = cast(AT); // We have an array of character type with known size. However, // the size may be smaller or larger than the string we are initializing. // FIXME: Avoid truncation for 64-bit length strings. if (S.getLangOpts().CPlusPlus) { if (StringLiteral *SL = dyn_cast(Str->IgnoreParens())) { // For Pascal strings it's OK to strip off the terminating null character, // so the example below is valid: // // unsigned char a[2] = "\pa"; if (SL->isPascal()) StrLength--; } // [dcl.init.string]p2 if (StrLength > CAT->getSize().getZExtValue()) S.Diag(Str->getLocStart(), diag::err_initializer_string_for_char_array_too_long) << Str->getSourceRange(); } else { // C99 6.7.8p14. if (StrLength-1 > CAT->getSize().getZExtValue()) S.Diag(Str->getLocStart(), diag::ext_initializer_string_for_char_array_too_long) << Str->getSourceRange(); } // Set the type to the actual size that we are initializing. If we have // something like: // char x[1] = "foo"; // then this will set the string literal's type to char[1]. updateStringLiteralType(Str, DeclT); } //===----------------------------------------------------------------------===// // Semantic checking for initializer lists. //===----------------------------------------------------------------------===// namespace { /// Semantic checking for initializer lists. /// /// The InitListChecker class contains a set of routines that each /// handle the initialization of a certain kind of entity, e.g., /// arrays, vectors, struct/union types, scalars, etc. The /// InitListChecker itself performs a recursive walk of the subobject /// structure of the type to be initialized, while stepping through /// the initializer list one element at a time. The IList and Index /// parameters to each of the Check* routines contain the active /// (syntactic) initializer list and the index into that initializer /// list that represents the current initializer. Each routine is /// responsible for moving that Index forward as it consumes elements. /// /// Each Check* routine also has a StructuredList/StructuredIndex /// arguments, which contains the current "structured" (semantic) /// initializer list and the index into that initializer list where we /// are copying initializers as we map them over to the semantic /// list. Once we have completed our recursive walk of the subobject /// structure, we will have constructed a full semantic initializer /// list. /// /// C99 designators cause changes in the initializer list traversal, /// because they make the initialization "jump" into a specific /// subobject and then continue the initialization from that /// point. CheckDesignatedInitializer() recursively steps into the /// designated subobject and manages backing out the recursion to /// initialize the subobjects after the one designated. class InitListChecker { Sema &SemaRef; bool hadError; bool VerifyOnly; // no diagnostics, no structure building bool TreatUnavailableAsInvalid; // Used only in VerifyOnly mode. llvm::DenseMap SyntacticToSemantic; InitListExpr *FullyStructuredList; void CheckImplicitInitList(const InitializedEntity &Entity, InitListExpr *ParentIList, QualType T, unsigned &Index, InitListExpr *StructuredList, unsigned &StructuredIndex); void CheckExplicitInitList(const InitializedEntity &Entity, InitListExpr *IList, QualType &T, InitListExpr *StructuredList, bool TopLevelObject = false); void CheckListElementTypes(const InitializedEntity &Entity, InitListExpr *IList, QualType &DeclType, bool SubobjectIsDesignatorContext, unsigned &Index, InitListExpr *StructuredList, unsigned &StructuredIndex, bool TopLevelObject = false); void CheckSubElementType(const InitializedEntity &Entity, InitListExpr *IList, QualType ElemType, unsigned &Index, InitListExpr *StructuredList, unsigned &StructuredIndex); void CheckComplexType(const InitializedEntity &Entity, InitListExpr *IList, QualType DeclType, unsigned &Index, InitListExpr *StructuredList, unsigned &StructuredIndex); void CheckScalarType(const InitializedEntity &Entity, InitListExpr *IList, QualType DeclType, unsigned &Index, InitListExpr *StructuredList, unsigned &StructuredIndex); void CheckReferenceType(const InitializedEntity &Entity, InitListExpr *IList, QualType DeclType, unsigned &Index, InitListExpr *StructuredList, unsigned &StructuredIndex); void CheckVectorType(const InitializedEntity &Entity, InitListExpr *IList, QualType DeclType, unsigned &Index, InitListExpr *StructuredList, unsigned &StructuredIndex); void CheckStructUnionTypes(const InitializedEntity &Entity, InitListExpr *IList, QualType DeclType, CXXRecordDecl::base_class_range Bases, RecordDecl::field_iterator Field, bool SubobjectIsDesignatorContext, unsigned &Index, InitListExpr *StructuredList, unsigned &StructuredIndex, bool TopLevelObject = false); void CheckArrayType(const InitializedEntity &Entity, InitListExpr *IList, QualType &DeclType, llvm::APSInt elementIndex, bool SubobjectIsDesignatorContext, unsigned &Index, InitListExpr *StructuredList, unsigned &StructuredIndex); bool CheckDesignatedInitializer(const InitializedEntity &Entity, InitListExpr *IList, DesignatedInitExpr *DIE, unsigned DesigIdx, QualType &CurrentObjectType, RecordDecl::field_iterator *NextField, llvm::APSInt *NextElementIndex, unsigned &Index, InitListExpr *StructuredList, unsigned &StructuredIndex, bool FinishSubobjectInit, bool TopLevelObject); InitListExpr *getStructuredSubobjectInit(InitListExpr *IList, unsigned Index, QualType CurrentObjectType, InitListExpr *StructuredList, unsigned StructuredIndex, SourceRange InitRange, bool IsFullyOverwritten = false); void UpdateStructuredListElement(InitListExpr *StructuredList, unsigned &StructuredIndex, Expr *expr); int numArrayElements(QualType DeclType); int numStructUnionElements(QualType DeclType); static ExprResult PerformEmptyInit(Sema &SemaRef, SourceLocation Loc, const InitializedEntity &Entity, bool VerifyOnly, bool TreatUnavailableAsInvalid); // Explanation on the "FillWithNoInit" mode: // // Assume we have the following definitions (Case#1): // struct P { char x[6][6]; } xp = { .x[1] = "bar" }; // struct PP { struct P lp; } l = { .lp = xp, .lp.x[1][2] = 'f' }; // // l.lp.x[1][0..1] should not be filled with implicit initializers because the // "base" initializer "xp" will provide values for them; l.lp.x[1] will be "baf". // // But if we have (Case#2): // struct PP l = { .lp = xp, .lp.x[1] = { [2] = 'f' } }; // // l.lp.x[1][0..1] are implicitly initialized and do not use values from the // "base" initializer; l.lp.x[1] will be "\0\0f\0\0\0". // // To distinguish Case#1 from Case#2, and also to avoid leaving many "holes" // in the InitListExpr, the "holes" in Case#1 are filled not with empty // initializers but with special "NoInitExpr" place holders, which tells the // CodeGen not to generate any initializers for these parts. void FillInEmptyInitForBase(unsigned Init, const CXXBaseSpecifier &Base, const InitializedEntity &ParentEntity, InitListExpr *ILE, bool &RequiresSecondPass, bool FillWithNoInit); void FillInEmptyInitForField(unsigned Init, FieldDecl *Field, const InitializedEntity &ParentEntity, InitListExpr *ILE, bool &RequiresSecondPass, bool FillWithNoInit = false); void FillInEmptyInitializations(const InitializedEntity &Entity, InitListExpr *ILE, bool &RequiresSecondPass, InitListExpr *OuterILE, unsigned OuterIndex, bool FillWithNoInit = false); bool CheckFlexibleArrayInit(const InitializedEntity &Entity, Expr *InitExpr, FieldDecl *Field, bool TopLevelObject); void CheckEmptyInitializable(const InitializedEntity &Entity, SourceLocation Loc); public: InitListChecker(Sema &S, const InitializedEntity &Entity, InitListExpr *IL, QualType &T, bool VerifyOnly, bool TreatUnavailableAsInvalid); bool HadError() { return hadError; } // Retrieves the fully-structured initializer list used for // semantic analysis and code generation. InitListExpr *getFullyStructuredList() const { return FullyStructuredList; } }; } // end anonymous namespace ExprResult InitListChecker::PerformEmptyInit(Sema &SemaRef, SourceLocation Loc, const InitializedEntity &Entity, bool VerifyOnly, bool TreatUnavailableAsInvalid) { InitializationKind Kind = InitializationKind::CreateValue(Loc, Loc, Loc, true); MultiExprArg SubInit; Expr *InitExpr; InitListExpr DummyInitList(SemaRef.Context, Loc, None, Loc); // C++ [dcl.init.aggr]p7: // If there are fewer initializer-clauses in the list than there are // members in the aggregate, then each member not explicitly initialized // ... bool EmptyInitList = SemaRef.getLangOpts().CPlusPlus11 && Entity.getType()->getBaseElementTypeUnsafe()->isRecordType(); if (EmptyInitList) { // C++1y / DR1070: // shall be initialized [...] from an empty initializer list. // // We apply the resolution of this DR to C++11 but not C++98, since C++98 // does not have useful semantics for initialization from an init list. // We treat this as copy-initialization, because aggregate initialization // always performs copy-initialization on its elements. // // Only do this if we're initializing a class type, to avoid filling in // the initializer list where possible. InitExpr = VerifyOnly ? &DummyInitList : new (SemaRef.Context) InitListExpr(SemaRef.Context, Loc, None, Loc); InitExpr->setType(SemaRef.Context.VoidTy); SubInit = InitExpr; Kind = InitializationKind::CreateCopy(Loc, Loc); } else { // C++03: // shall be value-initialized. } InitializationSequence InitSeq(SemaRef, Entity, Kind, SubInit); // libstdc++4.6 marks the vector default constructor as explicit in // _GLIBCXX_DEBUG mode, so recover using the C++03 logic in that case. // stlport does so too. Look for std::__debug for libstdc++, and for // std:: for stlport. This is effectively a compiler-side implementation of // LWG2193. if (!InitSeq && EmptyInitList && InitSeq.getFailureKind() == InitializationSequence::FK_ExplicitConstructor) { OverloadCandidateSet::iterator Best; OverloadingResult O = InitSeq.getFailedCandidateSet() .BestViableFunction(SemaRef, Kind.getLocation(), Best); (void)O; assert(O == OR_Success && "Inconsistent overload resolution"); CXXConstructorDecl *CtorDecl = cast(Best->Function); CXXRecordDecl *R = CtorDecl->getParent(); if (CtorDecl->getMinRequiredArguments() == 0 && CtorDecl->isExplicit() && R->getDeclName() && SemaRef.SourceMgr.isInSystemHeader(CtorDecl->getLocation())) { bool IsInStd = false; for (NamespaceDecl *ND = dyn_cast(R->getDeclContext()); ND && !IsInStd; ND = dyn_cast(ND->getParent())) { if (SemaRef.getStdNamespace()->InEnclosingNamespaceSetOf(ND)) IsInStd = true; } if (IsInStd && llvm::StringSwitch(R->getName()) .Cases("basic_string", "deque", "forward_list", true) .Cases("list", "map", "multimap", "multiset", true) .Cases("priority_queue", "queue", "set", "stack", true) .Cases("unordered_map", "unordered_set", "vector", true) .Default(false)) { InitSeq.InitializeFrom( SemaRef, Entity, InitializationKind::CreateValue(Loc, Loc, Loc, true), MultiExprArg(), /*TopLevelOfInitList=*/false, TreatUnavailableAsInvalid); // Emit a warning for this. System header warnings aren't shown // by default, but people working on system headers should see it. if (!VerifyOnly) { SemaRef.Diag(CtorDecl->getLocation(), diag::warn_invalid_initializer_from_system_header); if (Entity.getKind() == InitializedEntity::EK_Member) SemaRef.Diag(Entity.getDecl()->getLocation(), diag::note_used_in_initialization_here); else if (Entity.getKind() == InitializedEntity::EK_ArrayElement) SemaRef.Diag(Loc, diag::note_used_in_initialization_here); } } } } if (!InitSeq) { if (!VerifyOnly) { InitSeq.Diagnose(SemaRef, Entity, Kind, SubInit); if (Entity.getKind() == InitializedEntity::EK_Member) SemaRef.Diag(Entity.getDecl()->getLocation(), diag::note_in_omitted_aggregate_initializer) << /*field*/1 << Entity.getDecl(); else if (Entity.getKind() == InitializedEntity::EK_ArrayElement) { bool IsTrailingArrayNewMember = Entity.getParent() && Entity.getParent()->isVariableLengthArrayNew(); SemaRef.Diag(Loc, diag::note_in_omitted_aggregate_initializer) << (IsTrailingArrayNewMember ? 2 : /*array element*/0) << Entity.getElementIndex(); } } return ExprError(); } return VerifyOnly ? ExprResult(static_cast(nullptr)) : InitSeq.Perform(SemaRef, Entity, Kind, SubInit); } void InitListChecker::CheckEmptyInitializable(const InitializedEntity &Entity, SourceLocation Loc) { assert(VerifyOnly && "CheckEmptyInitializable is only inteded for verification mode."); if (PerformEmptyInit(SemaRef, Loc, Entity, /*VerifyOnly*/true, TreatUnavailableAsInvalid).isInvalid()) hadError = true; } void InitListChecker::FillInEmptyInitForBase( unsigned Init, const CXXBaseSpecifier &Base, const InitializedEntity &ParentEntity, InitListExpr *ILE, bool &RequiresSecondPass, bool FillWithNoInit) { assert(Init < ILE->getNumInits() && "should have been expanded"); InitializedEntity BaseEntity = InitializedEntity::InitializeBase( SemaRef.Context, &Base, false, &ParentEntity); if (!ILE->getInit(Init)) { ExprResult BaseInit = FillWithNoInit ? new (SemaRef.Context) NoInitExpr(Base.getType()) : PerformEmptyInit(SemaRef, ILE->getLocEnd(), BaseEntity, /*VerifyOnly*/ false, TreatUnavailableAsInvalid); if (BaseInit.isInvalid()) { hadError = true; return; } ILE->setInit(Init, BaseInit.getAs()); } else if (InitListExpr *InnerILE = dyn_cast(ILE->getInit(Init))) { FillInEmptyInitializations(BaseEntity, InnerILE, RequiresSecondPass, ILE, Init, FillWithNoInit); } else if (DesignatedInitUpdateExpr *InnerDIUE = dyn_cast(ILE->getInit(Init))) { FillInEmptyInitializations(BaseEntity, InnerDIUE->getUpdater(), RequiresSecondPass, ILE, Init, /*FillWithNoInit =*/true); } } void InitListChecker::FillInEmptyInitForField(unsigned Init, FieldDecl *Field, const InitializedEntity &ParentEntity, InitListExpr *ILE, bool &RequiresSecondPass, bool FillWithNoInit) { SourceLocation Loc = ILE->getLocEnd(); unsigned NumInits = ILE->getNumInits(); InitializedEntity MemberEntity = InitializedEntity::InitializeMember(Field, &ParentEntity); if (const RecordType *RType = ILE->getType()->getAs()) if (!RType->getDecl()->isUnion()) assert(Init < NumInits && "This ILE should have been expanded"); if (Init >= NumInits || !ILE->getInit(Init)) { if (FillWithNoInit) { Expr *Filler = new (SemaRef.Context) NoInitExpr(Field->getType()); if (Init < NumInits) ILE->setInit(Init, Filler); else ILE->updateInit(SemaRef.Context, Init, Filler); return; } // C++1y [dcl.init.aggr]p7: // If there are fewer initializer-clauses in the list than there are // members in the aggregate, then each member not explicitly initialized // shall be initialized from its brace-or-equal-initializer [...] if (Field->hasInClassInitializer()) { ExprResult DIE = SemaRef.BuildCXXDefaultInitExpr(Loc, Field); if (DIE.isInvalid()) { hadError = true; return; } SemaRef.checkInitializerLifetime(MemberEntity, DIE.get()); if (Init < NumInits) ILE->setInit(Init, DIE.get()); else { ILE->updateInit(SemaRef.Context, Init, DIE.get()); RequiresSecondPass = true; } return; } if (Field->getType()->isReferenceType()) { // C++ [dcl.init.aggr]p9: // If an incomplete or empty initializer-list leaves a // member of reference type uninitialized, the program is // ill-formed. SemaRef.Diag(Loc, diag::err_init_reference_member_uninitialized) << Field->getType() << ILE->getSyntacticForm()->getSourceRange(); SemaRef.Diag(Field->getLocation(), diag::note_uninit_reference_member); hadError = true; return; } ExprResult MemberInit = PerformEmptyInit(SemaRef, Loc, MemberEntity, /*VerifyOnly*/false, TreatUnavailableAsInvalid); if (MemberInit.isInvalid()) { hadError = true; return; } if (hadError) { // Do nothing } else if (Init < NumInits) { ILE->setInit(Init, MemberInit.getAs()); } else if (!isa(MemberInit.get())) { // Empty initialization requires a constructor call, so // extend the initializer list to include the constructor // call and make a note that we'll need to take another pass // through the initializer list. ILE->updateInit(SemaRef.Context, Init, MemberInit.getAs()); RequiresSecondPass = true; } } else if (InitListExpr *InnerILE = dyn_cast(ILE->getInit(Init))) FillInEmptyInitializations(MemberEntity, InnerILE, RequiresSecondPass, ILE, Init, FillWithNoInit); else if (DesignatedInitUpdateExpr *InnerDIUE = dyn_cast(ILE->getInit(Init))) FillInEmptyInitializations(MemberEntity, InnerDIUE->getUpdater(), RequiresSecondPass, ILE, Init, /*FillWithNoInit =*/true); } /// Recursively replaces NULL values within the given initializer list /// with expressions that perform value-initialization of the /// appropriate type, and finish off the InitListExpr formation. void InitListChecker::FillInEmptyInitializations(const InitializedEntity &Entity, InitListExpr *ILE, bool &RequiresSecondPass, InitListExpr *OuterILE, unsigned OuterIndex, bool FillWithNoInit) { assert((ILE->getType() != SemaRef.Context.VoidTy) && "Should not have void type"); // If this is a nested initializer list, we might have changed its contents // (and therefore some of its properties, such as instantiation-dependence) // while filling it in. Inform the outer initializer list so that its state // can be updated to match. // FIXME: We should fully build the inner initializers before constructing // the outer InitListExpr instead of mutating AST nodes after they have // been used as subexpressions of other nodes. struct UpdateOuterILEWithUpdatedInit { InitListExpr *Outer; unsigned OuterIndex; ~UpdateOuterILEWithUpdatedInit() { if (Outer) Outer->setInit(OuterIndex, Outer->getInit(OuterIndex)); } } UpdateOuterRAII = {OuterILE, OuterIndex}; // A transparent ILE is not performing aggregate initialization and should // not be filled in. if (ILE->isTransparent()) return; if (const RecordType *RType = ILE->getType()->getAs()) { const RecordDecl *RDecl = RType->getDecl(); if (RDecl->isUnion() && ILE->getInitializedFieldInUnion()) FillInEmptyInitForField(0, ILE->getInitializedFieldInUnion(), Entity, ILE, RequiresSecondPass, FillWithNoInit); else if (RDecl->isUnion() && isa(RDecl) && cast(RDecl)->hasInClassInitializer()) { for (auto *Field : RDecl->fields()) { if (Field->hasInClassInitializer()) { FillInEmptyInitForField(0, Field, Entity, ILE, RequiresSecondPass, FillWithNoInit); break; } } } else { // The fields beyond ILE->getNumInits() are default initialized, so in // order to leave them uninitialized, the ILE is expanded and the extra // fields are then filled with NoInitExpr. unsigned NumElems = numStructUnionElements(ILE->getType()); if (RDecl->hasFlexibleArrayMember()) ++NumElems; if (ILE->getNumInits() < NumElems) ILE->resizeInits(SemaRef.Context, NumElems); unsigned Init = 0; if (auto *CXXRD = dyn_cast(RDecl)) { for (auto &Base : CXXRD->bases()) { if (hadError) return; FillInEmptyInitForBase(Init, Base, Entity, ILE, RequiresSecondPass, FillWithNoInit); ++Init; } } for (auto *Field : RDecl->fields()) { if (Field->isUnnamedBitfield()) continue; if (hadError) return; FillInEmptyInitForField(Init, Field, Entity, ILE, RequiresSecondPass, FillWithNoInit); if (hadError) return; ++Init; // Only look at the first initialization of a union. if (RDecl->isUnion()) break; } } return; } QualType ElementType; InitializedEntity ElementEntity = Entity; unsigned NumInits = ILE->getNumInits(); unsigned NumElements = NumInits; if (const ArrayType *AType = SemaRef.Context.getAsArrayType(ILE->getType())) { ElementType = AType->getElementType(); if (const auto *CAType = dyn_cast(AType)) NumElements = CAType->getSize().getZExtValue(); // For an array new with an unknown bound, ask for one additional element // in order to populate the array filler. if (Entity.isVariableLengthArrayNew()) ++NumElements; ElementEntity = InitializedEntity::InitializeElement(SemaRef.Context, 0, Entity); } else if (const VectorType *VType = ILE->getType()->getAs()) { ElementType = VType->getElementType(); NumElements = VType->getNumElements(); ElementEntity = InitializedEntity::InitializeElement(SemaRef.Context, 0, Entity); } else ElementType = ILE->getType(); for (unsigned Init = 0; Init != NumElements; ++Init) { if (hadError) return; if (ElementEntity.getKind() == InitializedEntity::EK_ArrayElement || ElementEntity.getKind() == InitializedEntity::EK_VectorElement) ElementEntity.setElementIndex(Init); if (Init >= NumInits && ILE->hasArrayFiller()) return; Expr *InitExpr = (Init < NumInits ? ILE->getInit(Init) : nullptr); if (!InitExpr && Init < NumInits && ILE->hasArrayFiller()) ILE->setInit(Init, ILE->getArrayFiller()); else if (!InitExpr && !ILE->hasArrayFiller()) { Expr *Filler = nullptr; if (FillWithNoInit) Filler = new (SemaRef.Context) NoInitExpr(ElementType); else { ExprResult ElementInit = PerformEmptyInit(SemaRef, ILE->getLocEnd(), ElementEntity, /*VerifyOnly*/false, TreatUnavailableAsInvalid); if (ElementInit.isInvalid()) { hadError = true; return; } Filler = ElementInit.getAs(); } if (hadError) { // Do nothing } else if (Init < NumInits) { // For arrays, just set the expression used for value-initialization // of the "holes" in the array. if (ElementEntity.getKind() == InitializedEntity::EK_ArrayElement) ILE->setArrayFiller(Filler); else ILE->setInit(Init, Filler); } else { // For arrays, just set the expression used for value-initialization // of the rest of elements and exit. if (ElementEntity.getKind() == InitializedEntity::EK_ArrayElement) { ILE->setArrayFiller(Filler); return; } if (!isa(Filler) && !isa(Filler)) { // Empty initialization requires a constructor call, so // extend the initializer list to include the constructor // call and make a note that we'll need to take another pass // through the initializer list. ILE->updateInit(SemaRef.Context, Init, Filler); RequiresSecondPass = true; } } } else if (InitListExpr *InnerILE = dyn_cast_or_null(InitExpr)) FillInEmptyInitializations(ElementEntity, InnerILE, RequiresSecondPass, ILE, Init, FillWithNoInit); else if (DesignatedInitUpdateExpr *InnerDIUE = dyn_cast_or_null(InitExpr)) FillInEmptyInitializations(ElementEntity, InnerDIUE->getUpdater(), RequiresSecondPass, ILE, Init, /*FillWithNoInit =*/true); } } InitListChecker::InitListChecker(Sema &S, const InitializedEntity &Entity, InitListExpr *IL, QualType &T, bool VerifyOnly, bool TreatUnavailableAsInvalid) : SemaRef(S), VerifyOnly(VerifyOnly), TreatUnavailableAsInvalid(TreatUnavailableAsInvalid) { // FIXME: Check that IL isn't already the semantic form of some other // InitListExpr. If it is, we'd create a broken AST. hadError = false; FullyStructuredList = getStructuredSubobjectInit(IL, 0, T, nullptr, 0, IL->getSourceRange()); CheckExplicitInitList(Entity, IL, T, FullyStructuredList, /*TopLevelObject=*/true); if (!hadError && !VerifyOnly) { bool RequiresSecondPass = false; FillInEmptyInitializations(Entity, FullyStructuredList, RequiresSecondPass, /*OuterILE=*/nullptr, /*OuterIndex=*/0); if (RequiresSecondPass && !hadError) FillInEmptyInitializations(Entity, FullyStructuredList, RequiresSecondPass, nullptr, 0); } } int InitListChecker::numArrayElements(QualType DeclType) { // FIXME: use a proper constant int maxElements = 0x7FFFFFFF; if (const ConstantArrayType *CAT = SemaRef.Context.getAsConstantArrayType(DeclType)) { maxElements = static_cast(CAT->getSize().getZExtValue()); } return maxElements; } int InitListChecker::numStructUnionElements(QualType DeclType) { RecordDecl *structDecl = DeclType->getAs()->getDecl(); int InitializableMembers = 0; if (auto *CXXRD = dyn_cast(structDecl)) InitializableMembers += CXXRD->getNumBases(); for (const auto *Field : structDecl->fields()) if (!Field->isUnnamedBitfield()) ++InitializableMembers; if (structDecl->isUnion()) return std::min(InitializableMembers, 1); return InitializableMembers - structDecl->hasFlexibleArrayMember(); } /// Determine whether Entity is an entity for which it is idiomatic to elide /// the braces in aggregate initialization. static bool isIdiomaticBraceElisionEntity(const InitializedEntity &Entity) { // Recursive initialization of the one and only field within an aggregate // class is considered idiomatic. This case arises in particular for // initialization of std::array, where the C++ standard suggests the idiom of // // std::array arr = {1, 2, 3}; // // (where std::array is an aggregate struct containing a single array field. // FIXME: Should aggregate initialization of a struct with a single // base class and no members also suppress the warning? if (Entity.getKind() != InitializedEntity::EK_Member || !Entity.getParent()) return false; auto *ParentRD = Entity.getParent()->getType()->castAs()->getDecl(); if (CXXRecordDecl *CXXRD = dyn_cast(ParentRD)) if (CXXRD->getNumBases()) return false; auto FieldIt = ParentRD->field_begin(); assert(FieldIt != ParentRD->field_end() && "no fields but have initializer for member?"); return ++FieldIt == ParentRD->field_end(); } /// Check whether the range of the initializer \p ParentIList from element /// \p Index onwards can be used to initialize an object of type \p T. Update /// \p Index to indicate how many elements of the list were consumed. /// /// This also fills in \p StructuredList, from element \p StructuredIndex /// onwards, with the fully-braced, desugared form of the initialization. void InitListChecker::CheckImplicitInitList(const InitializedEntity &Entity, InitListExpr *ParentIList, QualType T, unsigned &Index, InitListExpr *StructuredList, unsigned &StructuredIndex) { int maxElements = 0; if (T->isArrayType()) maxElements = numArrayElements(T); else if (T->isRecordType()) maxElements = numStructUnionElements(T); else if (T->isVectorType()) maxElements = T->getAs()->getNumElements(); else llvm_unreachable("CheckImplicitInitList(): Illegal type"); if (maxElements == 0) { if (!VerifyOnly) SemaRef.Diag(ParentIList->getInit(Index)->getLocStart(), diag::err_implicit_empty_initializer); ++Index; hadError = true; return; } // Build a structured initializer list corresponding to this subobject. InitListExpr *StructuredSubobjectInitList = getStructuredSubobjectInit(ParentIList, Index, T, StructuredList, StructuredIndex, SourceRange(ParentIList->getInit(Index)->getLocStart(), ParentIList->getSourceRange().getEnd())); unsigned StructuredSubobjectInitIndex = 0; // Check the element types and build the structural subobject. unsigned StartIndex = Index; CheckListElementTypes(Entity, ParentIList, T, /*SubobjectIsDesignatorContext=*/false, Index, StructuredSubobjectInitList, StructuredSubobjectInitIndex); if (!VerifyOnly) { StructuredSubobjectInitList->setType(T); unsigned EndIndex = (Index == StartIndex? StartIndex : Index - 1); // Update the structured sub-object initializer so that it's ending // range corresponds with the end of the last initializer it used. if (EndIndex < ParentIList->getNumInits() && ParentIList->getInit(EndIndex)) { SourceLocation EndLoc = ParentIList->getInit(EndIndex)->getSourceRange().getEnd(); StructuredSubobjectInitList->setRBraceLoc(EndLoc); } // Complain about missing braces. if ((T->isArrayType() || T->isRecordType()) && !ParentIList->isIdiomaticZeroInitializer(SemaRef.getLangOpts()) && !isIdiomaticBraceElisionEntity(Entity)) { SemaRef.Diag(StructuredSubobjectInitList->getLocStart(), diag::warn_missing_braces) << StructuredSubobjectInitList->getSourceRange() << FixItHint::CreateInsertion( StructuredSubobjectInitList->getLocStart(), "{") << FixItHint::CreateInsertion( SemaRef.getLocForEndOfToken( StructuredSubobjectInitList->getLocEnd()), "}"); } } } /// Warn that \p Entity was of scalar type and was initialized by a /// single-element braced initializer list. static void warnBracedScalarInit(Sema &S, const InitializedEntity &Entity, SourceRange Braces) { // Don't warn during template instantiation. If the initialization was // non-dependent, we warned during the initial parse; otherwise, the // type might not be scalar in some uses of the template. if (S.inTemplateInstantiation()) return; unsigned DiagID = 0; switch (Entity.getKind()) { case InitializedEntity::EK_VectorElement: case InitializedEntity::EK_ComplexElement: case InitializedEntity::EK_ArrayElement: case InitializedEntity::EK_Parameter: case InitializedEntity::EK_Parameter_CF_Audited: case InitializedEntity::EK_Result: // Extra braces here are suspicious. DiagID = diag::warn_braces_around_scalar_init; break; case InitializedEntity::EK_Member: // Warn on aggregate initialization but not on ctor init list or // default member initializer. if (Entity.getParent()) DiagID = diag::warn_braces_around_scalar_init; break; case InitializedEntity::EK_Variable: case InitializedEntity::EK_LambdaCapture: // No warning, might be direct-list-initialization. // FIXME: Should we warn for copy-list-initialization in these cases? break; case InitializedEntity::EK_New: case InitializedEntity::EK_Temporary: case InitializedEntity::EK_CompoundLiteralInit: // No warning, braces are part of the syntax of the underlying construct. break; case InitializedEntity::EK_RelatedResult: // No warning, we already warned when initializing the result. break; case InitializedEntity::EK_Exception: case InitializedEntity::EK_Base: case InitializedEntity::EK_Delegating: case InitializedEntity::EK_BlockElement: case InitializedEntity::EK_LambdaToBlockConversionBlockElement: case InitializedEntity::EK_Binding: case InitializedEntity::EK_StmtExprResult: llvm_unreachable("unexpected braced scalar init"); } if (DiagID) { S.Diag(Braces.getBegin(), DiagID) << Braces << FixItHint::CreateRemoval(Braces.getBegin()) << FixItHint::CreateRemoval(Braces.getEnd()); } } /// Check whether the initializer \p IList (that was written with explicit /// braces) can be used to initialize an object of type \p T. /// /// This also fills in \p StructuredList with the fully-braced, desugared /// form of the initialization. void InitListChecker::CheckExplicitInitList(const InitializedEntity &Entity, InitListExpr *IList, QualType &T, InitListExpr *StructuredList, bool TopLevelObject) { if (!VerifyOnly) { SyntacticToSemantic[IList] = StructuredList; StructuredList->setSyntacticForm(IList); } unsigned Index = 0, StructuredIndex = 0; CheckListElementTypes(Entity, IList, T, /*SubobjectIsDesignatorContext=*/true, Index, StructuredList, StructuredIndex, TopLevelObject); if (!VerifyOnly) { QualType ExprTy = T; if (!ExprTy->isArrayType()) ExprTy = ExprTy.getNonLValueExprType(SemaRef.Context); IList->setType(ExprTy); StructuredList->setType(ExprTy); } if (hadError) return; if (Index < IList->getNumInits()) { // We have leftover initializers if (VerifyOnly) { if (SemaRef.getLangOpts().CPlusPlus || (SemaRef.getLangOpts().OpenCL && IList->getType()->isVectorType())) { hadError = true; } return; } if (StructuredIndex == 1 && IsStringInit(StructuredList->getInit(0), T, SemaRef.Context) == SIF_None) { unsigned DK = diag::ext_excess_initializers_in_char_array_initializer; if (SemaRef.getLangOpts().CPlusPlus) { DK = diag::err_excess_initializers_in_char_array_initializer; hadError = true; } // Special-case SemaRef.Diag(IList->getInit(Index)->getLocStart(), DK) << IList->getInit(Index)->getSourceRange(); } else if (!T->isIncompleteType()) { // Don't complain for incomplete types, since we'll get an error // elsewhere QualType CurrentObjectType = StructuredList->getType(); int initKind = CurrentObjectType->isArrayType()? 0 : CurrentObjectType->isVectorType()? 1 : CurrentObjectType->isScalarType()? 2 : CurrentObjectType->isUnionType()? 3 : 4; unsigned DK = diag::ext_excess_initializers; if (SemaRef.getLangOpts().CPlusPlus) { DK = diag::err_excess_initializers; hadError = true; } if (SemaRef.getLangOpts().OpenCL && initKind == 1) { DK = diag::err_excess_initializers; hadError = true; } SemaRef.Diag(IList->getInit(Index)->getLocStart(), DK) << initKind << IList->getInit(Index)->getSourceRange(); } } if (!VerifyOnly && T->isScalarType() && IList->getNumInits() == 1 && !isa(IList->getInit(0))) warnBracedScalarInit(SemaRef, Entity, IList->getSourceRange()); } void InitListChecker::CheckListElementTypes(const InitializedEntity &Entity, InitListExpr *IList, QualType &DeclType, bool SubobjectIsDesignatorContext, unsigned &Index, InitListExpr *StructuredList, unsigned &StructuredIndex, bool TopLevelObject) { if (DeclType->isAnyComplexType() && SubobjectIsDesignatorContext) { // Explicitly braced initializer for complex type can be real+imaginary // parts. CheckComplexType(Entity, IList, DeclType, Index, StructuredList, StructuredIndex); } else if (DeclType->isScalarType()) { CheckScalarType(Entity, IList, DeclType, Index, StructuredList, StructuredIndex); } else if (DeclType->isVectorType()) { CheckVectorType(Entity, IList, DeclType, Index, StructuredList, StructuredIndex); } else if (DeclType->isRecordType()) { assert(DeclType->isAggregateType() && "non-aggregate records should be handed in CheckSubElementType"); RecordDecl *RD = DeclType->getAs()->getDecl(); auto Bases = CXXRecordDecl::base_class_range(CXXRecordDecl::base_class_iterator(), CXXRecordDecl::base_class_iterator()); if (auto *CXXRD = dyn_cast(RD)) Bases = CXXRD->bases(); CheckStructUnionTypes(Entity, IList, DeclType, Bases, RD->field_begin(), SubobjectIsDesignatorContext, Index, StructuredList, StructuredIndex, TopLevelObject); } else if (DeclType->isArrayType()) { llvm::APSInt Zero( SemaRef.Context.getTypeSize(SemaRef.Context.getSizeType()), false); CheckArrayType(Entity, IList, DeclType, Zero, SubobjectIsDesignatorContext, Index, StructuredList, StructuredIndex); } else if (DeclType->isVoidType() || DeclType->isFunctionType()) { // This type is invalid, issue a diagnostic. ++Index; if (!VerifyOnly) SemaRef.Diag(IList->getLocStart(), diag::err_illegal_initializer_type) << DeclType; hadError = true; } else if (DeclType->isReferenceType()) { CheckReferenceType(Entity, IList, DeclType, Index, StructuredList, StructuredIndex); } else if (DeclType->isObjCObjectType()) { if (!VerifyOnly) SemaRef.Diag(IList->getLocStart(), diag::err_init_objc_class) << DeclType; hadError = true; } else { if (!VerifyOnly) SemaRef.Diag(IList->getLocStart(), diag::err_illegal_initializer_type) << DeclType; hadError = true; } } void InitListChecker::CheckSubElementType(const InitializedEntity &Entity, InitListExpr *IList, QualType ElemType, unsigned &Index, InitListExpr *StructuredList, unsigned &StructuredIndex) { Expr *expr = IList->getInit(Index); if (ElemType->isReferenceType()) return CheckReferenceType(Entity, IList, ElemType, Index, StructuredList, StructuredIndex); if (InitListExpr *SubInitList = dyn_cast(expr)) { if (SubInitList->getNumInits() == 1 && IsStringInit(SubInitList->getInit(0), ElemType, SemaRef.Context) == SIF_None) { expr = SubInitList->getInit(0); } else if (!SemaRef.getLangOpts().CPlusPlus) { InitListExpr *InnerStructuredList = getStructuredSubobjectInit(IList, Index, ElemType, StructuredList, StructuredIndex, SubInitList->getSourceRange(), true); CheckExplicitInitList(Entity, SubInitList, ElemType, InnerStructuredList); if (!hadError && !VerifyOnly) { bool RequiresSecondPass = false; FillInEmptyInitializations(Entity, InnerStructuredList, RequiresSecondPass, StructuredList, StructuredIndex); if (RequiresSecondPass && !hadError) FillInEmptyInitializations(Entity, InnerStructuredList, RequiresSecondPass, StructuredList, StructuredIndex); } ++StructuredIndex; ++Index; return; } // C++ initialization is handled later. } else if (isa(expr)) { // This happens during template instantiation when we see an InitListExpr // that we've already checked once. assert(SemaRef.Context.hasSameType(expr->getType(), ElemType) && "found implicit initialization for the wrong type"); if (!VerifyOnly) UpdateStructuredListElement(StructuredList, StructuredIndex, expr); ++Index; return; } if (SemaRef.getLangOpts().CPlusPlus) { // C++ [dcl.init.aggr]p2: // Each member is copy-initialized from the corresponding // initializer-clause. // FIXME: Better EqualLoc? InitializationKind Kind = InitializationKind::CreateCopy(expr->getLocStart(), SourceLocation()); InitializationSequence Seq(SemaRef, Entity, Kind, expr, /*TopLevelOfInitList*/ true); // C++14 [dcl.init.aggr]p13: // If the assignment-expression can initialize a member, the member is // initialized. Otherwise [...] brace elision is assumed // // Brace elision is never performed if the element is not an // assignment-expression. if (Seq || isa(expr)) { if (!VerifyOnly) { ExprResult Result = Seq.Perform(SemaRef, Entity, Kind, expr); if (Result.isInvalid()) hadError = true; UpdateStructuredListElement(StructuredList, StructuredIndex, Result.getAs()); } else if (!Seq) hadError = true; ++Index; return; } // Fall through for subaggregate initialization } else if (ElemType->isScalarType() || ElemType->isAtomicType()) { // FIXME: Need to handle atomic aggregate types with implicit init lists. return CheckScalarType(Entity, IList, ElemType, Index, StructuredList, StructuredIndex); } else if (const ArrayType *arrayType = SemaRef.Context.getAsArrayType(ElemType)) { // arrayType can be incomplete if we're initializing a flexible // array member. There's nothing we can do with the completed // type here, though. if (IsStringInit(expr, arrayType, SemaRef.Context) == SIF_None) { if (!VerifyOnly) { CheckStringInit(expr, ElemType, arrayType, SemaRef); UpdateStructuredListElement(StructuredList, StructuredIndex, expr); } ++Index; return; } // Fall through for subaggregate initialization. } else { assert((ElemType->isRecordType() || ElemType->isVectorType() || ElemType->isOpenCLSpecificType()) && "Unexpected type"); // C99 6.7.8p13: // // The initializer for a structure or union object that has // automatic storage duration shall be either an initializer // list as described below, or a single expression that has // compatible structure or union type. In the latter case, the // initial value of the object, including unnamed members, is // that of the expression. ExprResult ExprRes = expr; if (SemaRef.CheckSingleAssignmentConstraints( ElemType, ExprRes, !VerifyOnly) != Sema::Incompatible) { if (ExprRes.isInvalid()) hadError = true; else { ExprRes = SemaRef.DefaultFunctionArrayLvalueConversion(ExprRes.get()); if (ExprRes.isInvalid()) hadError = true; } UpdateStructuredListElement(StructuredList, StructuredIndex, ExprRes.getAs()); ++Index; return; } ExprRes.get(); // Fall through for subaggregate initialization } // C++ [dcl.init.aggr]p12: // // [...] Otherwise, if the member is itself a non-empty // subaggregate, brace elision is assumed and the initializer is // considered for the initialization of the first member of // the subaggregate. // OpenCL vector initializer is handled elsewhere. if ((!SemaRef.getLangOpts().OpenCL && ElemType->isVectorType()) || ElemType->isAggregateType()) { CheckImplicitInitList(Entity, IList, ElemType, Index, StructuredList, StructuredIndex); ++StructuredIndex; } else { if (!VerifyOnly) { // We cannot initialize this element, so let // PerformCopyInitialization produce the appropriate diagnostic. SemaRef.PerformCopyInitialization(Entity, SourceLocation(), expr, /*TopLevelOfInitList=*/true); } hadError = true; ++Index; ++StructuredIndex; } } void InitListChecker::CheckComplexType(const InitializedEntity &Entity, InitListExpr *IList, QualType DeclType, unsigned &Index, InitListExpr *StructuredList, unsigned &StructuredIndex) { assert(Index == 0 && "Index in explicit init list must be zero"); // As an extension, clang supports complex initializers, which initialize // a complex number component-wise. When an explicit initializer list for // a complex number contains two two initializers, this extension kicks in: // it exepcts the initializer list to contain two elements convertible to // the element type of the complex type. The first element initializes // the real part, and the second element intitializes the imaginary part. if (IList->getNumInits() != 2) return CheckScalarType(Entity, IList, DeclType, Index, StructuredList, StructuredIndex); // This is an extension in C. (The builtin _Complex type does not exist // in the C++ standard.) if (!SemaRef.getLangOpts().CPlusPlus && !VerifyOnly) SemaRef.Diag(IList->getLocStart(), diag::ext_complex_component_init) << IList->getSourceRange(); // Initialize the complex number. QualType elementType = DeclType->getAs()->getElementType(); InitializedEntity ElementEntity = InitializedEntity::InitializeElement(SemaRef.Context, 0, Entity); for (unsigned i = 0; i < 2; ++i) { ElementEntity.setElementIndex(Index); CheckSubElementType(ElementEntity, IList, elementType, Index, StructuredList, StructuredIndex); } } void InitListChecker::CheckScalarType(const InitializedEntity &Entity, InitListExpr *IList, QualType DeclType, unsigned &Index, InitListExpr *StructuredList, unsigned &StructuredIndex) { if (Index >= IList->getNumInits()) { if (!VerifyOnly) SemaRef.Diag(IList->getLocStart(), SemaRef.getLangOpts().CPlusPlus11 ? diag::warn_cxx98_compat_empty_scalar_initializer : diag::err_empty_scalar_initializer) << IList->getSourceRange(); hadError = !SemaRef.getLangOpts().CPlusPlus11; ++Index; ++StructuredIndex; return; } Expr *expr = IList->getInit(Index); if (InitListExpr *SubIList = dyn_cast(expr)) { // FIXME: This is invalid, and accepting it causes overload resolution // to pick the wrong overload in some corner cases. if (!VerifyOnly) SemaRef.Diag(SubIList->getLocStart(), diag::ext_many_braces_around_scalar_init) << SubIList->getSourceRange(); CheckScalarType(Entity, SubIList, DeclType, Index, StructuredList, StructuredIndex); return; } else if (isa(expr)) { if (!VerifyOnly) SemaRef.Diag(expr->getLocStart(), diag::err_designator_for_scalar_init) << DeclType << expr->getSourceRange(); hadError = true; ++Index; ++StructuredIndex; return; } if (VerifyOnly) { if (!SemaRef.CanPerformCopyInitialization(Entity,expr)) hadError = true; ++Index; return; } ExprResult Result = SemaRef.PerformCopyInitialization(Entity, expr->getLocStart(), expr, /*TopLevelOfInitList=*/true); Expr *ResultExpr = nullptr; if (Result.isInvalid()) hadError = true; // types weren't compatible. else { ResultExpr = Result.getAs(); if (ResultExpr != expr) { // The type was promoted, update initializer list. IList->setInit(Index, ResultExpr); } } if (hadError) ++StructuredIndex; else UpdateStructuredListElement(StructuredList, StructuredIndex, ResultExpr); ++Index; } void InitListChecker::CheckReferenceType(const InitializedEntity &Entity, InitListExpr *IList, QualType DeclType, unsigned &Index, InitListExpr *StructuredList, unsigned &StructuredIndex) { if (Index >= IList->getNumInits()) { // FIXME: It would be wonderful if we could point at the actual member. In // general, it would be useful to pass location information down the stack, // so that we know the location (or decl) of the "current object" being // initialized. if (!VerifyOnly) SemaRef.Diag(IList->getLocStart(), diag::err_init_reference_member_uninitialized) << DeclType << IList->getSourceRange(); hadError = true; ++Index; ++StructuredIndex; return; } Expr *expr = IList->getInit(Index); if (isa(expr) && !SemaRef.getLangOpts().CPlusPlus11) { if (!VerifyOnly) SemaRef.Diag(IList->getLocStart(), diag::err_init_non_aggr_init_list) << DeclType << IList->getSourceRange(); hadError = true; ++Index; ++StructuredIndex; return; } if (VerifyOnly) { if (!SemaRef.CanPerformCopyInitialization(Entity,expr)) hadError = true; ++Index; return; } ExprResult Result = SemaRef.PerformCopyInitialization(Entity, expr->getLocStart(), expr, /*TopLevelOfInitList=*/true); if (Result.isInvalid()) hadError = true; expr = Result.getAs(); IList->setInit(Index, expr); if (hadError) ++StructuredIndex; else UpdateStructuredListElement(StructuredList, StructuredIndex, expr); ++Index; } void InitListChecker::CheckVectorType(const InitializedEntity &Entity, InitListExpr *IList, QualType DeclType, unsigned &Index, InitListExpr *StructuredList, unsigned &StructuredIndex) { const VectorType *VT = DeclType->getAs(); unsigned maxElements = VT->getNumElements(); unsigned numEltsInit = 0; QualType elementType = VT->getElementType(); if (Index >= IList->getNumInits()) { // Make sure the element type can be value-initialized. if (VerifyOnly) CheckEmptyInitializable( InitializedEntity::InitializeElement(SemaRef.Context, 0, Entity), IList->getLocEnd()); return; } if (!SemaRef.getLangOpts().OpenCL) { // If the initializing element is a vector, try to copy-initialize // instead of breaking it apart (which is doomed to failure anyway). Expr *Init = IList->getInit(Index); if (!isa(Init) && Init->getType()->isVectorType()) { if (VerifyOnly) { if (!SemaRef.CanPerformCopyInitialization(Entity, Init)) hadError = true; ++Index; return; } ExprResult Result = SemaRef.PerformCopyInitialization(Entity, Init->getLocStart(), Init, /*TopLevelOfInitList=*/true); Expr *ResultExpr = nullptr; if (Result.isInvalid()) hadError = true; // types weren't compatible. else { ResultExpr = Result.getAs(); if (ResultExpr != Init) { // The type was promoted, update initializer list. IList->setInit(Index, ResultExpr); } } if (hadError) ++StructuredIndex; else UpdateStructuredListElement(StructuredList, StructuredIndex, ResultExpr); ++Index; return; } InitializedEntity ElementEntity = InitializedEntity::InitializeElement(SemaRef.Context, 0, Entity); for (unsigned i = 0; i < maxElements; ++i, ++numEltsInit) { // Don't attempt to go past the end of the init list if (Index >= IList->getNumInits()) { if (VerifyOnly) CheckEmptyInitializable(ElementEntity, IList->getLocEnd()); break; } ElementEntity.setElementIndex(Index); CheckSubElementType(ElementEntity, IList, elementType, Index, StructuredList, StructuredIndex); } if (VerifyOnly) return; bool isBigEndian = SemaRef.Context.getTargetInfo().isBigEndian(); const VectorType *T = Entity.getType()->getAs(); if (isBigEndian && (T->getVectorKind() == VectorType::NeonVector || T->getVectorKind() == VectorType::NeonPolyVector)) { // The ability to use vector initializer lists is a GNU vector extension // and is unrelated to the NEON intrinsics in arm_neon.h. On little // endian machines it works fine, however on big endian machines it // exhibits surprising behaviour: // // uint32x2_t x = {42, 64}; // return vget_lane_u32(x, 0); // Will return 64. // // Because of this, explicitly call out that it is non-portable. // SemaRef.Diag(IList->getLocStart(), diag::warn_neon_vector_initializer_non_portable); const char *typeCode; unsigned typeSize = SemaRef.Context.getTypeSize(elementType); if (elementType->isFloatingType()) typeCode = "f"; else if (elementType->isSignedIntegerType()) typeCode = "s"; else if (elementType->isUnsignedIntegerType()) typeCode = "u"; else llvm_unreachable("Invalid element type!"); SemaRef.Diag(IList->getLocStart(), SemaRef.Context.getTypeSize(VT) > 64 ? diag::note_neon_vector_initializer_non_portable_q : diag::note_neon_vector_initializer_non_portable) << typeCode << typeSize; } return; } InitializedEntity ElementEntity = InitializedEntity::InitializeElement(SemaRef.Context, 0, Entity); // OpenCL initializers allows vectors to be constructed from vectors. for (unsigned i = 0; i < maxElements; ++i) { // Don't attempt to go past the end of the init list if (Index >= IList->getNumInits()) break; ElementEntity.setElementIndex(Index); QualType IType = IList->getInit(Index)->getType(); if (!IType->isVectorType()) { CheckSubElementType(ElementEntity, IList, elementType, Index, StructuredList, StructuredIndex); ++numEltsInit; } else { QualType VecType; const VectorType *IVT = IType->getAs(); unsigned numIElts = IVT->getNumElements(); if (IType->isExtVectorType()) VecType = SemaRef.Context.getExtVectorType(elementType, numIElts); else VecType = SemaRef.Context.getVectorType(elementType, numIElts, IVT->getVectorKind()); CheckSubElementType(ElementEntity, IList, VecType, Index, StructuredList, StructuredIndex); numEltsInit += numIElts; } } // OpenCL requires all elements to be initialized. if (numEltsInit != maxElements) { if (!VerifyOnly) SemaRef.Diag(IList->getLocStart(), diag::err_vector_incorrect_num_initializers) << (numEltsInit < maxElements) << maxElements << numEltsInit; hadError = true; } } void InitListChecker::CheckArrayType(const InitializedEntity &Entity, InitListExpr *IList, QualType &DeclType, llvm::APSInt elementIndex, bool SubobjectIsDesignatorContext, unsigned &Index, InitListExpr *StructuredList, unsigned &StructuredIndex) { const ArrayType *arrayType = SemaRef.Context.getAsArrayType(DeclType); // Check for the special-case of initializing an array with a string. if (Index < IList->getNumInits()) { if (IsStringInit(IList->getInit(Index), arrayType, SemaRef.Context) == SIF_None) { // We place the string literal directly into the resulting // initializer list. This is the only place where the structure // of the structured initializer list doesn't match exactly, // because doing so would involve allocating one character // constant for each string. if (!VerifyOnly) { CheckStringInit(IList->getInit(Index), DeclType, arrayType, SemaRef); UpdateStructuredListElement(StructuredList, StructuredIndex, IList->getInit(Index)); StructuredList->resizeInits(SemaRef.Context, StructuredIndex); } ++Index; return; } } if (const VariableArrayType *VAT = dyn_cast(arrayType)) { // Check for VLAs; in standard C it would be possible to check this // earlier, but I don't know where clang accepts VLAs (gcc accepts // them in all sorts of strange places). if (!VerifyOnly) SemaRef.Diag(VAT->getSizeExpr()->getLocStart(), diag::err_variable_object_no_init) << VAT->getSizeExpr()->getSourceRange(); hadError = true; ++Index; ++StructuredIndex; return; } // We might know the maximum number of elements in advance. llvm::APSInt maxElements(elementIndex.getBitWidth(), elementIndex.isUnsigned()); bool maxElementsKnown = false; if (const ConstantArrayType *CAT = dyn_cast(arrayType)) { maxElements = CAT->getSize(); elementIndex = elementIndex.extOrTrunc(maxElements.getBitWidth()); elementIndex.setIsUnsigned(maxElements.isUnsigned()); maxElementsKnown = true; } QualType elementType = arrayType->getElementType(); while (Index < IList->getNumInits()) { Expr *Init = IList->getInit(Index); if (DesignatedInitExpr *DIE = dyn_cast(Init)) { // If we're not the subobject that matches up with the '{' for // the designator, we shouldn't be handling the // designator. Return immediately. if (!SubobjectIsDesignatorContext) return; // Handle this designated initializer. elementIndex will be // updated to be the next array element we'll initialize. if (CheckDesignatedInitializer(Entity, IList, DIE, 0, DeclType, nullptr, &elementIndex, Index, StructuredList, StructuredIndex, true, false)) { hadError = true; continue; } if (elementIndex.getBitWidth() > maxElements.getBitWidth()) maxElements = maxElements.extend(elementIndex.getBitWidth()); else if (elementIndex.getBitWidth() < maxElements.getBitWidth()) elementIndex = elementIndex.extend(maxElements.getBitWidth()); elementIndex.setIsUnsigned(maxElements.isUnsigned()); // If the array is of incomplete type, keep track of the number of // elements in the initializer. if (!maxElementsKnown && elementIndex > maxElements) maxElements = elementIndex; continue; } // If we know the maximum number of elements, and we've already // hit it, stop consuming elements in the initializer list. if (maxElementsKnown && elementIndex == maxElements) break; InitializedEntity ElementEntity = InitializedEntity::InitializeElement(SemaRef.Context, StructuredIndex, Entity); // Check this element. CheckSubElementType(ElementEntity, IList, elementType, Index, StructuredList, StructuredIndex); ++elementIndex; // If the array is of incomplete type, keep track of the number of // elements in the initializer. if (!maxElementsKnown && elementIndex > maxElements) maxElements = elementIndex; } if (!hadError && DeclType->isIncompleteArrayType() && !VerifyOnly) { // If this is an incomplete array type, the actual type needs to // be calculated here. llvm::APSInt Zero(maxElements.getBitWidth(), maxElements.isUnsigned()); if (maxElements == Zero && !Entity.isVariableLengthArrayNew()) { // Sizing an array implicitly to zero is not allowed by ISO C, // but is supported by GNU. SemaRef.Diag(IList->getLocStart(), diag::ext_typecheck_zero_array_size); } DeclType = SemaRef.Context.getConstantArrayType(elementType, maxElements, ArrayType::Normal, 0); } if (!hadError && VerifyOnly) { // If there are any members of the array that get value-initialized, check // that is possible. That happens if we know the bound and don't have // enough elements, or if we're performing an array new with an unknown // bound. // FIXME: This needs to detect holes left by designated initializers too. if ((maxElementsKnown && elementIndex < maxElements) || Entity.isVariableLengthArrayNew()) CheckEmptyInitializable(InitializedEntity::InitializeElement( SemaRef.Context, 0, Entity), IList->getLocEnd()); } } bool InitListChecker::CheckFlexibleArrayInit(const InitializedEntity &Entity, Expr *InitExpr, FieldDecl *Field, bool TopLevelObject) { // Handle GNU flexible array initializers. unsigned FlexArrayDiag; if (isa(InitExpr) && cast(InitExpr)->getNumInits() == 0) { // Empty flexible array init always allowed as an extension FlexArrayDiag = diag::ext_flexible_array_init; } else if (SemaRef.getLangOpts().CPlusPlus) { // Disallow flexible array init in C++; it is not required for gcc // compatibility, and it needs work to IRGen correctly in general. FlexArrayDiag = diag::err_flexible_array_init; } else if (!TopLevelObject) { // Disallow flexible array init on non-top-level object FlexArrayDiag = diag::err_flexible_array_init; } else if (Entity.getKind() != InitializedEntity::EK_Variable) { // Disallow flexible array init on anything which is not a variable. FlexArrayDiag = diag::err_flexible_array_init; } else if (cast(Entity.getDecl())->hasLocalStorage()) { // Disallow flexible array init on local variables. FlexArrayDiag = diag::err_flexible_array_init; } else { // Allow other cases. FlexArrayDiag = diag::ext_flexible_array_init; } if (!VerifyOnly) { SemaRef.Diag(InitExpr->getLocStart(), FlexArrayDiag) << InitExpr->getLocStart(); SemaRef.Diag(Field->getLocation(), diag::note_flexible_array_member) << Field; } return FlexArrayDiag != diag::ext_flexible_array_init; } void InitListChecker::CheckStructUnionTypes( const InitializedEntity &Entity, InitListExpr *IList, QualType DeclType, CXXRecordDecl::base_class_range Bases, RecordDecl::field_iterator Field, bool SubobjectIsDesignatorContext, unsigned &Index, InitListExpr *StructuredList, unsigned &StructuredIndex, bool TopLevelObject) { RecordDecl *structDecl = DeclType->getAs()->getDecl(); // If the record is invalid, some of it's members are invalid. To avoid // confusion, we forgo checking the intializer for the entire record. if (structDecl->isInvalidDecl()) { // Assume it was supposed to consume a single initializer. ++Index; hadError = true; return; } if (DeclType->isUnionType() && IList->getNumInits() == 0) { RecordDecl *RD = DeclType->getAs()->getDecl(); // If there's a default initializer, use it. if (isa(RD) && cast(RD)->hasInClassInitializer()) { if (VerifyOnly) return; for (RecordDecl::field_iterator FieldEnd = RD->field_end(); Field != FieldEnd; ++Field) { if (Field->hasInClassInitializer()) { StructuredList->setInitializedFieldInUnion(*Field); // FIXME: Actually build a CXXDefaultInitExpr? return; } } } // Value-initialize the first member of the union that isn't an unnamed // bitfield. for (RecordDecl::field_iterator FieldEnd = RD->field_end(); Field != FieldEnd; ++Field) { if (!Field->isUnnamedBitfield()) { if (VerifyOnly) CheckEmptyInitializable( InitializedEntity::InitializeMember(*Field, &Entity), IList->getLocEnd()); else StructuredList->setInitializedFieldInUnion(*Field); break; } } return; } bool InitializedSomething = false; // If we have any base classes, they are initialized prior to the fields. for (auto &Base : Bases) { Expr *Init = Index < IList->getNumInits() ? IList->getInit(Index) : nullptr; SourceLocation InitLoc = Init ? Init->getLocStart() : IList->getLocEnd(); // Designated inits always initialize fields, so if we see one, all // remaining base classes have no explicit initializer. if (Init && isa(Init)) Init = nullptr; InitializedEntity BaseEntity = InitializedEntity::InitializeBase( SemaRef.Context, &Base, false, &Entity); if (Init) { CheckSubElementType(BaseEntity, IList, Base.getType(), Index, StructuredList, StructuredIndex); InitializedSomething = true; } else if (VerifyOnly) { CheckEmptyInitializable(BaseEntity, InitLoc); } } // If structDecl is a forward declaration, this loop won't do // anything except look at designated initializers; That's okay, // because an error should get printed out elsewhere. It might be // worthwhile to skip over the rest of the initializer, though. RecordDecl *RD = DeclType->getAs()->getDecl(); RecordDecl::field_iterator FieldEnd = RD->field_end(); bool CheckForMissingFields = !IList->isIdiomaticZeroInitializer(SemaRef.getLangOpts()); while (Index < IList->getNumInits()) { Expr *Init = IList->getInit(Index); if (DesignatedInitExpr *DIE = dyn_cast(Init)) { // If we're not the subobject that matches up with the '{' for // the designator, we shouldn't be handling the // designator. Return immediately. if (!SubobjectIsDesignatorContext) return; // Handle this designated initializer. Field will be updated to // the next field that we'll be initializing. if (CheckDesignatedInitializer(Entity, IList, DIE, 0, DeclType, &Field, nullptr, Index, StructuredList, StructuredIndex, true, TopLevelObject)) hadError = true; InitializedSomething = true; // Disable check for missing fields when designators are used. // This matches gcc behaviour. CheckForMissingFields = false; continue; } if (Field == FieldEnd) { // We've run out of fields. We're done. break; } // We've already initialized a member of a union. We're done. if (InitializedSomething && DeclType->isUnionType()) break; // If we've hit the flexible array member at the end, we're done. if (Field->getType()->isIncompleteArrayType()) break; if (Field->isUnnamedBitfield()) { // Don't initialize unnamed bitfields, e.g. "int : 20;" ++Field; continue; } // Make sure we can use this declaration. bool InvalidUse; if (VerifyOnly) InvalidUse = !SemaRef.CanUseDecl(*Field, TreatUnavailableAsInvalid); else InvalidUse = SemaRef.DiagnoseUseOfDecl(*Field, IList->getInit(Index)->getLocStart()); if (InvalidUse) { ++Index; ++Field; hadError = true; continue; } InitializedEntity MemberEntity = InitializedEntity::InitializeMember(*Field, &Entity); CheckSubElementType(MemberEntity, IList, Field->getType(), Index, StructuredList, StructuredIndex); InitializedSomething = true; if (DeclType->isUnionType() && !VerifyOnly) { // Initialize the first field within the union. StructuredList->setInitializedFieldInUnion(*Field); } ++Field; } // Emit warnings for missing struct field initializers. if (!VerifyOnly && InitializedSomething && CheckForMissingFields && Field != FieldEnd && !Field->getType()->isIncompleteArrayType() && !DeclType->isUnionType()) { // It is possible we have one or more unnamed bitfields remaining. // Find first (if any) named field and emit warning. for (RecordDecl::field_iterator it = Field, end = RD->field_end(); it != end; ++it) { if (!it->isUnnamedBitfield() && !it->hasInClassInitializer()) { SemaRef.Diag(IList->getSourceRange().getEnd(), diag::warn_missing_field_initializers) << *it; break; } } } // Check that any remaining fields can be value-initialized. if (VerifyOnly && Field != FieldEnd && !DeclType->isUnionType() && !Field->getType()->isIncompleteArrayType()) { // FIXME: Should check for holes left by designated initializers too. for (; Field != FieldEnd && !hadError; ++Field) { if (!Field->isUnnamedBitfield() && !Field->hasInClassInitializer()) CheckEmptyInitializable( InitializedEntity::InitializeMember(*Field, &Entity), IList->getLocEnd()); } } if (Field == FieldEnd || !Field->getType()->isIncompleteArrayType() || Index >= IList->getNumInits()) return; if (CheckFlexibleArrayInit(Entity, IList->getInit(Index), *Field, TopLevelObject)) { hadError = true; ++Index; return; } InitializedEntity MemberEntity = InitializedEntity::InitializeMember(*Field, &Entity); if (isa(IList->getInit(Index))) CheckSubElementType(MemberEntity, IList, Field->getType(), Index, StructuredList, StructuredIndex); else CheckImplicitInitList(MemberEntity, IList, Field->getType(), Index, StructuredList, StructuredIndex); } /// Expand a field designator that refers to a member of an /// anonymous struct or union into a series of field designators that /// refers to the field within the appropriate subobject. /// static void ExpandAnonymousFieldDesignator(Sema &SemaRef, DesignatedInitExpr *DIE, unsigned DesigIdx, IndirectFieldDecl *IndirectField) { typedef DesignatedInitExpr::Designator Designator; // Build the replacement designators. SmallVector Replacements; for (IndirectFieldDecl::chain_iterator PI = IndirectField->chain_begin(), PE = IndirectField->chain_end(); PI != PE; ++PI) { if (PI + 1 == PE) Replacements.push_back(Designator((IdentifierInfo *)nullptr, DIE->getDesignator(DesigIdx)->getDotLoc(), DIE->getDesignator(DesigIdx)->getFieldLoc())); else Replacements.push_back(Designator((IdentifierInfo *)nullptr, SourceLocation(), SourceLocation())); assert(isa(*PI)); Replacements.back().setField(cast(*PI)); } // Expand the current designator into the set of replacement // designators, so we have a full subobject path down to where the // member of the anonymous struct/union is actually stored. DIE->ExpandDesignator(SemaRef.Context, DesigIdx, &Replacements[0], &Replacements[0] + Replacements.size()); } static DesignatedInitExpr *CloneDesignatedInitExpr(Sema &SemaRef, DesignatedInitExpr *DIE) { unsigned NumIndexExprs = DIE->getNumSubExprs() - 1; SmallVector IndexExprs(NumIndexExprs); for (unsigned I = 0; I < NumIndexExprs; ++I) IndexExprs[I] = DIE->getSubExpr(I + 1); return DesignatedInitExpr::Create(SemaRef.Context, DIE->designators(), IndexExprs, DIE->getEqualOrColonLoc(), DIE->usesGNUSyntax(), DIE->getInit()); } namespace { // Callback to only accept typo corrections that are for field members of // the given struct or union. class FieldInitializerValidatorCCC : public CorrectionCandidateCallback { public: explicit FieldInitializerValidatorCCC(RecordDecl *RD) : Record(RD) {} bool ValidateCandidate(const TypoCorrection &candidate) override { FieldDecl *FD = candidate.getCorrectionDeclAs(); return FD && FD->getDeclContext()->getRedeclContext()->Equals(Record); } private: RecordDecl *Record; }; } // end anonymous namespace /// Check the well-formedness of a C99 designated initializer. /// /// Determines whether the designated initializer @p DIE, which /// resides at the given @p Index within the initializer list @p /// IList, is well-formed for a current object of type @p DeclType /// (C99 6.7.8). The actual subobject that this designator refers to /// within the current subobject is returned in either /// @p NextField or @p NextElementIndex (whichever is appropriate). /// /// @param IList The initializer list in which this designated /// initializer occurs. /// /// @param DIE The designated initializer expression. /// /// @param DesigIdx The index of the current designator. /// /// @param CurrentObjectType The type of the "current object" (C99 6.7.8p17), /// into which the designation in @p DIE should refer. /// /// @param NextField If non-NULL and the first designator in @p DIE is /// a field, this will be set to the field declaration corresponding /// to the field named by the designator. /// /// @param NextElementIndex If non-NULL and the first designator in @p /// DIE is an array designator or GNU array-range designator, this /// will be set to the last index initialized by this designator. /// /// @param Index Index into @p IList where the designated initializer /// @p DIE occurs. /// /// @param StructuredList The initializer list expression that /// describes all of the subobject initializers in the order they'll /// actually be initialized. /// /// @returns true if there was an error, false otherwise. bool InitListChecker::CheckDesignatedInitializer(const InitializedEntity &Entity, InitListExpr *IList, DesignatedInitExpr *DIE, unsigned DesigIdx, QualType &CurrentObjectType, RecordDecl::field_iterator *NextField, llvm::APSInt *NextElementIndex, unsigned &Index, InitListExpr *StructuredList, unsigned &StructuredIndex, bool FinishSubobjectInit, bool TopLevelObject) { if (DesigIdx == DIE->size()) { // Check the actual initialization for the designated object type. bool prevHadError = hadError; // Temporarily remove the designator expression from the // initializer list that the child calls see, so that we don't try // to re-process the designator. unsigned OldIndex = Index; IList->setInit(OldIndex, DIE->getInit()); CheckSubElementType(Entity, IList, CurrentObjectType, Index, StructuredList, StructuredIndex); // Restore the designated initializer expression in the syntactic // form of the initializer list. if (IList->getInit(OldIndex) != DIE->getInit()) DIE->setInit(IList->getInit(OldIndex)); IList->setInit(OldIndex, DIE); return hadError && !prevHadError; } DesignatedInitExpr::Designator *D = DIE->getDesignator(DesigIdx); bool IsFirstDesignator = (DesigIdx == 0); if (!VerifyOnly) { assert((IsFirstDesignator || StructuredList) && "Need a non-designated initializer list to start from"); // Determine the structural initializer list that corresponds to the // current subobject. if (IsFirstDesignator) StructuredList = SyntacticToSemantic.lookup(IList); else { Expr *ExistingInit = StructuredIndex < StructuredList->getNumInits() ? StructuredList->getInit(StructuredIndex) : nullptr; if (!ExistingInit && StructuredList->hasArrayFiller()) ExistingInit = StructuredList->getArrayFiller(); if (!ExistingInit) StructuredList = getStructuredSubobjectInit(IList, Index, CurrentObjectType, StructuredList, StructuredIndex, SourceRange(D->getLocStart(), DIE->getLocEnd())); else if (InitListExpr *Result = dyn_cast(ExistingInit)) StructuredList = Result; else { if (DesignatedInitUpdateExpr *E = dyn_cast(ExistingInit)) StructuredList = E->getUpdater(); else { DesignatedInitUpdateExpr *DIUE = new (SemaRef.Context) DesignatedInitUpdateExpr(SemaRef.Context, D->getLocStart(), ExistingInit, DIE->getLocEnd()); StructuredList->updateInit(SemaRef.Context, StructuredIndex, DIUE); StructuredList = DIUE->getUpdater(); } // We need to check on source range validity because the previous // initializer does not have to be an explicit initializer. e.g., // // struct P { int a, b; }; // struct PP { struct P p } l = { { .a = 2 }, .p.b = 3 }; // // There is an overwrite taking place because the first braced initializer // list "{ .a = 2 }" already provides value for .p.b (which is zero). if (ExistingInit->getSourceRange().isValid()) { // We are creating an initializer list that initializes the // subobjects of the current object, but there was already an // initialization that completely initialized the current // subobject, e.g., by a compound literal: // // struct X { int a, b; }; // struct X xs[] = { [0] = (struct X) { 1, 2 }, [0].b = 3 }; // // Here, xs[0].a == 0 and xs[0].b == 3, since the second, // designated initializer re-initializes the whole // subobject [0], overwriting previous initializers. SemaRef.Diag(D->getLocStart(), diag::warn_subobject_initializer_overrides) << SourceRange(D->getLocStart(), DIE->getLocEnd()); SemaRef.Diag(ExistingInit->getLocStart(), diag::note_previous_initializer) << /*FIXME:has side effects=*/0 << ExistingInit->getSourceRange(); } } } assert(StructuredList && "Expected a structured initializer list"); } if (D->isFieldDesignator()) { // C99 6.7.8p7: // // If a designator has the form // // . identifier // // then the current object (defined below) shall have // structure or union type and the identifier shall be the // name of a member of that type. const RecordType *RT = CurrentObjectType->getAs(); if (!RT) { SourceLocation Loc = D->getDotLoc(); if (Loc.isInvalid()) Loc = D->getFieldLoc(); if (!VerifyOnly) SemaRef.Diag(Loc, diag::err_field_designator_non_aggr) << SemaRef.getLangOpts().CPlusPlus << CurrentObjectType; ++Index; return true; } FieldDecl *KnownField = D->getField(); if (!KnownField) { IdentifierInfo *FieldName = D->getFieldName(); DeclContext::lookup_result Lookup = RT->getDecl()->lookup(FieldName); for (NamedDecl *ND : Lookup) { if (auto *FD = dyn_cast(ND)) { KnownField = FD; break; } if (auto *IFD = dyn_cast(ND)) { // In verify mode, don't modify the original. if (VerifyOnly) DIE = CloneDesignatedInitExpr(SemaRef, DIE); ExpandAnonymousFieldDesignator(SemaRef, DIE, DesigIdx, IFD); D = DIE->getDesignator(DesigIdx); KnownField = cast(*IFD->chain_begin()); break; } } if (!KnownField) { if (VerifyOnly) { ++Index; return true; // No typo correction when just trying this out. } // Name lookup found something, but it wasn't a field. if (!Lookup.empty()) { SemaRef.Diag(D->getFieldLoc(), diag::err_field_designator_nonfield) << FieldName; SemaRef.Diag(Lookup.front()->getLocation(), diag::note_field_designator_found); ++Index; return true; } // Name lookup didn't find anything. // Determine whether this was a typo for another field name. if (TypoCorrection Corrected = SemaRef.CorrectTypo( DeclarationNameInfo(FieldName, D->getFieldLoc()), Sema::LookupMemberName, /*Scope=*/nullptr, /*SS=*/nullptr, llvm::make_unique(RT->getDecl()), Sema::CTK_ErrorRecovery, RT->getDecl())) { SemaRef.diagnoseTypo( Corrected, SemaRef.PDiag(diag::err_field_designator_unknown_suggest) << FieldName << CurrentObjectType); KnownField = Corrected.getCorrectionDeclAs(); hadError = true; } else { // Typo correction didn't find anything. SemaRef.Diag(D->getFieldLoc(), diag::err_field_designator_unknown) << FieldName << CurrentObjectType; ++Index; return true; } } } unsigned FieldIndex = 0; if (auto *CXXRD = dyn_cast(RT->getDecl())) FieldIndex = CXXRD->getNumBases(); for (auto *FI : RT->getDecl()->fields()) { if (FI->isUnnamedBitfield()) continue; if (declaresSameEntity(KnownField, FI)) { KnownField = FI; break; } ++FieldIndex; } RecordDecl::field_iterator Field = RecordDecl::field_iterator(DeclContext::decl_iterator(KnownField)); // All of the fields of a union are located at the same place in // the initializer list. if (RT->getDecl()->isUnion()) { FieldIndex = 0; if (!VerifyOnly) { FieldDecl *CurrentField = StructuredList->getInitializedFieldInUnion(); if (CurrentField && !declaresSameEntity(CurrentField, *Field)) { assert(StructuredList->getNumInits() == 1 && "A union should never have more than one initializer!"); Expr *ExistingInit = StructuredList->getInit(0); if (ExistingInit) { // We're about to throw away an initializer, emit warning. SemaRef.Diag(D->getFieldLoc(), diag::warn_initializer_overrides) << D->getSourceRange(); SemaRef.Diag(ExistingInit->getLocStart(), diag::note_previous_initializer) << /*FIXME:has side effects=*/0 << ExistingInit->getSourceRange(); } // remove existing initializer StructuredList->resizeInits(SemaRef.Context, 0); StructuredList->setInitializedFieldInUnion(nullptr); } StructuredList->setInitializedFieldInUnion(*Field); } } // Make sure we can use this declaration. bool InvalidUse; if (VerifyOnly) InvalidUse = !SemaRef.CanUseDecl(*Field, TreatUnavailableAsInvalid); else InvalidUse = SemaRef.DiagnoseUseOfDecl(*Field, D->getFieldLoc()); if (InvalidUse) { ++Index; return true; } if (!VerifyOnly) { // Update the designator with the field declaration. D->setField(*Field); // Make sure that our non-designated initializer list has space // for a subobject corresponding to this field. if (FieldIndex >= StructuredList->getNumInits()) StructuredList->resizeInits(SemaRef.Context, FieldIndex + 1); } // This designator names a flexible array member. if (Field->getType()->isIncompleteArrayType()) { bool Invalid = false; if ((DesigIdx + 1) != DIE->size()) { // We can't designate an object within the flexible array // member (because GCC doesn't allow it). if (!VerifyOnly) { DesignatedInitExpr::Designator *NextD = DIE->getDesignator(DesigIdx + 1); SemaRef.Diag(NextD->getLocStart(), diag::err_designator_into_flexible_array_member) << SourceRange(NextD->getLocStart(), DIE->getLocEnd()); SemaRef.Diag(Field->getLocation(), diag::note_flexible_array_member) << *Field; } Invalid = true; } if (!hadError && !isa(DIE->getInit()) && !isa(DIE->getInit())) { // The initializer is not an initializer list. if (!VerifyOnly) { SemaRef.Diag(DIE->getInit()->getLocStart(), diag::err_flexible_array_init_needs_braces) << DIE->getInit()->getSourceRange(); SemaRef.Diag(Field->getLocation(), diag::note_flexible_array_member) << *Field; } Invalid = true; } // Check GNU flexible array initializer. if (!Invalid && CheckFlexibleArrayInit(Entity, DIE->getInit(), *Field, TopLevelObject)) Invalid = true; if (Invalid) { ++Index; return true; } // Initialize the array. bool prevHadError = hadError; unsigned newStructuredIndex = FieldIndex; unsigned OldIndex = Index; IList->setInit(Index, DIE->getInit()); InitializedEntity MemberEntity = InitializedEntity::InitializeMember(*Field, &Entity); CheckSubElementType(MemberEntity, IList, Field->getType(), Index, StructuredList, newStructuredIndex); IList->setInit(OldIndex, DIE); if (hadError && !prevHadError) { ++Field; ++FieldIndex; if (NextField) *NextField = Field; StructuredIndex = FieldIndex; return true; } } else { // Recurse to check later designated subobjects. QualType FieldType = Field->getType(); unsigned newStructuredIndex = FieldIndex; InitializedEntity MemberEntity = InitializedEntity::InitializeMember(*Field, &Entity); if (CheckDesignatedInitializer(MemberEntity, IList, DIE, DesigIdx + 1, FieldType, nullptr, nullptr, Index, StructuredList, newStructuredIndex, FinishSubobjectInit, false)) return true; } // Find the position of the next field to be initialized in this // subobject. ++Field; ++FieldIndex; // If this the first designator, our caller will continue checking // the rest of this struct/class/union subobject. if (IsFirstDesignator) { if (NextField) *NextField = Field; StructuredIndex = FieldIndex; return false; } if (!FinishSubobjectInit) return false; // We've already initialized something in the union; we're done. if (RT->getDecl()->isUnion()) return hadError; // Check the remaining fields within this class/struct/union subobject. bool prevHadError = hadError; auto NoBases = CXXRecordDecl::base_class_range(CXXRecordDecl::base_class_iterator(), CXXRecordDecl::base_class_iterator()); CheckStructUnionTypes(Entity, IList, CurrentObjectType, NoBases, Field, false, Index, StructuredList, FieldIndex); return hadError && !prevHadError; } // C99 6.7.8p6: // // If a designator has the form // // [ constant-expression ] // // then the current object (defined below) shall have array // type and the expression shall be an integer constant // expression. If the array is of unknown size, any // nonnegative value is valid. // // Additionally, cope with the GNU extension that permits // designators of the form // // [ constant-expression ... constant-expression ] const ArrayType *AT = SemaRef.Context.getAsArrayType(CurrentObjectType); if (!AT) { if (!VerifyOnly) SemaRef.Diag(D->getLBracketLoc(), diag::err_array_designator_non_array) << CurrentObjectType; ++Index; return true; } Expr *IndexExpr = nullptr; llvm::APSInt DesignatedStartIndex, DesignatedEndIndex; if (D->isArrayDesignator()) { IndexExpr = DIE->getArrayIndex(*D); DesignatedStartIndex = IndexExpr->EvaluateKnownConstInt(SemaRef.Context); DesignatedEndIndex = DesignatedStartIndex; } else { assert(D->isArrayRangeDesignator() && "Need array-range designator"); DesignatedStartIndex = DIE->getArrayRangeStart(*D)->EvaluateKnownConstInt(SemaRef.Context); DesignatedEndIndex = DIE->getArrayRangeEnd(*D)->EvaluateKnownConstInt(SemaRef.Context); IndexExpr = DIE->getArrayRangeEnd(*D); // Codegen can't handle evaluating array range designators that have side // effects, because we replicate the AST value for each initialized element. // As such, set the sawArrayRangeDesignator() bit if we initialize multiple // elements with something that has a side effect, so codegen can emit an // "error unsupported" error instead of miscompiling the app. if (DesignatedStartIndex.getZExtValue()!=DesignatedEndIndex.getZExtValue()&& DIE->getInit()->HasSideEffects(SemaRef.Context) && !VerifyOnly) FullyStructuredList->sawArrayRangeDesignator(); } if (isa(AT)) { llvm::APSInt MaxElements(cast(AT)->getSize(), false); DesignatedStartIndex = DesignatedStartIndex.extOrTrunc(MaxElements.getBitWidth()); DesignatedStartIndex.setIsUnsigned(MaxElements.isUnsigned()); DesignatedEndIndex = DesignatedEndIndex.extOrTrunc(MaxElements.getBitWidth()); DesignatedEndIndex.setIsUnsigned(MaxElements.isUnsigned()); if (DesignatedEndIndex >= MaxElements) { if (!VerifyOnly) SemaRef.Diag(IndexExpr->getLocStart(), diag::err_array_designator_too_large) << DesignatedEndIndex.toString(10) << MaxElements.toString(10) << IndexExpr->getSourceRange(); ++Index; return true; } } else { unsigned DesignatedIndexBitWidth = ConstantArrayType::getMaxSizeBits(SemaRef.Context); DesignatedStartIndex = DesignatedStartIndex.extOrTrunc(DesignatedIndexBitWidth); DesignatedEndIndex = DesignatedEndIndex.extOrTrunc(DesignatedIndexBitWidth); DesignatedStartIndex.setIsUnsigned(true); DesignatedEndIndex.setIsUnsigned(true); } if (!VerifyOnly && StructuredList->isStringLiteralInit()) { // We're modifying a string literal init; we have to decompose the string // so we can modify the individual characters. ASTContext &Context = SemaRef.Context; Expr *SubExpr = StructuredList->getInit(0)->IgnoreParens(); // Compute the character type QualType CharTy = AT->getElementType(); // Compute the type of the integer literals. QualType PromotedCharTy = CharTy; if (CharTy->isPromotableIntegerType()) PromotedCharTy = Context.getPromotedIntegerType(CharTy); unsigned PromotedCharTyWidth = Context.getTypeSize(PromotedCharTy); if (StringLiteral *SL = dyn_cast(SubExpr)) { // Get the length of the string. uint64_t StrLen = SL->getLength(); if (cast(AT)->getSize().ult(StrLen)) StrLen = cast(AT)->getSize().getZExtValue(); StructuredList->resizeInits(Context, StrLen); // Build a literal for each character in the string, and put them into // the init list. for (unsigned i = 0, e = StrLen; i != e; ++i) { llvm::APInt CodeUnit(PromotedCharTyWidth, SL->getCodeUnit(i)); Expr *Init = new (Context) IntegerLiteral( Context, CodeUnit, PromotedCharTy, SubExpr->getExprLoc()); if (CharTy != PromotedCharTy) Init = ImplicitCastExpr::Create(Context, CharTy, CK_IntegralCast, Init, nullptr, VK_RValue); StructuredList->updateInit(Context, i, Init); } } else { ObjCEncodeExpr *E = cast(SubExpr); std::string Str; Context.getObjCEncodingForType(E->getEncodedType(), Str); // Get the length of the string. uint64_t StrLen = Str.size(); if (cast(AT)->getSize().ult(StrLen)) StrLen = cast(AT)->getSize().getZExtValue(); StructuredList->resizeInits(Context, StrLen); // Build a literal for each character in the string, and put them into // the init list. for (unsigned i = 0, e = StrLen; i != e; ++i) { llvm::APInt CodeUnit(PromotedCharTyWidth, Str[i]); Expr *Init = new (Context) IntegerLiteral( Context, CodeUnit, PromotedCharTy, SubExpr->getExprLoc()); if (CharTy != PromotedCharTy) Init = ImplicitCastExpr::Create(Context, CharTy, CK_IntegralCast, Init, nullptr, VK_RValue); StructuredList->updateInit(Context, i, Init); } } } // Make sure that our non-designated initializer list has space // for a subobject corresponding to this array element. if (!VerifyOnly && DesignatedEndIndex.getZExtValue() >= StructuredList->getNumInits()) StructuredList->resizeInits(SemaRef.Context, DesignatedEndIndex.getZExtValue() + 1); // Repeatedly perform subobject initializations in the range // [DesignatedStartIndex, DesignatedEndIndex]. // Move to the next designator unsigned ElementIndex = DesignatedStartIndex.getZExtValue(); unsigned OldIndex = Index; InitializedEntity ElementEntity = InitializedEntity::InitializeElement(SemaRef.Context, 0, Entity); while (DesignatedStartIndex <= DesignatedEndIndex) { // Recurse to check later designated subobjects. QualType ElementType = AT->getElementType(); Index = OldIndex; ElementEntity.setElementIndex(ElementIndex); if (CheckDesignatedInitializer( ElementEntity, IList, DIE, DesigIdx + 1, ElementType, nullptr, nullptr, Index, StructuredList, ElementIndex, FinishSubobjectInit && (DesignatedStartIndex == DesignatedEndIndex), false)) return true; // Move to the next index in the array that we'll be initializing. ++DesignatedStartIndex; ElementIndex = DesignatedStartIndex.getZExtValue(); } // If this the first designator, our caller will continue checking // the rest of this array subobject. if (IsFirstDesignator) { if (NextElementIndex) *NextElementIndex = DesignatedStartIndex; StructuredIndex = ElementIndex; return false; } if (!FinishSubobjectInit) return false; // Check the remaining elements within this array subobject. bool prevHadError = hadError; CheckArrayType(Entity, IList, CurrentObjectType, DesignatedStartIndex, /*SubobjectIsDesignatorContext=*/false, Index, StructuredList, ElementIndex); return hadError && !prevHadError; } // Get the structured initializer list for a subobject of type // @p CurrentObjectType. InitListExpr * InitListChecker::getStructuredSubobjectInit(InitListExpr *IList, unsigned Index, QualType CurrentObjectType, InitListExpr *StructuredList, unsigned StructuredIndex, SourceRange InitRange, bool IsFullyOverwritten) { if (VerifyOnly) return nullptr; // No structured list in verification-only mode. Expr *ExistingInit = nullptr; if (!StructuredList) ExistingInit = SyntacticToSemantic.lookup(IList); else if (StructuredIndex < StructuredList->getNumInits()) ExistingInit = StructuredList->getInit(StructuredIndex); if (InitListExpr *Result = dyn_cast_or_null(ExistingInit)) // There might have already been initializers for subobjects of the current // object, but a subsequent initializer list will overwrite the entirety // of the current object. (See DR 253 and C99 6.7.8p21). e.g., // // struct P { char x[6]; }; // struct P l = { .x[2] = 'x', .x = { [0] = 'f' } }; // // The first designated initializer is ignored, and l.x is just "f". if (!IsFullyOverwritten) return Result; if (ExistingInit) { // We are creating an initializer list that initializes the // subobjects of the current object, but there was already an // initialization that completely initialized the current // subobject, e.g., by a compound literal: // // struct X { int a, b; }; // struct X xs[] = { [0] = (struct X) { 1, 2 }, [0].b = 3 }; // // Here, xs[0].a == 0 and xs[0].b == 3, since the second, // designated initializer re-initializes the whole // subobject [0], overwriting previous initializers. SemaRef.Diag(InitRange.getBegin(), diag::warn_subobject_initializer_overrides) << InitRange; SemaRef.Diag(ExistingInit->getLocStart(), diag::note_previous_initializer) << /*FIXME:has side effects=*/0 << ExistingInit->getSourceRange(); } InitListExpr *Result = new (SemaRef.Context) InitListExpr(SemaRef.Context, InitRange.getBegin(), None, InitRange.getEnd()); QualType ResultType = CurrentObjectType; if (!ResultType->isArrayType()) ResultType = ResultType.getNonLValueExprType(SemaRef.Context); Result->setType(ResultType); // Pre-allocate storage for the structured initializer list. unsigned NumElements = 0; unsigned NumInits = 0; bool GotNumInits = false; if (!StructuredList) { NumInits = IList->getNumInits(); GotNumInits = true; } else if (Index < IList->getNumInits()) { if (InitListExpr *SubList = dyn_cast(IList->getInit(Index))) { NumInits = SubList->getNumInits(); GotNumInits = true; } } if (const ArrayType *AType = SemaRef.Context.getAsArrayType(CurrentObjectType)) { if (const ConstantArrayType *CAType = dyn_cast(AType)) { NumElements = CAType->getSize().getZExtValue(); // Simple heuristic so that we don't allocate a very large // initializer with many empty entries at the end. if (GotNumInits && NumElements > NumInits) NumElements = 0; } } else if (const VectorType *VType = CurrentObjectType->getAs()) NumElements = VType->getNumElements(); else if (const RecordType *RType = CurrentObjectType->getAs()) { RecordDecl *RDecl = RType->getDecl(); if (RDecl->isUnion()) NumElements = 1; else NumElements = std::distance(RDecl->field_begin(), RDecl->field_end()); } Result->reserveInits(SemaRef.Context, NumElements); // Link this new initializer list into the structured initializer // lists. if (StructuredList) StructuredList->updateInit(SemaRef.Context, StructuredIndex, Result); else { Result->setSyntacticForm(IList); SyntacticToSemantic[IList] = Result; } return Result; } /// Update the initializer at index @p StructuredIndex within the /// structured initializer list to the value @p expr. void InitListChecker::UpdateStructuredListElement(InitListExpr *StructuredList, unsigned &StructuredIndex, Expr *expr) { // No structured initializer list to update if (!StructuredList) return; if (Expr *PrevInit = StructuredList->updateInit(SemaRef.Context, StructuredIndex, expr)) { // This initializer overwrites a previous initializer. Warn. // We need to check on source range validity because the previous // initializer does not have to be an explicit initializer. // struct P { int a, b; }; // struct PP { struct P p } l = { { .a = 2 }, .p.b = 3 }; // There is an overwrite taking place because the first braced initializer // list "{ .a = 2 }' already provides value for .p.b (which is zero). if (PrevInit->getSourceRange().isValid()) { SemaRef.Diag(expr->getLocStart(), diag::warn_initializer_overrides) << expr->getSourceRange(); SemaRef.Diag(PrevInit->getLocStart(), diag::note_previous_initializer) << /*FIXME:has side effects=*/0 << PrevInit->getSourceRange(); } } ++StructuredIndex; } /// Check that the given Index expression is a valid array designator /// value. This is essentially just a wrapper around /// VerifyIntegerConstantExpression that also checks for negative values /// and produces a reasonable diagnostic if there is a /// failure. Returns the index expression, possibly with an implicit cast /// added, on success. If everything went okay, Value will receive the /// value of the constant expression. static ExprResult CheckArrayDesignatorExpr(Sema &S, Expr *Index, llvm::APSInt &Value) { SourceLocation Loc = Index->getLocStart(); // Make sure this is an integer constant expression. ExprResult Result = S.VerifyIntegerConstantExpression(Index, &Value); if (Result.isInvalid()) return Result; if (Value.isSigned() && Value.isNegative()) return S.Diag(Loc, diag::err_array_designator_negative) << Value.toString(10) << Index->getSourceRange(); Value.setIsUnsigned(true); return Result; } ExprResult Sema::ActOnDesignatedInitializer(Designation &Desig, SourceLocation Loc, bool GNUSyntax, ExprResult Init) { typedef DesignatedInitExpr::Designator ASTDesignator; bool Invalid = false; SmallVector Designators; SmallVector InitExpressions; // Build designators and check array designator expressions. for (unsigned Idx = 0; Idx < Desig.getNumDesignators(); ++Idx) { const Designator &D = Desig.getDesignator(Idx); switch (D.getKind()) { case Designator::FieldDesignator: Designators.push_back(ASTDesignator(D.getField(), D.getDotLoc(), D.getFieldLoc())); break; case Designator::ArrayDesignator: { Expr *Index = static_cast(D.getArrayIndex()); llvm::APSInt IndexValue; if (!Index->isTypeDependent() && !Index->isValueDependent()) Index = CheckArrayDesignatorExpr(*this, Index, IndexValue).get(); if (!Index) Invalid = true; else { Designators.push_back(ASTDesignator(InitExpressions.size(), D.getLBracketLoc(), D.getRBracketLoc())); InitExpressions.push_back(Index); } break; } case Designator::ArrayRangeDesignator: { Expr *StartIndex = static_cast(D.getArrayRangeStart()); Expr *EndIndex = static_cast(D.getArrayRangeEnd()); llvm::APSInt StartValue; llvm::APSInt EndValue; bool StartDependent = StartIndex->isTypeDependent() || StartIndex->isValueDependent(); bool EndDependent = EndIndex->isTypeDependent() || EndIndex->isValueDependent(); if (!StartDependent) StartIndex = CheckArrayDesignatorExpr(*this, StartIndex, StartValue).get(); if (!EndDependent) EndIndex = CheckArrayDesignatorExpr(*this, EndIndex, EndValue).get(); if (!StartIndex || !EndIndex) Invalid = true; else { // Make sure we're comparing values with the same bit width. if (StartDependent || EndDependent) { // Nothing to compute. } else if (StartValue.getBitWidth() > EndValue.getBitWidth()) EndValue = EndValue.extend(StartValue.getBitWidth()); else if (StartValue.getBitWidth() < EndValue.getBitWidth()) StartValue = StartValue.extend(EndValue.getBitWidth()); if (!StartDependent && !EndDependent && EndValue < StartValue) { Diag(D.getEllipsisLoc(), diag::err_array_designator_empty_range) << StartValue.toString(10) << EndValue.toString(10) << StartIndex->getSourceRange() << EndIndex->getSourceRange(); Invalid = true; } else { Designators.push_back(ASTDesignator(InitExpressions.size(), D.getLBracketLoc(), D.getEllipsisLoc(), D.getRBracketLoc())); InitExpressions.push_back(StartIndex); InitExpressions.push_back(EndIndex); } } break; } } } if (Invalid || Init.isInvalid()) return ExprError(); // Clear out the expressions within the designation. Desig.ClearExprs(*this); DesignatedInitExpr *DIE = DesignatedInitExpr::Create(Context, Designators, InitExpressions, Loc, GNUSyntax, Init.getAs()); if (!getLangOpts().C99) Diag(DIE->getLocStart(), diag::ext_designated_init) << DIE->getSourceRange(); return DIE; } //===----------------------------------------------------------------------===// // Initialization entity //===----------------------------------------------------------------------===// InitializedEntity::InitializedEntity(ASTContext &Context, unsigned Index, const InitializedEntity &Parent) : Parent(&Parent), Index(Index) { if (const ArrayType *AT = Context.getAsArrayType(Parent.getType())) { Kind = EK_ArrayElement; Type = AT->getElementType(); } else if (const VectorType *VT = Parent.getType()->getAs()) { Kind = EK_VectorElement; Type = VT->getElementType(); } else { const ComplexType *CT = Parent.getType()->getAs(); assert(CT && "Unexpected type"); Kind = EK_ComplexElement; Type = CT->getElementType(); } } InitializedEntity InitializedEntity::InitializeBase(ASTContext &Context, const CXXBaseSpecifier *Base, bool IsInheritedVirtualBase, const InitializedEntity *Parent) { InitializedEntity Result; Result.Kind = EK_Base; Result.Parent = Parent; Result.Base = reinterpret_cast(Base); if (IsInheritedVirtualBase) Result.Base |= 0x01; Result.Type = Base->getType(); return Result; } DeclarationName InitializedEntity::getName() const { switch (getKind()) { case EK_Parameter: case EK_Parameter_CF_Audited: { ParmVarDecl *D = reinterpret_cast(Parameter & ~0x1); return (D ? D->getDeclName() : DeclarationName()); } case EK_Variable: case EK_Member: case EK_Binding: return Variable.VariableOrMember->getDeclName(); case EK_LambdaCapture: return DeclarationName(Capture.VarID); case EK_Result: case EK_StmtExprResult: case EK_Exception: case EK_New: case EK_Temporary: case EK_Base: case EK_Delegating: case EK_ArrayElement: case EK_VectorElement: case EK_ComplexElement: case EK_BlockElement: case EK_LambdaToBlockConversionBlockElement: case EK_CompoundLiteralInit: case EK_RelatedResult: return DeclarationName(); } llvm_unreachable("Invalid EntityKind!"); } ValueDecl *InitializedEntity::getDecl() const { switch (getKind()) { case EK_Variable: case EK_Member: case EK_Binding: return Variable.VariableOrMember; case EK_Parameter: case EK_Parameter_CF_Audited: return reinterpret_cast(Parameter & ~0x1); case EK_Result: case EK_StmtExprResult: case EK_Exception: case EK_New: case EK_Temporary: case EK_Base: case EK_Delegating: case EK_ArrayElement: case EK_VectorElement: case EK_ComplexElement: case EK_BlockElement: case EK_LambdaToBlockConversionBlockElement: case EK_LambdaCapture: case EK_CompoundLiteralInit: case EK_RelatedResult: return nullptr; } llvm_unreachable("Invalid EntityKind!"); } bool InitializedEntity::allowsNRVO() const { switch (getKind()) { case EK_Result: case EK_Exception: return LocAndNRVO.NRVO; case EK_StmtExprResult: case EK_Variable: case EK_Parameter: case EK_Parameter_CF_Audited: case EK_Member: case EK_Binding: case EK_New: case EK_Temporary: case EK_CompoundLiteralInit: case EK_Base: case EK_Delegating: case EK_ArrayElement: case EK_VectorElement: case EK_ComplexElement: case EK_BlockElement: case EK_LambdaToBlockConversionBlockElement: case EK_LambdaCapture: case EK_RelatedResult: break; } return false; } unsigned InitializedEntity::dumpImpl(raw_ostream &OS) const { assert(getParent() != this); unsigned Depth = getParent() ? getParent()->dumpImpl(OS) : 0; for (unsigned I = 0; I != Depth; ++I) OS << "`-"; switch (getKind()) { case EK_Variable: OS << "Variable"; break; case EK_Parameter: OS << "Parameter"; break; case EK_Parameter_CF_Audited: OS << "CF audited function Parameter"; break; case EK_Result: OS << "Result"; break; case EK_StmtExprResult: OS << "StmtExprResult"; break; case EK_Exception: OS << "Exception"; break; case EK_Member: OS << "Member"; break; case EK_Binding: OS << "Binding"; break; case EK_New: OS << "New"; break; case EK_Temporary: OS << "Temporary"; break; case EK_CompoundLiteralInit: OS << "CompoundLiteral";break; case EK_RelatedResult: OS << "RelatedResult"; break; case EK_Base: OS << "Base"; break; case EK_Delegating: OS << "Delegating"; break; case EK_ArrayElement: OS << "ArrayElement " << Index; break; case EK_VectorElement: OS << "VectorElement " << Index; break; case EK_ComplexElement: OS << "ComplexElement " << Index; break; case EK_BlockElement: OS << "Block"; break; case EK_LambdaToBlockConversionBlockElement: OS << "Block (lambda)"; break; case EK_LambdaCapture: OS << "LambdaCapture "; OS << DeclarationName(Capture.VarID); break; } if (auto *D = getDecl()) { OS << " "; D->printQualifiedName(OS); } OS << " '" << getType().getAsString() << "'\n"; return Depth + 1; } LLVM_DUMP_METHOD void InitializedEntity::dump() const { dumpImpl(llvm::errs()); } //===----------------------------------------------------------------------===// // Initialization sequence //===----------------------------------------------------------------------===// void InitializationSequence::Step::Destroy() { switch (Kind) { case SK_ResolveAddressOfOverloadedFunction: case SK_CastDerivedToBaseRValue: case SK_CastDerivedToBaseXValue: case SK_CastDerivedToBaseLValue: case SK_BindReference: case SK_BindReferenceToTemporary: case SK_FinalCopy: case SK_ExtraneousCopyToTemporary: case SK_UserConversion: case SK_QualificationConversionRValue: case SK_QualificationConversionXValue: case SK_QualificationConversionLValue: case SK_AtomicConversion: case SK_LValueToRValue: case SK_ListInitialization: case SK_UnwrapInitList: case SK_RewrapInitList: case SK_ConstructorInitialization: case SK_ConstructorInitializationFromList: case SK_ZeroInitialization: case SK_CAssignment: case SK_StringInit: case SK_ObjCObjectConversion: case SK_ArrayLoopIndex: case SK_ArrayLoopInit: case SK_ArrayInit: case SK_GNUArrayInit: case SK_ParenthesizedArrayInit: case SK_PassByIndirectCopyRestore: case SK_PassByIndirectRestore: case SK_ProduceObjCObject: case SK_StdInitializerList: case SK_StdInitializerListConstructorCall: case SK_OCLSamplerInit: case SK_OCLZeroEvent: case SK_OCLZeroQueue: break; case SK_ConversionSequence: case SK_ConversionSequenceNoNarrowing: delete ICS; } } bool InitializationSequence::isDirectReferenceBinding() const { // There can be some lvalue adjustments after the SK_BindReference step. for (auto I = Steps.rbegin(); I != Steps.rend(); ++I) { if (I->Kind == SK_BindReference) return true; if (I->Kind == SK_BindReferenceToTemporary) return false; } return false; } bool InitializationSequence::isAmbiguous() const { if (!Failed()) return false; switch (getFailureKind()) { case FK_TooManyInitsForReference: case FK_ParenthesizedListInitForReference: case FK_ArrayNeedsInitList: case FK_ArrayNeedsInitListOrStringLiteral: case FK_ArrayNeedsInitListOrWideStringLiteral: case FK_NarrowStringIntoWideCharArray: case FK_WideStringIntoCharArray: case FK_IncompatWideStringIntoWideChar: case FK_PlainStringIntoUTF8Char: case FK_UTF8StringIntoPlainChar: case FK_AddressOfOverloadFailed: // FIXME: Could do better case FK_NonConstLValueReferenceBindingToTemporary: case FK_NonConstLValueReferenceBindingToBitfield: case FK_NonConstLValueReferenceBindingToVectorElement: case FK_NonConstLValueReferenceBindingToUnrelated: case FK_RValueReferenceBindingToLValue: case FK_ReferenceInitDropsQualifiers: case FK_ReferenceInitFailed: case FK_ConversionFailed: case FK_ConversionFromPropertyFailed: case FK_TooManyInitsForScalar: case FK_ParenthesizedListInitForScalar: case FK_ReferenceBindingToInitList: case FK_InitListBadDestinationType: case FK_DefaultInitOfConst: case FK_Incomplete: case FK_ArrayTypeMismatch: case FK_NonConstantArrayInit: case FK_ListInitializationFailed: case FK_VariableLengthArrayHasInitializer: case FK_PlaceholderType: case FK_ExplicitConstructor: case FK_AddressOfUnaddressableFunction: return false; case FK_ReferenceInitOverloadFailed: case FK_UserConversionOverloadFailed: case FK_ConstructorOverloadFailed: case FK_ListConstructorOverloadFailed: return FailedOverloadResult == OR_Ambiguous; } llvm_unreachable("Invalid EntityKind!"); } bool InitializationSequence::isConstructorInitialization() const { return !Steps.empty() && Steps.back().Kind == SK_ConstructorInitialization; } void InitializationSequence ::AddAddressOverloadResolutionStep(FunctionDecl *Function, DeclAccessPair Found, bool HadMultipleCandidates) { Step S; S.Kind = SK_ResolveAddressOfOverloadedFunction; S.Type = Function->getType(); S.Function.HadMultipleCandidates = HadMultipleCandidates; S.Function.Function = Function; S.Function.FoundDecl = Found; Steps.push_back(S); } void InitializationSequence::AddDerivedToBaseCastStep(QualType BaseType, ExprValueKind VK) { Step S; switch (VK) { case VK_RValue: S.Kind = SK_CastDerivedToBaseRValue; break; case VK_XValue: S.Kind = SK_CastDerivedToBaseXValue; break; case VK_LValue: S.Kind = SK_CastDerivedToBaseLValue; break; } S.Type = BaseType; Steps.push_back(S); } void InitializationSequence::AddReferenceBindingStep(QualType T, bool BindingTemporary) { Step S; S.Kind = BindingTemporary? SK_BindReferenceToTemporary : SK_BindReference; S.Type = T; Steps.push_back(S); } void InitializationSequence::AddFinalCopy(QualType T) { Step S; S.Kind = SK_FinalCopy; S.Type = T; Steps.push_back(S); } void InitializationSequence::AddExtraneousCopyToTemporary(QualType T) { Step S; S.Kind = SK_ExtraneousCopyToTemporary; S.Type = T; Steps.push_back(S); } void InitializationSequence::AddUserConversionStep(FunctionDecl *Function, DeclAccessPair FoundDecl, QualType T, bool HadMultipleCandidates) { Step S; S.Kind = SK_UserConversion; S.Type = T; S.Function.HadMultipleCandidates = HadMultipleCandidates; S.Function.Function = Function; S.Function.FoundDecl = FoundDecl; Steps.push_back(S); } void InitializationSequence::AddQualificationConversionStep(QualType Ty, ExprValueKind VK) { Step S; S.Kind = SK_QualificationConversionRValue; // work around a gcc warning switch (VK) { case VK_RValue: S.Kind = SK_QualificationConversionRValue; break; case VK_XValue: S.Kind = SK_QualificationConversionXValue; break; case VK_LValue: S.Kind = SK_QualificationConversionLValue; break; } S.Type = Ty; Steps.push_back(S); } void InitializationSequence::AddAtomicConversionStep(QualType Ty) { Step S; S.Kind = SK_AtomicConversion; S.Type = Ty; Steps.push_back(S); } void InitializationSequence::AddLValueToRValueStep(QualType Ty) { assert(!Ty.hasQualifiers() && "rvalues may not have qualifiers"); Step S; S.Kind = SK_LValueToRValue; S.Type = Ty; Steps.push_back(S); } void InitializationSequence::AddConversionSequenceStep( const ImplicitConversionSequence &ICS, QualType T, bool TopLevelOfInitList) { Step S; S.Kind = TopLevelOfInitList ? SK_ConversionSequenceNoNarrowing : SK_ConversionSequence; S.Type = T; S.ICS = new ImplicitConversionSequence(ICS); Steps.push_back(S); } void InitializationSequence::AddListInitializationStep(QualType T) { Step S; S.Kind = SK_ListInitialization; S.Type = T; Steps.push_back(S); } void InitializationSequence::AddConstructorInitializationStep( DeclAccessPair FoundDecl, CXXConstructorDecl *Constructor, QualType T, bool HadMultipleCandidates, bool FromInitList, bool AsInitList) { Step S; S.Kind = FromInitList ? AsInitList ? SK_StdInitializerListConstructorCall : SK_ConstructorInitializationFromList : SK_ConstructorInitialization; S.Type = T; S.Function.HadMultipleCandidates = HadMultipleCandidates; S.Function.Function = Constructor; S.Function.FoundDecl = FoundDecl; Steps.push_back(S); } void InitializationSequence::AddZeroInitializationStep(QualType T) { Step S; S.Kind = SK_ZeroInitialization; S.Type = T; Steps.push_back(S); } void InitializationSequence::AddCAssignmentStep(QualType T) { Step S; S.Kind = SK_CAssignment; S.Type = T; Steps.push_back(S); } void InitializationSequence::AddStringInitStep(QualType T) { Step S; S.Kind = SK_StringInit; S.Type = T; Steps.push_back(S); } void InitializationSequence::AddObjCObjectConversionStep(QualType T) { Step S; S.Kind = SK_ObjCObjectConversion; S.Type = T; Steps.push_back(S); } void InitializationSequence::AddArrayInitStep(QualType T, bool IsGNUExtension) { Step S; S.Kind = IsGNUExtension ? SK_GNUArrayInit : SK_ArrayInit; S.Type = T; Steps.push_back(S); } void InitializationSequence::AddArrayInitLoopStep(QualType T, QualType EltT) { Step S; S.Kind = SK_ArrayLoopIndex; S.Type = EltT; Steps.insert(Steps.begin(), S); S.Kind = SK_ArrayLoopInit; S.Type = T; Steps.push_back(S); } void InitializationSequence::AddParenthesizedArrayInitStep(QualType T) { Step S; S.Kind = SK_ParenthesizedArrayInit; S.Type = T; Steps.push_back(S); } void InitializationSequence::AddPassByIndirectCopyRestoreStep(QualType type, bool shouldCopy) { Step s; s.Kind = (shouldCopy ? SK_PassByIndirectCopyRestore : SK_PassByIndirectRestore); s.Type = type; Steps.push_back(s); } void InitializationSequence::AddProduceObjCObjectStep(QualType T) { Step S; S.Kind = SK_ProduceObjCObject; S.Type = T; Steps.push_back(S); } void InitializationSequence::AddStdInitializerListConstructionStep(QualType T) { Step S; S.Kind = SK_StdInitializerList; S.Type = T; Steps.push_back(S); } void InitializationSequence::AddOCLSamplerInitStep(QualType T) { Step S; S.Kind = SK_OCLSamplerInit; S.Type = T; Steps.push_back(S); } void InitializationSequence::AddOCLZeroEventStep(QualType T) { Step S; S.Kind = SK_OCLZeroEvent; S.Type = T; Steps.push_back(S); } void InitializationSequence::AddOCLZeroQueueStep(QualType T) { Step S; S.Kind = SK_OCLZeroQueue; S.Type = T; Steps.push_back(S); } void InitializationSequence::RewrapReferenceInitList(QualType T, InitListExpr *Syntactic) { assert(Syntactic->getNumInits() == 1 && "Can only rewrap trivial init lists."); Step S; S.Kind = SK_UnwrapInitList; S.Type = Syntactic->getInit(0)->getType(); Steps.insert(Steps.begin(), S); S.Kind = SK_RewrapInitList; S.Type = T; S.WrappingSyntacticList = Syntactic; Steps.push_back(S); } void InitializationSequence::SetOverloadFailure(FailureKind Failure, OverloadingResult Result) { setSequenceKind(FailedSequence); this->Failure = Failure; this->FailedOverloadResult = Result; } //===----------------------------------------------------------------------===// // Attempt initialization //===----------------------------------------------------------------------===// /// Tries to add a zero initializer. Returns true if that worked. static bool maybeRecoverWithZeroInitialization(Sema &S, InitializationSequence &Sequence, const InitializedEntity &Entity) { if (Entity.getKind() != InitializedEntity::EK_Variable) return false; VarDecl *VD = cast(Entity.getDecl()); if (VD->getInit() || VD->getLocEnd().isMacroID()) return false; QualType VariableTy = VD->getType().getCanonicalType(); SourceLocation Loc = S.getLocForEndOfToken(VD->getLocEnd()); std::string Init = S.getFixItZeroInitializerForType(VariableTy, Loc); if (!Init.empty()) { Sequence.AddZeroInitializationStep(Entity.getType()); Sequence.SetZeroInitializationFixit(Init, Loc); return true; } return false; } static void MaybeProduceObjCObject(Sema &S, InitializationSequence &Sequence, const InitializedEntity &Entity) { if (!S.getLangOpts().ObjCAutoRefCount) return; /// When initializing a parameter, produce the value if it's marked /// __attribute__((ns_consumed)). if (Entity.isParameterKind()) { if (!Entity.isParameterConsumed()) return; assert(Entity.getType()->isObjCRetainableType() && "consuming an object of unretainable type?"); Sequence.AddProduceObjCObjectStep(Entity.getType()); /// When initializing a return value, if the return type is a /// retainable type, then returns need to immediately retain the /// object. If an autorelease is required, it will be done at the /// last instant. } else if (Entity.getKind() == InitializedEntity::EK_Result || Entity.getKind() == InitializedEntity::EK_StmtExprResult) { if (!Entity.getType()->isObjCRetainableType()) return; Sequence.AddProduceObjCObjectStep(Entity.getType()); } } static void TryListInitialization(Sema &S, const InitializedEntity &Entity, const InitializationKind &Kind, InitListExpr *InitList, InitializationSequence &Sequence, bool TreatUnavailableAsInvalid); /// When initializing from init list via constructor, handle /// initialization of an object of type std::initializer_list. /// /// \return true if we have handled initialization of an object of type /// std::initializer_list, false otherwise. static bool TryInitializerListConstruction(Sema &S, InitListExpr *List, QualType DestType, InitializationSequence &Sequence, bool TreatUnavailableAsInvalid) { QualType E; if (!S.isStdInitializerList(DestType, &E)) return false; if (!S.isCompleteType(List->getExprLoc(), E)) { Sequence.setIncompleteTypeFailure(E); return true; } // Try initializing a temporary array from the init list. QualType ArrayType = S.Context.getConstantArrayType( E.withConst(), llvm::APInt(S.Context.getTypeSize(S.Context.getSizeType()), List->getNumInits()), clang::ArrayType::Normal, 0); InitializedEntity HiddenArray = InitializedEntity::InitializeTemporary(ArrayType); InitializationKind Kind = InitializationKind::CreateDirectList( List->getExprLoc(), List->getLocStart(), List->getLocEnd()); TryListInitialization(S, HiddenArray, Kind, List, Sequence, TreatUnavailableAsInvalid); if (Sequence) Sequence.AddStdInitializerListConstructionStep(DestType); return true; } /// Determine if the constructor has the signature of a copy or move /// constructor for the type T of the class in which it was found. That is, /// determine if its first parameter is of type T or reference to (possibly /// cv-qualified) T. static bool hasCopyOrMoveCtorParam(ASTContext &Ctx, const ConstructorInfo &Info) { if (Info.Constructor->getNumParams() == 0) return false; QualType ParmT = Info.Constructor->getParamDecl(0)->getType().getNonReferenceType(); QualType ClassT = Ctx.getRecordType(cast(Info.FoundDecl->getDeclContext())); return Ctx.hasSameUnqualifiedType(ParmT, ClassT); } static OverloadingResult ResolveConstructorOverload(Sema &S, SourceLocation DeclLoc, MultiExprArg Args, OverloadCandidateSet &CandidateSet, QualType DestType, DeclContext::lookup_result Ctors, OverloadCandidateSet::iterator &Best, bool CopyInitializing, bool AllowExplicit, bool OnlyListConstructors, bool IsListInit, bool SecondStepOfCopyInit = false) { CandidateSet.clear(OverloadCandidateSet::CSK_InitByConstructor); for (NamedDecl *D : Ctors) { auto Info = getConstructorInfo(D); if (!Info.Constructor || Info.Constructor->isInvalidDecl()) continue; if (!AllowExplicit && Info.Constructor->isExplicit()) continue; if (OnlyListConstructors && !S.isInitListConstructor(Info.Constructor)) continue; // C++11 [over.best.ics]p4: // ... and the constructor or user-defined conversion function is a // candidate by // - 13.3.1.3, when the argument is the temporary in the second step // of a class copy-initialization, or // - 13.3.1.4, 13.3.1.5, or 13.3.1.6 (in all cases), [not handled here] // - the second phase of 13.3.1.7 when the initializer list has exactly // one element that is itself an initializer list, and the target is // the first parameter of a constructor of class X, and the conversion // is to X or reference to (possibly cv-qualified X), // user-defined conversion sequences are not considered. bool SuppressUserConversions = SecondStepOfCopyInit || (IsListInit && Args.size() == 1 && isa(Args[0]) && hasCopyOrMoveCtorParam(S.Context, Info)); if (Info.ConstructorTmpl) S.AddTemplateOverloadCandidate(Info.ConstructorTmpl, Info.FoundDecl, /*ExplicitArgs*/ nullptr, Args, CandidateSet, SuppressUserConversions); else { // C++ [over.match.copy]p1: // - When initializing a temporary to be bound to the first parameter // of a constructor [for type T] that takes a reference to possibly // cv-qualified T as its first argument, called with a single // argument in the context of direct-initialization, explicit // conversion functions are also considered. // FIXME: What if a constructor template instantiates to such a signature? bool AllowExplicitConv = AllowExplicit && !CopyInitializing && Args.size() == 1 && hasCopyOrMoveCtorParam(S.Context, Info); S.AddOverloadCandidate(Info.Constructor, Info.FoundDecl, Args, CandidateSet, SuppressUserConversions, /*PartialOverloading=*/false, /*AllowExplicit=*/AllowExplicitConv); } } // FIXME: Work around a bug in C++17 guaranteed copy elision. // // When initializing an object of class type T by constructor // ([over.match.ctor]) or by list-initialization ([over.match.list]) // from a single expression of class type U, conversion functions of // U that convert to the non-reference type cv T are candidates. // Explicit conversion functions are only candidates during // direct-initialization. // // Note: SecondStepOfCopyInit is only ever true in this case when // evaluating whether to produce a C++98 compatibility warning. if (S.getLangOpts().CPlusPlus17 && Args.size() == 1 && !SecondStepOfCopyInit) { Expr *Initializer = Args[0]; auto *SourceRD = Initializer->getType()->getAsCXXRecordDecl(); if (SourceRD && S.isCompleteType(DeclLoc, Initializer->getType())) { const auto &Conversions = SourceRD->getVisibleConversionFunctions(); for (auto I = Conversions.begin(), E = Conversions.end(); I != E; ++I) { NamedDecl *D = *I; CXXRecordDecl *ActingDC = cast(D->getDeclContext()); D = D->getUnderlyingDecl(); FunctionTemplateDecl *ConvTemplate = dyn_cast(D); CXXConversionDecl *Conv; if (ConvTemplate) Conv = cast(ConvTemplate->getTemplatedDecl()); else Conv = cast(D); if ((AllowExplicit && !CopyInitializing) || !Conv->isExplicit()) { if (ConvTemplate) S.AddTemplateConversionCandidate(ConvTemplate, I.getPair(), ActingDC, Initializer, DestType, CandidateSet, AllowExplicit, /*AllowResultConversion*/false); else S.AddConversionCandidate(Conv, I.getPair(), ActingDC, Initializer, DestType, CandidateSet, AllowExplicit, /*AllowResultConversion*/false); } } } } // Perform overload resolution and return the result. return CandidateSet.BestViableFunction(S, DeclLoc, Best); } /// Attempt initialization by constructor (C++ [dcl.init]), which /// enumerates the constructors of the initialized entity and performs overload /// resolution to select the best. /// \param DestType The destination class type. /// \param DestArrayType The destination type, which is either DestType or /// a (possibly multidimensional) array of DestType. /// \param IsListInit Is this list-initialization? /// \param IsInitListCopy Is this non-list-initialization resulting from a /// list-initialization from {x} where x is the same /// type as the entity? static void TryConstructorInitialization(Sema &S, const InitializedEntity &Entity, const InitializationKind &Kind, MultiExprArg Args, QualType DestType, QualType DestArrayType, InitializationSequence &Sequence, bool IsListInit = false, bool IsInitListCopy = false) { assert(((!IsListInit && !IsInitListCopy) || (Args.size() == 1 && isa(Args[0]))) && "IsListInit/IsInitListCopy must come with a single initializer list " "argument."); InitListExpr *ILE = (IsListInit || IsInitListCopy) ? cast(Args[0]) : nullptr; MultiExprArg UnwrappedArgs = ILE ? MultiExprArg(ILE->getInits(), ILE->getNumInits()) : Args; // The type we're constructing needs to be complete. if (!S.isCompleteType(Kind.getLocation(), DestType)) { Sequence.setIncompleteTypeFailure(DestType); return; } // C++17 [dcl.init]p17: // - If the initializer expression is a prvalue and the cv-unqualified // version of the source type is the same class as the class of the // destination, the initializer expression is used to initialize the // destination object. // Per DR (no number yet), this does not apply when initializing a base // class or delegating to another constructor from a mem-initializer. // ObjC++: Lambda captured by the block in the lambda to block conversion // should avoid copy elision. if (S.getLangOpts().CPlusPlus17 && Entity.getKind() != InitializedEntity::EK_Base && Entity.getKind() != InitializedEntity::EK_Delegating && Entity.getKind() != InitializedEntity::EK_LambdaToBlockConversionBlockElement && UnwrappedArgs.size() == 1 && UnwrappedArgs[0]->isRValue() && S.Context.hasSameUnqualifiedType(UnwrappedArgs[0]->getType(), DestType)) { // Convert qualifications if necessary. Sequence.AddQualificationConversionStep(DestType, VK_RValue); if (ILE) Sequence.RewrapReferenceInitList(DestType, ILE); return; } const RecordType *DestRecordType = DestType->getAs(); assert(DestRecordType && "Constructor initialization requires record type"); CXXRecordDecl *DestRecordDecl = cast(DestRecordType->getDecl()); // Build the candidate set directly in the initialization sequence // structure, so that it will persist if we fail. OverloadCandidateSet &CandidateSet = Sequence.getFailedCandidateSet(); // Determine whether we are allowed to call explicit constructors or // explicit conversion operators. bool AllowExplicit = Kind.AllowExplicit() || IsListInit; bool CopyInitialization = Kind.getKind() == InitializationKind::IK_Copy; // - Otherwise, if T is a class type, constructors are considered. The // applicable constructors are enumerated, and the best one is chosen // through overload resolution. DeclContext::lookup_result Ctors = S.LookupConstructors(DestRecordDecl); OverloadingResult Result = OR_No_Viable_Function; OverloadCandidateSet::iterator Best; bool AsInitializerList = false; // C++11 [over.match.list]p1, per DR1467: // When objects of non-aggregate type T are list-initialized, such that // 8.5.4 [dcl.init.list] specifies that overload resolution is performed // according to the rules in this section, overload resolution selects // the constructor in two phases: // // - Initially, the candidate functions are the initializer-list // constructors of the class T and the argument list consists of the // initializer list as a single argument. if (IsListInit) { AsInitializerList = true; // If the initializer list has no elements and T has a default constructor, // the first phase is omitted. if (!(UnwrappedArgs.empty() && DestRecordDecl->hasDefaultConstructor())) Result = ResolveConstructorOverload(S, Kind.getLocation(), Args, CandidateSet, DestType, Ctors, Best, CopyInitialization, AllowExplicit, /*OnlyListConstructor=*/true, IsListInit); } // C++11 [over.match.list]p1: // - If no viable initializer-list constructor is found, overload resolution // is performed again, where the candidate functions are all the // constructors of the class T and the argument list consists of the // elements of the initializer list. if (Result == OR_No_Viable_Function) { AsInitializerList = false; Result = ResolveConstructorOverload(S, Kind.getLocation(), UnwrappedArgs, CandidateSet, DestType, Ctors, Best, CopyInitialization, AllowExplicit, /*OnlyListConstructors=*/false, IsListInit); } if (Result) { Sequence.SetOverloadFailure(IsListInit ? InitializationSequence::FK_ListConstructorOverloadFailed : InitializationSequence::FK_ConstructorOverloadFailed, Result); return; } bool HadMultipleCandidates = (CandidateSet.size() > 1); // In C++17, ResolveConstructorOverload can select a conversion function // instead of a constructor. if (auto *CD = dyn_cast(Best->Function)) { // Add the user-defined conversion step that calls the conversion function. QualType ConvType = CD->getConversionType(); assert(S.Context.hasSameUnqualifiedType(ConvType, DestType) && "should not have selected this conversion function"); Sequence.AddUserConversionStep(CD, Best->FoundDecl, ConvType, HadMultipleCandidates); if (!S.Context.hasSameType(ConvType, DestType)) Sequence.AddQualificationConversionStep(DestType, VK_RValue); if (IsListInit) Sequence.RewrapReferenceInitList(Entity.getType(), ILE); return; } // C++11 [dcl.init]p6: // If a program calls for the default initialization of an object // of a const-qualified type T, T shall be a class type with a // user-provided default constructor. // C++ core issue 253 proposal: // If the implicit default constructor initializes all subobjects, no // initializer should be required. // The 253 proposal is for example needed to process libstdc++ headers in 5.x. CXXConstructorDecl *CtorDecl = cast(Best->Function); if (Kind.getKind() == InitializationKind::IK_Default && Entity.getType().isConstQualified()) { if (!CtorDecl->getParent()->allowConstDefaultInit()) { if (!maybeRecoverWithZeroInitialization(S, Sequence, Entity)) Sequence.SetFailed(InitializationSequence::FK_DefaultInitOfConst); return; } } // C++11 [over.match.list]p1: // In copy-list-initialization, if an explicit constructor is chosen, the // initializer is ill-formed. if (IsListInit && !Kind.AllowExplicit() && CtorDecl->isExplicit()) { Sequence.SetFailed(InitializationSequence::FK_ExplicitConstructor); return; } // Add the constructor initialization step. Any cv-qualification conversion is // subsumed by the initialization. Sequence.AddConstructorInitializationStep( Best->FoundDecl, CtorDecl, DestArrayType, HadMultipleCandidates, IsListInit | IsInitListCopy, AsInitializerList); } static bool ResolveOverloadedFunctionForReferenceBinding(Sema &S, Expr *Initializer, QualType &SourceType, QualType &UnqualifiedSourceType, QualType UnqualifiedTargetType, InitializationSequence &Sequence) { if (S.Context.getCanonicalType(UnqualifiedSourceType) == S.Context.OverloadTy) { DeclAccessPair Found; bool HadMultipleCandidates = false; if (FunctionDecl *Fn = S.ResolveAddressOfOverloadedFunction(Initializer, UnqualifiedTargetType, false, Found, &HadMultipleCandidates)) { Sequence.AddAddressOverloadResolutionStep(Fn, Found, HadMultipleCandidates); SourceType = Fn->getType(); UnqualifiedSourceType = SourceType.getUnqualifiedType(); } else if (!UnqualifiedTargetType->isRecordType()) { Sequence.SetFailed(InitializationSequence::FK_AddressOfOverloadFailed); return true; } } return false; } static void TryReferenceInitializationCore(Sema &S, const InitializedEntity &Entity, const InitializationKind &Kind, Expr *Initializer, QualType cv1T1, QualType T1, Qualifiers T1Quals, QualType cv2T2, QualType T2, Qualifiers T2Quals, InitializationSequence &Sequence); static void TryValueInitialization(Sema &S, const InitializedEntity &Entity, const InitializationKind &Kind, InitializationSequence &Sequence, InitListExpr *InitList = nullptr); /// Attempt list initialization of a reference. static void TryReferenceListInitialization(Sema &S, const InitializedEntity &Entity, const InitializationKind &Kind, InitListExpr *InitList, InitializationSequence &Sequence, bool TreatUnavailableAsInvalid) { // First, catch C++03 where this isn't possible. if (!S.getLangOpts().CPlusPlus11) { Sequence.SetFailed(InitializationSequence::FK_ReferenceBindingToInitList); return; } // Can't reference initialize a compound literal. if (Entity.getKind() == InitializedEntity::EK_CompoundLiteralInit) { Sequence.SetFailed(InitializationSequence::FK_ReferenceBindingToInitList); return; } QualType DestType = Entity.getType(); QualType cv1T1 = DestType->getAs()->getPointeeType(); Qualifiers T1Quals; QualType T1 = S.Context.getUnqualifiedArrayType(cv1T1, T1Quals); // Reference initialization via an initializer list works thus: // If the initializer list consists of a single element that is // reference-related to the referenced type, bind directly to that element // (possibly creating temporaries). // Otherwise, initialize a temporary with the initializer list and // bind to that. if (InitList->getNumInits() == 1) { Expr *Initializer = InitList->getInit(0); QualType cv2T2 = Initializer->getType(); Qualifiers T2Quals; QualType T2 = S.Context.getUnqualifiedArrayType(cv2T2, T2Quals); // If this fails, creating a temporary wouldn't work either. if (ResolveOverloadedFunctionForReferenceBinding(S, Initializer, cv2T2, T2, T1, Sequence)) return; SourceLocation DeclLoc = Initializer->getLocStart(); bool dummy1, dummy2, dummy3; Sema::ReferenceCompareResult RefRelationship = S.CompareReferenceRelationship(DeclLoc, cv1T1, cv2T2, dummy1, dummy2, dummy3); if (RefRelationship >= Sema::Ref_Related) { // Try to bind the reference here. TryReferenceInitializationCore(S, Entity, Kind, Initializer, cv1T1, T1, T1Quals, cv2T2, T2, T2Quals, Sequence); if (Sequence) Sequence.RewrapReferenceInitList(cv1T1, InitList); return; } // Update the initializer if we've resolved an overloaded function. if (Sequence.step_begin() != Sequence.step_end()) Sequence.RewrapReferenceInitList(cv1T1, InitList); } // Not reference-related. Create a temporary and bind to that. InitializedEntity TempEntity = InitializedEntity::InitializeTemporary(cv1T1); TryListInitialization(S, TempEntity, Kind, InitList, Sequence, TreatUnavailableAsInvalid); if (Sequence) { if (DestType->isRValueReferenceType() || (T1Quals.hasConst() && !T1Quals.hasVolatile())) Sequence.AddReferenceBindingStep(cv1T1, /*bindingTemporary=*/true); else Sequence.SetFailed( InitializationSequence::FK_NonConstLValueReferenceBindingToTemporary); } } /// Attempt list initialization (C++0x [dcl.init.list]) static void TryListInitialization(Sema &S, const InitializedEntity &Entity, const InitializationKind &Kind, InitListExpr *InitList, InitializationSequence &Sequence, bool TreatUnavailableAsInvalid) { QualType DestType = Entity.getType(); // C++ doesn't allow scalar initialization with more than one argument. // But C99 complex numbers are scalars and it makes sense there. if (S.getLangOpts().CPlusPlus && DestType->isScalarType() && !DestType->isAnyComplexType() && InitList->getNumInits() > 1) { Sequence.SetFailed(InitializationSequence::FK_TooManyInitsForScalar); return; } if (DestType->isReferenceType()) { TryReferenceListInitialization(S, Entity, Kind, InitList, Sequence, TreatUnavailableAsInvalid); return; } if (DestType->isRecordType() && !S.isCompleteType(InitList->getLocStart(), DestType)) { Sequence.setIncompleteTypeFailure(DestType); return; } // C++11 [dcl.init.list]p3, per DR1467: // - If T is a class type and the initializer list has a single element of // type cv U, where U is T or a class derived from T, the object is // initialized from that element (by copy-initialization for // copy-list-initialization, or by direct-initialization for // direct-list-initialization). // - Otherwise, if T is a character array and the initializer list has a // single element that is an appropriately-typed string literal // (8.5.2 [dcl.init.string]), initialization is performed as described // in that section. // - Otherwise, if T is an aggregate, [...] (continue below). if (S.getLangOpts().CPlusPlus11 && InitList->getNumInits() == 1) { if (DestType->isRecordType()) { QualType InitType = InitList->getInit(0)->getType(); if (S.Context.hasSameUnqualifiedType(InitType, DestType) || S.IsDerivedFrom(InitList->getLocStart(), InitType, DestType)) { Expr *InitListAsExpr = InitList; TryConstructorInitialization(S, Entity, Kind, InitListAsExpr, DestType, DestType, Sequence, /*InitListSyntax*/false, /*IsInitListCopy*/true); return; } } if (const ArrayType *DestAT = S.Context.getAsArrayType(DestType)) { Expr *SubInit[1] = {InitList->getInit(0)}; if (!isa(DestAT) && IsStringInit(SubInit[0], DestAT, S.Context) == SIF_None) { InitializationKind SubKind = Kind.getKind() == InitializationKind::IK_DirectList ? InitializationKind::CreateDirect(Kind.getLocation(), InitList->getLBraceLoc(), InitList->getRBraceLoc()) : Kind; Sequence.InitializeFrom(S, Entity, SubKind, SubInit, /*TopLevelOfInitList*/ true, TreatUnavailableAsInvalid); // TryStringLiteralInitialization() (in InitializeFrom()) will fail if // the element is not an appropriately-typed string literal, in which // case we should proceed as in C++11 (below). if (Sequence) { Sequence.RewrapReferenceInitList(Entity.getType(), InitList); return; } } } } // C++11 [dcl.init.list]p3: // - If T is an aggregate, aggregate initialization is performed. if ((DestType->isRecordType() && !DestType->isAggregateType()) || (S.getLangOpts().CPlusPlus11 && S.isStdInitializerList(DestType, nullptr))) { if (S.getLangOpts().CPlusPlus11) { // - Otherwise, if the initializer list has no elements and T is a // class type with a default constructor, the object is // value-initialized. if (InitList->getNumInits() == 0) { CXXRecordDecl *RD = DestType->getAsCXXRecordDecl(); if (RD->hasDefaultConstructor()) { TryValueInitialization(S, Entity, Kind, Sequence, InitList); return; } } // - Otherwise, if T is a specialization of std::initializer_list, // an initializer_list object constructed [...] if (TryInitializerListConstruction(S, InitList, DestType, Sequence, TreatUnavailableAsInvalid)) return; // - Otherwise, if T is a class type, constructors are considered. Expr *InitListAsExpr = InitList; TryConstructorInitialization(S, Entity, Kind, InitListAsExpr, DestType, DestType, Sequence, /*InitListSyntax*/true); } else Sequence.SetFailed(InitializationSequence::FK_InitListBadDestinationType); return; } if (S.getLangOpts().CPlusPlus && !DestType->isAggregateType() && InitList->getNumInits() == 1) { Expr *E = InitList->getInit(0); // - Otherwise, if T is an enumeration with a fixed underlying type, // the initializer-list has a single element v, and the initialization // is direct-list-initialization, the object is initialized with the // value T(v); if a narrowing conversion is required to convert v to // the underlying type of T, the program is ill-formed. auto *ET = DestType->getAs(); if (S.getLangOpts().CPlusPlus17 && Kind.getKind() == InitializationKind::IK_DirectList && ET && ET->getDecl()->isFixed() && !S.Context.hasSameUnqualifiedType(E->getType(), DestType) && (E->getType()->isIntegralOrEnumerationType() || E->getType()->isFloatingType())) { // There are two ways that T(v) can work when T is an enumeration type. // If there is either an implicit conversion sequence from v to T or // a conversion function that can convert from v to T, then we use that. // Otherwise, if v is of integral, enumeration, or floating-point type, // it is converted to the enumeration type via its underlying type. // There is no overlap possible between these two cases (except when the // source value is already of the destination type), and the first // case is handled by the general case for single-element lists below. ImplicitConversionSequence ICS; ICS.setStandard(); ICS.Standard.setAsIdentityConversion(); if (!E->isRValue()) ICS.Standard.First = ICK_Lvalue_To_Rvalue; // If E is of a floating-point type, then the conversion is ill-formed // due to narrowing, but go through the motions in order to produce the // right diagnostic. ICS.Standard.Second = E->getType()->isFloatingType() ? ICK_Floating_Integral : ICK_Integral_Conversion; ICS.Standard.setFromType(E->getType()); ICS.Standard.setToType(0, E->getType()); ICS.Standard.setToType(1, DestType); ICS.Standard.setToType(2, DestType); Sequence.AddConversionSequenceStep(ICS, ICS.Standard.getToType(2), /*TopLevelOfInitList*/true); Sequence.RewrapReferenceInitList(Entity.getType(), InitList); return; } // - Otherwise, if the initializer list has a single element of type E // [...references are handled above...], the object or reference is // initialized from that element (by copy-initialization for // copy-list-initialization, or by direct-initialization for // direct-list-initialization); if a narrowing conversion is required // to convert the element to T, the program is ill-formed. // // Per core-24034, this is direct-initialization if we were performing // direct-list-initialization and copy-initialization otherwise. // We can't use InitListChecker for this, because it always performs // copy-initialization. This only matters if we might use an 'explicit' // conversion operator, so we only need to handle the cases where the source // is of record type. if (InitList->getInit(0)->getType()->isRecordType()) { InitializationKind SubKind = Kind.getKind() == InitializationKind::IK_DirectList ? InitializationKind::CreateDirect(Kind.getLocation(), InitList->getLBraceLoc(), InitList->getRBraceLoc()) : Kind; Expr *SubInit[1] = { InitList->getInit(0) }; Sequence.InitializeFrom(S, Entity, SubKind, SubInit, /*TopLevelOfInitList*/true, TreatUnavailableAsInvalid); if (Sequence) Sequence.RewrapReferenceInitList(Entity.getType(), InitList); return; } } InitListChecker CheckInitList(S, Entity, InitList, DestType, /*VerifyOnly=*/true, TreatUnavailableAsInvalid); if (CheckInitList.HadError()) { Sequence.SetFailed(InitializationSequence::FK_ListInitializationFailed); return; } // Add the list initialization step with the built init list. Sequence.AddListInitializationStep(DestType); } /// Try a reference initialization that involves calling a conversion /// function. static OverloadingResult TryRefInitWithConversionFunction( Sema &S, const InitializedEntity &Entity, const InitializationKind &Kind, Expr *Initializer, bool AllowRValues, bool IsLValueRef, InitializationSequence &Sequence) { QualType DestType = Entity.getType(); QualType cv1T1 = DestType->getAs()->getPointeeType(); QualType T1 = cv1T1.getUnqualifiedType(); QualType cv2T2 = Initializer->getType(); QualType T2 = cv2T2.getUnqualifiedType(); bool DerivedToBase; bool ObjCConversion; bool ObjCLifetimeConversion; assert(!S.CompareReferenceRelationship(Initializer->getLocStart(), T1, T2, DerivedToBase, ObjCConversion, ObjCLifetimeConversion) && "Must have incompatible references when binding via conversion"); (void)DerivedToBase; (void)ObjCConversion; (void)ObjCLifetimeConversion; // Build the candidate set directly in the initialization sequence // structure, so that it will persist if we fail. OverloadCandidateSet &CandidateSet = Sequence.getFailedCandidateSet(); CandidateSet.clear(OverloadCandidateSet::CSK_InitByUserDefinedConversion); // Determine whether we are allowed to call explicit conversion operators. // Note that none of [over.match.copy], [over.match.conv], nor // [over.match.ref] permit an explicit constructor to be chosen when // initializing a reference, not even for direct-initialization. bool AllowExplicitCtors = false; bool AllowExplicitConvs = Kind.allowExplicitConversionFunctionsInRefBinding(); const RecordType *T1RecordType = nullptr; if (AllowRValues && (T1RecordType = T1->getAs()) && S.isCompleteType(Kind.getLocation(), T1)) { // The type we're converting to is a class type. Enumerate its constructors // to see if there is a suitable conversion. CXXRecordDecl *T1RecordDecl = cast(T1RecordType->getDecl()); for (NamedDecl *D : S.LookupConstructors(T1RecordDecl)) { auto Info = getConstructorInfo(D); if (!Info.Constructor) continue; if (!Info.Constructor->isInvalidDecl() && Info.Constructor->isConvertingConstructor(AllowExplicitCtors)) { if (Info.ConstructorTmpl) S.AddTemplateOverloadCandidate(Info.ConstructorTmpl, Info.FoundDecl, /*ExplicitArgs*/ nullptr, Initializer, CandidateSet, /*SuppressUserConversions=*/true); else S.AddOverloadCandidate(Info.Constructor, Info.FoundDecl, Initializer, CandidateSet, /*SuppressUserConversions=*/true); } } } if (T1RecordType && T1RecordType->getDecl()->isInvalidDecl()) return OR_No_Viable_Function; const RecordType *T2RecordType = nullptr; if ((T2RecordType = T2->getAs()) && S.isCompleteType(Kind.getLocation(), T2)) { // The type we're converting from is a class type, enumerate its conversion // functions. CXXRecordDecl *T2RecordDecl = cast(T2RecordType->getDecl()); const auto &Conversions = T2RecordDecl->getVisibleConversionFunctions(); for (auto I = Conversions.begin(), E = Conversions.end(); I != E; ++I) { NamedDecl *D = *I; CXXRecordDecl *ActingDC = cast(D->getDeclContext()); if (isa(D)) D = cast(D)->getTargetDecl(); FunctionTemplateDecl *ConvTemplate = dyn_cast(D); CXXConversionDecl *Conv; if (ConvTemplate) Conv = cast(ConvTemplate->getTemplatedDecl()); else Conv = cast(D); // If the conversion function doesn't return a reference type, // it can't be considered for this conversion unless we're allowed to // consider rvalues. // FIXME: Do we need to make sure that we only consider conversion // candidates with reference-compatible results? That might be needed to // break recursion. if ((AllowExplicitConvs || !Conv->isExplicit()) && (AllowRValues || Conv->getConversionType()->isLValueReferenceType())){ if (ConvTemplate) S.AddTemplateConversionCandidate(ConvTemplate, I.getPair(), ActingDC, Initializer, DestType, CandidateSet, /*AllowObjCConversionOnExplicit=*/ false); else S.AddConversionCandidate(Conv, I.getPair(), ActingDC, Initializer, DestType, CandidateSet, /*AllowObjCConversionOnExplicit=*/false); } } } if (T2RecordType && T2RecordType->getDecl()->isInvalidDecl()) return OR_No_Viable_Function; SourceLocation DeclLoc = Initializer->getLocStart(); // Perform overload resolution. If it fails, return the failed result. OverloadCandidateSet::iterator Best; if (OverloadingResult Result = CandidateSet.BestViableFunction(S, DeclLoc, Best)) return Result; FunctionDecl *Function = Best->Function; // This is the overload that will be used for this initialization step if we // use this initialization. Mark it as referenced. Function->setReferenced(); // Compute the returned type and value kind of the conversion. QualType cv3T3; if (isa(Function)) cv3T3 = Function->getReturnType(); else cv3T3 = T1; ExprValueKind VK = VK_RValue; if (cv3T3->isLValueReferenceType()) VK = VK_LValue; else if (const auto *RRef = cv3T3->getAs()) VK = RRef->getPointeeType()->isFunctionType() ? VK_LValue : VK_XValue; cv3T3 = cv3T3.getNonLValueExprType(S.Context); // Add the user-defined conversion step. bool HadMultipleCandidates = (CandidateSet.size() > 1); Sequence.AddUserConversionStep(Function, Best->FoundDecl, cv3T3, HadMultipleCandidates); // Determine whether we'll need to perform derived-to-base adjustments or // other conversions. bool NewDerivedToBase = false; bool NewObjCConversion = false; bool NewObjCLifetimeConversion = false; Sema::ReferenceCompareResult NewRefRelationship = S.CompareReferenceRelationship(DeclLoc, T1, cv3T3, NewDerivedToBase, NewObjCConversion, NewObjCLifetimeConversion); // Add the final conversion sequence, if necessary. if (NewRefRelationship == Sema::Ref_Incompatible) { assert(!isa(Function) && "should not have conversion after constructor"); ImplicitConversionSequence ICS; ICS.setStandard(); ICS.Standard = Best->FinalConversion; Sequence.AddConversionSequenceStep(ICS, ICS.Standard.getToType(2)); // Every implicit conversion results in a prvalue, except for a glvalue // derived-to-base conversion, which we handle below. cv3T3 = ICS.Standard.getToType(2); VK = VK_RValue; } // If the converted initializer is a prvalue, its type T4 is adjusted to // type "cv1 T4" and the temporary materialization conversion is applied. // // We adjust the cv-qualifications to match the reference regardless of // whether we have a prvalue so that the AST records the change. In this // case, T4 is "cv3 T3". QualType cv1T4 = S.Context.getQualifiedType(cv3T3, cv1T1.getQualifiers()); if (cv1T4.getQualifiers() != cv3T3.getQualifiers()) Sequence.AddQualificationConversionStep(cv1T4, VK); Sequence.AddReferenceBindingStep(cv1T4, VK == VK_RValue); VK = IsLValueRef ? VK_LValue : VK_XValue; if (NewDerivedToBase) Sequence.AddDerivedToBaseCastStep(cv1T1, VK); else if (NewObjCConversion) Sequence.AddObjCObjectConversionStep(cv1T1); return OR_Success; } static void CheckCXX98CompatAccessibleCopy(Sema &S, const InitializedEntity &Entity, Expr *CurInitExpr); /// Attempt reference initialization (C++0x [dcl.init.ref]) static void TryReferenceInitialization(Sema &S, const InitializedEntity &Entity, const InitializationKind &Kind, Expr *Initializer, InitializationSequence &Sequence) { QualType DestType = Entity.getType(); QualType cv1T1 = DestType->getAs()->getPointeeType(); Qualifiers T1Quals; QualType T1 = S.Context.getUnqualifiedArrayType(cv1T1, T1Quals); QualType cv2T2 = Initializer->getType(); Qualifiers T2Quals; QualType T2 = S.Context.getUnqualifiedArrayType(cv2T2, T2Quals); // If the initializer is the address of an overloaded function, try // to resolve the overloaded function. If all goes well, T2 is the // type of the resulting function. if (ResolveOverloadedFunctionForReferenceBinding(S, Initializer, cv2T2, T2, T1, Sequence)) return; // Delegate everything else to a subfunction. TryReferenceInitializationCore(S, Entity, Kind, Initializer, cv1T1, T1, T1Quals, cv2T2, T2, T2Quals, Sequence); } /// Determine whether an expression is a non-referenceable glvalue (one to /// which a reference can never bind). Attempting to bind a reference to /// such a glvalue will always create a temporary. static bool isNonReferenceableGLValue(Expr *E) { return E->refersToBitField() || E->refersToVectorElement(); } /// Reference initialization without resolving overloaded functions. static void TryReferenceInitializationCore(Sema &S, const InitializedEntity &Entity, const InitializationKind &Kind, Expr *Initializer, QualType cv1T1, QualType T1, Qualifiers T1Quals, QualType cv2T2, QualType T2, Qualifiers T2Quals, InitializationSequence &Sequence) { QualType DestType = Entity.getType(); SourceLocation DeclLoc = Initializer->getLocStart(); // Compute some basic properties of the types and the initializer. bool isLValueRef = DestType->isLValueReferenceType(); bool isRValueRef = !isLValueRef; bool DerivedToBase = false; bool ObjCConversion = false; bool ObjCLifetimeConversion = false; Expr::Classification InitCategory = Initializer->Classify(S.Context); Sema::ReferenceCompareResult RefRelationship = S.CompareReferenceRelationship(DeclLoc, cv1T1, cv2T2, DerivedToBase, ObjCConversion, ObjCLifetimeConversion); // C++0x [dcl.init.ref]p5: // A reference to type "cv1 T1" is initialized by an expression of type // "cv2 T2" as follows: // // - If the reference is an lvalue reference and the initializer // expression // Note the analogous bullet points for rvalue refs to functions. Because // there are no function rvalues in C++, rvalue refs to functions are treated // like lvalue refs. OverloadingResult ConvOvlResult = OR_Success; bool T1Function = T1->isFunctionType(); if (isLValueRef || T1Function) { if (InitCategory.isLValue() && !isNonReferenceableGLValue(Initializer) && (RefRelationship == Sema::Ref_Compatible || (Kind.isCStyleOrFunctionalCast() && RefRelationship == Sema::Ref_Related))) { // - is an lvalue (but is not a bit-field), and "cv1 T1" is // reference-compatible with "cv2 T2," or if (T1Quals != T2Quals) // Convert to cv1 T2. This should only add qualifiers unless this is a // c-style cast. The removal of qualifiers in that case notionally // happens after the reference binding, but that doesn't matter. Sequence.AddQualificationConversionStep( S.Context.getQualifiedType(T2, T1Quals), Initializer->getValueKind()); if (DerivedToBase) Sequence.AddDerivedToBaseCastStep(cv1T1, VK_LValue); else if (ObjCConversion) Sequence.AddObjCObjectConversionStep(cv1T1); // We only create a temporary here when binding a reference to a // bit-field or vector element. Those cases are't supposed to be // handled by this bullet, but the outcome is the same either way. Sequence.AddReferenceBindingStep(cv1T1, false); return; } // - has a class type (i.e., T2 is a class type), where T1 is not // reference-related to T2, and can be implicitly converted to an // lvalue of type "cv3 T3," where "cv1 T1" is reference-compatible // with "cv3 T3" (this conversion is selected by enumerating the // applicable conversion functions (13.3.1.6) and choosing the best // one through overload resolution (13.3)), // If we have an rvalue ref to function type here, the rhs must be // an rvalue. DR1287 removed the "implicitly" here. if (RefRelationship == Sema::Ref_Incompatible && T2->isRecordType() && (isLValueRef || InitCategory.isRValue())) { ConvOvlResult = TryRefInitWithConversionFunction( S, Entity, Kind, Initializer, /*AllowRValues*/ isRValueRef, /*IsLValueRef*/ isLValueRef, Sequence); if (ConvOvlResult == OR_Success) return; if (ConvOvlResult != OR_No_Viable_Function) Sequence.SetOverloadFailure( InitializationSequence::FK_ReferenceInitOverloadFailed, ConvOvlResult); } } // - Otherwise, the reference shall be an lvalue reference to a // non-volatile const type (i.e., cv1 shall be const), or the reference // shall be an rvalue reference. if (isLValueRef && !(T1Quals.hasConst() && !T1Quals.hasVolatile())) { if (S.Context.getCanonicalType(T2) == S.Context.OverloadTy) Sequence.SetFailed(InitializationSequence::FK_AddressOfOverloadFailed); else if (ConvOvlResult && !Sequence.getFailedCandidateSet().empty()) Sequence.SetOverloadFailure( InitializationSequence::FK_ReferenceInitOverloadFailed, ConvOvlResult); else if (!InitCategory.isLValue()) Sequence.SetFailed( InitializationSequence::FK_NonConstLValueReferenceBindingToTemporary); else { InitializationSequence::FailureKind FK; switch (RefRelationship) { case Sema::Ref_Compatible: if (Initializer->refersToBitField()) FK = InitializationSequence:: FK_NonConstLValueReferenceBindingToBitfield; else if (Initializer->refersToVectorElement()) FK = InitializationSequence:: FK_NonConstLValueReferenceBindingToVectorElement; else llvm_unreachable("unexpected kind of compatible initializer"); break; case Sema::Ref_Related: FK = InitializationSequence::FK_ReferenceInitDropsQualifiers; break; case Sema::Ref_Incompatible: FK = InitializationSequence:: FK_NonConstLValueReferenceBindingToUnrelated; break; } Sequence.SetFailed(FK); } return; } // - If the initializer expression // - is an // [<=14] xvalue (but not a bit-field), class prvalue, array prvalue, or // [1z] rvalue (but not a bit-field) or // function lvalue and "cv1 T1" is reference-compatible with "cv2 T2" // // Note: functions are handled above and below rather than here... if (!T1Function && (RefRelationship == Sema::Ref_Compatible || (Kind.isCStyleOrFunctionalCast() && RefRelationship == Sema::Ref_Related)) && ((InitCategory.isXValue() && !isNonReferenceableGLValue(Initializer)) || (InitCategory.isPRValue() && (S.getLangOpts().CPlusPlus17 || T2->isRecordType() || T2->isArrayType())))) { ExprValueKind ValueKind = InitCategory.isXValue() ? VK_XValue : VK_RValue; if (InitCategory.isPRValue() && T2->isRecordType()) { // The corresponding bullet in C++03 [dcl.init.ref]p5 gives the // compiler the freedom to perform a copy here or bind to the // object, while C++0x requires that we bind directly to the // object. Hence, we always bind to the object without making an // extra copy. However, in C++03 requires that we check for the // presence of a suitable copy constructor: // // The constructor that would be used to make the copy shall // be callable whether or not the copy is actually done. if (!S.getLangOpts().CPlusPlus11 && !S.getLangOpts().MicrosoftExt) Sequence.AddExtraneousCopyToTemporary(cv2T2); else if (S.getLangOpts().CPlusPlus11) CheckCXX98CompatAccessibleCopy(S, Entity, Initializer); } // C++1z [dcl.init.ref]/5.2.1.2: // If the converted initializer is a prvalue, its type T4 is adjusted // to type "cv1 T4" and the temporary materialization conversion is // applied. QualType cv1T4 = S.Context.getQualifiedType(cv2T2, T1Quals); if (T1Quals != T2Quals) Sequence.AddQualificationConversionStep(cv1T4, ValueKind); Sequence.AddReferenceBindingStep(cv1T4, ValueKind == VK_RValue); ValueKind = isLValueRef ? VK_LValue : VK_XValue; // In any case, the reference is bound to the resulting glvalue (or to // an appropriate base class subobject). if (DerivedToBase) Sequence.AddDerivedToBaseCastStep(cv1T1, ValueKind); else if (ObjCConversion) Sequence.AddObjCObjectConversionStep(cv1T1); return; } // - has a class type (i.e., T2 is a class type), where T1 is not // reference-related to T2, and can be implicitly converted to an // xvalue, class prvalue, or function lvalue of type "cv3 T3", // where "cv1 T1" is reference-compatible with "cv3 T3", // // DR1287 removes the "implicitly" here. if (T2->isRecordType()) { if (RefRelationship == Sema::Ref_Incompatible) { ConvOvlResult = TryRefInitWithConversionFunction( S, Entity, Kind, Initializer, /*AllowRValues*/ true, /*IsLValueRef*/ isLValueRef, Sequence); if (ConvOvlResult) Sequence.SetOverloadFailure( InitializationSequence::FK_ReferenceInitOverloadFailed, ConvOvlResult); return; } if (RefRelationship == Sema::Ref_Compatible && isRValueRef && InitCategory.isLValue()) { Sequence.SetFailed( InitializationSequence::FK_RValueReferenceBindingToLValue); return; } Sequence.SetFailed(InitializationSequence::FK_ReferenceInitDropsQualifiers); return; } // - Otherwise, a temporary of type "cv1 T1" is created and initialized // from the initializer expression using the rules for a non-reference // copy-initialization (8.5). The reference is then bound to the // temporary. [...] InitializedEntity TempEntity = InitializedEntity::InitializeTemporary(cv1T1); // FIXME: Why do we use an implicit conversion here rather than trying // copy-initialization? ImplicitConversionSequence ICS = S.TryImplicitConversion(Initializer, TempEntity.getType(), /*SuppressUserConversions=*/false, /*AllowExplicit=*/false, /*FIXME:InOverloadResolution=*/false, /*CStyle=*/Kind.isCStyleOrFunctionalCast(), /*AllowObjCWritebackConversion=*/false); if (ICS.isBad()) { // FIXME: Use the conversion function set stored in ICS to turn // this into an overloading ambiguity diagnostic. However, we need // to keep that set as an OverloadCandidateSet rather than as some // other kind of set. if (ConvOvlResult && !Sequence.getFailedCandidateSet().empty()) Sequence.SetOverloadFailure( InitializationSequence::FK_ReferenceInitOverloadFailed, ConvOvlResult); else if (S.Context.getCanonicalType(T2) == S.Context.OverloadTy) Sequence.SetFailed(InitializationSequence::FK_AddressOfOverloadFailed); else Sequence.SetFailed(InitializationSequence::FK_ReferenceInitFailed); return; } else { Sequence.AddConversionSequenceStep(ICS, TempEntity.getType()); } // [...] If T1 is reference-related to T2, cv1 must be the // same cv-qualification as, or greater cv-qualification // than, cv2; otherwise, the program is ill-formed. unsigned T1CVRQuals = T1Quals.getCVRQualifiers(); unsigned T2CVRQuals = T2Quals.getCVRQualifiers(); if (RefRelationship == Sema::Ref_Related && (T1CVRQuals | T2CVRQuals) != T1CVRQuals) { Sequence.SetFailed(InitializationSequence::FK_ReferenceInitDropsQualifiers); return; } // [...] If T1 is reference-related to T2 and the reference is an rvalue // reference, the initializer expression shall not be an lvalue. if (RefRelationship >= Sema::Ref_Related && !isLValueRef && InitCategory.isLValue()) { Sequence.SetFailed( InitializationSequence::FK_RValueReferenceBindingToLValue); return; } Sequence.AddReferenceBindingStep(cv1T1, /*bindingTemporary=*/true); } /// Attempt character array initialization from a string literal /// (C++ [dcl.init.string], C99 6.7.8). static void TryStringLiteralInitialization(Sema &S, const InitializedEntity &Entity, const InitializationKind &Kind, Expr *Initializer, InitializationSequence &Sequence) { Sequence.AddStringInitStep(Entity.getType()); } /// Attempt value initialization (C++ [dcl.init]p7). static void TryValueInitialization(Sema &S, const InitializedEntity &Entity, const InitializationKind &Kind, InitializationSequence &Sequence, InitListExpr *InitList) { assert((!InitList || InitList->getNumInits() == 0) && "Shouldn't use value-init for non-empty init lists"); // C++98 [dcl.init]p5, C++11 [dcl.init]p7: // // To value-initialize an object of type T means: QualType T = Entity.getType(); // -- if T is an array type, then each element is value-initialized; T = S.Context.getBaseElementType(T); if (const RecordType *RT = T->getAs()) { if (CXXRecordDecl *ClassDecl = dyn_cast(RT->getDecl())) { bool NeedZeroInitialization = true; // C++98: // -- if T is a class type (clause 9) with a user-declared constructor // (12.1), then the default constructor for T is called (and the // initialization is ill-formed if T has no accessible default // constructor); // C++11: // -- if T is a class type (clause 9) with either no default constructor // (12.1 [class.ctor]) or a default constructor that is user-provided // or deleted, then the object is default-initialized; // // Note that the C++11 rule is the same as the C++98 rule if there are no // defaulted or deleted constructors, so we just use it unconditionally. CXXConstructorDecl *CD = S.LookupDefaultConstructor(ClassDecl); if (!CD || !CD->getCanonicalDecl()->isDefaulted() || CD->isDeleted()) NeedZeroInitialization = false; // -- if T is a (possibly cv-qualified) non-union class type without a // user-provided or deleted default constructor, then the object is // zero-initialized and, if T has a non-trivial default constructor, // default-initialized; // The 'non-union' here was removed by DR1502. The 'non-trivial default // constructor' part was removed by DR1507. if (NeedZeroInitialization) Sequence.AddZeroInitializationStep(Entity.getType()); // C++03: // -- if T is a non-union class type without a user-declared constructor, // then every non-static data member and base class component of T is // value-initialized; // [...] A program that calls for [...] value-initialization of an // entity of reference type is ill-formed. // // C++11 doesn't need this handling, because value-initialization does not // occur recursively there, and the implicit default constructor is // defined as deleted in the problematic cases. if (!S.getLangOpts().CPlusPlus11 && ClassDecl->hasUninitializedReferenceMember()) { Sequence.SetFailed(InitializationSequence::FK_TooManyInitsForReference); return; } // If this is list-value-initialization, pass the empty init list on when // building the constructor call. This affects the semantics of a few // things (such as whether an explicit default constructor can be called). Expr *InitListAsExpr = InitList; MultiExprArg Args(&InitListAsExpr, InitList ? 1 : 0); bool InitListSyntax = InitList; // FIXME: Instead of creating a CXXConstructExpr of array type here, // wrap a class-typed CXXConstructExpr in an ArrayInitLoopExpr. return TryConstructorInitialization( S, Entity, Kind, Args, T, Entity.getType(), Sequence, InitListSyntax); } } Sequence.AddZeroInitializationStep(Entity.getType()); } /// Attempt default initialization (C++ [dcl.init]p6). static void TryDefaultInitialization(Sema &S, const InitializedEntity &Entity, const InitializationKind &Kind, InitializationSequence &Sequence) { assert(Kind.getKind() == InitializationKind::IK_Default); // C++ [dcl.init]p6: // To default-initialize an object of type T means: // - if T is an array type, each element is default-initialized; QualType DestType = S.Context.getBaseElementType(Entity.getType()); // - if T is a (possibly cv-qualified) class type (Clause 9), the default // constructor for T is called (and the initialization is ill-formed if // T has no accessible default constructor); if (DestType->isRecordType() && S.getLangOpts().CPlusPlus) { TryConstructorInitialization(S, Entity, Kind, None, DestType, Entity.getType(), Sequence); return; } // - otherwise, no initialization is performed. // If a program calls for the default initialization of an object of // a const-qualified type T, T shall be a class type with a user-provided // default constructor. if (DestType.isConstQualified() && S.getLangOpts().CPlusPlus) { if (!maybeRecoverWithZeroInitialization(S, Sequence, Entity)) Sequence.SetFailed(InitializationSequence::FK_DefaultInitOfConst); return; } // If the destination type has a lifetime property, zero-initialize it. if (DestType.getQualifiers().hasObjCLifetime()) { Sequence.AddZeroInitializationStep(Entity.getType()); return; } } /// Attempt a user-defined conversion between two types (C++ [dcl.init]), /// which enumerates all conversion functions and performs overload resolution /// to select the best. static void TryUserDefinedConversion(Sema &S, QualType DestType, const InitializationKind &Kind, Expr *Initializer, InitializationSequence &Sequence, bool TopLevelOfInitList) { assert(!DestType->isReferenceType() && "References are handled elsewhere"); QualType SourceType = Initializer->getType(); assert((DestType->isRecordType() || SourceType->isRecordType()) && "Must have a class type to perform a user-defined conversion"); // Build the candidate set directly in the initialization sequence // structure, so that it will persist if we fail. OverloadCandidateSet &CandidateSet = Sequence.getFailedCandidateSet(); CandidateSet.clear(OverloadCandidateSet::CSK_InitByUserDefinedConversion); // Determine whether we are allowed to call explicit constructors or // explicit conversion operators. bool AllowExplicit = Kind.AllowExplicit(); if (const RecordType *DestRecordType = DestType->getAs()) { // The type we're converting to is a class type. Enumerate its constructors // to see if there is a suitable conversion. CXXRecordDecl *DestRecordDecl = cast(DestRecordType->getDecl()); // Try to complete the type we're converting to. if (S.isCompleteType(Kind.getLocation(), DestType)) { for (NamedDecl *D : S.LookupConstructors(DestRecordDecl)) { auto Info = getConstructorInfo(D); if (!Info.Constructor) continue; if (!Info.Constructor->isInvalidDecl() && Info.Constructor->isConvertingConstructor(AllowExplicit)) { if (Info.ConstructorTmpl) S.AddTemplateOverloadCandidate(Info.ConstructorTmpl, Info.FoundDecl, /*ExplicitArgs*/ nullptr, Initializer, CandidateSet, /*SuppressUserConversions=*/true); else S.AddOverloadCandidate(Info.Constructor, Info.FoundDecl, Initializer, CandidateSet, /*SuppressUserConversions=*/true); } } } } SourceLocation DeclLoc = Initializer->getLocStart(); if (const RecordType *SourceRecordType = SourceType->getAs()) { // The type we're converting from is a class type, enumerate its conversion // functions. // We can only enumerate the conversion functions for a complete type; if // the type isn't complete, simply skip this step. if (S.isCompleteType(DeclLoc, SourceType)) { CXXRecordDecl *SourceRecordDecl = cast(SourceRecordType->getDecl()); const auto &Conversions = SourceRecordDecl->getVisibleConversionFunctions(); for (auto I = Conversions.begin(), E = Conversions.end(); I != E; ++I) { NamedDecl *D = *I; CXXRecordDecl *ActingDC = cast(D->getDeclContext()); if (isa(D)) D = cast(D)->getTargetDecl(); FunctionTemplateDecl *ConvTemplate = dyn_cast(D); CXXConversionDecl *Conv; if (ConvTemplate) Conv = cast(ConvTemplate->getTemplatedDecl()); else Conv = cast(D); if (AllowExplicit || !Conv->isExplicit()) { if (ConvTemplate) S.AddTemplateConversionCandidate(ConvTemplate, I.getPair(), ActingDC, Initializer, DestType, CandidateSet, AllowExplicit); else S.AddConversionCandidate(Conv, I.getPair(), ActingDC, Initializer, DestType, CandidateSet, AllowExplicit); } } } } // Perform overload resolution. If it fails, return the failed result. OverloadCandidateSet::iterator Best; if (OverloadingResult Result = CandidateSet.BestViableFunction(S, DeclLoc, Best)) { Sequence.SetOverloadFailure( InitializationSequence::FK_UserConversionOverloadFailed, Result); return; } FunctionDecl *Function = Best->Function; Function->setReferenced(); bool HadMultipleCandidates = (CandidateSet.size() > 1); if (isa(Function)) { // Add the user-defined conversion step. Any cv-qualification conversion is // subsumed by the initialization. Per DR5, the created temporary is of the // cv-unqualified type of the destination. Sequence.AddUserConversionStep(Function, Best->FoundDecl, DestType.getUnqualifiedType(), HadMultipleCandidates); // C++14 and before: // - if the function is a constructor, the call initializes a temporary // of the cv-unqualified version of the destination type. The [...] // temporary [...] is then used to direct-initialize, according to the // rules above, the object that is the destination of the // copy-initialization. // Note that this just performs a simple object copy from the temporary. // // C++17: // - if the function is a constructor, the call is a prvalue of the // cv-unqualified version of the destination type whose return object // is initialized by the constructor. The call is used to // direct-initialize, according to the rules above, the object that // is the destination of the copy-initialization. // Therefore we need to do nothing further. // // FIXME: Mark this copy as extraneous. if (!S.getLangOpts().CPlusPlus17) Sequence.AddFinalCopy(DestType); else if (DestType.hasQualifiers()) Sequence.AddQualificationConversionStep(DestType, VK_RValue); return; } // Add the user-defined conversion step that calls the conversion function. QualType ConvType = Function->getCallResultType(); Sequence.AddUserConversionStep(Function, Best->FoundDecl, ConvType, HadMultipleCandidates); if (ConvType->getAs()) { // The call is used to direct-initialize [...] the object that is the // destination of the copy-initialization. // // In C++17, this does not call a constructor if we enter /17.6.1: // - If the initializer expression is a prvalue and the cv-unqualified // version of the source type is the same as the class of the // destination [... do not make an extra copy] // // FIXME: Mark this copy as extraneous. if (!S.getLangOpts().CPlusPlus17 || Function->getReturnType()->isReferenceType() || !S.Context.hasSameUnqualifiedType(ConvType, DestType)) Sequence.AddFinalCopy(DestType); else if (!S.Context.hasSameType(ConvType, DestType)) Sequence.AddQualificationConversionStep(DestType, VK_RValue); return; } // If the conversion following the call to the conversion function // is interesting, add it as a separate step. if (Best->FinalConversion.First || Best->FinalConversion.Second || Best->FinalConversion.Third) { ImplicitConversionSequence ICS; ICS.setStandard(); ICS.Standard = Best->FinalConversion; Sequence.AddConversionSequenceStep(ICS, DestType, TopLevelOfInitList); } } /// An egregious hack for compatibility with libstdc++-4.2: in , /// a function with a pointer return type contains a 'return false;' statement. /// In C++11, 'false' is not a null pointer, so this breaks the build of any /// code using that header. /// /// Work around this by treating 'return false;' as zero-initializing the result /// if it's used in a pointer-returning function in a system header. static bool isLibstdcxxPointerReturnFalseHack(Sema &S, const InitializedEntity &Entity, const Expr *Init) { return S.getLangOpts().CPlusPlus11 && Entity.getKind() == InitializedEntity::EK_Result && Entity.getType()->isPointerType() && isa(Init) && !cast(Init)->getValue() && S.getSourceManager().isInSystemHeader(Init->getExprLoc()); } /// The non-zero enum values here are indexes into diagnostic alternatives. enum InvalidICRKind { IIK_okay, IIK_nonlocal, IIK_nonscalar }; /// Determines whether this expression is an acceptable ICR source. static InvalidICRKind isInvalidICRSource(ASTContext &C, Expr *e, bool isAddressOf, bool &isWeakAccess) { // Skip parens. e = e->IgnoreParens(); // Skip address-of nodes. if (UnaryOperator *op = dyn_cast(e)) { if (op->getOpcode() == UO_AddrOf) return isInvalidICRSource(C, op->getSubExpr(), /*addressof*/ true, isWeakAccess); // Skip certain casts. } else if (CastExpr *ce = dyn_cast(e)) { switch (ce->getCastKind()) { case CK_Dependent: case CK_BitCast: case CK_LValueBitCast: case CK_NoOp: return isInvalidICRSource(C, ce->getSubExpr(), isAddressOf, isWeakAccess); case CK_ArrayToPointerDecay: return IIK_nonscalar; case CK_NullToPointer: return IIK_okay; default: break; } // If we have a declaration reference, it had better be a local variable. } else if (isa(e)) { // set isWeakAccess to true, to mean that there will be an implicit // load which requires a cleanup. if (e->getType().getObjCLifetime() == Qualifiers::OCL_Weak) isWeakAccess = true; if (!isAddressOf) return IIK_nonlocal; VarDecl *var = dyn_cast(cast(e)->getDecl()); if (!var) return IIK_nonlocal; return (var->hasLocalStorage() ? IIK_okay : IIK_nonlocal); // If we have a conditional operator, check both sides. } else if (ConditionalOperator *cond = dyn_cast(e)) { if (InvalidICRKind iik = isInvalidICRSource(C, cond->getLHS(), isAddressOf, isWeakAccess)) return iik; return isInvalidICRSource(C, cond->getRHS(), isAddressOf, isWeakAccess); // These are never scalar. } else if (isa(e)) { return IIK_nonscalar; // Otherwise, it needs to be a null pointer constant. } else { return (e->isNullPointerConstant(C, Expr::NPC_ValueDependentIsNull) ? IIK_okay : IIK_nonlocal); } return IIK_nonlocal; } /// Check whether the given expression is a valid operand for an /// indirect copy/restore. static void checkIndirectCopyRestoreSource(Sema &S, Expr *src) { assert(src->isRValue()); bool isWeakAccess = false; InvalidICRKind iik = isInvalidICRSource(S.Context, src, false, isWeakAccess); // If isWeakAccess to true, there will be an implicit // load which requires a cleanup. if (S.getLangOpts().ObjCAutoRefCount && isWeakAccess) S.Cleanup.setExprNeedsCleanups(true); if (iik == IIK_okay) return; S.Diag(src->getExprLoc(), diag::err_arc_nonlocal_writeback) << ((unsigned) iik - 1) // shift index into diagnostic explanations << src->getSourceRange(); } /// Determine whether we have compatible array types for the /// purposes of GNU by-copy array initialization. static bool hasCompatibleArrayTypes(ASTContext &Context, const ArrayType *Dest, const ArrayType *Source) { // If the source and destination array types are equivalent, we're // done. if (Context.hasSameType(QualType(Dest, 0), QualType(Source, 0))) return true; // Make sure that the element types are the same. if (!Context.hasSameType(Dest->getElementType(), Source->getElementType())) return false; // The only mismatch we allow is when the destination is an // incomplete array type and the source is a constant array type. return Source->isConstantArrayType() && Dest->isIncompleteArrayType(); } static bool tryObjCWritebackConversion(Sema &S, InitializationSequence &Sequence, const InitializedEntity &Entity, Expr *Initializer) { bool ArrayDecay = false; QualType ArgType = Initializer->getType(); QualType ArgPointee; if (const ArrayType *ArgArrayType = S.Context.getAsArrayType(ArgType)) { ArrayDecay = true; ArgPointee = ArgArrayType->getElementType(); ArgType = S.Context.getPointerType(ArgPointee); } // Handle write-back conversion. QualType ConvertedArgType; if (!S.isObjCWritebackConversion(ArgType, Entity.getType(), ConvertedArgType)) return false; // We should copy unless we're passing to an argument explicitly // marked 'out'. bool ShouldCopy = true; if (ParmVarDecl *param = cast_or_null(Entity.getDecl())) ShouldCopy = (param->getObjCDeclQualifier() != ParmVarDecl::OBJC_TQ_Out); // Do we need an lvalue conversion? if (ArrayDecay || Initializer->isGLValue()) { ImplicitConversionSequence ICS; ICS.setStandard(); ICS.Standard.setAsIdentityConversion(); QualType ResultType; if (ArrayDecay) { ICS.Standard.First = ICK_Array_To_Pointer; ResultType = S.Context.getPointerType(ArgPointee); } else { ICS.Standard.First = ICK_Lvalue_To_Rvalue; ResultType = Initializer->getType().getNonLValueExprType(S.Context); } Sequence.AddConversionSequenceStep(ICS, ResultType); } Sequence.AddPassByIndirectCopyRestoreStep(Entity.getType(), ShouldCopy); return true; } static bool TryOCLSamplerInitialization(Sema &S, InitializationSequence &Sequence, QualType DestType, Expr *Initializer) { if (!S.getLangOpts().OpenCL || !DestType->isSamplerT() || (!Initializer->isIntegerConstantExpr(S.Context) && !Initializer->getType()->isSamplerT())) return false; Sequence.AddOCLSamplerInitStep(DestType); return true; } // // OpenCL 1.2 spec, s6.12.10 // // The event argument can also be used to associate the // async_work_group_copy with a previous async copy allowing // an event to be shared by multiple async copies; otherwise // event should be zero. // static bool TryOCLZeroEventInitialization(Sema &S, InitializationSequence &Sequence, QualType DestType, Expr *Initializer) { if (!S.getLangOpts().OpenCL || !DestType->isEventT() || !Initializer->isIntegerConstantExpr(S.getASTContext()) || (Initializer->EvaluateKnownConstInt(S.getASTContext()) != 0)) return false; Sequence.AddOCLZeroEventStep(DestType); return true; } static bool TryOCLZeroQueueInitialization(Sema &S, InitializationSequence &Sequence, QualType DestType, Expr *Initializer) { if (!S.getLangOpts().OpenCL || S.getLangOpts().OpenCLVersion < 200 || !DestType->isQueueT() || !Initializer->isIntegerConstantExpr(S.getASTContext()) || (Initializer->EvaluateKnownConstInt(S.getASTContext()) != 0)) return false; Sequence.AddOCLZeroQueueStep(DestType); return true; } InitializationSequence::InitializationSequence(Sema &S, const InitializedEntity &Entity, const InitializationKind &Kind, MultiExprArg Args, bool TopLevelOfInitList, bool TreatUnavailableAsInvalid) : FailedCandidateSet(Kind.getLocation(), OverloadCandidateSet::CSK_Normal) { InitializeFrom(S, Entity, Kind, Args, TopLevelOfInitList, TreatUnavailableAsInvalid); } /// Tries to get a FunctionDecl out of `E`. If it succeeds and we can take the /// address of that function, this returns true. Otherwise, it returns false. static bool isExprAnUnaddressableFunction(Sema &S, const Expr *E) { auto *DRE = dyn_cast(E); if (!DRE || !isa(DRE->getDecl())) return false; return !S.checkAddressOfFunctionIsAvailable( cast(DRE->getDecl())); } /// Determine whether we can perform an elementwise array copy for this kind /// of entity. static bool canPerformArrayCopy(const InitializedEntity &Entity) { switch (Entity.getKind()) { case InitializedEntity::EK_LambdaCapture: // C++ [expr.prim.lambda]p24: // For array members, the array elements are direct-initialized in // increasing subscript order. return true; case InitializedEntity::EK_Variable: // C++ [dcl.decomp]p1: // [...] each element is copy-initialized or direct-initialized from the // corresponding element of the assignment-expression [...] return isa(Entity.getDecl()); case InitializedEntity::EK_Member: // C++ [class.copy.ctor]p14: // - if the member is an array, each element is direct-initialized with // the corresponding subobject of x return Entity.isImplicitMemberInitializer(); case InitializedEntity::EK_ArrayElement: // All the above cases are intended to apply recursively, even though none // of them actually say that. if (auto *E = Entity.getParent()) return canPerformArrayCopy(*E); break; default: break; } return false; } void InitializationSequence::InitializeFrom(Sema &S, const InitializedEntity &Entity, const InitializationKind &Kind, MultiExprArg Args, bool TopLevelOfInitList, bool TreatUnavailableAsInvalid) { ASTContext &Context = S.Context; // Eliminate non-overload placeholder types in the arguments. We // need to do this before checking whether types are dependent // because lowering a pseudo-object expression might well give us // something of dependent type. for (unsigned I = 0, E = Args.size(); I != E; ++I) if (Args[I]->getType()->isNonOverloadPlaceholderType()) { // FIXME: should we be doing this here? ExprResult result = S.CheckPlaceholderExpr(Args[I]); if (result.isInvalid()) { SetFailed(FK_PlaceholderType); return; } Args[I] = result.get(); } // C++0x [dcl.init]p16: // The semantics of initializers are as follows. The destination type is // the type of the object or reference being initialized and the source // type is the type of the initializer expression. The source type is not // defined when the initializer is a braced-init-list or when it is a // parenthesized list of expressions. QualType DestType = Entity.getType(); if (DestType->isDependentType() || Expr::hasAnyTypeDependentArguments(Args)) { SequenceKind = DependentSequence; return; } // Almost everything is a normal sequence. setSequenceKind(NormalSequence); QualType SourceType; Expr *Initializer = nullptr; if (Args.size() == 1) { Initializer = Args[0]; if (S.getLangOpts().ObjC1) { if (S.CheckObjCBridgeRelatedConversions(Initializer->getLocStart(), DestType, Initializer->getType(), Initializer) || S.ConversionToObjCStringLiteralCheck(DestType, Initializer)) Args[0] = Initializer; } if (!isa(Initializer)) SourceType = Initializer->getType(); } // - If the initializer is a (non-parenthesized) braced-init-list, the // object is list-initialized (8.5.4). if (Kind.getKind() != InitializationKind::IK_Direct) { if (InitListExpr *InitList = dyn_cast_or_null(Initializer)) { TryListInitialization(S, Entity, Kind, InitList, *this, TreatUnavailableAsInvalid); return; } } // - If the destination type is a reference type, see 8.5.3. if (DestType->isReferenceType()) { // C++0x [dcl.init.ref]p1: // A variable declared to be a T& or T&&, that is, "reference to type T" // (8.3.2), shall be initialized by an object, or function, of type T or // by an object that can be converted into a T. // (Therefore, multiple arguments are not permitted.) if (Args.size() != 1) SetFailed(FK_TooManyInitsForReference); // C++17 [dcl.init.ref]p5: // A reference [...] is initialized by an expression [...] as follows: // If the initializer is not an expression, presumably we should reject, // but the standard fails to actually say so. else if (isa(Args[0])) SetFailed(FK_ParenthesizedListInitForReference); else TryReferenceInitialization(S, Entity, Kind, Args[0], *this); return; } // - If the initializer is (), the object is value-initialized. if (Kind.getKind() == InitializationKind::IK_Value || (Kind.getKind() == InitializationKind::IK_Direct && Args.empty())) { TryValueInitialization(S, Entity, Kind, *this); return; } // Handle default initialization. if (Kind.getKind() == InitializationKind::IK_Default) { TryDefaultInitialization(S, Entity, Kind, *this); return; } // - If the destination type is an array of characters, an array of // char16_t, an array of char32_t, or an array of wchar_t, and the // initializer is a string literal, see 8.5.2. // - Otherwise, if the destination type is an array, the program is // ill-formed. if (const ArrayType *DestAT = Context.getAsArrayType(DestType)) { if (Initializer && isa(DestAT)) { SetFailed(FK_VariableLengthArrayHasInitializer); return; } if (Initializer) { switch (IsStringInit(Initializer, DestAT, Context)) { case SIF_None: TryStringLiteralInitialization(S, Entity, Kind, Initializer, *this); return; case SIF_NarrowStringIntoWideChar: SetFailed(FK_NarrowStringIntoWideCharArray); return; case SIF_WideStringIntoChar: SetFailed(FK_WideStringIntoCharArray); return; case SIF_IncompatWideStringIntoWideChar: SetFailed(FK_IncompatWideStringIntoWideChar); return; case SIF_PlainStringIntoUTF8Char: SetFailed(FK_PlainStringIntoUTF8Char); return; case SIF_UTF8StringIntoPlainChar: SetFailed(FK_UTF8StringIntoPlainChar); return; case SIF_Other: break; } } // Some kinds of initialization permit an array to be initialized from // another array of the same type, and perform elementwise initialization. if (Initializer && isa(DestAT) && S.Context.hasSameUnqualifiedType(Initializer->getType(), Entity.getType()) && canPerformArrayCopy(Entity)) { // If source is a prvalue, use it directly. if (Initializer->getValueKind() == VK_RValue) { AddArrayInitStep(DestType, /*IsGNUExtension*/false); return; } // Emit element-at-a-time copy loop. InitializedEntity Element = InitializedEntity::InitializeElement(S.Context, 0, Entity); QualType InitEltT = Context.getAsArrayType(Initializer->getType())->getElementType(); OpaqueValueExpr OVE(Initializer->getExprLoc(), InitEltT, Initializer->getValueKind(), Initializer->getObjectKind()); Expr *OVEAsExpr = &OVE; InitializeFrom(S, Element, Kind, OVEAsExpr, TopLevelOfInitList, TreatUnavailableAsInvalid); if (!Failed()) AddArrayInitLoopStep(Entity.getType(), InitEltT); return; } // Note: as an GNU C extension, we allow initialization of an // array from a compound literal that creates an array of the same // type, so long as the initializer has no side effects. if (!S.getLangOpts().CPlusPlus && Initializer && isa(Initializer->IgnoreParens()) && Initializer->getType()->isArrayType()) { const ArrayType *SourceAT = Context.getAsArrayType(Initializer->getType()); if (!hasCompatibleArrayTypes(S.Context, DestAT, SourceAT)) SetFailed(FK_ArrayTypeMismatch); else if (Initializer->HasSideEffects(S.Context)) SetFailed(FK_NonConstantArrayInit); else { AddArrayInitStep(DestType, /*IsGNUExtension*/true); } } // Note: as a GNU C++ extension, we allow list-initialization of a // class member of array type from a parenthesized initializer list. else if (S.getLangOpts().CPlusPlus && Entity.getKind() == InitializedEntity::EK_Member && Initializer && isa(Initializer)) { TryListInitialization(S, Entity, Kind, cast(Initializer), *this, TreatUnavailableAsInvalid); AddParenthesizedArrayInitStep(DestType); } else if (DestAT->getElementType()->isCharType()) SetFailed(FK_ArrayNeedsInitListOrStringLiteral); else if (IsWideCharCompatible(DestAT->getElementType(), Context)) SetFailed(FK_ArrayNeedsInitListOrWideStringLiteral); else SetFailed(FK_ArrayNeedsInitList); return; } // Determine whether we should consider writeback conversions for // Objective-C ARC. bool allowObjCWritebackConversion = S.getLangOpts().ObjCAutoRefCount && Entity.isParameterKind(); // We're at the end of the line for C: it's either a write-back conversion // or it's a C assignment. There's no need to check anything else. if (!S.getLangOpts().CPlusPlus) { // If allowed, check whether this is an Objective-C writeback conversion. if (allowObjCWritebackConversion && tryObjCWritebackConversion(S, *this, Entity, Initializer)) { return; } if (TryOCLSamplerInitialization(S, *this, DestType, Initializer)) return; if (TryOCLZeroEventInitialization(S, *this, DestType, Initializer)) return; if (TryOCLZeroQueueInitialization(S, *this, DestType, Initializer)) return; // Handle initialization in C AddCAssignmentStep(DestType); MaybeProduceObjCObject(S, *this, Entity); return; } assert(S.getLangOpts().CPlusPlus); // - If the destination type is a (possibly cv-qualified) class type: if (DestType->isRecordType()) { // - If the initialization is direct-initialization, or if it is // copy-initialization where the cv-unqualified version of the // source type is the same class as, or a derived class of, the // class of the destination, constructors are considered. [...] if (Kind.getKind() == InitializationKind::IK_Direct || (Kind.getKind() == InitializationKind::IK_Copy && (Context.hasSameUnqualifiedType(SourceType, DestType) || S.IsDerivedFrom(Initializer->getLocStart(), SourceType, DestType)))) TryConstructorInitialization(S, Entity, Kind, Args, DestType, DestType, *this); // - Otherwise (i.e., for the remaining copy-initialization cases), // user-defined conversion sequences that can convert from the source // type to the destination type or (when a conversion function is // used) to a derived class thereof are enumerated as described in // 13.3.1.4, and the best one is chosen through overload resolution // (13.3). else TryUserDefinedConversion(S, DestType, Kind, Initializer, *this, TopLevelOfInitList); return; } assert(Args.size() >= 1 && "Zero-argument case handled above"); // The remaining cases all need a source type. if (Args.size() > 1) { SetFailed(FK_TooManyInitsForScalar); return; } else if (isa(Args[0])) { SetFailed(FK_ParenthesizedListInitForScalar); return; } // - Otherwise, if the source type is a (possibly cv-qualified) class // type, conversion functions are considered. if (!SourceType.isNull() && SourceType->isRecordType()) { // For a conversion to _Atomic(T) from either T or a class type derived // from T, initialize the T object then convert to _Atomic type. bool NeedAtomicConversion = false; if (const AtomicType *Atomic = DestType->getAs()) { if (Context.hasSameUnqualifiedType(SourceType, Atomic->getValueType()) || S.IsDerivedFrom(Initializer->getLocStart(), SourceType, Atomic->getValueType())) { DestType = Atomic->getValueType(); NeedAtomicConversion = true; } } TryUserDefinedConversion(S, DestType, Kind, Initializer, *this, TopLevelOfInitList); MaybeProduceObjCObject(S, *this, Entity); if (!Failed() && NeedAtomicConversion) AddAtomicConversionStep(Entity.getType()); return; } // - Otherwise, the initial value of the object being initialized is the // (possibly converted) value of the initializer expression. Standard // conversions (Clause 4) will be used, if necessary, to convert the // initializer expression to the cv-unqualified version of the // destination type; no user-defined conversions are considered. ImplicitConversionSequence ICS = S.TryImplicitConversion(Initializer, DestType, /*SuppressUserConversions*/true, /*AllowExplicitConversions*/ false, /*InOverloadResolution*/ false, /*CStyle=*/Kind.isCStyleOrFunctionalCast(), allowObjCWritebackConversion); if (ICS.isStandard() && ICS.Standard.Second == ICK_Writeback_Conversion) { // Objective-C ARC writeback conversion. // We should copy unless we're passing to an argument explicitly // marked 'out'. bool ShouldCopy = true; if (ParmVarDecl *Param = cast_or_null(Entity.getDecl())) ShouldCopy = (Param->getObjCDeclQualifier() != ParmVarDecl::OBJC_TQ_Out); // If there was an lvalue adjustment, add it as a separate conversion. if (ICS.Standard.First == ICK_Array_To_Pointer || ICS.Standard.First == ICK_Lvalue_To_Rvalue) { ImplicitConversionSequence LvalueICS; LvalueICS.setStandard(); LvalueICS.Standard.setAsIdentityConversion(); LvalueICS.Standard.setAllToTypes(ICS.Standard.getToType(0)); LvalueICS.Standard.First = ICS.Standard.First; AddConversionSequenceStep(LvalueICS, ICS.Standard.getToType(0)); } AddPassByIndirectCopyRestoreStep(DestType, ShouldCopy); } else if (ICS.isBad()) { DeclAccessPair dap; if (isLibstdcxxPointerReturnFalseHack(S, Entity, Initializer)) { AddZeroInitializationStep(Entity.getType()); } else if (Initializer->getType() == Context.OverloadTy && !S.ResolveAddressOfOverloadedFunction(Initializer, DestType, false, dap)) SetFailed(InitializationSequence::FK_AddressOfOverloadFailed); else if (Initializer->getType()->isFunctionType() && isExprAnUnaddressableFunction(S, Initializer)) SetFailed(InitializationSequence::FK_AddressOfUnaddressableFunction); else SetFailed(InitializationSequence::FK_ConversionFailed); } else { AddConversionSequenceStep(ICS, DestType, TopLevelOfInitList); MaybeProduceObjCObject(S, *this, Entity); } } InitializationSequence::~InitializationSequence() { for (auto &S : Steps) S.Destroy(); } //===----------------------------------------------------------------------===// // Perform initialization //===----------------------------------------------------------------------===// static Sema::AssignmentAction getAssignmentAction(const InitializedEntity &Entity, bool Diagnose = false) { switch(Entity.getKind()) { case InitializedEntity::EK_Variable: case InitializedEntity::EK_New: case InitializedEntity::EK_Exception: case InitializedEntity::EK_Base: case InitializedEntity::EK_Delegating: return Sema::AA_Initializing; case InitializedEntity::EK_Parameter: if (Entity.getDecl() && isa(Entity.getDecl()->getDeclContext())) return Sema::AA_Sending; return Sema::AA_Passing; case InitializedEntity::EK_Parameter_CF_Audited: if (Entity.getDecl() && isa(Entity.getDecl()->getDeclContext())) return Sema::AA_Sending; return !Diagnose ? Sema::AA_Passing : Sema::AA_Passing_CFAudited; case InitializedEntity::EK_Result: case InitializedEntity::EK_StmtExprResult: // FIXME: Not quite right. return Sema::AA_Returning; case InitializedEntity::EK_Temporary: case InitializedEntity::EK_RelatedResult: // FIXME: Can we tell apart casting vs. converting? return Sema::AA_Casting; case InitializedEntity::EK_Member: case InitializedEntity::EK_Binding: case InitializedEntity::EK_ArrayElement: case InitializedEntity::EK_VectorElement: case InitializedEntity::EK_ComplexElement: case InitializedEntity::EK_BlockElement: case InitializedEntity::EK_LambdaToBlockConversionBlockElement: case InitializedEntity::EK_LambdaCapture: case InitializedEntity::EK_CompoundLiteralInit: return Sema::AA_Initializing; } llvm_unreachable("Invalid EntityKind!"); } /// Whether we should bind a created object as a temporary when /// initializing the given entity. static bool shouldBindAsTemporary(const InitializedEntity &Entity) { switch (Entity.getKind()) { case InitializedEntity::EK_ArrayElement: case InitializedEntity::EK_Member: case InitializedEntity::EK_Result: case InitializedEntity::EK_StmtExprResult: case InitializedEntity::EK_New: case InitializedEntity::EK_Variable: case InitializedEntity::EK_Base: case InitializedEntity::EK_Delegating: case InitializedEntity::EK_VectorElement: case InitializedEntity::EK_ComplexElement: case InitializedEntity::EK_Exception: case InitializedEntity::EK_BlockElement: case InitializedEntity::EK_LambdaToBlockConversionBlockElement: case InitializedEntity::EK_LambdaCapture: case InitializedEntity::EK_CompoundLiteralInit: return false; case InitializedEntity::EK_Parameter: case InitializedEntity::EK_Parameter_CF_Audited: case InitializedEntity::EK_Temporary: case InitializedEntity::EK_RelatedResult: case InitializedEntity::EK_Binding: return true; } llvm_unreachable("missed an InitializedEntity kind?"); } /// Whether the given entity, when initialized with an object /// created for that initialization, requires destruction. static bool shouldDestroyEntity(const InitializedEntity &Entity) { switch (Entity.getKind()) { case InitializedEntity::EK_Result: case InitializedEntity::EK_StmtExprResult: case InitializedEntity::EK_New: case InitializedEntity::EK_Base: case InitializedEntity::EK_Delegating: case InitializedEntity::EK_VectorElement: case InitializedEntity::EK_ComplexElement: case InitializedEntity::EK_BlockElement: case InitializedEntity::EK_LambdaToBlockConversionBlockElement: case InitializedEntity::EK_LambdaCapture: return false; case InitializedEntity::EK_Member: case InitializedEntity::EK_Binding: case InitializedEntity::EK_Variable: case InitializedEntity::EK_Parameter: case InitializedEntity::EK_Parameter_CF_Audited: case InitializedEntity::EK_Temporary: case InitializedEntity::EK_ArrayElement: case InitializedEntity::EK_Exception: case InitializedEntity::EK_CompoundLiteralInit: case InitializedEntity::EK_RelatedResult: return true; } llvm_unreachable("missed an InitializedEntity kind?"); } /// Get the location at which initialization diagnostics should appear. static SourceLocation getInitializationLoc(const InitializedEntity &Entity, Expr *Initializer) { switch (Entity.getKind()) { case InitializedEntity::EK_Result: case InitializedEntity::EK_StmtExprResult: return Entity.getReturnLoc(); case InitializedEntity::EK_Exception: return Entity.getThrowLoc(); case InitializedEntity::EK_Variable: case InitializedEntity::EK_Binding: return Entity.getDecl()->getLocation(); case InitializedEntity::EK_LambdaCapture: return Entity.getCaptureLoc(); case InitializedEntity::EK_ArrayElement: case InitializedEntity::EK_Member: case InitializedEntity::EK_Parameter: case InitializedEntity::EK_Parameter_CF_Audited: case InitializedEntity::EK_Temporary: case InitializedEntity::EK_New: case InitializedEntity::EK_Base: case InitializedEntity::EK_Delegating: case InitializedEntity::EK_VectorElement: case InitializedEntity::EK_ComplexElement: case InitializedEntity::EK_BlockElement: case InitializedEntity::EK_LambdaToBlockConversionBlockElement: case InitializedEntity::EK_CompoundLiteralInit: case InitializedEntity::EK_RelatedResult: return Initializer->getLocStart(); } llvm_unreachable("missed an InitializedEntity kind?"); } /// Make a (potentially elidable) temporary copy of the object /// provided by the given initializer by calling the appropriate copy /// constructor. /// /// \param S The Sema object used for type-checking. /// /// \param T The type of the temporary object, which must either be /// the type of the initializer expression or a superclass thereof. /// /// \param Entity The entity being initialized. /// /// \param CurInit The initializer expression. /// /// \param IsExtraneousCopy Whether this is an "extraneous" copy that /// is permitted in C++03 (but not C++0x) when binding a reference to /// an rvalue. /// /// \returns An expression that copies the initializer expression into /// a temporary object, or an error expression if a copy could not be /// created. static ExprResult CopyObject(Sema &S, QualType T, const InitializedEntity &Entity, ExprResult CurInit, bool IsExtraneousCopy) { if (CurInit.isInvalid()) return CurInit; // Determine which class type we're copying to. Expr *CurInitExpr = (Expr *)CurInit.get(); CXXRecordDecl *Class = nullptr; if (const RecordType *Record = T->getAs()) Class = cast(Record->getDecl()); if (!Class) return CurInit; SourceLocation Loc = getInitializationLoc(Entity, CurInit.get()); // Make sure that the type we are copying is complete. if (S.RequireCompleteType(Loc, T, diag::err_temp_copy_incomplete)) return CurInit; // Perform overload resolution using the class's constructors. Per // C++11 [dcl.init]p16, second bullet for class types, this initialization // is direct-initialization. OverloadCandidateSet CandidateSet(Loc, OverloadCandidateSet::CSK_Normal); DeclContext::lookup_result Ctors = S.LookupConstructors(Class); OverloadCandidateSet::iterator Best; switch (ResolveConstructorOverload( S, Loc, CurInitExpr, CandidateSet, T, Ctors, Best, /*CopyInitializing=*/false, /*AllowExplicit=*/true, /*OnlyListConstructors=*/false, /*IsListInit=*/false, /*SecondStepOfCopyInit=*/true)) { case OR_Success: break; case OR_No_Viable_Function: S.Diag(Loc, IsExtraneousCopy && !S.isSFINAEContext() ? diag::ext_rvalue_to_reference_temp_copy_no_viable : diag::err_temp_copy_no_viable) << (int)Entity.getKind() << CurInitExpr->getType() << CurInitExpr->getSourceRange(); CandidateSet.NoteCandidates(S, OCD_AllCandidates, CurInitExpr); if (!IsExtraneousCopy || S.isSFINAEContext()) return ExprError(); return CurInit; case OR_Ambiguous: S.Diag(Loc, diag::err_temp_copy_ambiguous) << (int)Entity.getKind() << CurInitExpr->getType() << CurInitExpr->getSourceRange(); CandidateSet.NoteCandidates(S, OCD_ViableCandidates, CurInitExpr); return ExprError(); case OR_Deleted: S.Diag(Loc, diag::err_temp_copy_deleted) << (int)Entity.getKind() << CurInitExpr->getType() << CurInitExpr->getSourceRange(); S.NoteDeletedFunction(Best->Function); return ExprError(); } bool HadMultipleCandidates = CandidateSet.size() > 1; CXXConstructorDecl *Constructor = cast(Best->Function); SmallVector ConstructorArgs; CurInit.get(); // Ownership transferred into MultiExprArg, below. S.CheckConstructorAccess(Loc, Constructor, Best->FoundDecl, Entity, IsExtraneousCopy); if (IsExtraneousCopy) { // If this is a totally extraneous copy for C++03 reference // binding purposes, just return the original initialization // expression. We don't generate an (elided) copy operation here // because doing so would require us to pass down a flag to avoid // infinite recursion, where each step adds another extraneous, // elidable copy. // Instantiate the default arguments of any extra parameters in // the selected copy constructor, as if we were going to create a // proper call to the copy constructor. for (unsigned I = 1, N = Constructor->getNumParams(); I != N; ++I) { ParmVarDecl *Parm = Constructor->getParamDecl(I); if (S.RequireCompleteType(Loc, Parm->getType(), diag::err_call_incomplete_argument)) break; // Build the default argument expression; we don't actually care // if this succeeds or not, because this routine will complain // if there was a problem. S.BuildCXXDefaultArgExpr(Loc, Constructor, Parm); } return CurInitExpr; } // Determine the arguments required to actually perform the // constructor call (we might have derived-to-base conversions, or // the copy constructor may have default arguments). if (S.CompleteConstructorCall(Constructor, CurInitExpr, Loc, ConstructorArgs)) return ExprError(); // C++0x [class.copy]p32: // When certain criteria are met, an implementation is allowed to // omit the copy/move construction of a class object, even if the // copy/move constructor and/or destructor for the object have // side effects. [...] // - when a temporary class object that has not been bound to a // reference (12.2) would be copied/moved to a class object // with the same cv-unqualified type, the copy/move operation // can be omitted by constructing the temporary object // directly into the target of the omitted copy/move // // Note that the other three bullets are handled elsewhere. Copy // elision for return statements and throw expressions are handled as part // of constructor initialization, while copy elision for exception handlers // is handled by the run-time. // // FIXME: If the function parameter is not the same type as the temporary, we // should still be able to elide the copy, but we don't have a way to // represent in the AST how much should be elided in this case. bool Elidable = CurInitExpr->isTemporaryObject(S.Context, Class) && S.Context.hasSameUnqualifiedType( Best->Function->getParamDecl(0)->getType().getNonReferenceType(), CurInitExpr->getType()); // Actually perform the constructor call. CurInit = S.BuildCXXConstructExpr(Loc, T, Best->FoundDecl, Constructor, Elidable, ConstructorArgs, HadMultipleCandidates, /*ListInit*/ false, /*StdInitListInit*/ false, /*ZeroInit*/ false, CXXConstructExpr::CK_Complete, SourceRange()); // If we're supposed to bind temporaries, do so. if (!CurInit.isInvalid() && shouldBindAsTemporary(Entity)) CurInit = S.MaybeBindToTemporary(CurInit.getAs()); return CurInit; } /// Check whether elidable copy construction for binding a reference to /// a temporary would have succeeded if we were building in C++98 mode, for /// -Wc++98-compat. static void CheckCXX98CompatAccessibleCopy(Sema &S, const InitializedEntity &Entity, Expr *CurInitExpr) { assert(S.getLangOpts().CPlusPlus11); const RecordType *Record = CurInitExpr->getType()->getAs(); if (!Record) return; SourceLocation Loc = getInitializationLoc(Entity, CurInitExpr); if (S.Diags.isIgnored(diag::warn_cxx98_compat_temp_copy, Loc)) return; // Find constructors which would have been considered. OverloadCandidateSet CandidateSet(Loc, OverloadCandidateSet::CSK_Normal); DeclContext::lookup_result Ctors = S.LookupConstructors(cast(Record->getDecl())); // Perform overload resolution. OverloadCandidateSet::iterator Best; OverloadingResult OR = ResolveConstructorOverload( S, Loc, CurInitExpr, CandidateSet, CurInitExpr->getType(), Ctors, Best, /*CopyInitializing=*/false, /*AllowExplicit=*/true, /*OnlyListConstructors=*/false, /*IsListInit=*/false, /*SecondStepOfCopyInit=*/true); PartialDiagnostic Diag = S.PDiag(diag::warn_cxx98_compat_temp_copy) << OR << (int)Entity.getKind() << CurInitExpr->getType() << CurInitExpr->getSourceRange(); switch (OR) { case OR_Success: S.CheckConstructorAccess(Loc, cast(Best->Function), Best->FoundDecl, Entity, Diag); // FIXME: Check default arguments as far as that's possible. break; case OR_No_Viable_Function: S.Diag(Loc, Diag); CandidateSet.NoteCandidates(S, OCD_AllCandidates, CurInitExpr); break; case OR_Ambiguous: S.Diag(Loc, Diag); CandidateSet.NoteCandidates(S, OCD_ViableCandidates, CurInitExpr); break; case OR_Deleted: S.Diag(Loc, Diag); S.NoteDeletedFunction(Best->Function); break; } } void InitializationSequence::PrintInitLocationNote(Sema &S, const InitializedEntity &Entity) { if (Entity.isParameterKind() && Entity.getDecl()) { if (Entity.getDecl()->getLocation().isInvalid()) return; if (Entity.getDecl()->getDeclName()) S.Diag(Entity.getDecl()->getLocation(), diag::note_parameter_named_here) << Entity.getDecl()->getDeclName(); else S.Diag(Entity.getDecl()->getLocation(), diag::note_parameter_here); } else if (Entity.getKind() == InitializedEntity::EK_RelatedResult && Entity.getMethodDecl()) S.Diag(Entity.getMethodDecl()->getLocation(), diag::note_method_return_type_change) << Entity.getMethodDecl()->getDeclName(); } /// Returns true if the parameters describe a constructor initialization of /// an explicit temporary object, e.g. "Point(x, y)". static bool isExplicitTemporary(const InitializedEntity &Entity, const InitializationKind &Kind, unsigned NumArgs) { switch (Entity.getKind()) { case InitializedEntity::EK_Temporary: case InitializedEntity::EK_CompoundLiteralInit: case InitializedEntity::EK_RelatedResult: break; default: return false; } switch (Kind.getKind()) { case InitializationKind::IK_DirectList: return true; // FIXME: Hack to work around cast weirdness. case InitializationKind::IK_Direct: case InitializationKind::IK_Value: return NumArgs != 1; default: return false; } } static ExprResult PerformConstructorInitialization(Sema &S, const InitializedEntity &Entity, const InitializationKind &Kind, MultiExprArg Args, const InitializationSequence::Step& Step, bool &ConstructorInitRequiresZeroInit, bool IsListInitialization, bool IsStdInitListInitialization, SourceLocation LBraceLoc, SourceLocation RBraceLoc) { unsigned NumArgs = Args.size(); CXXConstructorDecl *Constructor = cast(Step.Function.Function); bool HadMultipleCandidates = Step.Function.HadMultipleCandidates; // Build a call to the selected constructor. SmallVector ConstructorArgs; SourceLocation Loc = (Kind.isCopyInit() && Kind.getEqualLoc().isValid()) ? Kind.getEqualLoc() : Kind.getLocation(); if (Kind.getKind() == InitializationKind::IK_Default) { // Force even a trivial, implicit default constructor to be // semantically checked. We do this explicitly because we don't build // the definition for completely trivial constructors. assert(Constructor->getParent() && "No parent class for constructor."); if (Constructor->isDefaulted() && Constructor->isDefaultConstructor() && Constructor->isTrivial() && !Constructor->isUsed(false)) S.DefineImplicitDefaultConstructor(Loc, Constructor); } ExprResult CurInit((Expr *)nullptr); // C++ [over.match.copy]p1: // - When initializing a temporary to be bound to the first parameter // of a constructor that takes a reference to possibly cv-qualified // T as its first argument, called with a single argument in the // context of direct-initialization, explicit conversion functions // are also considered. bool AllowExplicitConv = Kind.AllowExplicit() && !Kind.isCopyInit() && Args.size() == 1 && hasCopyOrMoveCtorParam(S.Context, getConstructorInfo(Step.Function.FoundDecl)); // Determine the arguments required to actually perform the constructor // call. if (S.CompleteConstructorCall(Constructor, Args, Loc, ConstructorArgs, AllowExplicitConv, IsListInitialization)) return ExprError(); if (isExplicitTemporary(Entity, Kind, NumArgs)) { // An explicitly-constructed temporary, e.g., X(1, 2). if (S.DiagnoseUseOfDecl(Constructor, Loc)) return ExprError(); TypeSourceInfo *TSInfo = Entity.getTypeSourceInfo(); if (!TSInfo) TSInfo = S.Context.getTrivialTypeSourceInfo(Entity.getType(), Loc); SourceRange ParenOrBraceRange = Kind.getParenOrBraceRange(); if (auto *Shadow = dyn_cast( Step.Function.FoundDecl.getDecl())) { Constructor = S.findInheritingConstructor(Loc, Constructor, Shadow); if (S.DiagnoseUseOfDecl(Constructor, Loc)) return ExprError(); } S.MarkFunctionReferenced(Loc, Constructor); CurInit = new (S.Context) CXXTemporaryObjectExpr( S.Context, Constructor, Entity.getType().getNonLValueExprType(S.Context), TSInfo, ConstructorArgs, ParenOrBraceRange, HadMultipleCandidates, IsListInitialization, IsStdInitListInitialization, ConstructorInitRequiresZeroInit); } else { CXXConstructExpr::ConstructionKind ConstructKind = CXXConstructExpr::CK_Complete; if (Entity.getKind() == InitializedEntity::EK_Base) { ConstructKind = Entity.getBaseSpecifier()->isVirtual() ? CXXConstructExpr::CK_VirtualBase : CXXConstructExpr::CK_NonVirtualBase; } else if (Entity.getKind() == InitializedEntity::EK_Delegating) { ConstructKind = CXXConstructExpr::CK_Delegating; } // Only get the parenthesis or brace range if it is a list initialization or // direct construction. SourceRange ParenOrBraceRange; if (IsListInitialization) ParenOrBraceRange = SourceRange(LBraceLoc, RBraceLoc); else if (Kind.getKind() == InitializationKind::IK_Direct) ParenOrBraceRange = Kind.getParenOrBraceRange(); // If the entity allows NRVO, mark the construction as elidable // unconditionally. if (Entity.allowsNRVO()) CurInit = S.BuildCXXConstructExpr(Loc, Step.Type, Step.Function.FoundDecl, Constructor, /*Elidable=*/true, ConstructorArgs, HadMultipleCandidates, IsListInitialization, IsStdInitListInitialization, ConstructorInitRequiresZeroInit, ConstructKind, ParenOrBraceRange); else CurInit = S.BuildCXXConstructExpr(Loc, Step.Type, Step.Function.FoundDecl, Constructor, ConstructorArgs, HadMultipleCandidates, IsListInitialization, IsStdInitListInitialization, ConstructorInitRequiresZeroInit, ConstructKind, ParenOrBraceRange); } if (CurInit.isInvalid()) return ExprError(); // Only check access if all of that succeeded. S.CheckConstructorAccess(Loc, Constructor, Step.Function.FoundDecl, Entity); if (S.DiagnoseUseOfDecl(Step.Function.FoundDecl, Loc)) return ExprError(); if (shouldBindAsTemporary(Entity)) CurInit = S.MaybeBindToTemporary(CurInit.get()); return CurInit; } namespace { enum LifetimeKind { /// The lifetime of a temporary bound to this entity ends at the end of the /// full-expression, and that's (probably) fine. LK_FullExpression, /// The lifetime of a temporary bound to this entity is extended to the /// lifeitme of the entity itself. LK_Extended, /// The lifetime of a temporary bound to this entity probably ends too soon, /// because the entity is allocated in a new-expression. LK_New, /// The lifetime of a temporary bound to this entity ends too soon, because /// the entity is a return object. LK_Return, /// The lifetime of a temporary bound to this entity ends too soon, because /// the entity is the result of a statement expression. LK_StmtExprResult, /// This is a mem-initializer: if it would extend a temporary (other than via /// a default member initializer), the program is ill-formed. LK_MemInitializer, }; using LifetimeResult = llvm::PointerIntPair; } /// Determine the declaration which an initialized entity ultimately refers to, /// for the purpose of lifetime-extending a temporary bound to a reference in /// the initialization of \p Entity. static LifetimeResult getEntityLifetime( const InitializedEntity *Entity, const InitializedEntity *InitField = nullptr) { // C++11 [class.temporary]p5: switch (Entity->getKind()) { case InitializedEntity::EK_Variable: // The temporary [...] persists for the lifetime of the reference return {Entity, LK_Extended}; case InitializedEntity::EK_Member: // For subobjects, we look at the complete object. if (Entity->getParent()) return getEntityLifetime(Entity->getParent(), Entity); // except: // C++17 [class.base.init]p8: // A temporary expression bound to a reference member in a // mem-initializer is ill-formed. // C++17 [class.base.init]p11: // A temporary expression bound to a reference member from a // default member initializer is ill-formed. // // The context of p11 and its example suggest that it's only the use of a // default member initializer from a constructor that makes the program // ill-formed, not its mere existence, and that it can even be used by // aggregate initialization. return {Entity, Entity->isDefaultMemberInitializer() ? LK_Extended : LK_MemInitializer}; case InitializedEntity::EK_Binding: // Per [dcl.decomp]p3, the binding is treated as a variable of reference // type. return {Entity, LK_Extended}; case InitializedEntity::EK_Parameter: case InitializedEntity::EK_Parameter_CF_Audited: // -- A temporary bound to a reference parameter in a function call // persists until the completion of the full-expression containing // the call. return {nullptr, LK_FullExpression}; case InitializedEntity::EK_Result: // -- The lifetime of a temporary bound to the returned value in a // function return statement is not extended; the temporary is // destroyed at the end of the full-expression in the return statement. return {nullptr, LK_Return}; case InitializedEntity::EK_StmtExprResult: // FIXME: Should we lifetime-extend through the result of a statement // expression? return {nullptr, LK_StmtExprResult}; case InitializedEntity::EK_New: // -- A temporary bound to a reference in a new-initializer persists // until the completion of the full-expression containing the // new-initializer. return {nullptr, LK_New}; case InitializedEntity::EK_Temporary: case InitializedEntity::EK_CompoundLiteralInit: case InitializedEntity::EK_RelatedResult: // We don't yet know the storage duration of the surrounding temporary. // Assume it's got full-expression duration for now, it will patch up our // storage duration if that's not correct. return {nullptr, LK_FullExpression}; case InitializedEntity::EK_ArrayElement: // For subobjects, we look at the complete object. return getEntityLifetime(Entity->getParent(), InitField); case InitializedEntity::EK_Base: // For subobjects, we look at the complete object. if (Entity->getParent()) return getEntityLifetime(Entity->getParent(), InitField); return {InitField, LK_MemInitializer}; case InitializedEntity::EK_Delegating: // We can reach this case for aggregate initialization in a constructor: // struct A { int &&r; }; // struct B : A { B() : A{0} {} }; // In this case, use the outermost field decl as the context. return {InitField, LK_MemInitializer}; case InitializedEntity::EK_BlockElement: case InitializedEntity::EK_LambdaToBlockConversionBlockElement: case InitializedEntity::EK_LambdaCapture: case InitializedEntity::EK_VectorElement: case InitializedEntity::EK_ComplexElement: return {nullptr, LK_FullExpression}; case InitializedEntity::EK_Exception: // FIXME: Can we diagnose lifetime problems with exceptions? return {nullptr, LK_FullExpression}; } llvm_unreachable("unknown entity kind"); } namespace { enum ReferenceKind { /// Lifetime would be extended by a reference binding to a temporary. RK_ReferenceBinding, /// Lifetime would be extended by a std::initializer_list object binding to /// its backing array. RK_StdInitializerList, }; /// A temporary or local variable. This will be one of: /// * A MaterializeTemporaryExpr. /// * A DeclRefExpr whose declaration is a local. /// * An AddrLabelExpr. /// * A BlockExpr for a block with captures. using Local = Expr*; /// Expressions we stepped over when looking for the local state. Any steps /// that would inhibit lifetime extension or take us out of subexpressions of /// the initializer are included. struct IndirectLocalPathEntry { enum EntryKind { DefaultInit, AddressOf, VarInit, LValToRVal, LifetimeBoundCall, } Kind; Expr *E; const Decl *D = nullptr; IndirectLocalPathEntry() {} IndirectLocalPathEntry(EntryKind K, Expr *E) : Kind(K), E(E) {} IndirectLocalPathEntry(EntryKind K, Expr *E, const Decl *D) : Kind(K), E(E), D(D) {} }; using IndirectLocalPath = llvm::SmallVectorImpl; struct RevertToOldSizeRAII { IndirectLocalPath &Path; unsigned OldSize = Path.size(); RevertToOldSizeRAII(IndirectLocalPath &Path) : Path(Path) {} ~RevertToOldSizeRAII() { Path.resize(OldSize); } }; using LocalVisitor = llvm::function_ref; } static bool isVarOnPath(IndirectLocalPath &Path, VarDecl *VD) { for (auto E : Path) if (E.Kind == IndirectLocalPathEntry::VarInit && E.D == VD) return true; return false; } static bool pathContainsInit(IndirectLocalPath &Path) { return std::any_of(Path.begin(), Path.end(), [=](IndirectLocalPathEntry E) { return E.Kind == IndirectLocalPathEntry::DefaultInit || E.Kind == IndirectLocalPathEntry::VarInit; }); } static void visitLocalsRetainedByInitializer(IndirectLocalPath &Path, Expr *Init, LocalVisitor Visit, bool RevisitSubinits); static void visitLocalsRetainedByReferenceBinding(IndirectLocalPath &Path, Expr *Init, ReferenceKind RK, LocalVisitor Visit); static bool implicitObjectParamIsLifetimeBound(const FunctionDecl *FD) { const TypeSourceInfo *TSI = FD->getTypeSourceInfo(); if (!TSI) return false; + // Don't declare this variable in the second operand of the for-statement; + // GCC miscompiles that by ending its lifetime before evaluating the + // third operand. See gcc.gnu.org/PR86769. + AttributedTypeLoc ATL; for (TypeLoc TL = TSI->getTypeLoc(); - auto ATL = TL.getAsAdjusted(); + (ATL = TL.getAsAdjusted()); TL = ATL.getModifiedLoc()) { if (ATL.getAttrKind() == AttributedType::attr_lifetimebound) return true; } return false; } static void visitLifetimeBoundArguments(IndirectLocalPath &Path, Expr *Call, LocalVisitor Visit) { const FunctionDecl *Callee; ArrayRef Args; if (auto *CE = dyn_cast(Call)) { Callee = CE->getDirectCallee(); Args = llvm::makeArrayRef(CE->getArgs(), CE->getNumArgs()); } else { auto *CCE = cast(Call); Callee = CCE->getConstructor(); Args = llvm::makeArrayRef(CCE->getArgs(), CCE->getNumArgs()); } if (!Callee) return; Expr *ObjectArg = nullptr; if (isa(Call) && Callee->isCXXInstanceMember()) { ObjectArg = Args[0]; Args = Args.slice(1); } else if (auto *MCE = dyn_cast(Call)) { ObjectArg = MCE->getImplicitObjectArgument(); } auto VisitLifetimeBoundArg = [&](const Decl *D, Expr *Arg) { Path.push_back({IndirectLocalPathEntry::LifetimeBoundCall, Arg, D}); if (Arg->isGLValue()) visitLocalsRetainedByReferenceBinding(Path, Arg, RK_ReferenceBinding, Visit); else visitLocalsRetainedByInitializer(Path, Arg, Visit, true); Path.pop_back(); }; if (ObjectArg && implicitObjectParamIsLifetimeBound(Callee)) VisitLifetimeBoundArg(Callee, ObjectArg); for (unsigned I = 0, N = std::min(Callee->getNumParams(), Args.size()); I != N; ++I) { if (Callee->getParamDecl(I)->hasAttr()) VisitLifetimeBoundArg(Callee->getParamDecl(I), Args[I]); } } /// Visit the locals that would be reachable through a reference bound to the /// glvalue expression \c Init. static void visitLocalsRetainedByReferenceBinding(IndirectLocalPath &Path, Expr *Init, ReferenceKind RK, LocalVisitor Visit) { RevertToOldSizeRAII RAII(Path); // Walk past any constructs which we can lifetime-extend across. Expr *Old; do { Old = Init; if (auto *EWC = dyn_cast(Init)) Init = EWC->getSubExpr(); if (InitListExpr *ILE = dyn_cast(Init)) { // If this is just redundant braces around an initializer, step over it. if (ILE->isTransparent()) Init = ILE->getInit(0); } // Step over any subobject adjustments; we may have a materialized // temporary inside them. Init = const_cast(Init->skipRValueSubobjectAdjustments()); // Per current approach for DR1376, look through casts to reference type // when performing lifetime extension. if (CastExpr *CE = dyn_cast(Init)) if (CE->getSubExpr()->isGLValue()) Init = CE->getSubExpr(); // Per the current approach for DR1299, look through array element access // on array glvalues when performing lifetime extension. if (auto *ASE = dyn_cast(Init)) { Init = ASE->getBase(); auto *ICE = dyn_cast(Init); if (ICE && ICE->getCastKind() == CK_ArrayToPointerDecay) Init = ICE->getSubExpr(); else // We can't lifetime extend through this but we might still find some // retained temporaries. return visitLocalsRetainedByInitializer(Path, Init, Visit, true); } // Step into CXXDefaultInitExprs so we can diagnose cases where a // constructor inherits one as an implicit mem-initializer. if (auto *DIE = dyn_cast(Init)) { Path.push_back( {IndirectLocalPathEntry::DefaultInit, DIE, DIE->getField()}); Init = DIE->getExpr(); } } while (Init != Old); if (auto *MTE = dyn_cast(Init)) { if (Visit(Path, Local(MTE), RK)) visitLocalsRetainedByInitializer(Path, MTE->GetTemporaryExpr(), Visit, true); } if (isa(Init)) return visitLifetimeBoundArguments(Path, Init, Visit); switch (Init->getStmtClass()) { case Stmt::DeclRefExprClass: { // If we find the name of a local non-reference parameter, we could have a // lifetime problem. auto *DRE = cast(Init); auto *VD = dyn_cast(DRE->getDecl()); if (VD && VD->hasLocalStorage() && !DRE->refersToEnclosingVariableOrCapture()) { if (!VD->getType()->isReferenceType()) { Visit(Path, Local(DRE), RK); } else if (isa(DRE->getDecl())) { // The lifetime of a reference parameter is unknown; assume it's OK // for now. break; } else if (VD->getInit() && !isVarOnPath(Path, VD)) { Path.push_back({IndirectLocalPathEntry::VarInit, DRE, VD}); visitLocalsRetainedByReferenceBinding(Path, VD->getInit(), RK_ReferenceBinding, Visit); } } break; } case Stmt::UnaryOperatorClass: { // The only unary operator that make sense to handle here // is Deref. All others don't resolve to a "name." This includes // handling all sorts of rvalues passed to a unary operator. const UnaryOperator *U = cast(Init); if (U->getOpcode() == UO_Deref) visitLocalsRetainedByInitializer(Path, U->getSubExpr(), Visit, true); break; } case Stmt::OMPArraySectionExprClass: { visitLocalsRetainedByInitializer( Path, cast(Init)->getBase(), Visit, true); break; } case Stmt::ConditionalOperatorClass: case Stmt::BinaryConditionalOperatorClass: { auto *C = cast(Init); if (!C->getTrueExpr()->getType()->isVoidType()) visitLocalsRetainedByReferenceBinding(Path, C->getTrueExpr(), RK, Visit); if (!C->getFalseExpr()->getType()->isVoidType()) visitLocalsRetainedByReferenceBinding(Path, C->getFalseExpr(), RK, Visit); break; } // FIXME: Visit the left-hand side of an -> or ->*. default: break; } } /// Visit the locals that would be reachable through an object initialized by /// the prvalue expression \c Init. static void visitLocalsRetainedByInitializer(IndirectLocalPath &Path, Expr *Init, LocalVisitor Visit, bool RevisitSubinits) { RevertToOldSizeRAII RAII(Path); Expr *Old; do { Old = Init; // Step into CXXDefaultInitExprs so we can diagnose cases where a // constructor inherits one as an implicit mem-initializer. if (auto *DIE = dyn_cast(Init)) { Path.push_back({IndirectLocalPathEntry::DefaultInit, DIE, DIE->getField()}); Init = DIE->getExpr(); } if (auto *EWC = dyn_cast(Init)) Init = EWC->getSubExpr(); // Dig out the expression which constructs the extended temporary. Init = const_cast(Init->skipRValueSubobjectAdjustments()); if (CXXBindTemporaryExpr *BTE = dyn_cast(Init)) Init = BTE->getSubExpr(); Init = Init->IgnoreParens(); // Step over value-preserving rvalue casts. if (auto *CE = dyn_cast(Init)) { switch (CE->getCastKind()) { case CK_LValueToRValue: // If we can match the lvalue to a const object, we can look at its // initializer. Path.push_back({IndirectLocalPathEntry::LValToRVal, CE}); return visitLocalsRetainedByReferenceBinding( Path, Init, RK_ReferenceBinding, [&](IndirectLocalPath &Path, Local L, ReferenceKind RK) -> bool { if (auto *DRE = dyn_cast(L)) { auto *VD = dyn_cast(DRE->getDecl()); if (VD && VD->getType().isConstQualified() && VD->getInit() && !isVarOnPath(Path, VD)) { Path.push_back({IndirectLocalPathEntry::VarInit, DRE, VD}); visitLocalsRetainedByInitializer(Path, VD->getInit(), Visit, true); } } else if (auto *MTE = dyn_cast(L)) { if (MTE->getType().isConstQualified()) visitLocalsRetainedByInitializer(Path, MTE->GetTemporaryExpr(), Visit, true); } return false; }); // We assume that objects can be retained by pointers cast to integers, // but not if the integer is cast to floating-point type or to _Complex. // We assume that casts to 'bool' do not preserve enough information to // retain a local object. case CK_NoOp: case CK_BitCast: case CK_BaseToDerived: case CK_DerivedToBase: case CK_UncheckedDerivedToBase: case CK_Dynamic: case CK_ToUnion: case CK_UserDefinedConversion: case CK_ConstructorConversion: case CK_IntegralToPointer: case CK_PointerToIntegral: case CK_VectorSplat: case CK_IntegralCast: case CK_CPointerToObjCPointerCast: case CK_BlockPointerToObjCPointerCast: case CK_AnyPointerToBlockPointerCast: case CK_AddressSpaceConversion: break; case CK_ArrayToPointerDecay: // Model array-to-pointer decay as taking the address of the array // lvalue. Path.push_back({IndirectLocalPathEntry::AddressOf, CE}); return visitLocalsRetainedByReferenceBinding(Path, CE->getSubExpr(), RK_ReferenceBinding, Visit); default: return; } Init = CE->getSubExpr(); } } while (Old != Init); // C++17 [dcl.init.list]p6: // initializing an initializer_list object from the array extends the // lifetime of the array exactly like binding a reference to a temporary. if (auto *ILE = dyn_cast(Init)) return visitLocalsRetainedByReferenceBinding(Path, ILE->getSubExpr(), RK_StdInitializerList, Visit); if (InitListExpr *ILE = dyn_cast(Init)) { // We already visited the elements of this initializer list while // performing the initialization. Don't visit them again unless we've // changed the lifetime of the initialized entity. if (!RevisitSubinits) return; if (ILE->isTransparent()) return visitLocalsRetainedByInitializer(Path, ILE->getInit(0), Visit, RevisitSubinits); if (ILE->getType()->isArrayType()) { for (unsigned I = 0, N = ILE->getNumInits(); I != N; ++I) visitLocalsRetainedByInitializer(Path, ILE->getInit(I), Visit, RevisitSubinits); return; } if (CXXRecordDecl *RD = ILE->getType()->getAsCXXRecordDecl()) { assert(RD->isAggregate() && "aggregate init on non-aggregate"); // If we lifetime-extend a braced initializer which is initializing an // aggregate, and that aggregate contains reference members which are // bound to temporaries, those temporaries are also lifetime-extended. if (RD->isUnion() && ILE->getInitializedFieldInUnion() && ILE->getInitializedFieldInUnion()->getType()->isReferenceType()) visitLocalsRetainedByReferenceBinding(Path, ILE->getInit(0), RK_ReferenceBinding, Visit); else { unsigned Index = 0; for (const auto *I : RD->fields()) { if (Index >= ILE->getNumInits()) break; if (I->isUnnamedBitfield()) continue; Expr *SubInit = ILE->getInit(Index); if (I->getType()->isReferenceType()) visitLocalsRetainedByReferenceBinding(Path, SubInit, RK_ReferenceBinding, Visit); else // This might be either aggregate-initialization of a member or // initialization of a std::initializer_list object. Regardless, // we should recursively lifetime-extend that initializer. visitLocalsRetainedByInitializer(Path, SubInit, Visit, RevisitSubinits); ++Index; } } } return; } if (isa(Init) || isa(Init)) return visitLifetimeBoundArguments(Path, Init, Visit); switch (Init->getStmtClass()) { case Stmt::UnaryOperatorClass: { auto *UO = cast(Init); // If the initializer is the address of a local, we could have a lifetime // problem. if (UO->getOpcode() == UO_AddrOf) { // If this is &rvalue, then it's ill-formed and we have already diagnosed // it. Don't produce a redundant warning about the lifetime of the // temporary. if (isa(UO->getSubExpr())) return; Path.push_back({IndirectLocalPathEntry::AddressOf, UO}); visitLocalsRetainedByReferenceBinding(Path, UO->getSubExpr(), RK_ReferenceBinding, Visit); } break; } case Stmt::BinaryOperatorClass: { // Handle pointer arithmetic. auto *BO = cast(Init); BinaryOperatorKind BOK = BO->getOpcode(); if (!BO->getType()->isPointerType() || (BOK != BO_Add && BOK != BO_Sub)) break; if (BO->getLHS()->getType()->isPointerType()) visitLocalsRetainedByInitializer(Path, BO->getLHS(), Visit, true); else if (BO->getRHS()->getType()->isPointerType()) visitLocalsRetainedByInitializer(Path, BO->getRHS(), Visit, true); break; } case Stmt::ConditionalOperatorClass: case Stmt::BinaryConditionalOperatorClass: { auto *C = cast(Init); // In C++, we can have a throw-expression operand, which has 'void' type // and isn't interesting from a lifetime perspective. if (!C->getTrueExpr()->getType()->isVoidType()) visitLocalsRetainedByInitializer(Path, C->getTrueExpr(), Visit, true); if (!C->getFalseExpr()->getType()->isVoidType()) visitLocalsRetainedByInitializer(Path, C->getFalseExpr(), Visit, true); break; } case Stmt::BlockExprClass: if (cast(Init)->getBlockDecl()->hasCaptures()) { // This is a local block, whose lifetime is that of the function. Visit(Path, Local(cast(Init)), RK_ReferenceBinding); } break; case Stmt::AddrLabelExprClass: // We want to warn if the address of a label would escape the function. Visit(Path, Local(cast(Init)), RK_ReferenceBinding); break; default: break; } } /// Determine whether this is an indirect path to a temporary that we are /// supposed to lifetime-extend along (but don't). static bool shouldLifetimeExtendThroughPath(const IndirectLocalPath &Path) { for (auto Elem : Path) { if (Elem.Kind != IndirectLocalPathEntry::DefaultInit) return false; } return true; } /// Find the range for the first interesting entry in the path at or after I. static SourceRange nextPathEntryRange(const IndirectLocalPath &Path, unsigned I, Expr *E) { for (unsigned N = Path.size(); I != N; ++I) { switch (Path[I].Kind) { case IndirectLocalPathEntry::AddressOf: case IndirectLocalPathEntry::LValToRVal: case IndirectLocalPathEntry::LifetimeBoundCall: // These exist primarily to mark the path as not permitting or // supporting lifetime extension. break; case IndirectLocalPathEntry::DefaultInit: case IndirectLocalPathEntry::VarInit: return Path[I].E->getSourceRange(); } } return E->getSourceRange(); } void Sema::checkInitializerLifetime(const InitializedEntity &Entity, Expr *Init) { LifetimeResult LR = getEntityLifetime(&Entity); LifetimeKind LK = LR.getInt(); const InitializedEntity *ExtendingEntity = LR.getPointer(); // If this entity doesn't have an interesting lifetime, don't bother looking // for temporaries within its initializer. if (LK == LK_FullExpression) return; auto TemporaryVisitor = [&](IndirectLocalPath &Path, Local L, ReferenceKind RK) -> bool { SourceRange DiagRange = nextPathEntryRange(Path, 0, L); SourceLocation DiagLoc = DiagRange.getBegin(); switch (LK) { case LK_FullExpression: llvm_unreachable("already handled this"); case LK_Extended: { auto *MTE = dyn_cast(L); if (!MTE) { // The initialized entity has lifetime beyond the full-expression, // and the local entity does too, so don't warn. // // FIXME: We should consider warning if a static / thread storage // duration variable retains an automatic storage duration local. return false; } // Lifetime-extend the temporary. if (Path.empty()) { // Update the storage duration of the materialized temporary. // FIXME: Rebuild the expression instead of mutating it. MTE->setExtendingDecl(ExtendingEntity->getDecl(), ExtendingEntity->allocateManglingNumber()); // Also visit the temporaries lifetime-extended by this initializer. return true; } if (shouldLifetimeExtendThroughPath(Path)) { // We're supposed to lifetime-extend the temporary along this path (per // the resolution of DR1815), but we don't support that yet. // // FIXME: Properly handle this situation. Perhaps the easiest approach // would be to clone the initializer expression on each use that would // lifetime extend its temporaries. Diag(DiagLoc, diag::warn_unsupported_lifetime_extension) << RK << DiagRange; } else { // If the path goes through the initialization of a variable or field, // it can't possibly reach a temporary created in this full-expression. // We will have already diagnosed any problems with the initializer. if (pathContainsInit(Path)) return false; Diag(DiagLoc, diag::warn_dangling_variable) << RK << !Entity.getParent() << ExtendingEntity->getDecl()->isImplicit() << ExtendingEntity->getDecl() << Init->isGLValue() << DiagRange; } break; } case LK_MemInitializer: { if (isa(L)) { // Under C++ DR1696, if a mem-initializer (or a default member // initializer used by the absence of one) would lifetime-extend a // temporary, the program is ill-formed. if (auto *ExtendingDecl = ExtendingEntity ? ExtendingEntity->getDecl() : nullptr) { bool IsSubobjectMember = ExtendingEntity != &Entity; Diag(DiagLoc, shouldLifetimeExtendThroughPath(Path) ? diag::err_dangling_member : diag::warn_dangling_member) << ExtendingDecl << IsSubobjectMember << RK << DiagRange; // Don't bother adding a note pointing to the field if we're inside // its default member initializer; our primary diagnostic points to // the same place in that case. if (Path.empty() || Path.back().Kind != IndirectLocalPathEntry::DefaultInit) { Diag(ExtendingDecl->getLocation(), diag::note_lifetime_extending_member_declared_here) << RK << IsSubobjectMember; } } else { // We have a mem-initializer but no particular field within it; this // is either a base class or a delegating initializer directly // initializing the base-class from something that doesn't live long // enough. // // FIXME: Warn on this. return false; } } else { // Paths via a default initializer can only occur during error recovery // (there's no other way that a default initializer can refer to a // local). Don't produce a bogus warning on those cases. if (pathContainsInit(Path)) return false; auto *DRE = dyn_cast(L); auto *VD = DRE ? dyn_cast(DRE->getDecl()) : nullptr; if (!VD) { // A member was initialized to a local block. // FIXME: Warn on this. return false; } if (auto *Member = ExtendingEntity ? ExtendingEntity->getDecl() : nullptr) { bool IsPointer = Member->getType()->isAnyPointerType(); Diag(DiagLoc, IsPointer ? diag::warn_init_ptr_member_to_parameter_addr : diag::warn_bind_ref_member_to_parameter) << Member << VD << isa(VD) << DiagRange; Diag(Member->getLocation(), diag::note_ref_or_ptr_member_declared_here) << (unsigned)IsPointer; } } break; } case LK_New: if (isa(L)) { Diag(DiagLoc, RK == RK_ReferenceBinding ? diag::warn_new_dangling_reference : diag::warn_new_dangling_initializer_list) << !Entity.getParent() << DiagRange; } else { // We can't determine if the allocation outlives the local declaration. return false; } break; case LK_Return: case LK_StmtExprResult: if (auto *DRE = dyn_cast(L)) { // We can't determine if the local variable outlives the statement // expression. if (LK == LK_StmtExprResult) return false; Diag(DiagLoc, diag::warn_ret_stack_addr_ref) << Entity.getType()->isReferenceType() << DRE->getDecl() << isa(DRE->getDecl()) << DiagRange; } else if (isa(L)) { Diag(DiagLoc, diag::err_ret_local_block) << DiagRange; } else if (isa(L)) { Diag(DiagLoc, diag::warn_ret_addr_label) << DiagRange; } else { Diag(DiagLoc, diag::warn_ret_local_temp_addr_ref) << Entity.getType()->isReferenceType() << DiagRange; } break; } for (unsigned I = 0; I != Path.size(); ++I) { auto Elem = Path[I]; switch (Elem.Kind) { case IndirectLocalPathEntry::AddressOf: case IndirectLocalPathEntry::LValToRVal: // These exist primarily to mark the path as not permitting or // supporting lifetime extension. break; case IndirectLocalPathEntry::LifetimeBoundCall: // FIXME: Consider adding a note for this. break; case IndirectLocalPathEntry::DefaultInit: { auto *FD = cast(Elem.D); Diag(FD->getLocation(), diag::note_init_with_default_member_initalizer) << FD << nextPathEntryRange(Path, I + 1, L); break; } case IndirectLocalPathEntry::VarInit: const VarDecl *VD = cast(Elem.D); Diag(VD->getLocation(), diag::note_local_var_initializer) << VD->getType()->isReferenceType() << VD->isImplicit() << VD->getDeclName() << nextPathEntryRange(Path, I + 1, L); break; } } // We didn't lifetime-extend, so don't go any further; we don't need more // warnings or errors on inner temporaries within this one's initializer. return false; }; llvm::SmallVector Path; if (Init->isGLValue()) visitLocalsRetainedByReferenceBinding(Path, Init, RK_ReferenceBinding, TemporaryVisitor); else visitLocalsRetainedByInitializer(Path, Init, TemporaryVisitor, false); } static void DiagnoseNarrowingInInitList(Sema &S, const ImplicitConversionSequence &ICS, QualType PreNarrowingType, QualType EntityType, const Expr *PostInit); /// Provide warnings when std::move is used on construction. static void CheckMoveOnConstruction(Sema &S, const Expr *InitExpr, bool IsReturnStmt) { if (!InitExpr) return; if (S.inTemplateInstantiation()) return; QualType DestType = InitExpr->getType(); if (!DestType->isRecordType()) return; unsigned DiagID = 0; if (IsReturnStmt) { const CXXConstructExpr *CCE = dyn_cast(InitExpr->IgnoreParens()); if (!CCE || CCE->getNumArgs() != 1) return; if (!CCE->getConstructor()->isCopyOrMoveConstructor()) return; InitExpr = CCE->getArg(0)->IgnoreImpCasts(); } // Find the std::move call and get the argument. const CallExpr *CE = dyn_cast(InitExpr->IgnoreParens()); if (!CE || !CE->isCallToStdMove()) return; const Expr *Arg = CE->getArg(0)->IgnoreImplicit(); if (IsReturnStmt) { const DeclRefExpr *DRE = dyn_cast(Arg->IgnoreParenImpCasts()); if (!DRE || DRE->refersToEnclosingVariableOrCapture()) return; const VarDecl *VD = dyn_cast(DRE->getDecl()); if (!VD || !VD->hasLocalStorage()) return; // __block variables are not moved implicitly. if (VD->hasAttr()) return; QualType SourceType = VD->getType(); if (!SourceType->isRecordType()) return; if (!S.Context.hasSameUnqualifiedType(DestType, SourceType)) { return; } // If we're returning a function parameter, copy elision // is not possible. if (isa(VD)) DiagID = diag::warn_redundant_move_on_return; else DiagID = diag::warn_pessimizing_move_on_return; } else { DiagID = diag::warn_pessimizing_move_on_initialization; const Expr *ArgStripped = Arg->IgnoreImplicit()->IgnoreParens(); if (!ArgStripped->isRValue() || !ArgStripped->getType()->isRecordType()) return; } S.Diag(CE->getLocStart(), DiagID); // Get all the locations for a fix-it. Don't emit the fix-it if any location // is within a macro. SourceLocation CallBegin = CE->getCallee()->getLocStart(); if (CallBegin.isMacroID()) return; SourceLocation RParen = CE->getRParenLoc(); if (RParen.isMacroID()) return; SourceLocation LParen; SourceLocation ArgLoc = Arg->getLocStart(); // Special testing for the argument location. Since the fix-it needs the // location right before the argument, the argument location can be in a // macro only if it is at the beginning of the macro. while (ArgLoc.isMacroID() && S.getSourceManager().isAtStartOfImmediateMacroExpansion(ArgLoc)) { ArgLoc = S.getSourceManager().getImmediateExpansionRange(ArgLoc).getBegin(); } if (LParen.isMacroID()) return; LParen = ArgLoc.getLocWithOffset(-1); S.Diag(CE->getLocStart(), diag::note_remove_move) << FixItHint::CreateRemoval(SourceRange(CallBegin, LParen)) << FixItHint::CreateRemoval(SourceRange(RParen, RParen)); } static void CheckForNullPointerDereference(Sema &S, const Expr *E) { // Check to see if we are dereferencing a null pointer. If so, this is // undefined behavior, so warn about it. This only handles the pattern // "*null", which is a very syntactic check. if (const UnaryOperator *UO = dyn_cast(E->IgnoreParenCasts())) if (UO->getOpcode() == UO_Deref && UO->getSubExpr()->IgnoreParenCasts()-> isNullPointerConstant(S.Context, Expr::NPC_ValueDependentIsNotNull)) { S.DiagRuntimeBehavior(UO->getOperatorLoc(), UO, S.PDiag(diag::warn_binding_null_to_reference) << UO->getSubExpr()->getSourceRange()); } } MaterializeTemporaryExpr * Sema::CreateMaterializeTemporaryExpr(QualType T, Expr *Temporary, bool BoundToLvalueReference) { auto MTE = new (Context) MaterializeTemporaryExpr(T, Temporary, BoundToLvalueReference); // Order an ExprWithCleanups for lifetime marks. // // TODO: It'll be good to have a single place to check the access of the // destructor and generate ExprWithCleanups for various uses. Currently these // are done in both CreateMaterializeTemporaryExpr and MaybeBindToTemporary, // but there may be a chance to merge them. Cleanup.setExprNeedsCleanups(false); return MTE; } ExprResult Sema::TemporaryMaterializationConversion(Expr *E) { // In C++98, we don't want to implicitly create an xvalue. // FIXME: This means that AST consumers need to deal with "prvalues" that // denote materialized temporaries. Maybe we should add another ValueKind // for "xvalue pretending to be a prvalue" for C++98 support. if (!E->isRValue() || !getLangOpts().CPlusPlus11) return E; // C++1z [conv.rval]/1: T shall be a complete type. // FIXME: Does this ever matter (can we form a prvalue of incomplete type)? // If so, we should check for a non-abstract class type here too. QualType T = E->getType(); if (RequireCompleteType(E->getExprLoc(), T, diag::err_incomplete_type)) return ExprError(); return CreateMaterializeTemporaryExpr(E->getType(), E, false); } ExprResult InitializationSequence::Perform(Sema &S, const InitializedEntity &Entity, const InitializationKind &Kind, MultiExprArg Args, QualType *ResultType) { if (Failed()) { Diagnose(S, Entity, Kind, Args); return ExprError(); } if (!ZeroInitializationFixit.empty()) { unsigned DiagID = diag::err_default_init_const; if (Decl *D = Entity.getDecl()) if (S.getLangOpts().MSVCCompat && D->hasAttr()) DiagID = diag::ext_default_init_const; // The initialization would have succeeded with this fixit. Since the fixit // is on the error, we need to build a valid AST in this case, so this isn't // handled in the Failed() branch above. QualType DestType = Entity.getType(); S.Diag(Kind.getLocation(), DiagID) << DestType << (bool)DestType->getAs() << FixItHint::CreateInsertion(ZeroInitializationFixitLoc, ZeroInitializationFixit); } if (getKind() == DependentSequence) { // If the declaration is a non-dependent, incomplete array type // that has an initializer, then its type will be completed once // the initializer is instantiated. if (ResultType && !Entity.getType()->isDependentType() && Args.size() == 1) { QualType DeclType = Entity.getType(); if (const IncompleteArrayType *ArrayT = S.Context.getAsIncompleteArrayType(DeclType)) { // FIXME: We don't currently have the ability to accurately // compute the length of an initializer list without // performing full type-checking of the initializer list // (since we have to determine where braces are implicitly // introduced and such). So, we fall back to making the array // type a dependently-sized array type with no specified // bound. if (isa((Expr *)Args[0])) { SourceRange Brackets; // Scavange the location of the brackets from the entity, if we can. if (auto *DD = dyn_cast_or_null(Entity.getDecl())) { if (TypeSourceInfo *TInfo = DD->getTypeSourceInfo()) { TypeLoc TL = TInfo->getTypeLoc(); if (IncompleteArrayTypeLoc ArrayLoc = TL.getAs()) Brackets = ArrayLoc.getBracketsRange(); } } *ResultType = S.Context.getDependentSizedArrayType(ArrayT->getElementType(), /*NumElts=*/nullptr, ArrayT->getSizeModifier(), ArrayT->getIndexTypeCVRQualifiers(), Brackets); } } } if (Kind.getKind() == InitializationKind::IK_Direct && !Kind.isExplicitCast()) { // Rebuild the ParenListExpr. SourceRange ParenRange = Kind.getParenOrBraceRange(); return S.ActOnParenListExpr(ParenRange.getBegin(), ParenRange.getEnd(), Args); } assert(Kind.getKind() == InitializationKind::IK_Copy || Kind.isExplicitCast() || Kind.getKind() == InitializationKind::IK_DirectList); return ExprResult(Args[0]); } // No steps means no initialization. if (Steps.empty()) return ExprResult((Expr *)nullptr); if (S.getLangOpts().CPlusPlus11 && Entity.getType()->isReferenceType() && Args.size() == 1 && isa(Args[0]) && !Entity.isParameterKind()) { // Produce a C++98 compatibility warning if we are initializing a reference // from an initializer list. For parameters, we produce a better warning // elsewhere. Expr *Init = Args[0]; S.Diag(Init->getLocStart(), diag::warn_cxx98_compat_reference_list_init) << Init->getSourceRange(); } // OpenCL v2.0 s6.13.11.1. atomic variables can be initialized in global scope QualType ETy = Entity.getType(); Qualifiers TyQualifiers = ETy.getQualifiers(); bool HasGlobalAS = TyQualifiers.hasAddressSpace() && TyQualifiers.getAddressSpace() == LangAS::opencl_global; if (S.getLangOpts().OpenCLVersion >= 200 && ETy->isAtomicType() && !HasGlobalAS && Entity.getKind() == InitializedEntity::EK_Variable && Args.size() > 0) { S.Diag(Args[0]->getLocStart(), diag::err_opencl_atomic_init) << 1 << SourceRange(Entity.getDecl()->getLocStart(), Args[0]->getLocEnd()); return ExprError(); } QualType DestType = Entity.getType().getNonReferenceType(); // FIXME: Ugly hack around the fact that Entity.getType() is not // the same as Entity.getDecl()->getType() in cases involving type merging, // and we want latter when it makes sense. if (ResultType) *ResultType = Entity.getDecl() ? Entity.getDecl()->getType() : Entity.getType(); ExprResult CurInit((Expr *)nullptr); SmallVector ArrayLoopCommonExprs; // For initialization steps that start with a single initializer, // grab the only argument out the Args and place it into the "current" // initializer. switch (Steps.front().Kind) { case SK_ResolveAddressOfOverloadedFunction: case SK_CastDerivedToBaseRValue: case SK_CastDerivedToBaseXValue: case SK_CastDerivedToBaseLValue: case SK_BindReference: case SK_BindReferenceToTemporary: case SK_FinalCopy: case SK_ExtraneousCopyToTemporary: case SK_UserConversion: case SK_QualificationConversionLValue: case SK_QualificationConversionXValue: case SK_QualificationConversionRValue: case SK_AtomicConversion: case SK_LValueToRValue: case SK_ConversionSequence: case SK_ConversionSequenceNoNarrowing: case SK_ListInitialization: case SK_UnwrapInitList: case SK_RewrapInitList: case SK_CAssignment: case SK_StringInit: case SK_ObjCObjectConversion: case SK_ArrayLoopIndex: case SK_ArrayLoopInit: case SK_ArrayInit: case SK_GNUArrayInit: case SK_ParenthesizedArrayInit: case SK_PassByIndirectCopyRestore: case SK_PassByIndirectRestore: case SK_ProduceObjCObject: case SK_StdInitializerList: case SK_OCLSamplerInit: case SK_OCLZeroEvent: case SK_OCLZeroQueue: { assert(Args.size() == 1); CurInit = Args[0]; if (!CurInit.get()) return ExprError(); break; } case SK_ConstructorInitialization: case SK_ConstructorInitializationFromList: case SK_StdInitializerListConstructorCall: case SK_ZeroInitialization: break; } // Promote from an unevaluated context to an unevaluated list context in // C++11 list-initialization; we need to instantiate entities usable in // constant expressions here in order to perform narrowing checks =( EnterExpressionEvaluationContext Evaluated( S, EnterExpressionEvaluationContext::InitList, CurInit.get() && isa(CurInit.get())); // C++ [class.abstract]p2: // no objects of an abstract class can be created except as subobjects // of a class derived from it auto checkAbstractType = [&](QualType T) -> bool { if (Entity.getKind() == InitializedEntity::EK_Base || Entity.getKind() == InitializedEntity::EK_Delegating) return false; return S.RequireNonAbstractType(Kind.getLocation(), T, diag::err_allocation_of_abstract_type); }; // Walk through the computed steps for the initialization sequence, // performing the specified conversions along the way. bool ConstructorInitRequiresZeroInit = false; for (step_iterator Step = step_begin(), StepEnd = step_end(); Step != StepEnd; ++Step) { if (CurInit.isInvalid()) return ExprError(); QualType SourceType = CurInit.get() ? CurInit.get()->getType() : QualType(); switch (Step->Kind) { case SK_ResolveAddressOfOverloadedFunction: // Overload resolution determined which function invoke; update the // initializer to reflect that choice. S.CheckAddressOfMemberAccess(CurInit.get(), Step->Function.FoundDecl); if (S.DiagnoseUseOfDecl(Step->Function.FoundDecl, Kind.getLocation())) return ExprError(); CurInit = S.FixOverloadedFunctionReference(CurInit, Step->Function.FoundDecl, Step->Function.Function); break; case SK_CastDerivedToBaseRValue: case SK_CastDerivedToBaseXValue: case SK_CastDerivedToBaseLValue: { // We have a derived-to-base cast that produces either an rvalue or an // lvalue. Perform that cast. CXXCastPath BasePath; // Casts to inaccessible base classes are allowed with C-style casts. bool IgnoreBaseAccess = Kind.isCStyleOrFunctionalCast(); if (S.CheckDerivedToBaseConversion(SourceType, Step->Type, CurInit.get()->getLocStart(), CurInit.get()->getSourceRange(), &BasePath, IgnoreBaseAccess)) return ExprError(); ExprValueKind VK = Step->Kind == SK_CastDerivedToBaseLValue ? VK_LValue : (Step->Kind == SK_CastDerivedToBaseXValue ? VK_XValue : VK_RValue); CurInit = ImplicitCastExpr::Create(S.Context, Step->Type, CK_DerivedToBase, CurInit.get(), &BasePath, VK); break; } case SK_BindReference: // Reference binding does not have any corresponding ASTs. // Check exception specifications if (S.CheckExceptionSpecCompatibility(CurInit.get(), DestType)) return ExprError(); // We don't check for e.g. function pointers here, since address // availability checks should only occur when the function first decays // into a pointer or reference. if (CurInit.get()->getType()->isFunctionProtoType()) { if (auto *DRE = dyn_cast(CurInit.get()->IgnoreParens())) { if (auto *FD = dyn_cast(DRE->getDecl())) { if (!S.checkAddressOfFunctionIsAvailable(FD, /*Complain=*/true, DRE->getLocStart())) return ExprError(); } } } CheckForNullPointerDereference(S, CurInit.get()); break; case SK_BindReferenceToTemporary: { // Make sure the "temporary" is actually an rvalue. assert(CurInit.get()->isRValue() && "not a temporary"); // Check exception specifications if (S.CheckExceptionSpecCompatibility(CurInit.get(), DestType)) return ExprError(); // Materialize the temporary into memory. MaterializeTemporaryExpr *MTE = S.CreateMaterializeTemporaryExpr( Step->Type, CurInit.get(), Entity.getType()->isLValueReferenceType()); CurInit = MTE; // If we're extending this temporary to automatic storage duration -- we // need to register its cleanup during the full-expression's cleanups. if (MTE->getStorageDuration() == SD_Automatic && MTE->getType().isDestructedType()) S.Cleanup.setExprNeedsCleanups(true); break; } case SK_FinalCopy: if (checkAbstractType(Step->Type)) return ExprError(); // If the overall initialization is initializing a temporary, we already // bound our argument if it was necessary to do so. If not (if we're // ultimately initializing a non-temporary), our argument needs to be // bound since it's initializing a function parameter. // FIXME: This is a mess. Rationalize temporary destruction. if (!shouldBindAsTemporary(Entity)) CurInit = S.MaybeBindToTemporary(CurInit.get()); CurInit = CopyObject(S, Step->Type, Entity, CurInit, /*IsExtraneousCopy=*/false); break; case SK_ExtraneousCopyToTemporary: CurInit = CopyObject(S, Step->Type, Entity, CurInit, /*IsExtraneousCopy=*/true); break; case SK_UserConversion: { // We have a user-defined conversion that invokes either a constructor // or a conversion function. CastKind CastKind; FunctionDecl *Fn = Step->Function.Function; DeclAccessPair FoundFn = Step->Function.FoundDecl; bool HadMultipleCandidates = Step->Function.HadMultipleCandidates; bool CreatedObject = false; if (CXXConstructorDecl *Constructor = dyn_cast(Fn)) { // Build a call to the selected constructor. SmallVector ConstructorArgs; SourceLocation Loc = CurInit.get()->getLocStart(); // Determine the arguments required to actually perform the constructor // call. Expr *Arg = CurInit.get(); if (S.CompleteConstructorCall(Constructor, MultiExprArg(&Arg, 1), Loc, ConstructorArgs)) return ExprError(); // Build an expression that constructs a temporary. CurInit = S.BuildCXXConstructExpr(Loc, Step->Type, FoundFn, Constructor, ConstructorArgs, HadMultipleCandidates, /*ListInit*/ false, /*StdInitListInit*/ false, /*ZeroInit*/ false, CXXConstructExpr::CK_Complete, SourceRange()); if (CurInit.isInvalid()) return ExprError(); S.CheckConstructorAccess(Kind.getLocation(), Constructor, FoundFn, Entity); if (S.DiagnoseUseOfDecl(FoundFn, Kind.getLocation())) return ExprError(); CastKind = CK_ConstructorConversion; CreatedObject = true; } else { // Build a call to the conversion function. CXXConversionDecl *Conversion = cast(Fn); S.CheckMemberOperatorAccess(Kind.getLocation(), CurInit.get(), nullptr, FoundFn); if (S.DiagnoseUseOfDecl(FoundFn, Kind.getLocation())) return ExprError(); CurInit = S.BuildCXXMemberCallExpr(CurInit.get(), FoundFn, Conversion, HadMultipleCandidates); if (CurInit.isInvalid()) return ExprError(); CastKind = CK_UserDefinedConversion; CreatedObject = Conversion->getReturnType()->isRecordType(); } if (CreatedObject && checkAbstractType(CurInit.get()->getType())) return ExprError(); CurInit = ImplicitCastExpr::Create(S.Context, CurInit.get()->getType(), CastKind, CurInit.get(), nullptr, CurInit.get()->getValueKind()); if (shouldBindAsTemporary(Entity)) // The overall entity is temporary, so this expression should be // destroyed at the end of its full-expression. CurInit = S.MaybeBindToTemporary(CurInit.getAs()); else if (CreatedObject && shouldDestroyEntity(Entity)) { // The object outlasts the full-expression, but we need to prepare for // a destructor being run on it. // FIXME: It makes no sense to do this here. This should happen // regardless of how we initialized the entity. QualType T = CurInit.get()->getType(); if (const RecordType *Record = T->getAs()) { CXXDestructorDecl *Destructor = S.LookupDestructor(cast(Record->getDecl())); S.CheckDestructorAccess(CurInit.get()->getLocStart(), Destructor, S.PDiag(diag::err_access_dtor_temp) << T); S.MarkFunctionReferenced(CurInit.get()->getLocStart(), Destructor); if (S.DiagnoseUseOfDecl(Destructor, CurInit.get()->getLocStart())) return ExprError(); } } break; } case SK_QualificationConversionLValue: case SK_QualificationConversionXValue: case SK_QualificationConversionRValue: { // Perform a qualification conversion; these can never go wrong. ExprValueKind VK = Step->Kind == SK_QualificationConversionLValue ? VK_LValue : (Step->Kind == SK_QualificationConversionXValue ? VK_XValue : VK_RValue); CurInit = S.ImpCastExprToType(CurInit.get(), Step->Type, CK_NoOp, VK); break; } case SK_AtomicConversion: { assert(CurInit.get()->isRValue() && "cannot convert glvalue to atomic"); CurInit = S.ImpCastExprToType(CurInit.get(), Step->Type, CK_NonAtomicToAtomic, VK_RValue); break; } case SK_LValueToRValue: { assert(CurInit.get()->isGLValue() && "cannot load from a prvalue"); CurInit = ImplicitCastExpr::Create(S.Context, Step->Type, CK_LValueToRValue, CurInit.get(), /*BasePath=*/nullptr, VK_RValue); break; } case SK_ConversionSequence: case SK_ConversionSequenceNoNarrowing: { Sema::CheckedConversionKind CCK = Kind.isCStyleCast()? Sema::CCK_CStyleCast : Kind.isFunctionalCast()? Sema::CCK_FunctionalCast : Kind.isExplicitCast()? Sema::CCK_OtherCast : Sema::CCK_ImplicitConversion; ExprResult CurInitExprRes = S.PerformImplicitConversion(CurInit.get(), Step->Type, *Step->ICS, getAssignmentAction(Entity), CCK); if (CurInitExprRes.isInvalid()) return ExprError(); S.DiscardMisalignedMemberAddress(Step->Type.getTypePtr(), CurInit.get()); CurInit = CurInitExprRes; if (Step->Kind == SK_ConversionSequenceNoNarrowing && S.getLangOpts().CPlusPlus) DiagnoseNarrowingInInitList(S, *Step->ICS, SourceType, Entity.getType(), CurInit.get()); break; } case SK_ListInitialization: { if (checkAbstractType(Step->Type)) return ExprError(); InitListExpr *InitList = cast(CurInit.get()); // If we're not initializing the top-level entity, we need to create an // InitializeTemporary entity for our target type. QualType Ty = Step->Type; bool IsTemporary = !S.Context.hasSameType(Entity.getType(), Ty); InitializedEntity TempEntity = InitializedEntity::InitializeTemporary(Ty); InitializedEntity InitEntity = IsTemporary ? TempEntity : Entity; InitListChecker PerformInitList(S, InitEntity, InitList, Ty, /*VerifyOnly=*/false, /*TreatUnavailableAsInvalid=*/false); if (PerformInitList.HadError()) return ExprError(); // Hack: We must update *ResultType if available in order to set the // bounds of arrays, e.g. in 'int ar[] = {1, 2, 3};'. // Worst case: 'const int (&arref)[] = {1, 2, 3};'. if (ResultType && ResultType->getNonReferenceType()->isIncompleteArrayType()) { if ((*ResultType)->isRValueReferenceType()) Ty = S.Context.getRValueReferenceType(Ty); else if ((*ResultType)->isLValueReferenceType()) Ty = S.Context.getLValueReferenceType(Ty, (*ResultType)->getAs()->isSpelledAsLValue()); *ResultType = Ty; } InitListExpr *StructuredInitList = PerformInitList.getFullyStructuredList(); CurInit.get(); CurInit = shouldBindAsTemporary(InitEntity) ? S.MaybeBindToTemporary(StructuredInitList) : StructuredInitList; break; } case SK_ConstructorInitializationFromList: { if (checkAbstractType(Step->Type)) return ExprError(); // When an initializer list is passed for a parameter of type "reference // to object", we don't get an EK_Temporary entity, but instead an // EK_Parameter entity with reference type. // FIXME: This is a hack. What we really should do is create a user // conversion step for this case, but this makes it considerably more // complicated. For now, this will do. InitializedEntity TempEntity = InitializedEntity::InitializeTemporary( Entity.getType().getNonReferenceType()); bool UseTemporary = Entity.getType()->isReferenceType(); assert(Args.size() == 1 && "expected a single argument for list init"); InitListExpr *InitList = cast(Args[0]); S.Diag(InitList->getExprLoc(), diag::warn_cxx98_compat_ctor_list_init) << InitList->getSourceRange(); MultiExprArg Arg(InitList->getInits(), InitList->getNumInits()); CurInit = PerformConstructorInitialization(S, UseTemporary ? TempEntity : Entity, Kind, Arg, *Step, ConstructorInitRequiresZeroInit, /*IsListInitialization*/true, /*IsStdInitListInit*/false, InitList->getLBraceLoc(), InitList->getRBraceLoc()); break; } case SK_UnwrapInitList: CurInit = cast(CurInit.get())->getInit(0); break; case SK_RewrapInitList: { Expr *E = CurInit.get(); InitListExpr *Syntactic = Step->WrappingSyntacticList; InitListExpr *ILE = new (S.Context) InitListExpr(S.Context, Syntactic->getLBraceLoc(), E, Syntactic->getRBraceLoc()); ILE->setSyntacticForm(Syntactic); ILE->setType(E->getType()); ILE->setValueKind(E->getValueKind()); CurInit = ILE; break; } case SK_ConstructorInitialization: case SK_StdInitializerListConstructorCall: { if (checkAbstractType(Step->Type)) return ExprError(); // When an initializer list is passed for a parameter of type "reference // to object", we don't get an EK_Temporary entity, but instead an // EK_Parameter entity with reference type. // FIXME: This is a hack. What we really should do is create a user // conversion step for this case, but this makes it considerably more // complicated. For now, this will do. InitializedEntity TempEntity = InitializedEntity::InitializeTemporary( Entity.getType().getNonReferenceType()); bool UseTemporary = Entity.getType()->isReferenceType(); bool IsStdInitListInit = Step->Kind == SK_StdInitializerListConstructorCall; Expr *Source = CurInit.get(); SourceRange Range = Kind.hasParenOrBraceRange() ? Kind.getParenOrBraceRange() : SourceRange(); CurInit = PerformConstructorInitialization( S, UseTemporary ? TempEntity : Entity, Kind, Source ? MultiExprArg(Source) : Args, *Step, ConstructorInitRequiresZeroInit, /*IsListInitialization*/ IsStdInitListInit, /*IsStdInitListInitialization*/ IsStdInitListInit, /*LBraceLoc*/ Range.getBegin(), /*RBraceLoc*/ Range.getEnd()); break; } case SK_ZeroInitialization: { step_iterator NextStep = Step; ++NextStep; if (NextStep != StepEnd && (NextStep->Kind == SK_ConstructorInitialization || NextStep->Kind == SK_ConstructorInitializationFromList)) { // The need for zero-initialization is recorded directly into // the call to the object's constructor within the next step. ConstructorInitRequiresZeroInit = true; } else if (Kind.getKind() == InitializationKind::IK_Value && S.getLangOpts().CPlusPlus && !Kind.isImplicitValueInit()) { TypeSourceInfo *TSInfo = Entity.getTypeSourceInfo(); if (!TSInfo) TSInfo = S.Context.getTrivialTypeSourceInfo(Step->Type, Kind.getRange().getBegin()); CurInit = new (S.Context) CXXScalarValueInitExpr( Entity.getType().getNonLValueExprType(S.Context), TSInfo, Kind.getRange().getEnd()); } else { CurInit = new (S.Context) ImplicitValueInitExpr(Step->Type); } break; } case SK_CAssignment: { QualType SourceType = CurInit.get()->getType(); // Save off the initial CurInit in case we need to emit a diagnostic ExprResult InitialCurInit = CurInit; ExprResult Result = CurInit; Sema::AssignConvertType ConvTy = S.CheckSingleAssignmentConstraints(Step->Type, Result, true, Entity.getKind() == InitializedEntity::EK_Parameter_CF_Audited); if (Result.isInvalid()) return ExprError(); CurInit = Result; // If this is a call, allow conversion to a transparent union. ExprResult CurInitExprRes = CurInit; if (ConvTy != Sema::Compatible && Entity.isParameterKind() && S.CheckTransparentUnionArgumentConstraints(Step->Type, CurInitExprRes) == Sema::Compatible) ConvTy = Sema::Compatible; if (CurInitExprRes.isInvalid()) return ExprError(); CurInit = CurInitExprRes; bool Complained; if (S.DiagnoseAssignmentResult(ConvTy, Kind.getLocation(), Step->Type, SourceType, InitialCurInit.get(), getAssignmentAction(Entity, true), &Complained)) { PrintInitLocationNote(S, Entity); return ExprError(); } else if (Complained) PrintInitLocationNote(S, Entity); break; } case SK_StringInit: { QualType Ty = Step->Type; CheckStringInit(CurInit.get(), ResultType ? *ResultType : Ty, S.Context.getAsArrayType(Ty), S); break; } case SK_ObjCObjectConversion: CurInit = S.ImpCastExprToType(CurInit.get(), Step->Type, CK_ObjCObjectLValueCast, CurInit.get()->getValueKind()); break; case SK_ArrayLoopIndex: { Expr *Cur = CurInit.get(); Expr *BaseExpr = new (S.Context) OpaqueValueExpr(Cur->getExprLoc(), Cur->getType(), Cur->getValueKind(), Cur->getObjectKind(), Cur); Expr *IndexExpr = new (S.Context) ArrayInitIndexExpr(S.Context.getSizeType()); CurInit = S.CreateBuiltinArraySubscriptExpr( BaseExpr, Kind.getLocation(), IndexExpr, Kind.getLocation()); ArrayLoopCommonExprs.push_back(BaseExpr); break; } case SK_ArrayLoopInit: { assert(!ArrayLoopCommonExprs.empty() && "mismatched SK_ArrayLoopIndex and SK_ArrayLoopInit"); Expr *Common = ArrayLoopCommonExprs.pop_back_val(); CurInit = new (S.Context) ArrayInitLoopExpr(Step->Type, Common, CurInit.get()); break; } case SK_GNUArrayInit: // Okay: we checked everything before creating this step. Note that // this is a GNU extension. S.Diag(Kind.getLocation(), diag::ext_array_init_copy) << Step->Type << CurInit.get()->getType() << CurInit.get()->getSourceRange(); LLVM_FALLTHROUGH; case SK_ArrayInit: // If the destination type is an incomplete array type, update the // type accordingly. if (ResultType) { if (const IncompleteArrayType *IncompleteDest = S.Context.getAsIncompleteArrayType(Step->Type)) { if (const ConstantArrayType *ConstantSource = S.Context.getAsConstantArrayType(CurInit.get()->getType())) { *ResultType = S.Context.getConstantArrayType( IncompleteDest->getElementType(), ConstantSource->getSize(), ArrayType::Normal, 0); } } } break; case SK_ParenthesizedArrayInit: // Okay: we checked everything before creating this step. Note that // this is a GNU extension. S.Diag(Kind.getLocation(), diag::ext_array_init_parens) << CurInit.get()->getSourceRange(); break; case SK_PassByIndirectCopyRestore: case SK_PassByIndirectRestore: checkIndirectCopyRestoreSource(S, CurInit.get()); CurInit = new (S.Context) ObjCIndirectCopyRestoreExpr( CurInit.get(), Step->Type, Step->Kind == SK_PassByIndirectCopyRestore); break; case SK_ProduceObjCObject: CurInit = ImplicitCastExpr::Create(S.Context, Step->Type, CK_ARCProduceObject, CurInit.get(), nullptr, VK_RValue); break; case SK_StdInitializerList: { S.Diag(CurInit.get()->getExprLoc(), diag::warn_cxx98_compat_initializer_list_init) << CurInit.get()->getSourceRange(); // Materialize the temporary into memory. MaterializeTemporaryExpr *MTE = S.CreateMaterializeTemporaryExpr( CurInit.get()->getType(), CurInit.get(), /*BoundToLvalueReference=*/false); // Wrap it in a construction of a std::initializer_list. CurInit = new (S.Context) CXXStdInitializerListExpr(Step->Type, MTE); // Bind the result, in case the library has given initializer_list a // non-trivial destructor. if (shouldBindAsTemporary(Entity)) CurInit = S.MaybeBindToTemporary(CurInit.get()); break; } case SK_OCLSamplerInit: { // Sampler initialzation have 5 cases: // 1. function argument passing // 1a. argument is a file-scope variable // 1b. argument is a function-scope variable // 1c. argument is one of caller function's parameters // 2. variable initialization // 2a. initializing a file-scope variable // 2b. initializing a function-scope variable // // For file-scope variables, since they cannot be initialized by function // call of __translate_sampler_initializer in LLVM IR, their references // need to be replaced by a cast from their literal initializers to // sampler type. Since sampler variables can only be used in function // calls as arguments, we only need to replace them when handling the // argument passing. assert(Step->Type->isSamplerT() && "Sampler initialization on non-sampler type."); Expr *Init = CurInit.get(); QualType SourceType = Init->getType(); // Case 1 if (Entity.isParameterKind()) { if (!SourceType->isSamplerT() && !SourceType->isIntegerType()) { S.Diag(Kind.getLocation(), diag::err_sampler_argument_required) << SourceType; break; } else if (const DeclRefExpr *DRE = dyn_cast(Init)) { auto Var = cast(DRE->getDecl()); // Case 1b and 1c // No cast from integer to sampler is needed. if (!Var->hasGlobalStorage()) { CurInit = ImplicitCastExpr::Create(S.Context, Step->Type, CK_LValueToRValue, Init, /*BasePath=*/nullptr, VK_RValue); break; } // Case 1a // For function call with a file-scope sampler variable as argument, // get the integer literal. // Do not diagnose if the file-scope variable does not have initializer // since this has already been diagnosed when parsing the variable // declaration. if (!Var->getInit() || !isa(Var->getInit())) break; Init = cast(const_cast( Var->getInit()))->getSubExpr(); SourceType = Init->getType(); } } else { // Case 2 // Check initializer is 32 bit integer constant. // If the initializer is taken from global variable, do not diagnose since // this has already been done when parsing the variable declaration. if (!Init->isConstantInitializer(S.Context, false)) break; if (!SourceType->isIntegerType() || 32 != S.Context.getIntWidth(SourceType)) { S.Diag(Kind.getLocation(), diag::err_sampler_initializer_not_integer) << SourceType; break; } llvm::APSInt Result; Init->EvaluateAsInt(Result, S.Context); const uint64_t SamplerValue = Result.getLimitedValue(); // 32-bit value of sampler's initializer is interpreted as // bit-field with the following structure: // |unspecified|Filter|Addressing Mode| Normalized Coords| // |31 6|5 4|3 1| 0| // This structure corresponds to enum values of sampler properties // defined in SPIR spec v1.2 and also opencl-c.h unsigned AddressingMode = (0x0E & SamplerValue) >> 1; unsigned FilterMode = (0x30 & SamplerValue) >> 4; if (FilterMode != 1 && FilterMode != 2) S.Diag(Kind.getLocation(), diag::warn_sampler_initializer_invalid_bits) << "Filter Mode"; if (AddressingMode > 4) S.Diag(Kind.getLocation(), diag::warn_sampler_initializer_invalid_bits) << "Addressing Mode"; } // Cases 1a, 2a and 2b // Insert cast from integer to sampler. CurInit = S.ImpCastExprToType(Init, S.Context.OCLSamplerTy, CK_IntToOCLSampler); break; } case SK_OCLZeroEvent: { assert(Step->Type->isEventT() && "Event initialization on non-event type."); CurInit = S.ImpCastExprToType(CurInit.get(), Step->Type, CK_ZeroToOCLEvent, CurInit.get()->getValueKind()); break; } case SK_OCLZeroQueue: { assert(Step->Type->isQueueT() && "Event initialization on non queue type."); CurInit = S.ImpCastExprToType(CurInit.get(), Step->Type, CK_ZeroToOCLQueue, CurInit.get()->getValueKind()); break; } } } // Check whether the initializer has a shorter lifetime than the initialized // entity, and if not, either lifetime-extend or warn as appropriate. if (auto *Init = CurInit.get()) S.checkInitializerLifetime(Entity, Init); // Diagnose non-fatal problems with the completed initialization. if (Entity.getKind() == InitializedEntity::EK_Member && cast(Entity.getDecl())->isBitField()) S.CheckBitFieldInitialization(Kind.getLocation(), cast(Entity.getDecl()), CurInit.get()); // Check for std::move on construction. if (const Expr *E = CurInit.get()) { CheckMoveOnConstruction(S, E, Entity.getKind() == InitializedEntity::EK_Result); } return CurInit; } /// Somewhere within T there is an uninitialized reference subobject. /// Dig it out and diagnose it. static bool DiagnoseUninitializedReference(Sema &S, SourceLocation Loc, QualType T) { if (T->isReferenceType()) { S.Diag(Loc, diag::err_reference_without_init) << T.getNonReferenceType(); return true; } CXXRecordDecl *RD = T->getBaseElementTypeUnsafe()->getAsCXXRecordDecl(); if (!RD || !RD->hasUninitializedReferenceMember()) return false; for (const auto *FI : RD->fields()) { if (FI->isUnnamedBitfield()) continue; if (DiagnoseUninitializedReference(S, FI->getLocation(), FI->getType())) { S.Diag(Loc, diag::note_value_initialization_here) << RD; return true; } } for (const auto &BI : RD->bases()) { if (DiagnoseUninitializedReference(S, BI.getLocStart(), BI.getType())) { S.Diag(Loc, diag::note_value_initialization_here) << RD; return true; } } return false; } //===----------------------------------------------------------------------===// // Diagnose initialization failures //===----------------------------------------------------------------------===// /// Emit notes associated with an initialization that failed due to a /// "simple" conversion failure. static void emitBadConversionNotes(Sema &S, const InitializedEntity &entity, Expr *op) { QualType destType = entity.getType(); if (destType.getNonReferenceType()->isObjCObjectPointerType() && op->getType()->isObjCObjectPointerType()) { // Emit a possible note about the conversion failing because the // operand is a message send with a related result type. S.EmitRelatedResultTypeNote(op); // Emit a possible note about a return failing because we're // expecting a related result type. if (entity.getKind() == InitializedEntity::EK_Result) S.EmitRelatedResultTypeNoteForReturn(destType); } } static void diagnoseListInit(Sema &S, const InitializedEntity &Entity, InitListExpr *InitList) { QualType DestType = Entity.getType(); QualType E; if (S.getLangOpts().CPlusPlus11 && S.isStdInitializerList(DestType, &E)) { QualType ArrayType = S.Context.getConstantArrayType( E.withConst(), llvm::APInt(S.Context.getTypeSize(S.Context.getSizeType()), InitList->getNumInits()), clang::ArrayType::Normal, 0); InitializedEntity HiddenArray = InitializedEntity::InitializeTemporary(ArrayType); return diagnoseListInit(S, HiddenArray, InitList); } if (DestType->isReferenceType()) { // A list-initialization failure for a reference means that we tried to // create a temporary of the inner type (per [dcl.init.list]p3.6) and the // inner initialization failed. QualType T = DestType->getAs()->getPointeeType(); diagnoseListInit(S, InitializedEntity::InitializeTemporary(T), InitList); SourceLocation Loc = InitList->getLocStart(); if (auto *D = Entity.getDecl()) Loc = D->getLocation(); S.Diag(Loc, diag::note_in_reference_temporary_list_initializer) << T; return; } InitListChecker DiagnoseInitList(S, Entity, InitList, DestType, /*VerifyOnly=*/false, /*TreatUnavailableAsInvalid=*/false); assert(DiagnoseInitList.HadError() && "Inconsistent init list check result."); } bool InitializationSequence::Diagnose(Sema &S, const InitializedEntity &Entity, const InitializationKind &Kind, ArrayRef Args) { if (!Failed()) return false; // When we want to diagnose only one element of a braced-init-list, // we need to factor it out. Expr *OnlyArg; if (Args.size() == 1) { auto *List = dyn_cast(Args[0]); if (List && List->getNumInits() == 1) OnlyArg = List->getInit(0); else OnlyArg = Args[0]; } else OnlyArg = nullptr; QualType DestType = Entity.getType(); switch (Failure) { case FK_TooManyInitsForReference: // FIXME: Customize for the initialized entity? if (Args.empty()) { // Dig out the reference subobject which is uninitialized and diagnose it. // If this is value-initialization, this could be nested some way within // the target type. assert(Kind.getKind() == InitializationKind::IK_Value || DestType->isReferenceType()); bool Diagnosed = DiagnoseUninitializedReference(S, Kind.getLocation(), DestType); assert(Diagnosed && "couldn't find uninitialized reference to diagnose"); (void)Diagnosed; } else // FIXME: diagnostic below could be better! S.Diag(Kind.getLocation(), diag::err_reference_has_multiple_inits) << SourceRange(Args.front()->getLocStart(), Args.back()->getLocEnd()); break; case FK_ParenthesizedListInitForReference: S.Diag(Kind.getLocation(), diag::err_list_init_in_parens) << 1 << Entity.getType() << Args[0]->getSourceRange(); break; case FK_ArrayNeedsInitList: S.Diag(Kind.getLocation(), diag::err_array_init_not_init_list) << 0; break; case FK_ArrayNeedsInitListOrStringLiteral: S.Diag(Kind.getLocation(), diag::err_array_init_not_init_list) << 1; break; case FK_ArrayNeedsInitListOrWideStringLiteral: S.Diag(Kind.getLocation(), diag::err_array_init_not_init_list) << 2; break; case FK_NarrowStringIntoWideCharArray: S.Diag(Kind.getLocation(), diag::err_array_init_narrow_string_into_wchar); break; case FK_WideStringIntoCharArray: S.Diag(Kind.getLocation(), diag::err_array_init_wide_string_into_char); break; case FK_IncompatWideStringIntoWideChar: S.Diag(Kind.getLocation(), diag::err_array_init_incompat_wide_string_into_wchar); break; case FK_PlainStringIntoUTF8Char: S.Diag(Kind.getLocation(), diag::err_array_init_plain_string_into_char8_t); S.Diag(Args.front()->getLocStart(), diag::note_array_init_plain_string_into_char8_t) << FixItHint::CreateInsertion(Args.front()->getLocStart(), "u8"); break; case FK_UTF8StringIntoPlainChar: S.Diag(Kind.getLocation(), diag::err_array_init_utf8_string_into_char); break; case FK_ArrayTypeMismatch: case FK_NonConstantArrayInit: S.Diag(Kind.getLocation(), (Failure == FK_ArrayTypeMismatch ? diag::err_array_init_different_type : diag::err_array_init_non_constant_array)) << DestType.getNonReferenceType() << OnlyArg->getType() << Args[0]->getSourceRange(); break; case FK_VariableLengthArrayHasInitializer: S.Diag(Kind.getLocation(), diag::err_variable_object_no_init) << Args[0]->getSourceRange(); break; case FK_AddressOfOverloadFailed: { DeclAccessPair Found; S.ResolveAddressOfOverloadedFunction(OnlyArg, DestType.getNonReferenceType(), true, Found); break; } case FK_AddressOfUnaddressableFunction: { auto *FD = cast(cast(OnlyArg)->getDecl()); S.checkAddressOfFunctionIsAvailable(FD, /*Complain=*/true, OnlyArg->getLocStart()); break; } case FK_ReferenceInitOverloadFailed: case FK_UserConversionOverloadFailed: switch (FailedOverloadResult) { case OR_Ambiguous: if (Failure == FK_UserConversionOverloadFailed) S.Diag(Kind.getLocation(), diag::err_typecheck_ambiguous_condition) << OnlyArg->getType() << DestType << Args[0]->getSourceRange(); else S.Diag(Kind.getLocation(), diag::err_ref_init_ambiguous) << DestType << OnlyArg->getType() << Args[0]->getSourceRange(); FailedCandidateSet.NoteCandidates(S, OCD_ViableCandidates, Args); break; case OR_No_Viable_Function: if (!S.RequireCompleteType(Kind.getLocation(), DestType.getNonReferenceType(), diag::err_typecheck_nonviable_condition_incomplete, OnlyArg->getType(), Args[0]->getSourceRange())) S.Diag(Kind.getLocation(), diag::err_typecheck_nonviable_condition) << (Entity.getKind() == InitializedEntity::EK_Result) << OnlyArg->getType() << Args[0]->getSourceRange() << DestType.getNonReferenceType(); FailedCandidateSet.NoteCandidates(S, OCD_AllCandidates, Args); break; case OR_Deleted: { S.Diag(Kind.getLocation(), diag::err_typecheck_deleted_function) << OnlyArg->getType() << DestType.getNonReferenceType() << Args[0]->getSourceRange(); OverloadCandidateSet::iterator Best; OverloadingResult Ovl = FailedCandidateSet.BestViableFunction(S, Kind.getLocation(), Best); if (Ovl == OR_Deleted) { S.NoteDeletedFunction(Best->Function); } else { llvm_unreachable("Inconsistent overload resolution?"); } break; } case OR_Success: llvm_unreachable("Conversion did not fail!"); } break; case FK_NonConstLValueReferenceBindingToTemporary: if (isa(Args[0])) { S.Diag(Kind.getLocation(), diag::err_lvalue_reference_bind_to_initlist) << DestType.getNonReferenceType().isVolatileQualified() << DestType.getNonReferenceType() << Args[0]->getSourceRange(); break; } LLVM_FALLTHROUGH; case FK_NonConstLValueReferenceBindingToUnrelated: S.Diag(Kind.getLocation(), Failure == FK_NonConstLValueReferenceBindingToTemporary ? diag::err_lvalue_reference_bind_to_temporary : diag::err_lvalue_reference_bind_to_unrelated) << DestType.getNonReferenceType().isVolatileQualified() << DestType.getNonReferenceType() << OnlyArg->getType() << Args[0]->getSourceRange(); break; case FK_NonConstLValueReferenceBindingToBitfield: { // We don't necessarily have an unambiguous source bit-field. FieldDecl *BitField = Args[0]->getSourceBitField(); S.Diag(Kind.getLocation(), diag::err_reference_bind_to_bitfield) << DestType.isVolatileQualified() << (BitField ? BitField->getDeclName() : DeclarationName()) << (BitField != nullptr) << Args[0]->getSourceRange(); if (BitField) S.Diag(BitField->getLocation(), diag::note_bitfield_decl); break; } case FK_NonConstLValueReferenceBindingToVectorElement: S.Diag(Kind.getLocation(), diag::err_reference_bind_to_vector_element) << DestType.isVolatileQualified() << Args[0]->getSourceRange(); break; case FK_RValueReferenceBindingToLValue: S.Diag(Kind.getLocation(), diag::err_lvalue_to_rvalue_ref) << DestType.getNonReferenceType() << OnlyArg->getType() << Args[0]->getSourceRange(); break; case FK_ReferenceInitDropsQualifiers: { QualType SourceType = OnlyArg->getType(); QualType NonRefType = DestType.getNonReferenceType(); Qualifiers DroppedQualifiers = SourceType.getQualifiers() - NonRefType.getQualifiers(); S.Diag(Kind.getLocation(), diag::err_reference_bind_drops_quals) << SourceType << NonRefType << DroppedQualifiers.getCVRQualifiers() << Args[0]->getSourceRange(); break; } case FK_ReferenceInitFailed: S.Diag(Kind.getLocation(), diag::err_reference_bind_failed) << DestType.getNonReferenceType() << OnlyArg->isLValue() << OnlyArg->getType() << Args[0]->getSourceRange(); emitBadConversionNotes(S, Entity, Args[0]); break; case FK_ConversionFailed: { QualType FromType = OnlyArg->getType(); PartialDiagnostic PDiag = S.PDiag(diag::err_init_conversion_failed) << (int)Entity.getKind() << DestType << OnlyArg->isLValue() << FromType << Args[0]->getSourceRange(); S.HandleFunctionTypeMismatch(PDiag, FromType, DestType); S.Diag(Kind.getLocation(), PDiag); emitBadConversionNotes(S, Entity, Args[0]); break; } case FK_ConversionFromPropertyFailed: // No-op. This error has already been reported. break; case FK_TooManyInitsForScalar: { SourceRange R; auto *InitList = dyn_cast(Args[0]); if (InitList && InitList->getNumInits() >= 1) { R = SourceRange(InitList->getInit(0)->getLocEnd(), InitList->getLocEnd()); } else { assert(Args.size() > 1 && "Expected multiple initializers!"); R = SourceRange(Args.front()->getLocEnd(), Args.back()->getLocEnd()); } R.setBegin(S.getLocForEndOfToken(R.getBegin())); if (Kind.isCStyleOrFunctionalCast()) S.Diag(Kind.getLocation(), diag::err_builtin_func_cast_more_than_one_arg) << R; else S.Diag(Kind.getLocation(), diag::err_excess_initializers) << /*scalar=*/2 << R; break; } case FK_ParenthesizedListInitForScalar: S.Diag(Kind.getLocation(), diag::err_list_init_in_parens) << 0 << Entity.getType() << Args[0]->getSourceRange(); break; case FK_ReferenceBindingToInitList: S.Diag(Kind.getLocation(), diag::err_reference_bind_init_list) << DestType.getNonReferenceType() << Args[0]->getSourceRange(); break; case FK_InitListBadDestinationType: S.Diag(Kind.getLocation(), diag::err_init_list_bad_dest_type) << (DestType->isRecordType()) << DestType << Args[0]->getSourceRange(); break; case FK_ListConstructorOverloadFailed: case FK_ConstructorOverloadFailed: { SourceRange ArgsRange; if (Args.size()) ArgsRange = SourceRange(Args.front()->getLocStart(), Args.back()->getLocEnd()); if (Failure == FK_ListConstructorOverloadFailed) { assert(Args.size() == 1 && "List construction from other than 1 argument."); InitListExpr *InitList = cast(Args[0]); Args = MultiExprArg(InitList->getInits(), InitList->getNumInits()); } // FIXME: Using "DestType" for the entity we're printing is probably // bad. switch (FailedOverloadResult) { case OR_Ambiguous: S.Diag(Kind.getLocation(), diag::err_ovl_ambiguous_init) << DestType << ArgsRange; FailedCandidateSet.NoteCandidates(S, OCD_ViableCandidates, Args); break; case OR_No_Viable_Function: if (Kind.getKind() == InitializationKind::IK_Default && (Entity.getKind() == InitializedEntity::EK_Base || Entity.getKind() == InitializedEntity::EK_Member) && isa(S.CurContext)) { // This is implicit default initialization of a member or // base within a constructor. If no viable function was // found, notify the user that they need to explicitly // initialize this base/member. CXXConstructorDecl *Constructor = cast(S.CurContext); const CXXRecordDecl *InheritedFrom = nullptr; if (auto Inherited = Constructor->getInheritedConstructor()) InheritedFrom = Inherited.getShadowDecl()->getNominatedBaseClass(); if (Entity.getKind() == InitializedEntity::EK_Base) { S.Diag(Kind.getLocation(), diag::err_missing_default_ctor) << (InheritedFrom ? 2 : Constructor->isImplicit() ? 1 : 0) << S.Context.getTypeDeclType(Constructor->getParent()) << /*base=*/0 << Entity.getType() << InheritedFrom; RecordDecl *BaseDecl = Entity.getBaseSpecifier()->getType()->getAs() ->getDecl(); S.Diag(BaseDecl->getLocation(), diag::note_previous_decl) << S.Context.getTagDeclType(BaseDecl); } else { S.Diag(Kind.getLocation(), diag::err_missing_default_ctor) << (InheritedFrom ? 2 : Constructor->isImplicit() ? 1 : 0) << S.Context.getTypeDeclType(Constructor->getParent()) << /*member=*/1 << Entity.getName() << InheritedFrom; S.Diag(Entity.getDecl()->getLocation(), diag::note_member_declared_at); if (const RecordType *Record = Entity.getType()->getAs()) S.Diag(Record->getDecl()->getLocation(), diag::note_previous_decl) << S.Context.getTagDeclType(Record->getDecl()); } break; } S.Diag(Kind.getLocation(), diag::err_ovl_no_viable_function_in_init) << DestType << ArgsRange; FailedCandidateSet.NoteCandidates(S, OCD_AllCandidates, Args); break; case OR_Deleted: { OverloadCandidateSet::iterator Best; OverloadingResult Ovl = FailedCandidateSet.BestViableFunction(S, Kind.getLocation(), Best); if (Ovl != OR_Deleted) { S.Diag(Kind.getLocation(), diag::err_ovl_deleted_init) << true << DestType << ArgsRange; llvm_unreachable("Inconsistent overload resolution?"); break; } // If this is a defaulted or implicitly-declared function, then // it was implicitly deleted. Make it clear that the deletion was // implicit. if (S.isImplicitlyDeleted(Best->Function)) S.Diag(Kind.getLocation(), diag::err_ovl_deleted_special_init) << S.getSpecialMember(cast(Best->Function)) << DestType << ArgsRange; else S.Diag(Kind.getLocation(), diag::err_ovl_deleted_init) << true << DestType << ArgsRange; S.NoteDeletedFunction(Best->Function); break; } case OR_Success: llvm_unreachable("Conversion did not fail!"); } } break; case FK_DefaultInitOfConst: if (Entity.getKind() == InitializedEntity::EK_Member && isa(S.CurContext)) { // This is implicit default-initialization of a const member in // a constructor. Complain that it needs to be explicitly // initialized. CXXConstructorDecl *Constructor = cast(S.CurContext); S.Diag(Kind.getLocation(), diag::err_uninitialized_member_in_ctor) << (Constructor->getInheritedConstructor() ? 2 : Constructor->isImplicit() ? 1 : 0) << S.Context.getTypeDeclType(Constructor->getParent()) << /*const=*/1 << Entity.getName(); S.Diag(Entity.getDecl()->getLocation(), diag::note_previous_decl) << Entity.getName(); } else { S.Diag(Kind.getLocation(), diag::err_default_init_const) << DestType << (bool)DestType->getAs(); } break; case FK_Incomplete: S.RequireCompleteType(Kind.getLocation(), FailedIncompleteType, diag::err_init_incomplete_type); break; case FK_ListInitializationFailed: { // Run the init list checker again to emit diagnostics. InitListExpr *InitList = cast(Args[0]); diagnoseListInit(S, Entity, InitList); break; } case FK_PlaceholderType: { // FIXME: Already diagnosed! break; } case FK_ExplicitConstructor: { S.Diag(Kind.getLocation(), diag::err_selected_explicit_constructor) << Args[0]->getSourceRange(); OverloadCandidateSet::iterator Best; OverloadingResult Ovl = FailedCandidateSet.BestViableFunction(S, Kind.getLocation(), Best); (void)Ovl; assert(Ovl == OR_Success && "Inconsistent overload resolution"); CXXConstructorDecl *CtorDecl = cast(Best->Function); S.Diag(CtorDecl->getLocation(), diag::note_explicit_ctor_deduction_guide_here) << false; break; } } PrintInitLocationNote(S, Entity); return true; } void InitializationSequence::dump(raw_ostream &OS) const { switch (SequenceKind) { case FailedSequence: { OS << "Failed sequence: "; switch (Failure) { case FK_TooManyInitsForReference: OS << "too many initializers for reference"; break; case FK_ParenthesizedListInitForReference: OS << "parenthesized list init for reference"; break; case FK_ArrayNeedsInitList: OS << "array requires initializer list"; break; case FK_AddressOfUnaddressableFunction: OS << "address of unaddressable function was taken"; break; case FK_ArrayNeedsInitListOrStringLiteral: OS << "array requires initializer list or string literal"; break; case FK_ArrayNeedsInitListOrWideStringLiteral: OS << "array requires initializer list or wide string literal"; break; case FK_NarrowStringIntoWideCharArray: OS << "narrow string into wide char array"; break; case FK_WideStringIntoCharArray: OS << "wide string into char array"; break; case FK_IncompatWideStringIntoWideChar: OS << "incompatible wide string into wide char array"; break; case FK_PlainStringIntoUTF8Char: OS << "plain string literal into char8_t array"; break; case FK_UTF8StringIntoPlainChar: OS << "u8 string literal into char array"; break; case FK_ArrayTypeMismatch: OS << "array type mismatch"; break; case FK_NonConstantArrayInit: OS << "non-constant array initializer"; break; case FK_AddressOfOverloadFailed: OS << "address of overloaded function failed"; break; case FK_ReferenceInitOverloadFailed: OS << "overload resolution for reference initialization failed"; break; case FK_NonConstLValueReferenceBindingToTemporary: OS << "non-const lvalue reference bound to temporary"; break; case FK_NonConstLValueReferenceBindingToBitfield: OS << "non-const lvalue reference bound to bit-field"; break; case FK_NonConstLValueReferenceBindingToVectorElement: OS << "non-const lvalue reference bound to vector element"; break; case FK_NonConstLValueReferenceBindingToUnrelated: OS << "non-const lvalue reference bound to unrelated type"; break; case FK_RValueReferenceBindingToLValue: OS << "rvalue reference bound to an lvalue"; break; case FK_ReferenceInitDropsQualifiers: OS << "reference initialization drops qualifiers"; break; case FK_ReferenceInitFailed: OS << "reference initialization failed"; break; case FK_ConversionFailed: OS << "conversion failed"; break; case FK_ConversionFromPropertyFailed: OS << "conversion from property failed"; break; case FK_TooManyInitsForScalar: OS << "too many initializers for scalar"; break; case FK_ParenthesizedListInitForScalar: OS << "parenthesized list init for reference"; break; case FK_ReferenceBindingToInitList: OS << "referencing binding to initializer list"; break; case FK_InitListBadDestinationType: OS << "initializer list for non-aggregate, non-scalar type"; break; case FK_UserConversionOverloadFailed: OS << "overloading failed for user-defined conversion"; break; case FK_ConstructorOverloadFailed: OS << "constructor overloading failed"; break; case FK_DefaultInitOfConst: OS << "default initialization of a const variable"; break; case FK_Incomplete: OS << "initialization of incomplete type"; break; case FK_ListInitializationFailed: OS << "list initialization checker failure"; break; case FK_VariableLengthArrayHasInitializer: OS << "variable length array has an initializer"; break; case FK_PlaceholderType: OS << "initializer expression isn't contextually valid"; break; case FK_ListConstructorOverloadFailed: OS << "list constructor overloading failed"; break; case FK_ExplicitConstructor: OS << "list copy initialization chose explicit constructor"; break; } OS << '\n'; return; } case DependentSequence: OS << "Dependent sequence\n"; return; case NormalSequence: OS << "Normal sequence: "; break; } for (step_iterator S = step_begin(), SEnd = step_end(); S != SEnd; ++S) { if (S != step_begin()) { OS << " -> "; } switch (S->Kind) { case SK_ResolveAddressOfOverloadedFunction: OS << "resolve address of overloaded function"; break; case SK_CastDerivedToBaseRValue: OS << "derived-to-base (rvalue)"; break; case SK_CastDerivedToBaseXValue: OS << "derived-to-base (xvalue)"; break; case SK_CastDerivedToBaseLValue: OS << "derived-to-base (lvalue)"; break; case SK_BindReference: OS << "bind reference to lvalue"; break; case SK_BindReferenceToTemporary: OS << "bind reference to a temporary"; break; case SK_FinalCopy: OS << "final copy in class direct-initialization"; break; case SK_ExtraneousCopyToTemporary: OS << "extraneous C++03 copy to temporary"; break; case SK_UserConversion: OS << "user-defined conversion via " << *S->Function.Function; break; case SK_QualificationConversionRValue: OS << "qualification conversion (rvalue)"; break; case SK_QualificationConversionXValue: OS << "qualification conversion (xvalue)"; break; case SK_QualificationConversionLValue: OS << "qualification conversion (lvalue)"; break; case SK_AtomicConversion: OS << "non-atomic-to-atomic conversion"; break; case SK_LValueToRValue: OS << "load (lvalue to rvalue)"; break; case SK_ConversionSequence: OS << "implicit conversion sequence ("; S->ICS->dump(); // FIXME: use OS OS << ")"; break; case SK_ConversionSequenceNoNarrowing: OS << "implicit conversion sequence with narrowing prohibited ("; S->ICS->dump(); // FIXME: use OS OS << ")"; break; case SK_ListInitialization: OS << "list aggregate initialization"; break; case SK_UnwrapInitList: OS << "unwrap reference initializer list"; break; case SK_RewrapInitList: OS << "rewrap reference initializer list"; break; case SK_ConstructorInitialization: OS << "constructor initialization"; break; case SK_ConstructorInitializationFromList: OS << "list initialization via constructor"; break; case SK_ZeroInitialization: OS << "zero initialization"; break; case SK_CAssignment: OS << "C assignment"; break; case SK_StringInit: OS << "string initialization"; break; case SK_ObjCObjectConversion: OS << "Objective-C object conversion"; break; case SK_ArrayLoopIndex: OS << "indexing for array initialization loop"; break; case SK_ArrayLoopInit: OS << "array initialization loop"; break; case SK_ArrayInit: OS << "array initialization"; break; case SK_GNUArrayInit: OS << "array initialization (GNU extension)"; break; case SK_ParenthesizedArrayInit: OS << "parenthesized array initialization"; break; case SK_PassByIndirectCopyRestore: OS << "pass by indirect copy and restore"; break; case SK_PassByIndirectRestore: OS << "pass by indirect restore"; break; case SK_ProduceObjCObject: OS << "Objective-C object retension"; break; case SK_StdInitializerList: OS << "std::initializer_list from initializer list"; break; case SK_StdInitializerListConstructorCall: OS << "list initialization from std::initializer_list"; break; case SK_OCLSamplerInit: OS << "OpenCL sampler_t from integer constant"; break; case SK_OCLZeroEvent: OS << "OpenCL event_t from zero"; break; case SK_OCLZeroQueue: OS << "OpenCL queue_t from zero"; break; } OS << " [" << S->Type.getAsString() << ']'; } OS << '\n'; } void InitializationSequence::dump() const { dump(llvm::errs()); } static bool NarrowingErrs(const LangOptions &L) { return L.CPlusPlus11 && (!L.MicrosoftExt || L.isCompatibleWithMSVC(LangOptions::MSVC2015)); } static void DiagnoseNarrowingInInitList(Sema &S, const ImplicitConversionSequence &ICS, QualType PreNarrowingType, QualType EntityType, const Expr *PostInit) { const StandardConversionSequence *SCS = nullptr; switch (ICS.getKind()) { case ImplicitConversionSequence::StandardConversion: SCS = &ICS.Standard; break; case ImplicitConversionSequence::UserDefinedConversion: SCS = &ICS.UserDefined.After; break; case ImplicitConversionSequence::AmbiguousConversion: case ImplicitConversionSequence::EllipsisConversion: case ImplicitConversionSequence::BadConversion: return; } // C++11 [dcl.init.list]p7: Check whether this is a narrowing conversion. APValue ConstantValue; QualType ConstantType; switch (SCS->getNarrowingKind(S.Context, PostInit, ConstantValue, ConstantType)) { case NK_Not_Narrowing: case NK_Dependent_Narrowing: // No narrowing occurred. return; case NK_Type_Narrowing: // This was a floating-to-integer conversion, which is always considered a // narrowing conversion even if the value is a constant and can be // represented exactly as an integer. S.Diag(PostInit->getLocStart(), NarrowingErrs(S.getLangOpts()) ? diag::ext_init_list_type_narrowing : diag::warn_init_list_type_narrowing) << PostInit->getSourceRange() << PreNarrowingType.getLocalUnqualifiedType() << EntityType.getLocalUnqualifiedType(); break; case NK_Constant_Narrowing: // A constant value was narrowed. S.Diag(PostInit->getLocStart(), NarrowingErrs(S.getLangOpts()) ? diag::ext_init_list_constant_narrowing : diag::warn_init_list_constant_narrowing) << PostInit->getSourceRange() << ConstantValue.getAsString(S.getASTContext(), ConstantType) << EntityType.getLocalUnqualifiedType(); break; case NK_Variable_Narrowing: // A variable's value may have been narrowed. S.Diag(PostInit->getLocStart(), NarrowingErrs(S.getLangOpts()) ? diag::ext_init_list_variable_narrowing : diag::warn_init_list_variable_narrowing) << PostInit->getSourceRange() << PreNarrowingType.getLocalUnqualifiedType() << EntityType.getLocalUnqualifiedType(); break; } SmallString<128> StaticCast; llvm::raw_svector_ostream OS(StaticCast); OS << "static_cast<"; if (const TypedefType *TT = EntityType->getAs()) { // It's important to use the typedef's name if there is one so that the // fixit doesn't break code using types like int64_t. // // FIXME: This will break if the typedef requires qualification. But // getQualifiedNameAsString() includes non-machine-parsable components. OS << *TT->getDecl(); } else if (const BuiltinType *BT = EntityType->getAs()) OS << BT->getName(S.getLangOpts()); else { // Oops, we didn't find the actual type of the variable. Don't emit a fixit // with a broken cast. return; } OS << ">("; S.Diag(PostInit->getLocStart(), diag::note_init_list_narrowing_silence) << PostInit->getSourceRange() << FixItHint::CreateInsertion(PostInit->getLocStart(), OS.str()) << FixItHint::CreateInsertion( S.getLocForEndOfToken(PostInit->getLocEnd()), ")"); } //===----------------------------------------------------------------------===// // Initialization helper functions //===----------------------------------------------------------------------===// bool Sema::CanPerformCopyInitialization(const InitializedEntity &Entity, ExprResult Init) { if (Init.isInvalid()) return false; Expr *InitE = Init.get(); assert(InitE && "No initialization expression"); InitializationKind Kind = InitializationKind::CreateCopy(InitE->getLocStart(), SourceLocation()); InitializationSequence Seq(*this, Entity, Kind, InitE); return !Seq.Failed(); } ExprResult Sema::PerformCopyInitialization(const InitializedEntity &Entity, SourceLocation EqualLoc, ExprResult Init, bool TopLevelOfInitList, bool AllowExplicit) { if (Init.isInvalid()) return ExprError(); Expr *InitE = Init.get(); assert(InitE && "No initialization expression?"); if (EqualLoc.isInvalid()) EqualLoc = InitE->getLocStart(); InitializationKind Kind = InitializationKind::CreateCopy(InitE->getLocStart(), EqualLoc, AllowExplicit); InitializationSequence Seq(*this, Entity, Kind, InitE, TopLevelOfInitList); // Prevent infinite recursion when performing parameter copy-initialization. const bool ShouldTrackCopy = Entity.isParameterKind() && Seq.isConstructorInitialization(); if (ShouldTrackCopy) { if (llvm::find(CurrentParameterCopyTypes, Entity.getType()) != CurrentParameterCopyTypes.end()) { Seq.SetOverloadFailure( InitializationSequence::FK_ConstructorOverloadFailed, OR_No_Viable_Function); // Try to give a meaningful diagnostic note for the problematic // constructor. const auto LastStep = Seq.step_end() - 1; assert(LastStep->Kind == InitializationSequence::SK_ConstructorInitialization); const FunctionDecl *Function = LastStep->Function.Function; auto Candidate = llvm::find_if(Seq.getFailedCandidateSet(), [Function](const OverloadCandidate &Candidate) -> bool { return Candidate.Viable && Candidate.Function == Function && Candidate.Conversions.size() > 0; }); if (Candidate != Seq.getFailedCandidateSet().end() && Function->getNumParams() > 0) { Candidate->Viable = false; Candidate->FailureKind = ovl_fail_bad_conversion; Candidate->Conversions[0].setBad(BadConversionSequence::no_conversion, InitE, Function->getParamDecl(0)->getType()); } } CurrentParameterCopyTypes.push_back(Entity.getType()); } ExprResult Result = Seq.Perform(*this, Entity, Kind, InitE); if (ShouldTrackCopy) CurrentParameterCopyTypes.pop_back(); return Result; } /// Determine whether RD is, or is derived from, a specialization of CTD. static bool isOrIsDerivedFromSpecializationOf(CXXRecordDecl *RD, ClassTemplateDecl *CTD) { auto NotSpecialization = [&] (const CXXRecordDecl *Candidate) { auto *CTSD = dyn_cast(Candidate); return !CTSD || !declaresSameEntity(CTSD->getSpecializedTemplate(), CTD); }; return !(NotSpecialization(RD) && RD->forallBases(NotSpecialization)); } QualType Sema::DeduceTemplateSpecializationFromInitializer( TypeSourceInfo *TSInfo, const InitializedEntity &Entity, const InitializationKind &Kind, MultiExprArg Inits) { auto *DeducedTST = dyn_cast( TSInfo->getType()->getContainedDeducedType()); assert(DeducedTST && "not a deduced template specialization type"); // We can only perform deduction for class templates. auto TemplateName = DeducedTST->getTemplateName(); auto *Template = dyn_cast_or_null(TemplateName.getAsTemplateDecl()); if (!Template) { Diag(Kind.getLocation(), diag::err_deduced_non_class_template_specialization_type) << (int)getTemplateNameKindForDiagnostics(TemplateName) << TemplateName; if (auto *TD = TemplateName.getAsTemplateDecl()) Diag(TD->getLocation(), diag::note_template_decl_here); return QualType(); } // Can't deduce from dependent arguments. if (Expr::hasAnyTypeDependentArguments(Inits)) return Context.DependentTy; // FIXME: Perform "exact type" matching first, per CWG discussion? // Or implement this via an implied 'T(T) -> T' deduction guide? // FIXME: Do we need/want a std::initializer_list special case? // Look up deduction guides, including those synthesized from constructors. // // C++1z [over.match.class.deduct]p1: // A set of functions and function templates is formed comprising: // - For each constructor of the class template designated by the // template-name, a function template [...] // - For each deduction-guide, a function or function template [...] DeclarationNameInfo NameInfo( Context.DeclarationNames.getCXXDeductionGuideName(Template), TSInfo->getTypeLoc().getEndLoc()); LookupResult Guides(*this, NameInfo, LookupOrdinaryName); LookupQualifiedName(Guides, Template->getDeclContext()); // FIXME: Do not diagnose inaccessible deduction guides. The standard isn't // clear on this, but they're not found by name so access does not apply. Guides.suppressDiagnostics(); // Figure out if this is list-initialization. InitListExpr *ListInit = (Inits.size() == 1 && Kind.getKind() != InitializationKind::IK_Direct) ? dyn_cast(Inits[0]) : nullptr; // C++1z [over.match.class.deduct]p1: // Initialization and overload resolution are performed as described in // [dcl.init] and [over.match.ctor], [over.match.copy], or [over.match.list] // (as appropriate for the type of initialization performed) for an object // of a hypothetical class type, where the selected functions and function // templates are considered to be the constructors of that class type // // Since we know we're initializing a class type of a type unrelated to that // of the initializer, this reduces to something fairly reasonable. OverloadCandidateSet Candidates(Kind.getLocation(), OverloadCandidateSet::CSK_Normal); OverloadCandidateSet::iterator Best; auto tryToResolveOverload = [&](bool OnlyListConstructors) -> OverloadingResult { Candidates.clear(OverloadCandidateSet::CSK_Normal); for (auto I = Guides.begin(), E = Guides.end(); I != E; ++I) { NamedDecl *D = (*I)->getUnderlyingDecl(); if (D->isInvalidDecl()) continue; auto *TD = dyn_cast(D); auto *GD = dyn_cast_or_null( TD ? TD->getTemplatedDecl() : dyn_cast(D)); if (!GD) continue; // C++ [over.match.ctor]p1: (non-list copy-initialization from non-class) // For copy-initialization, the candidate functions are all the // converting constructors (12.3.1) of that class. // C++ [over.match.copy]p1: (non-list copy-initialization from class) // The converting constructors of T are candidate functions. if (Kind.isCopyInit() && !ListInit) { // Only consider converting constructors. if (GD->isExplicit()) continue; // When looking for a converting constructor, deduction guides that // could never be called with one argument are not interesting to // check or note. if (GD->getMinRequiredArguments() > 1 || (GD->getNumParams() == 0 && !GD->isVariadic())) continue; } // C++ [over.match.list]p1.1: (first phase list initialization) // Initially, the candidate functions are the initializer-list // constructors of the class T if (OnlyListConstructors && !isInitListConstructor(GD)) continue; // C++ [over.match.list]p1.2: (second phase list initialization) // the candidate functions are all the constructors of the class T // C++ [over.match.ctor]p1: (all other cases) // the candidate functions are all the constructors of the class of // the object being initialized // C++ [over.best.ics]p4: // When [...] the constructor [...] is a candidate by // - [over.match.copy] (in all cases) // FIXME: The "second phase of [over.match.list] case can also // theoretically happen here, but it's not clear whether we can // ever have a parameter of the right type. bool SuppressUserConversions = Kind.isCopyInit(); if (TD) AddTemplateOverloadCandidate(TD, I.getPair(), /*ExplicitArgs*/ nullptr, Inits, Candidates, SuppressUserConversions); else AddOverloadCandidate(GD, I.getPair(), Inits, Candidates, SuppressUserConversions); } return Candidates.BestViableFunction(*this, Kind.getLocation(), Best); }; OverloadingResult Result = OR_No_Viable_Function; // C++11 [over.match.list]p1, per DR1467: for list-initialization, first // try initializer-list constructors. if (ListInit) { bool TryListConstructors = true; // Try list constructors unless the list is empty and the class has one or // more default constructors, in which case those constructors win. if (!ListInit->getNumInits()) { for (NamedDecl *D : Guides) { auto *FD = dyn_cast(D->getUnderlyingDecl()); if (FD && FD->getMinRequiredArguments() == 0) { TryListConstructors = false; break; } } } else if (ListInit->getNumInits() == 1) { // C++ [over.match.class.deduct]: // As an exception, the first phase in [over.match.list] (considering // initializer-list constructors) is omitted if the initializer list // consists of a single expression of type cv U, where U is a // specialization of C or a class derived from a specialization of C. Expr *E = ListInit->getInit(0); auto *RD = E->getType()->getAsCXXRecordDecl(); if (!isa(E) && RD && isCompleteType(Kind.getLocation(), E->getType()) && isOrIsDerivedFromSpecializationOf(RD, Template)) TryListConstructors = false; } if (TryListConstructors) Result = tryToResolveOverload(/*OnlyListConstructor*/true); // Then unwrap the initializer list and try again considering all // constructors. Inits = MultiExprArg(ListInit->getInits(), ListInit->getNumInits()); } // If list-initialization fails, or if we're doing any other kind of // initialization, we (eventually) consider constructors. if (Result == OR_No_Viable_Function) Result = tryToResolveOverload(/*OnlyListConstructor*/false); switch (Result) { case OR_Ambiguous: Diag(Kind.getLocation(), diag::err_deduced_class_template_ctor_ambiguous) << TemplateName; // FIXME: For list-initialization candidates, it'd usually be better to // list why they were not viable when given the initializer list itself as // an argument. Candidates.NoteCandidates(*this, OCD_ViableCandidates, Inits); return QualType(); case OR_No_Viable_Function: { CXXRecordDecl *Primary = cast(Template)->getTemplatedDecl(); bool Complete = isCompleteType(Kind.getLocation(), Context.getTypeDeclType(Primary)); Diag(Kind.getLocation(), Complete ? diag::err_deduced_class_template_ctor_no_viable : diag::err_deduced_class_template_incomplete) << TemplateName << !Guides.empty(); Candidates.NoteCandidates(*this, OCD_AllCandidates, Inits); return QualType(); } case OR_Deleted: { Diag(Kind.getLocation(), diag::err_deduced_class_template_deleted) << TemplateName; NoteDeletedFunction(Best->Function); return QualType(); } case OR_Success: // C++ [over.match.list]p1: // In copy-list-initialization, if an explicit constructor is chosen, the // initialization is ill-formed. if (Kind.isCopyInit() && ListInit && cast(Best->Function)->isExplicit()) { bool IsDeductionGuide = !Best->Function->isImplicit(); Diag(Kind.getLocation(), diag::err_deduced_class_template_explicit) << TemplateName << IsDeductionGuide; Diag(Best->Function->getLocation(), diag::note_explicit_ctor_deduction_guide_here) << IsDeductionGuide; return QualType(); } // Make sure we didn't select an unusable deduction guide, and mark it // as referenced. DiagnoseUseOfDecl(Best->Function, Kind.getLocation()); MarkFunctionReferenced(Kind.getLocation(), Best->Function); break; } // C++ [dcl.type.class.deduct]p1: // The placeholder is replaced by the return type of the function selected // by overload resolution for class template deduction. return SubstAutoType(TSInfo->getType(), Best->Function->getReturnType()); } Index: projects/clang700-import/contrib/llvm/tools/clang =================================================================== --- projects/clang700-import/contrib/llvm/tools/clang (revision 337309) +++ projects/clang700-import/contrib/llvm/tools/clang (revision 337310) Property changes on: projects/clang700-import/contrib/llvm/tools/clang ___________________________________________________________________ Modified: svn:mergeinfo ## -0,0 +0,2 ## Merged /vendor/clang/dist:r337150-337309 Merged /vendor/clang/dist-release_70:r337293-337309