diff --git a/Makefile.inc1 b/Makefile.inc1 index ffd0b14ce87..5b130d9c327 100644 --- a/Makefile.inc1 +++ b/Makefile.inc1 @@ -2498,6 +2498,7 @@ _gensnmptree= usr.sbin/bsnmpd/gensnmptree ${MK_LLDB} != "no" || ${MK_LLVM_BINUTILS} != "no" _clang_tblgen= \ lib/clang/libllvmminimal \ + usr.bin/clang/llvm-min-tblgen \ usr.bin/clang/llvm-tblgen .if ${MK_CLANG_BOOTSTRAP} != "no" || ${MK_CLANG} != "no" || \ ${MK_LLDB} != "no" @@ -2508,8 +2509,10 @@ _clang_tblgen+= usr.bin/clang/clang-tblgen _clang_tblgen+= usr.bin/clang/lldb-tblgen .endif ${_bt}-usr.bin/clang/clang-tblgen: ${_bt}-lib/clang/libllvmminimal -${_bt}-usr.bin/clang/llvm-tblgen: ${_bt}-lib/clang/libllvmminimal ${_bt}-usr.bin/clang/lldb-tblgen: ${_bt}-lib/clang/libllvmminimal +${_bt}-usr.bin/clang/llvm-min-tblgen: ${_bt}-lib/clang/libllvmminimal +${_bt}-usr.bin/clang/llvm-tblgen: ${_bt}-lib/clang/libllvmminimal +${_bt}-usr.bin/clang/llvm-tblgen: ${_bt}-usr.bin/clang/llvm-min-tblgen .endif # C.UTF-8 is always built in share/ctypes and we need localedef for that. diff --git a/ObsoleteFiles.inc b/ObsoleteFiles.inc index 49ba0898132..26d6e20ab0d 100644 --- a/ObsoleteFiles.inc +++ b/ObsoleteFiles.inc @@ -51,6 +51,408 @@ # xargs -n1 | sort | uniq -d; # done +# 20240107: new clang import which bumps version from 16 to 17 +OLD_FILES+=usr/lib/clang/16/include/__clang_cuda_builtin_vars.h +OLD_FILES+=usr/lib/clang/16/include/__clang_cuda_cmath.h +OLD_FILES+=usr/lib/clang/16/include/__clang_cuda_complex_builtins.h +OLD_FILES+=usr/lib/clang/16/include/__clang_cuda_device_functions.h +OLD_FILES+=usr/lib/clang/16/include/__clang_cuda_intrinsics.h +OLD_FILES+=usr/lib/clang/16/include/__clang_cuda_libdevice_declares.h +OLD_FILES+=usr/lib/clang/16/include/__clang_cuda_math.h +OLD_FILES+=usr/lib/clang/16/include/__clang_cuda_math_forward_declares.h +OLD_FILES+=usr/lib/clang/16/include/__clang_cuda_runtime_wrapper.h +OLD_FILES+=usr/lib/clang/16/include/__clang_cuda_texture_intrinsics.h +OLD_FILES+=usr/lib/clang/16/include/__clang_hip_cmath.h +OLD_FILES+=usr/lib/clang/16/include/__clang_hip_libdevice_declares.h +OLD_FILES+=usr/lib/clang/16/include/__clang_hip_math.h +OLD_FILES+=usr/lib/clang/16/include/__clang_hip_runtime_wrapper.h +OLD_FILES+=usr/lib/clang/16/include/__clang_hip_stdlib.h +OLD_FILES+=usr/lib/clang/16/include/__stddef_max_align_t.h +OLD_FILES+=usr/lib/clang/16/include/__wmmintrin_aes.h +OLD_FILES+=usr/lib/clang/16/include/__wmmintrin_pclmul.h +OLD_FILES+=usr/lib/clang/16/include/adxintrin.h +OLD_FILES+=usr/lib/clang/16/include/altivec.h +OLD_FILES+=usr/lib/clang/16/include/ammintrin.h +OLD_FILES+=usr/lib/clang/16/include/amxfp16intrin.h +OLD_FILES+=usr/lib/clang/16/include/amxintrin.h +OLD_FILES+=usr/lib/clang/16/include/arm64intr.h +OLD_FILES+=usr/lib/clang/16/include/arm_acle.h +OLD_FILES+=usr/lib/clang/16/include/arm_bf16.h +OLD_FILES+=usr/lib/clang/16/include/arm_cde.h +OLD_FILES+=usr/lib/clang/16/include/arm_cmse.h +OLD_FILES+=usr/lib/clang/16/include/arm_fp16.h +OLD_FILES+=usr/lib/clang/16/include/arm_mve.h +OLD_FILES+=usr/lib/clang/16/include/arm_neon.h +OLD_FILES+=usr/lib/clang/16/include/arm_neon_sve_bridge.h +OLD_FILES+=usr/lib/clang/16/include/arm_sve.h +OLD_FILES+=usr/lib/clang/16/include/armintr.h +OLD_FILES+=usr/lib/clang/16/include/avx2intrin.h +OLD_FILES+=usr/lib/clang/16/include/avx512bf16intrin.h +OLD_FILES+=usr/lib/clang/16/include/avx512bitalgintrin.h +OLD_FILES+=usr/lib/clang/16/include/avx512bwintrin.h +OLD_FILES+=usr/lib/clang/16/include/avx512cdintrin.h +OLD_FILES+=usr/lib/clang/16/include/avx512dqintrin.h +OLD_FILES+=usr/lib/clang/16/include/avx512erintrin.h +OLD_FILES+=usr/lib/clang/16/include/avx512fintrin.h +OLD_FILES+=usr/lib/clang/16/include/avx512fp16intrin.h +OLD_FILES+=usr/lib/clang/16/include/avx512ifmaintrin.h +OLD_FILES+=usr/lib/clang/16/include/avx512ifmavlintrin.h +OLD_FILES+=usr/lib/clang/16/include/avx512pfintrin.h +OLD_FILES+=usr/lib/clang/16/include/avx512vbmi2intrin.h +OLD_FILES+=usr/lib/clang/16/include/avx512vbmiintrin.h +OLD_FILES+=usr/lib/clang/16/include/avx512vbmivlintrin.h +OLD_FILES+=usr/lib/clang/16/include/avx512vlbf16intrin.h +OLD_FILES+=usr/lib/clang/16/include/avx512vlbitalgintrin.h +OLD_FILES+=usr/lib/clang/16/include/avx512vlbwintrin.h +OLD_FILES+=usr/lib/clang/16/include/avx512vlcdintrin.h +OLD_FILES+=usr/lib/clang/16/include/avx512vldqintrin.h +OLD_FILES+=usr/lib/clang/16/include/avx512vlfp16intrin.h +OLD_FILES+=usr/lib/clang/16/include/avx512vlintrin.h +OLD_FILES+=usr/lib/clang/16/include/avx512vlvbmi2intrin.h +OLD_FILES+=usr/lib/clang/16/include/avx512vlvnniintrin.h +OLD_FILES+=usr/lib/clang/16/include/avx512vlvp2intersectintrin.h +OLD_FILES+=usr/lib/clang/16/include/avx512vnniintrin.h +OLD_FILES+=usr/lib/clang/16/include/avx512vp2intersectintrin.h +OLD_FILES+=usr/lib/clang/16/include/avx512vpopcntdqintrin.h +OLD_FILES+=usr/lib/clang/16/include/avx512vpopcntdqvlintrin.h +OLD_FILES+=usr/lib/clang/16/include/avxifmaintrin.h +OLD_FILES+=usr/lib/clang/16/include/avxintrin.h +OLD_FILES+=usr/lib/clang/16/include/avxneconvertintrin.h +OLD_FILES+=usr/lib/clang/16/include/avxvnniint8intrin.h +OLD_FILES+=usr/lib/clang/16/include/avxvnniintrin.h +OLD_FILES+=usr/lib/clang/16/include/bmi2intrin.h +OLD_FILES+=usr/lib/clang/16/include/bmiintrin.h +OLD_FILES+=usr/lib/clang/16/include/builtins.h +OLD_FILES+=usr/lib/clang/16/include/cet.h +OLD_FILES+=usr/lib/clang/16/include/cetintrin.h +OLD_FILES+=usr/lib/clang/16/include/cldemoteintrin.h +OLD_FILES+=usr/lib/clang/16/include/clflushoptintrin.h +OLD_FILES+=usr/lib/clang/16/include/clwbintrin.h +OLD_FILES+=usr/lib/clang/16/include/clzerointrin.h +OLD_FILES+=usr/lib/clang/16/include/cmpccxaddintrin.h +OLD_FILES+=usr/lib/clang/16/include/cpuid.h +OLD_FILES+=usr/lib/clang/16/include/crc32intrin.h +OLD_FILES+=usr/lib/clang/16/include/cuda_wrappers/algorithm +OLD_FILES+=usr/lib/clang/16/include/cuda_wrappers/cmath +OLD_FILES+=usr/lib/clang/16/include/cuda_wrappers/complex +OLD_FILES+=usr/lib/clang/16/include/cuda_wrappers/new +OLD_DIRS+=usr/lib/clang/16/include/cuda_wrappers +OLD_FILES+=usr/lib/clang/16/include/emmintrin.h +OLD_FILES+=usr/lib/clang/16/include/enqcmdintrin.h +OLD_FILES+=usr/lib/clang/16/include/f16cintrin.h +OLD_FILES+=usr/lib/clang/16/include/float.h +OLD_FILES+=usr/lib/clang/16/include/fma4intrin.h +OLD_FILES+=usr/lib/clang/16/include/fmaintrin.h +OLD_FILES+=usr/lib/clang/16/include/fuzzer/FuzzedDataProvider.h +OLD_DIRS+=usr/lib/clang/16/include/fuzzer +OLD_FILES+=usr/lib/clang/16/include/fxsrintrin.h +OLD_FILES+=usr/lib/clang/16/include/gfniintrin.h +OLD_FILES+=usr/lib/clang/16/include/hexagon_circ_brev_intrinsics.h +OLD_FILES+=usr/lib/clang/16/include/hexagon_protos.h +OLD_FILES+=usr/lib/clang/16/include/hexagon_types.h +OLD_FILES+=usr/lib/clang/16/include/hlsl/hlsl_basic_types.h +OLD_FILES+=usr/lib/clang/16/include/hlsl/hlsl_intrinsics.h +OLD_DIRS+=usr/lib/clang/16/include/hlsl +OLD_FILES+=usr/lib/clang/16/include/hlsl.h +OLD_FILES+=usr/lib/clang/16/include/hresetintrin.h +OLD_FILES+=usr/lib/clang/16/include/htmintrin.h +OLD_FILES+=usr/lib/clang/16/include/htmxlintrin.h +OLD_FILES+=usr/lib/clang/16/include/hvx_hexagon_protos.h +OLD_FILES+=usr/lib/clang/16/include/ia32intrin.h +OLD_FILES+=usr/lib/clang/16/include/immintrin.h +OLD_FILES+=usr/lib/clang/16/include/intrin.h +OLD_FILES+=usr/lib/clang/16/include/inttypes.h +OLD_FILES+=usr/lib/clang/16/include/invpcidintrin.h +OLD_FILES+=usr/lib/clang/16/include/iso646.h +OLD_FILES+=usr/lib/clang/16/include/keylockerintrin.h +OLD_FILES+=usr/lib/clang/16/include/larchintrin.h +OLD_FILES+=usr/lib/clang/16/include/limits.h +OLD_FILES+=usr/lib/clang/16/include/lwpintrin.h +OLD_FILES+=usr/lib/clang/16/include/lzcntintrin.h +OLD_FILES+=usr/lib/clang/16/include/mm3dnow.h +OLD_FILES+=usr/lib/clang/16/include/mm_malloc.h +OLD_FILES+=usr/lib/clang/16/include/mmintrin.h +OLD_FILES+=usr/lib/clang/16/include/module.modulemap +OLD_FILES+=usr/lib/clang/16/include/movdirintrin.h +OLD_FILES+=usr/lib/clang/16/include/msa.h +OLD_FILES+=usr/lib/clang/16/include/mwaitxintrin.h +OLD_FILES+=usr/lib/clang/16/include/nmmintrin.h +OLD_FILES+=usr/lib/clang/16/include/omp-tools.h +OLD_FILES+=usr/lib/clang/16/include/omp.h +OLD_FILES+=usr/lib/clang/16/include/ompt.h +OLD_FILES+=usr/lib/clang/16/include/opencl-c-base.h +OLD_FILES+=usr/lib/clang/16/include/opencl-c.h +OLD_FILES+=usr/lib/clang/16/include/openmp_wrappers/__clang_openmp_device_functions.h +OLD_FILES+=usr/lib/clang/16/include/openmp_wrappers/cmath +OLD_FILES+=usr/lib/clang/16/include/openmp_wrappers/complex +OLD_FILES+=usr/lib/clang/16/include/openmp_wrappers/complex.h +OLD_FILES+=usr/lib/clang/16/include/openmp_wrappers/complex_cmath.h +OLD_FILES+=usr/lib/clang/16/include/openmp_wrappers/math.h +OLD_FILES+=usr/lib/clang/16/include/openmp_wrappers/new +OLD_DIRS+=usr/lib/clang/16/include/openmp_wrappers +OLD_FILES+=usr/lib/clang/16/include/orc_rt/c_api.h +OLD_DIRS+=usr/lib/clang/16/include/orc_rt +OLD_FILES+=usr/lib/clang/16/include/pconfigintrin.h +OLD_FILES+=usr/lib/clang/16/include/pkuintrin.h +OLD_FILES+=usr/lib/clang/16/include/pmmintrin.h +OLD_FILES+=usr/lib/clang/16/include/popcntintrin.h +OLD_FILES+=usr/lib/clang/16/include/ppc_wrappers/bmi2intrin.h +OLD_FILES+=usr/lib/clang/16/include/ppc_wrappers/bmiintrin.h +OLD_FILES+=usr/lib/clang/16/include/ppc_wrappers/emmintrin.h +OLD_FILES+=usr/lib/clang/16/include/ppc_wrappers/immintrin.h +OLD_FILES+=usr/lib/clang/16/include/ppc_wrappers/mm_malloc.h +OLD_FILES+=usr/lib/clang/16/include/ppc_wrappers/mmintrin.h +OLD_FILES+=usr/lib/clang/16/include/ppc_wrappers/pmmintrin.h +OLD_FILES+=usr/lib/clang/16/include/ppc_wrappers/smmintrin.h +OLD_FILES+=usr/lib/clang/16/include/ppc_wrappers/tmmintrin.h +OLD_FILES+=usr/lib/clang/16/include/ppc_wrappers/x86gprintrin.h +OLD_FILES+=usr/lib/clang/16/include/ppc_wrappers/x86intrin.h +OLD_FILES+=usr/lib/clang/16/include/ppc_wrappers/xmmintrin.h +OLD_DIRS+=usr/lib/clang/16/include/ppc_wrappers +OLD_FILES+=usr/lib/clang/16/include/prfchiintrin.h +OLD_FILES+=usr/lib/clang/16/include/prfchwintrin.h +OLD_FILES+=usr/lib/clang/16/include/profile/InstrProfData.inc +OLD_FILES+=usr/lib/clang/16/include/profile/MemProfData.inc +OLD_DIRS+=usr/lib/clang/16/include/profile +OLD_FILES+=usr/lib/clang/16/include/ptwriteintrin.h +OLD_FILES+=usr/lib/clang/16/include/raointintrin.h +OLD_FILES+=usr/lib/clang/16/include/rdpruintrin.h +OLD_FILES+=usr/lib/clang/16/include/rdseedintrin.h +OLD_FILES+=usr/lib/clang/16/include/riscv_vector.h +OLD_FILES+=usr/lib/clang/16/include/rtmintrin.h +OLD_FILES+=usr/lib/clang/16/include/s390intrin.h +OLD_FILES+=usr/lib/clang/16/include/sanitizer/allocator_interface.h +OLD_FILES+=usr/lib/clang/16/include/sanitizer/asan_interface.h +OLD_FILES+=usr/lib/clang/16/include/sanitizer/common_interface_defs.h +OLD_FILES+=usr/lib/clang/16/include/sanitizer/coverage_interface.h +OLD_FILES+=usr/lib/clang/16/include/sanitizer/dfsan_interface.h +OLD_FILES+=usr/lib/clang/16/include/sanitizer/hwasan_interface.h +OLD_FILES+=usr/lib/clang/16/include/sanitizer/linux_syscall_hooks.h +OLD_FILES+=usr/lib/clang/16/include/sanitizer/lsan_interface.h +OLD_FILES+=usr/lib/clang/16/include/sanitizer/memprof_interface.h +OLD_FILES+=usr/lib/clang/16/include/sanitizer/msan_interface.h +OLD_FILES+=usr/lib/clang/16/include/sanitizer/netbsd_syscall_hooks.h +OLD_FILES+=usr/lib/clang/16/include/sanitizer/scudo_interface.h +OLD_FILES+=usr/lib/clang/16/include/sanitizer/tsan_interface.h +OLD_FILES+=usr/lib/clang/16/include/sanitizer/tsan_interface_atomic.h +OLD_FILES+=usr/lib/clang/16/include/sanitizer/ubsan_interface.h +OLD_DIRS+=usr/lib/clang/16/include/sanitizer +OLD_FILES+=usr/lib/clang/16/include/serializeintrin.h +OLD_FILES+=usr/lib/clang/16/include/sgxintrin.h +OLD_FILES+=usr/lib/clang/16/include/shaintrin.h +OLD_FILES+=usr/lib/clang/16/include/smmintrin.h +OLD_FILES+=usr/lib/clang/16/include/stdalign.h +OLD_FILES+=usr/lib/clang/16/include/stdarg.h +OLD_FILES+=usr/lib/clang/16/include/stdatomic.h +OLD_FILES+=usr/lib/clang/16/include/stdbool.h +OLD_FILES+=usr/lib/clang/16/include/stddef.h +OLD_FILES+=usr/lib/clang/16/include/stdint.h +OLD_FILES+=usr/lib/clang/16/include/stdnoreturn.h +OLD_FILES+=usr/lib/clang/16/include/tbmintrin.h +OLD_FILES+=usr/lib/clang/16/include/tgmath.h +OLD_FILES+=usr/lib/clang/16/include/tmmintrin.h +OLD_FILES+=usr/lib/clang/16/include/tsxldtrkintrin.h +OLD_FILES+=usr/lib/clang/16/include/uintrintrin.h +OLD_FILES+=usr/lib/clang/16/include/unwind.h +OLD_FILES+=usr/lib/clang/16/include/vadefs.h +OLD_FILES+=usr/lib/clang/16/include/vaesintrin.h +OLD_FILES+=usr/lib/clang/16/include/varargs.h +OLD_FILES+=usr/lib/clang/16/include/vecintrin.h +OLD_FILES+=usr/lib/clang/16/include/velintrin.h +OLD_FILES+=usr/lib/clang/16/include/velintrin_approx.h +OLD_FILES+=usr/lib/clang/16/include/velintrin_gen.h +OLD_FILES+=usr/lib/clang/16/include/vpclmulqdqintrin.h +OLD_FILES+=usr/lib/clang/16/include/waitpkgintrin.h +OLD_FILES+=usr/lib/clang/16/include/wasm_simd128.h +OLD_FILES+=usr/lib/clang/16/include/wbnoinvdintrin.h +OLD_FILES+=usr/lib/clang/16/include/wmmintrin.h +OLD_FILES+=usr/lib/clang/16/include/x86gprintrin.h +OLD_FILES+=usr/lib/clang/16/include/x86intrin.h +OLD_FILES+=usr/lib/clang/16/include/xmmintrin.h +OLD_FILES+=usr/lib/clang/16/include/xopintrin.h +OLD_FILES+=usr/lib/clang/16/include/xray/xray_interface.h +OLD_FILES+=usr/lib/clang/16/include/xray/xray_log_interface.h +OLD_FILES+=usr/lib/clang/16/include/xray/xray_records.h +OLD_DIRS+=usr/lib/clang/16/include/xray +OLD_FILES+=usr/lib/clang/16/include/xsavecintrin.h +OLD_FILES+=usr/lib/clang/16/include/xsaveintrin.h +OLD_FILES+=usr/lib/clang/16/include/xsaveoptintrin.h +OLD_FILES+=usr/lib/clang/16/include/xsavesintrin.h +OLD_FILES+=usr/lib/clang/16/include/xtestintrin.h +OLD_DIRS+=usr/lib/clang/16/include +OLD_FILES+=usr/lib/clang/16/lib/freebsd/libclang_rt.asan-aarch64.a +OLD_FILES+=usr/lib/clang/16/lib/freebsd/libclang_rt.asan-aarch64.so +OLD_FILES+=usr/lib/clang/16/lib/freebsd/libclang_rt.asan-arm.a +OLD_FILES+=usr/lib/clang/16/lib/freebsd/libclang_rt.asan-arm.so +OLD_FILES+=usr/lib/clang/16/lib/freebsd/libclang_rt.asan-armhf.a +OLD_FILES+=usr/lib/clang/16/lib/freebsd/libclang_rt.asan-armhf.so +OLD_FILES+=usr/lib/clang/16/lib/freebsd/libclang_rt.asan-i386.a +OLD_FILES+=usr/lib/clang/16/lib/freebsd/libclang_rt.asan-i386.so +OLD_FILES+=usr/lib/clang/16/lib/freebsd/libclang_rt.asan-powerpc64.a +OLD_FILES+=usr/lib/clang/16/lib/freebsd/libclang_rt.asan-powerpc64.so +OLD_FILES+=usr/lib/clang/16/lib/freebsd/libclang_rt.asan-powerpc64le.a +OLD_FILES+=usr/lib/clang/16/lib/freebsd/libclang_rt.asan-powerpc64le.so +OLD_FILES+=usr/lib/clang/16/lib/freebsd/libclang_rt.asan-preinit-aarch64.a +OLD_FILES+=usr/lib/clang/16/lib/freebsd/libclang_rt.asan-preinit-arm.a +OLD_FILES+=usr/lib/clang/16/lib/freebsd/libclang_rt.asan-preinit-armhf.a +OLD_FILES+=usr/lib/clang/16/lib/freebsd/libclang_rt.asan-preinit-i386.a +OLD_FILES+=usr/lib/clang/16/lib/freebsd/libclang_rt.asan-preinit-powerpc64.a +OLD_FILES+=usr/lib/clang/16/lib/freebsd/libclang_rt.asan-preinit-powerpc64le.a +OLD_FILES+=usr/lib/clang/16/lib/freebsd/libclang_rt.asan-preinit-riscv64.a +OLD_FILES+=usr/lib/clang/16/lib/freebsd/libclang_rt.asan-preinit-x86_64.a +OLD_FILES+=usr/lib/clang/16/lib/freebsd/libclang_rt.asan-riscv64.a +OLD_FILES+=usr/lib/clang/16/lib/freebsd/libclang_rt.asan-riscv64.so +OLD_FILES+=usr/lib/clang/16/lib/freebsd/libclang_rt.asan-x86_64.a +OLD_FILES+=usr/lib/clang/16/lib/freebsd/libclang_rt.asan-x86_64.so +OLD_FILES+=usr/lib/clang/16/lib/freebsd/libclang_rt.asan_cxx-aarch64.a +OLD_FILES+=usr/lib/clang/16/lib/freebsd/libclang_rt.asan_cxx-arm.a +OLD_FILES+=usr/lib/clang/16/lib/freebsd/libclang_rt.asan_cxx-armhf.a +OLD_FILES+=usr/lib/clang/16/lib/freebsd/libclang_rt.asan_cxx-i386.a +OLD_FILES+=usr/lib/clang/16/lib/freebsd/libclang_rt.asan_cxx-powerpc64.a +OLD_FILES+=usr/lib/clang/16/lib/freebsd/libclang_rt.asan_cxx-powerpc64le.a +OLD_FILES+=usr/lib/clang/16/lib/freebsd/libclang_rt.asan_cxx-riscv64.a +OLD_FILES+=usr/lib/clang/16/lib/freebsd/libclang_rt.asan_cxx-x86_64.a +OLD_FILES+=usr/lib/clang/16/lib/freebsd/libclang_rt.asan_static-i386.a +OLD_FILES+=usr/lib/clang/16/lib/freebsd/libclang_rt.asan_static-powerpc64.a +OLD_FILES+=usr/lib/clang/16/lib/freebsd/libclang_rt.asan_static-powerpc64le.a +OLD_FILES+=usr/lib/clang/16/lib/freebsd/libclang_rt.asan_static-x86_64.a +OLD_FILES+=usr/lib/clang/16/lib/freebsd/libclang_rt.cfi-aarch64.a +OLD_FILES+=usr/lib/clang/16/lib/freebsd/libclang_rt.cfi-arm.a +OLD_FILES+=usr/lib/clang/16/lib/freebsd/libclang_rt.cfi-armhf.a +OLD_FILES+=usr/lib/clang/16/lib/freebsd/libclang_rt.cfi-i386.a +OLD_FILES+=usr/lib/clang/16/lib/freebsd/libclang_rt.cfi-x86_64.a +OLD_FILES+=usr/lib/clang/16/lib/freebsd/libclang_rt.cfi_diag-aarch64.a +OLD_FILES+=usr/lib/clang/16/lib/freebsd/libclang_rt.cfi_diag-arm.a +OLD_FILES+=usr/lib/clang/16/lib/freebsd/libclang_rt.cfi_diag-armhf.a +OLD_FILES+=usr/lib/clang/16/lib/freebsd/libclang_rt.cfi_diag-i386.a +OLD_FILES+=usr/lib/clang/16/lib/freebsd/libclang_rt.cfi_diag-x86_64.a +OLD_FILES+=usr/lib/clang/16/lib/freebsd/libclang_rt.dd-aarch64.a +OLD_FILES+=usr/lib/clang/16/lib/freebsd/libclang_rt.dd-x86_64.a +OLD_FILES+=usr/lib/clang/16/lib/freebsd/libclang_rt.fuzzer-aarch64.a +OLD_FILES+=usr/lib/clang/16/lib/freebsd/libclang_rt.fuzzer-x86_64.a +OLD_FILES+=usr/lib/clang/16/lib/freebsd/libclang_rt.fuzzer_interceptors-x86_64.a +OLD_FILES+=usr/lib/clang/16/lib/freebsd/libclang_rt.fuzzer_no_main-aarch64.a +OLD_FILES+=usr/lib/clang/16/lib/freebsd/libclang_rt.fuzzer_no_main-x86_64.a +OLD_FILES+=usr/lib/clang/16/lib/freebsd/libclang_rt.msan-aarch64.a +OLD_FILES+=usr/lib/clang/16/lib/freebsd/libclang_rt.msan-powerpc64.a +OLD_FILES+=usr/lib/clang/16/lib/freebsd/libclang_rt.msan-powerpc64le.a +OLD_FILES+=usr/lib/clang/16/lib/freebsd/libclang_rt.msan-x86_64.a +OLD_FILES+=usr/lib/clang/16/lib/freebsd/libclang_rt.msan_cxx-aarch64.a +OLD_FILES+=usr/lib/clang/16/lib/freebsd/libclang_rt.msan_cxx-powerpc64.a +OLD_FILES+=usr/lib/clang/16/lib/freebsd/libclang_rt.msan_cxx-powerpc64le.a +OLD_FILES+=usr/lib/clang/16/lib/freebsd/libclang_rt.msan_cxx-x86_64.a +OLD_FILES+=usr/lib/clang/16/lib/freebsd/libclang_rt.profile-aarch64.a +OLD_FILES+=usr/lib/clang/16/lib/freebsd/libclang_rt.profile-arm.a +OLD_FILES+=usr/lib/clang/16/lib/freebsd/libclang_rt.profile-armhf.a +OLD_FILES+=usr/lib/clang/16/lib/freebsd/libclang_rt.profile-i386.a +OLD_FILES+=usr/lib/clang/16/lib/freebsd/libclang_rt.profile-powerpc.a +OLD_FILES+=usr/lib/clang/16/lib/freebsd/libclang_rt.profile-powerpc64.a +OLD_FILES+=usr/lib/clang/16/lib/freebsd/libclang_rt.profile-powerpc64le.a +OLD_FILES+=usr/lib/clang/16/lib/freebsd/libclang_rt.profile-riscv64.a +OLD_FILES+=usr/lib/clang/16/lib/freebsd/libclang_rt.profile-x86_64.a +OLD_FILES+=usr/lib/clang/16/lib/freebsd/libclang_rt.safestack-aarch64.a +OLD_FILES+=usr/lib/clang/16/lib/freebsd/libclang_rt.safestack-i386.a +OLD_FILES+=usr/lib/clang/16/lib/freebsd/libclang_rt.safestack-x86_64.a +OLD_FILES+=usr/lib/clang/16/lib/freebsd/libclang_rt.stats-aarch64.a +OLD_FILES+=usr/lib/clang/16/lib/freebsd/libclang_rt.stats-arm.a +OLD_FILES+=usr/lib/clang/16/lib/freebsd/libclang_rt.stats-armhf.a +OLD_FILES+=usr/lib/clang/16/lib/freebsd/libclang_rt.stats-i386.a +OLD_FILES+=usr/lib/clang/16/lib/freebsd/libclang_rt.stats-powerpc64.a +OLD_FILES+=usr/lib/clang/16/lib/freebsd/libclang_rt.stats-powerpc64le.a +OLD_FILES+=usr/lib/clang/16/lib/freebsd/libclang_rt.stats-riscv64.a +OLD_FILES+=usr/lib/clang/16/lib/freebsd/libclang_rt.stats-x86_64.a +OLD_FILES+=usr/lib/clang/16/lib/freebsd/libclang_rt.stats_client-aarch64.a +OLD_FILES+=usr/lib/clang/16/lib/freebsd/libclang_rt.stats_client-arm.a +OLD_FILES+=usr/lib/clang/16/lib/freebsd/libclang_rt.stats_client-armhf.a +OLD_FILES+=usr/lib/clang/16/lib/freebsd/libclang_rt.stats_client-i386.a +OLD_FILES+=usr/lib/clang/16/lib/freebsd/libclang_rt.stats_client-powerpc64.a +OLD_FILES+=usr/lib/clang/16/lib/freebsd/libclang_rt.stats_client-powerpc64le.a +OLD_FILES+=usr/lib/clang/16/lib/freebsd/libclang_rt.stats_client-riscv64.a +OLD_FILES+=usr/lib/clang/16/lib/freebsd/libclang_rt.stats_client-x86_64.a +OLD_FILES+=usr/lib/clang/16/lib/freebsd/libclang_rt.tsan-aarch64.a +OLD_FILES+=usr/lib/clang/16/lib/freebsd/libclang_rt.tsan-powerpc64.a +OLD_FILES+=usr/lib/clang/16/lib/freebsd/libclang_rt.tsan-powerpc64le.a +OLD_FILES+=usr/lib/clang/16/lib/freebsd/libclang_rt.tsan-x86_64.a +OLD_FILES+=usr/lib/clang/16/lib/freebsd/libclang_rt.tsan_cxx-aarch64.a +OLD_FILES+=usr/lib/clang/16/lib/freebsd/libclang_rt.tsan_cxx-powerpc64.a +OLD_FILES+=usr/lib/clang/16/lib/freebsd/libclang_rt.tsan_cxx-powerpc64le.a +OLD_FILES+=usr/lib/clang/16/lib/freebsd/libclang_rt.tsan_cxx-x86_64.a +OLD_FILES+=usr/lib/clang/16/lib/freebsd/libclang_rt.ubsan_minimal-aarch64.a +OLD_FILES+=usr/lib/clang/16/lib/freebsd/libclang_rt.ubsan_minimal-arm.a +OLD_FILES+=usr/lib/clang/16/lib/freebsd/libclang_rt.ubsan_minimal-armhf.a +OLD_FILES+=usr/lib/clang/16/lib/freebsd/libclang_rt.ubsan_minimal-i386.a +OLD_FILES+=usr/lib/clang/16/lib/freebsd/libclang_rt.ubsan_minimal-powerpc64.a +OLD_FILES+=usr/lib/clang/16/lib/freebsd/libclang_rt.ubsan_minimal-powerpc64le.a +OLD_FILES+=usr/lib/clang/16/lib/freebsd/libclang_rt.ubsan_minimal-riscv64.a +OLD_FILES+=usr/lib/clang/16/lib/freebsd/libclang_rt.ubsan_minimal-x86_64.a +OLD_FILES+=usr/lib/clang/16/lib/freebsd/libclang_rt.ubsan_standalone-aarch64.a +OLD_FILES+=usr/lib/clang/16/lib/freebsd/libclang_rt.ubsan_standalone-arm.a +OLD_FILES+=usr/lib/clang/16/lib/freebsd/libclang_rt.ubsan_standalone-armhf.a +OLD_FILES+=usr/lib/clang/16/lib/freebsd/libclang_rt.ubsan_standalone-i386.a +OLD_FILES+=usr/lib/clang/16/lib/freebsd/libclang_rt.ubsan_standalone-powerpc64.a +OLD_FILES+=usr/lib/clang/16/lib/freebsd/libclang_rt.ubsan_standalone-powerpc64le.a +OLD_FILES+=usr/lib/clang/16/lib/freebsd/libclang_rt.ubsan_standalone-riscv64.a +OLD_FILES+=usr/lib/clang/16/lib/freebsd/libclang_rt.ubsan_standalone-x86_64.a +OLD_FILES+=usr/lib/clang/16/lib/freebsd/libclang_rt.ubsan_standalone_cxx-aarch64.a +OLD_FILES+=usr/lib/clang/16/lib/freebsd/libclang_rt.ubsan_standalone_cxx-arm.a +OLD_FILES+=usr/lib/clang/16/lib/freebsd/libclang_rt.ubsan_standalone_cxx-armhf.a +OLD_FILES+=usr/lib/clang/16/lib/freebsd/libclang_rt.ubsan_standalone_cxx-i386.a +OLD_FILES+=usr/lib/clang/16/lib/freebsd/libclang_rt.ubsan_standalone_cxx-powerpc64.a +OLD_FILES+=usr/lib/clang/16/lib/freebsd/libclang_rt.ubsan_standalone_cxx-powerpc64le.a +OLD_FILES+=usr/lib/clang/16/lib/freebsd/libclang_rt.ubsan_standalone_cxx-riscv64.a +OLD_FILES+=usr/lib/clang/16/lib/freebsd/libclang_rt.ubsan_standalone_cxx-x86_64.a +OLD_FILES+=usr/lib/clang/16/lib/freebsd/libclang_rt.xray-aarch64.a +OLD_FILES+=usr/lib/clang/16/lib/freebsd/libclang_rt.xray-arm.a +OLD_FILES+=usr/lib/clang/16/lib/freebsd/libclang_rt.xray-armhf.a +OLD_FILES+=usr/lib/clang/16/lib/freebsd/libclang_rt.xray-basic-aarch64.a +OLD_FILES+=usr/lib/clang/16/lib/freebsd/libclang_rt.xray-basic-arm.a +OLD_FILES+=usr/lib/clang/16/lib/freebsd/libclang_rt.xray-basic-armhf.a +OLD_FILES+=usr/lib/clang/16/lib/freebsd/libclang_rt.xray-basic-powerpc64le.a +OLD_FILES+=usr/lib/clang/16/lib/freebsd/libclang_rt.xray-basic-x86_64.a +OLD_FILES+=usr/lib/clang/16/lib/freebsd/libclang_rt.xray-fdr-aarch64.a +OLD_FILES+=usr/lib/clang/16/lib/freebsd/libclang_rt.xray-fdr-arm.a +OLD_FILES+=usr/lib/clang/16/lib/freebsd/libclang_rt.xray-fdr-armhf.a +OLD_FILES+=usr/lib/clang/16/lib/freebsd/libclang_rt.xray-fdr-powerpc64le.a +OLD_FILES+=usr/lib/clang/16/lib/freebsd/libclang_rt.xray-fdr-x86_64.a +OLD_FILES+=usr/lib/clang/16/lib/freebsd/libclang_rt.xray-powerpc64le.a +OLD_FILES+=usr/lib/clang/16/lib/freebsd/libclang_rt.xray-profiling-aarch64.a +OLD_FILES+=usr/lib/clang/16/lib/freebsd/libclang_rt.xray-profiling-arm.a +OLD_FILES+=usr/lib/clang/16/lib/freebsd/libclang_rt.xray-profiling-armhf.a +OLD_FILES+=usr/lib/clang/16/lib/freebsd/libclang_rt.xray-profiling-powerpc64le.a +OLD_FILES+=usr/lib/clang/16/lib/freebsd/libclang_rt.xray-profiling-x86_64.a +OLD_FILES+=usr/lib/clang/16/lib/freebsd/libclang_rt.xray-x86_64.a +OLD_DIRS+=usr/lib/clang/16/lib/freebsd +OLD_DIRS+=usr/lib/clang/16/lib +OLD_FILES+=usr/lib/clang/16/share/asan_ignorelist.txt +OLD_FILES+=usr/lib/clang/16/share/cfi_ignorelist.txt +OLD_FILES+=usr/lib/clang/16/share/msan_ignorelist.txt +OLD_DIRS+=usr/lib/clang/16/share +OLD_DIRS+=usr/lib/clang/16 + +# 20240107: new libc++ import which bumps version from 16 to 17 +OLD_FILES+=usr/include/c++/v1/__bsd_locale_defaults.h +OLD_FILES+=usr/include/c++/v1/__bsd_locale_fallbacks.h +OLD_FILES+=usr/include/c++/v1/__debug +OLD_FILES+=usr/include/c++/v1/__errc +OLD_FILES+=usr/include/c++/v1/__functional/unwrap_ref.h +OLD_FILES+=usr/include/c++/v1/__mutex_base +OLD_FILES+=usr/include/c++/v1/__ranges/copyable_box.h +OLD_FILES+=usr/include/c++/v1/__std_stream +OLD_FILES+=usr/include/c++/v1/__tuple_dir/apply_cv.h +OLD_FILES+=usr/include/c++/v1/__tuple_dir/make_tuple_types.h +OLD_FILES+=usr/include/c++/v1/__tuple_dir/pair_like.h +OLD_FILES+=usr/include/c++/v1/__tuple_dir/sfinae_helpers.h +OLD_FILES+=usr/include/c++/v1/__tuple_dir/tuple_element.h +OLD_FILES+=usr/include/c++/v1/__tuple_dir/tuple_indices.h +OLD_FILES+=usr/include/c++/v1/__tuple_dir/tuple_like.h +OLD_FILES+=usr/include/c++/v1/__tuple_dir/tuple_like_ext.h +OLD_FILES+=usr/include/c++/v1/__tuple_dir/tuple_size.h +OLD_FILES+=usr/include/c++/v1/__tuple_dir/tuple_types.h +OLD_DIRS+=usr/include/c++/v1/__tuple_dir +OLD_FILES+=usr/include/c++/v1/experimental/algorithm +OLD_FILES+=usr/include/c++/v1/experimental/coroutine +OLD_FILES+=usr/include/c++/v1/experimental/functional + # 20231006: rename tcp6_v4unmapped_bind_test OLD_FILES+=usr/tests/sys/netinet/tcp6_v4unmapped_bind_test diff --git a/contrib/llvm-project/FREEBSD-Xlist b/contrib/llvm-project/FREEBSD-Xlist index 48972748b4b..33dc1ed3867 100644 --- a/contrib/llvm-project/FREEBSD-Xlist +++ b/contrib/llvm-project/FREEBSD-Xlist @@ -1,5 +1,6 @@ .arcconfig .arclint +.ci/ .clang-format .clang-tidy .git-blame-ignore-revs @@ -11,14 +12,12 @@ LICENSE.TXT README.md SECURITY.md bolt/ -clang-tools-extra/ clang/.clang-format clang/.clang-tidy clang/.gitignore clang/CMakeLists.txt clang/CodeOwners.rst clang/INSTALL.txt -clang/ModuleInfo.txt clang/NOTES.txt clang/README.txt clang/bindings/ @@ -102,7 +101,6 @@ clang/tools/c-index-test/ clang/tools/clang-check/ clang/tools/clang-diff/ clang/tools/clang-extdef-mapping/ -clang/tools/clang-format-vs/ clang/tools/clang-format/.clang-format clang/tools/clang-format/CMakeLists.txt clang/tools/clang-format/clang-format-bbedit.applescript @@ -113,6 +111,7 @@ clang/tools/clang-format/clang-format.el clang/tools/clang-format/clang-format.py clang/tools/clang-format/fuzzer/ clang/tools/clang-format/git-clang-format +clang/tools/clang-format-vs/ clang/tools/clang-fuzzer/ clang/tools/clang-import-test/ clang/tools/clang-linker-wrapper/ @@ -130,8 +129,8 @@ clang/tools/driver/Info.plist.in clang/tools/include-mapping/ clang/tools/libclang/ clang/tools/nvptx-arch/CMakeLists.txt -clang/tools/scan-build-py/ clang/tools/scan-build/ +clang/tools/scan-build-py/ clang/tools/scan-view/ clang/unittests/ clang/utils/ABITest/ @@ -148,7 +147,9 @@ clang/utils/VtableTest/ clang/utils/analyzer/ clang/utils/bash-autocomplete.sh clang/utils/builtin-defines.c +clang/utils/bundle_resources.py clang/utils/check_cfc/ +clang/utils/ci/ clang/utils/clangdiag.py clang/utils/convert_arm_neon.py clang/utils/creduce-clang-crash.py @@ -161,6 +162,7 @@ clang/utils/perf-training/ clang/utils/token-delta.py clang/utils/valgrind/ clang/www/ +clang-tools-extra/ cmake/ compiler-rt/.gitignore compiler-rt/CMakeLists.txt @@ -173,11 +175,11 @@ compiler-rt/lib/asan/.clang-format compiler-rt/lib/asan/CMakeLists.txt compiler-rt/lib/asan/scripts/ compiler-rt/lib/asan/tests/ +compiler-rt/lib/asan_abi/CMakeLists.txt compiler-rt/lib/builtins/CMakeLists.txt compiler-rt/lib/builtins/Darwin-excludes/ compiler-rt/lib/builtins/macho_embedded/ compiler-rt/lib/cfi/CMakeLists.txt -compiler-rt/lib/crt/CMakeLists.txt compiler-rt/lib/dfsan/.clang-format compiler-rt/lib/dfsan/CMakeLists.txt compiler-rt/lib/dfsan/scripts/ @@ -258,8 +260,9 @@ libcxx/include/CMakeLists.txt libcxx/include/__config_site.in libcxx/include/__support/ libcxx/lib/ +libcxx/modules/CMakeLists.txt +libcxx/modules/CMakeLists.txt.in libcxx/src/CMakeLists.txt -libcxx/src/support/solaris/ libcxx/src/support/win32/ libcxx/test/ libcxx/utils/ @@ -281,6 +284,7 @@ lld/cmake/ lld/docs/CMakeLists.txt lld/test/ lld/tools/lld/CMakeLists.txt +lld/unittests/ lld/utils/ lld/wasm/ lldb/.clang-format @@ -334,6 +338,7 @@ lldb/source/Plugins/ABI/ARC/CMakeLists.txt lldb/source/Plugins/ABI/ARM/CMakeLists.txt lldb/source/Plugins/ABI/CMakeLists.txt lldb/source/Plugins/ABI/Hexagon/CMakeLists.txt +lldb/source/Plugins/ABI/MSP430/CMakeLists.txt lldb/source/Plugins/ABI/Mips/CMakeLists.txt lldb/source/Plugins/ABI/PowerPC/CMakeLists.txt lldb/source/Plugins/ABI/SystemZ/CMakeLists.txt @@ -381,8 +386,7 @@ lldb/source/Plugins/LanguageRuntime/CPlusPlus/CMakeLists.txt lldb/source/Plugins/LanguageRuntime/CPlusPlus/ItaniumABI/CMakeLists.txt lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/CMakeLists.txt lldb/source/Plugins/LanguageRuntime/ObjC/CMakeLists.txt -lldb/source/Plugins/LanguageRuntime/RenderScript/CMakeLists.txt -lldb/source/Plugins/LanguageRuntime/RenderScript/RenderScriptRuntime/CMakeLists.txt +lldb/source/Plugins/LanguageRuntime/ObjC/GNUstepObjCRuntime/CMakeLists.txt lldb/source/Plugins/MemoryHistory/CMakeLists.txt lldb/source/Plugins/MemoryHistory/asan/CMakeLists.txt lldb/source/Plugins/ObjectContainer/BSD-Archive/CMakeLists.txt @@ -391,12 +395,14 @@ lldb/source/Plugins/ObjectContainer/Mach-O-Fileset/CMakeLists.txt lldb/source/Plugins/ObjectContainer/Universal-Mach-O/ lldb/source/Plugins/ObjectFile/Breakpad/CMakeLists.txt lldb/source/Plugins/ObjectFile/CMakeLists.txt +lldb/source/Plugins/ObjectFile/COFF/CMakeLists.txt lldb/source/Plugins/ObjectFile/ELF/CMakeLists.txt -lldb/source/Plugins/ObjectFile/JIT/CMakeLists.txt +lldb/source/Plugins/ObjectFile/JSON/CMakeLists.txt lldb/source/Plugins/ObjectFile/Mach-O/ lldb/source/Plugins/ObjectFile/Minidump/CMakeLists.txt lldb/source/Plugins/ObjectFile/PDB/CMakeLists.txt lldb/source/Plugins/ObjectFile/PECOFF/ +lldb/source/Plugins/ObjectFile/Placeholder/CMakeLists.txt lldb/source/Plugins/ObjectFile/wasm/CMakeLists.txt lldb/source/Plugins/OperatingSystem/CMakeLists.txt lldb/source/Plugins/OperatingSystem/Python/CMakeLists.txt @@ -427,6 +433,7 @@ lldb/source/Plugins/Process/minidump/CMakeLists.txt lldb/source/Plugins/Process/scripted/CMakeLists.txt lldb/source/Plugins/REPL/CMakeLists.txt lldb/source/Plugins/REPL/Clang/CMakeLists.txt +lldb/source/Plugins/RegisterTypeBuilder/CMakeLists.txt lldb/source/Plugins/ScriptInterpreter/CMakeLists.txt lldb/source/Plugins/ScriptInterpreter/Lua/CMakeLists.txt lldb/source/Plugins/ScriptInterpreter/None/CMakeLists.txt @@ -435,7 +442,9 @@ lldb/source/Plugins/StructuredData/CMakeLists.txt lldb/source/Plugins/StructuredData/DarwinLog/CMakeLists.txt lldb/source/Plugins/SymbolFile/Breakpad/CMakeLists.txt lldb/source/Plugins/SymbolFile/CMakeLists.txt +lldb/source/Plugins/SymbolFile/CTF/CMakeLists.txt lldb/source/Plugins/SymbolFile/DWARF/CMakeLists.txt +lldb/source/Plugins/SymbolFile/JSON/CMakeLists.txt lldb/source/Plugins/SymbolFile/NativePDB/CMakeLists.txt lldb/source/Plugins/SymbolFile/PDB/CMakeLists.txt lldb/source/Plugins/SymbolFile/Symtab/CMakeLists.txt @@ -483,7 +492,6 @@ lldb/utils/lit-cpuid/ lldb/utils/lldb-dotest/ lldb/utils/lldb-repro/ lldb/utils/lui/ -llvm-libgcc/ llvm/.clang-format llvm/.clang-tidy llvm/.gitattributes @@ -499,7 +507,9 @@ llvm/cmake/ llvm/configure llvm/docs/ llvm/examples/ +llvm/include/CMakeLists.txt llvm/include/llvm/CMakeLists.txt +llvm/include/llvm/CodeGen/CMakeLists.txt llvm/include/llvm/Config/ llvm/include/llvm/Frontend/CMakeLists.txt llvm/include/llvm/Frontend/OpenACC/CMakeLists.txt @@ -509,7 +519,6 @@ llvm/include/llvm/Support/CMakeLists.txt llvm/include/llvm/Support/LICENSE.TXT llvm/include/llvm/TargetParser/CMakeLists.txt llvm/lib/Analysis/CMakeLists.txt -llvm/lib/Analysis/README.txt llvm/lib/Analysis/models/ llvm/lib/AsmParser/CMakeLists.txt llvm/lib/BinaryFormat/CMakeLists.txt @@ -528,6 +537,7 @@ llvm/lib/CodeGen/SelectionDAG/CMakeLists.txt llvm/lib/DWARFLinker/CMakeLists.txt llvm/lib/DWARFLinkerParallel/CMakeLists.txt llvm/lib/DWP/CMakeLists.txt +llvm/lib/DebugInfo/BTF/CMakeLists.txt llvm/lib/DebugInfo/CMakeLists.txt llvm/lib/DebugInfo/CodeView/CMakeLists.txt llvm/lib/DebugInfo/DWARF/CMakeLists.txt @@ -749,8 +759,8 @@ llvm/resources/ llvm/runtimes/ llvm/test/ llvm/tools/CMakeLists.txt -llvm/tools/bugpoint-passes/ llvm/tools/bugpoint/CMakeLists.txt +llvm/tools/bugpoint-passes/ llvm/tools/dsymutil/ llvm/tools/dxil-dis/ llvm/tools/gold/ @@ -758,8 +768,8 @@ llvm/tools/llc/CMakeLists.txt llvm/tools/lli/CMakeLists.txt llvm/tools/lli/ChildTarget/CMakeLists.txt llvm/tools/llvm-ar/CMakeLists.txt -llvm/tools/llvm-as-fuzzer/ llvm/tools/llvm-as/CMakeLists.txt +llvm/tools/llvm-as-fuzzer/ llvm/tools/llvm-bcanalyzer/CMakeLists.txt llvm/tools/llvm-c-test/ llvm/tools/llvm-cat/ @@ -771,12 +781,12 @@ llvm/tools/llvm-cxxdump/CMakeLists.txt llvm/tools/llvm-cxxfilt/CMakeLists.txt llvm/tools/llvm-cxxmap/CMakeLists.txt llvm/tools/llvm-debuginfo-analyzer/CMakeLists.txt -llvm/tools/llvm-debuginfod-find/ llvm/tools/llvm-debuginfod/ +llvm/tools/llvm-debuginfod-find/ llvm/tools/llvm-diff/CMakeLists.txt llvm/tools/llvm-diff/lib/CMakeLists.txt -llvm/tools/llvm-dis-fuzzer/ llvm/tools/llvm-dis/CMakeLists.txt +llvm/tools/llvm-dis-fuzzer/ llvm/tools/llvm-dlang-demangle-fuzzer/ llvm/tools/llvm-driver/ llvm/tools/llvm-dwarfdump/CMakeLists.txt @@ -796,9 +806,9 @@ llvm/tools/llvm-link/CMakeLists.txt llvm/tools/llvm-lipo/ llvm/tools/llvm-lto/CMakeLists.txt llvm/tools/llvm-lto2/CMakeLists.txt +llvm/tools/llvm-mc/CMakeLists.txt llvm/tools/llvm-mc-assemble-fuzzer/ llvm/tools/llvm-mc-disassemble-fuzzer/ -llvm/tools/llvm-mc/CMakeLists.txt llvm/tools/llvm-mca/CMakeLists.txt llvm/tools/llvm-microsoft-demangle-fuzzer/ llvm/tools/llvm-ml/ @@ -835,8 +845,8 @@ llvm/tools/llvm-yaml-numeric-parser-fuzzer/ llvm/tools/llvm-yaml-parser-fuzzer/ llvm/tools/lto/ llvm/tools/obj2yaml/ -llvm/tools/opt-viewer/ llvm/tools/opt/CMakeLists.txt +llvm/tools/opt-viewer/ llvm/tools/remarks-shlib/ llvm/tools/sancov/ llvm/tools/sanstats/ @@ -899,7 +909,6 @@ llvm/utils/kate/ llvm/utils/lint/ llvm/utils/lit/ llvm/utils/lldbDataFormatters.py -llvm/utils/llvm-compilers-check llvm/utils/llvm-gisel-cov.py llvm/utils/llvm-lit/ llvm/utils/llvm-locstats/ @@ -945,6 +954,7 @@ llvm/utils/vim/ llvm/utils/vscode/ llvm/utils/wciia.py llvm/utils/yaml-bench/ +llvm-libgcc/ mlir/ openmp/.gitignore openmp/CMakeLists.txt diff --git a/contrib/llvm-project/clang/include/clang-c/Index.h b/contrib/llvm-project/clang/include/clang-c/Index.h index a3e54285f89..601b91f67d6 100644 --- a/contrib/llvm-project/clang/include/clang-c/Index.h +++ b/contrib/llvm-project/clang/include/clang-c/Index.h @@ -34,7 +34,7 @@ * compatible, thus CINDEX_VERSION_MAJOR is expected to remain stable. */ #define CINDEX_VERSION_MAJOR 0 -#define CINDEX_VERSION_MINOR 63 +#define CINDEX_VERSION_MINOR 64 #define CINDEX_VERSION_ENCODE(major, minor) (((major)*10000) + ((minor)*1)) @@ -48,6 +48,10 @@ #define CINDEX_VERSION_STRING \ CINDEX_VERSION_STRINGIZE(CINDEX_VERSION_MAJOR, CINDEX_VERSION_MINOR) +#ifndef __has_feature +#define __has_feature(feature) 0 +#endif + LLVM_CLANG_C_EXTERN_C_BEGIN /** \defgroup CINDEX libclang: C Interface to Clang @@ -275,6 +279,22 @@ CINDEX_LINKAGE CXIndex clang_createIndex(int excludeDeclarationsFromPCH, */ CINDEX_LINKAGE void clang_disposeIndex(CXIndex index); +typedef enum { + /** + * Use the default value of an option that may depend on the process + * environment. + */ + CXChoice_Default = 0, + /** + * Enable the option. + */ + CXChoice_Enabled = 1, + /** + * Disable the option. + */ + CXChoice_Disabled = 2 +} CXChoice; + typedef enum { /** * Used to indicate that no special CXIndex options are needed. @@ -309,9 +329,131 @@ typedef enum { } CXGlobalOptFlags; +/** + * Index initialization options. + * + * 0 is the default value of each member of this struct except for Size. + * Initialize the struct in one of the following three ways to avoid adapting + * code each time a new member is added to it: + * \code + * CXIndexOptions Opts; + * memset(&Opts, 0, sizeof(Opts)); + * Opts.Size = sizeof(CXIndexOptions); + * \endcode + * or explicitly initialize the first data member and zero-initialize the rest: + * \code + * CXIndexOptions Opts = { sizeof(CXIndexOptions) }; + * \endcode + * or to prevent the -Wmissing-field-initializers warning for the above version: + * \code + * CXIndexOptions Opts{}; + * Opts.Size = sizeof(CXIndexOptions); + * \endcode + */ +typedef struct CXIndexOptions { + /** + * The size of struct CXIndexOptions used for option versioning. + * + * Always initialize this member to sizeof(CXIndexOptions), or assign + * sizeof(CXIndexOptions) to it right after creating a CXIndexOptions object. + */ + unsigned Size; + /** + * A CXChoice enumerator that specifies the indexing priority policy. + * \sa CXGlobalOpt_ThreadBackgroundPriorityForIndexing + */ + unsigned char ThreadBackgroundPriorityForIndexing; + /** + * A CXChoice enumerator that specifies the editing priority policy. + * \sa CXGlobalOpt_ThreadBackgroundPriorityForEditing + */ + unsigned char ThreadBackgroundPriorityForEditing; + /** + * \see clang_createIndex() + */ + unsigned ExcludeDeclarationsFromPCH : 1; + /** + * \see clang_createIndex() + */ + unsigned DisplayDiagnostics : 1; + /** + * Store PCH in memory. If zero, PCH are stored in temporary files. + */ + unsigned StorePreamblesInMemory : 1; + unsigned /*Reserved*/ : 13; + + /** + * The path to a directory, in which to store temporary PCH files. If null or + * empty, the default system temporary directory is used. These PCH files are + * deleted on clean exit but stay on disk if the program crashes or is killed. + * + * This option is ignored if \a StorePreamblesInMemory is non-zero. + * + * Libclang does not create the directory at the specified path in the file + * system. Therefore it must exist, or storing PCH files will fail. + */ + const char *PreambleStoragePath; + /** + * Specifies a path which will contain log files for certain libclang + * invocations. A null value implies that libclang invocations are not logged. + */ + const char *InvocationEmissionPath; +} CXIndexOptions; + +/** + * Provides a shared context for creating translation units. + * + * Call this function instead of clang_createIndex() if you need to configure + * the additional options in CXIndexOptions. + * + * \returns The created index or null in case of error, such as an unsupported + * value of options->Size. + * + * For example: + * \code + * CXIndex createIndex(const char *ApplicationTemporaryPath) { + * const int ExcludeDeclarationsFromPCH = 1; + * const int DisplayDiagnostics = 1; + * CXIndex Idx; + * #if CINDEX_VERSION_MINOR >= 64 + * CXIndexOptions Opts; + * memset(&Opts, 0, sizeof(Opts)); + * Opts.Size = sizeof(CXIndexOptions); + * Opts.ThreadBackgroundPriorityForIndexing = 1; + * Opts.ExcludeDeclarationsFromPCH = ExcludeDeclarationsFromPCH; + * Opts.DisplayDiagnostics = DisplayDiagnostics; + * Opts.PreambleStoragePath = ApplicationTemporaryPath; + * Idx = clang_createIndexWithOptions(&Opts); + * if (Idx) + * return Idx; + * fprintf(stderr, + * "clang_createIndexWithOptions() failed. " + * "CINDEX_VERSION_MINOR = %d, sizeof(CXIndexOptions) = %u\n", + * CINDEX_VERSION_MINOR, Opts.Size); + * #else + * (void)ApplicationTemporaryPath; + * #endif + * Idx = clang_createIndex(ExcludeDeclarationsFromPCH, DisplayDiagnostics); + * clang_CXIndex_setGlobalOptions( + * Idx, clang_CXIndex_getGlobalOptions(Idx) | + * CXGlobalOpt_ThreadBackgroundPriorityForIndexing); + * return Idx; + * } + * \endcode + * + * \sa clang_createIndex() + */ +CINDEX_LINKAGE CXIndex +clang_createIndexWithOptions(const CXIndexOptions *options); + /** * Sets general options associated with a CXIndex. * + * This function is DEPRECATED. Set + * CXIndexOptions::ThreadBackgroundPriorityForIndexing and/or + * CXIndexOptions::ThreadBackgroundPriorityForEditing and call + * clang_createIndexWithOptions() instead. + * * For example: * \code * CXIndex idx = ...; @@ -327,6 +469,9 @@ CINDEX_LINKAGE void clang_CXIndex_setGlobalOptions(CXIndex, unsigned options); /** * Gets the general options associated with a CXIndex. * + * This function allows to obtain the final option values used by libclang after + * specifying the option policies via CXChoice enumerators. + * * \returns A bitmask of options, a bitwise OR of CXGlobalOpt_XXX flags that * are associated with the given CXIndex object. */ @@ -335,6 +480,9 @@ CINDEX_LINKAGE unsigned clang_CXIndex_getGlobalOptions(CXIndex); /** * Sets the invocation emission path option in a CXIndex. * + * This function is DEPRECATED. Set CXIndexOptions::InvocationEmissionPath and + * call clang_createIndexWithOptions() instead. + * * The invocation emission path specifies a path which will contain log * files for certain libclang invocations. A null value (default) implies that * libclang invocations are not logged.. @@ -2787,10 +2935,15 @@ enum CXTypeKind { CXType_OCLIntelSubgroupAVCImeResult = 169, CXType_OCLIntelSubgroupAVCRefResult = 170, CXType_OCLIntelSubgroupAVCSicResult = 171, + CXType_OCLIntelSubgroupAVCImeResultSingleReferenceStreamout = 172, + CXType_OCLIntelSubgroupAVCImeResultDualReferenceStreamout = 173, + CXType_OCLIntelSubgroupAVCImeSingleReferenceStreamin = 174, + CXType_OCLIntelSubgroupAVCImeDualReferenceStreamin = 175, + + /* Old aliases for AVC OpenCL extension types. */ CXType_OCLIntelSubgroupAVCImeResultSingleRefStreamout = 172, CXType_OCLIntelSubgroupAVCImeResultDualRefStreamout = 173, CXType_OCLIntelSubgroupAVCImeSingleRefStreamin = 174, - CXType_OCLIntelSubgroupAVCImeDualRefStreamin = 175, CXType_ExtVector = 176, @@ -2888,9 +3041,25 @@ CINDEX_LINKAGE unsigned long long clang_getEnumConstantDeclUnsignedValue(CXCursor C); /** - * Retrieve the bit width of a bit field declaration as an integer. + * Returns non-zero if the cursor specifies a Record member that is a bit-field. + */ +CINDEX_LINKAGE unsigned clang_Cursor_isBitField(CXCursor C); + +/** + * Retrieve the bit width of a bit-field declaration as an integer. * - * If a cursor that is not a bit field declaration is passed in, -1 is returned. + * If the cursor does not reference a bit-field, or if the bit-field's width + * expression cannot be evaluated, -1 is returned. + * + * For example: + * \code + * if (clang_Cursor_isBitField(Cursor)) { + * int Width = clang_getFieldDeclBitWidth(Cursor); + * if (Width != -1) { + * // The bit-field width is not value-dependent. + * } + * } + * \endcode */ CINDEX_LINKAGE int clang_getFieldDeclBitWidth(CXCursor C); @@ -3519,12 +3688,6 @@ CINDEX_LINKAGE CXType clang_Type_getTemplateArgumentAsType(CXType T, */ CINDEX_LINKAGE enum CXRefQualifierKind clang_Type_getCXXRefQualifier(CXType T); -/** - * Returns non-zero if the cursor specifies a Record member that is a - * bitfield. - */ -CINDEX_LINKAGE unsigned clang_Cursor_isBitField(CXCursor C); - /** * Returns 1 if the base class specified by the cursor with kind * CX_CXXBaseSpecifier is virtual. @@ -3697,8 +3860,6 @@ typedef enum CXChildVisitResult (*CXCursorVisitor)(CXCursor cursor, CINDEX_LINKAGE unsigned clang_visitChildren(CXCursor parent, CXCursorVisitor visitor, CXClientData client_data); -#ifdef __has_feature -#if __has_feature(blocks) /** * Visitor invoked for each cursor found by a traversal. * @@ -3709,8 +3870,12 @@ CINDEX_LINKAGE unsigned clang_visitChildren(CXCursor parent, * The visitor should return one of the \c CXChildVisitResult values * to direct clang_visitChildrenWithBlock(). */ +#if __has_feature(blocks) typedef enum CXChildVisitResult (^CXCursorVisitorBlock)(CXCursor cursor, CXCursor parent); +#else +typedef struct _CXChildVisitResult *CXCursorVisitorBlock; +#endif /** * Visits the children of a cursor using the specified block. Behaves @@ -3718,8 +3883,6 @@ typedef enum CXChildVisitResult (^CXCursorVisitorBlock)(CXCursor cursor, */ CINDEX_LINKAGE unsigned clang_visitChildrenWithBlock(CXCursor parent, CXCursorVisitorBlock block); -#endif -#endif /** * @} @@ -4343,6 +4506,51 @@ CINDEX_LINKAGE unsigned clang_CXXMethod_isCopyAssignmentOperator(CXCursor C); */ CINDEX_LINKAGE unsigned clang_CXXMethod_isMoveAssignmentOperator(CXCursor C); +/** + * Determines if a C++ constructor or conversion function was declared + * explicit, returning 1 if such is the case and 0 otherwise. + * + * Constructors or conversion functions are declared explicit through + * the use of the explicit specifier. + * + * For example, the following constructor and conversion function are + * not explicit as they lack the explicit specifier: + * + * class Foo { + * Foo(); + * operator int(); + * }; + * + * While the following constructor and conversion function are + * explicit as they are declared with the explicit specifier. + * + * class Foo { + * explicit Foo(); + * explicit operator int(); + * }; + * + * This function will return 0 when given a cursor pointing to one of + * the former declarations and it will return 1 for a cursor pointing + * to the latter declarations. + * + * The explicit specifier allows the user to specify a + * conditional compile-time expression whose value decides + * whether the marked element is explicit or not. + * + * For example: + * + * constexpr bool foo(int i) { return i % 2 == 0; } + * + * class Foo { + * explicit(foo(1)) Foo(); + * explicit(foo(2)) operator int(); + * } + * + * This function will return 0 for the constructor and 1 for + * the conversion function. + */ +CINDEX_LINKAGE unsigned clang_CXXMethod_isExplicit(CXCursor C); + /** * Determine if a C++ record is abstract, i.e. whether a class or struct * has a pure virtual member function. @@ -5675,11 +5883,12 @@ CINDEX_LINKAGE CXResult clang_findReferencesInFile( CINDEX_LINKAGE CXResult clang_findIncludesInFile( CXTranslationUnit TU, CXFile file, CXCursorAndRangeVisitor visitor); -#ifdef __has_feature #if __has_feature(blocks) - typedef enum CXVisitorResult (^CXCursorAndRangeVisitorBlock)(CXCursor, CXSourceRange); +#else +typedef struct _CXCursorAndRangeVisitorBlock *CXCursorAndRangeVisitorBlock; +#endif CINDEX_LINKAGE CXResult clang_findReferencesInFileWithBlock(CXCursor, CXFile, @@ -5689,9 +5898,6 @@ CINDEX_LINKAGE CXResult clang_findIncludesInFileWithBlock(CXTranslationUnit, CXFile, CXCursorAndRangeVisitorBlock); -#endif -#endif - /** * The client's data object that is associated with a CXFile. */ @@ -6304,6 +6510,144 @@ typedef enum CXVisitorResult (*CXFieldVisitor)(CXCursor C, CINDEX_LINKAGE unsigned clang_Type_visitFields(CXType T, CXFieldVisitor visitor, CXClientData client_data); +/** + * Describes the kind of binary operators. + */ +enum CXBinaryOperatorKind { + /** This value describes cursors which are not binary operators. */ + CXBinaryOperator_Invalid, + /** C++ Pointer - to - member operator. */ + CXBinaryOperator_PtrMemD, + /** C++ Pointer - to - member operator. */ + CXBinaryOperator_PtrMemI, + /** Multiplication operator. */ + CXBinaryOperator_Mul, + /** Division operator. */ + CXBinaryOperator_Div, + /** Remainder operator. */ + CXBinaryOperator_Rem, + /** Addition operator. */ + CXBinaryOperator_Add, + /** Subtraction operator. */ + CXBinaryOperator_Sub, + /** Bitwise shift left operator. */ + CXBinaryOperator_Shl, + /** Bitwise shift right operator. */ + CXBinaryOperator_Shr, + /** C++ three-way comparison (spaceship) operator. */ + CXBinaryOperator_Cmp, + /** Less than operator. */ + CXBinaryOperator_LT, + /** Greater than operator. */ + CXBinaryOperator_GT, + /** Less or equal operator. */ + CXBinaryOperator_LE, + /** Greater or equal operator. */ + CXBinaryOperator_GE, + /** Equal operator. */ + CXBinaryOperator_EQ, + /** Not equal operator. */ + CXBinaryOperator_NE, + /** Bitwise AND operator. */ + CXBinaryOperator_And, + /** Bitwise XOR operator. */ + CXBinaryOperator_Xor, + /** Bitwise OR operator. */ + CXBinaryOperator_Or, + /** Logical AND operator. */ + CXBinaryOperator_LAnd, + /** Logical OR operator. */ + CXBinaryOperator_LOr, + /** Assignment operator. */ + CXBinaryOperator_Assign, + /** Multiplication assignment operator. */ + CXBinaryOperator_MulAssign, + /** Division assignment operator. */ + CXBinaryOperator_DivAssign, + /** Remainder assignment operator. */ + CXBinaryOperator_RemAssign, + /** Addition assignment operator. */ + CXBinaryOperator_AddAssign, + /** Subtraction assignment operator. */ + CXBinaryOperator_SubAssign, + /** Bitwise shift left assignment operator. */ + CXBinaryOperator_ShlAssign, + /** Bitwise shift right assignment operator. */ + CXBinaryOperator_ShrAssign, + /** Bitwise AND assignment operator. */ + CXBinaryOperator_AndAssign, + /** Bitwise XOR assignment operator. */ + CXBinaryOperator_XorAssign, + /** Bitwise OR assignment operator. */ + CXBinaryOperator_OrAssign, + /** Comma operator. */ + CXBinaryOperator_Comma +}; + +/** + * Retrieve the spelling of a given CXBinaryOperatorKind. + */ +CINDEX_LINKAGE CXString +clang_getBinaryOperatorKindSpelling(enum CXBinaryOperatorKind kind); + +/** + * Retrieve the binary operator kind of this cursor. + * + * If this cursor is not a binary operator then returns Invalid. + */ +CINDEX_LINKAGE enum CXBinaryOperatorKind +clang_getCursorBinaryOperatorKind(CXCursor cursor); + +/** + * Describes the kind of unary operators. + */ +enum CXUnaryOperatorKind { + /** This value describes cursors which are not unary operators. */ + CXUnaryOperator_Invalid, + /** Postfix increment operator. */ + CXUnaryOperator_PostInc, + /** Postfix decrement operator. */ + CXUnaryOperator_PostDec, + /** Prefix increment operator. */ + CXUnaryOperator_PreInc, + /** Prefix decrement operator. */ + CXUnaryOperator_PreDec, + /** Address of operator. */ + CXUnaryOperator_AddrOf, + /** Dereference operator. */ + CXUnaryOperator_Deref, + /** Plus operator. */ + CXUnaryOperator_Plus, + /** Minus operator. */ + CXUnaryOperator_Minus, + /** Not operator. */ + CXUnaryOperator_Not, + /** LNot operator. */ + CXUnaryOperator_LNot, + /** "__real expr" operator. */ + CXUnaryOperator_Real, + /** "__imag expr" operator. */ + CXUnaryOperator_Imag, + /** __extension__ marker operator. */ + CXUnaryOperator_Extension, + /** C++ co_await operator. */ + CXUnaryOperator_Coawait +}; + +/** + * Retrieve the spelling of a given CXUnaryOperatorKind. + */ +CINDEX_LINKAGE CXString +clang_getUnaryOperatorKindSpelling(enum CXUnaryOperatorKind kind); + +/** + * Retrieve the unary operator kind of this cursor. + * + * If this cursor is not a unary operator then returns Invalid. + */ +CINDEX_LINKAGE enum CXUnaryOperatorKind +clang_getCursorUnaryOperatorKind(CXCursor cursor); + /** * @} */ diff --git a/contrib/llvm-project/clang/include/clang-c/module.modulemap b/contrib/llvm-project/clang/include/clang-c/module.modulemap deleted file mode 100644 index 95a59d62344..00000000000 --- a/contrib/llvm-project/clang/include/clang-c/module.modulemap +++ /dev/null @@ -1,4 +0,0 @@ -module Clang_C { - umbrella "." - module * { export * } -} diff --git a/contrib/llvm-project/clang/include/clang/AST/APValue.h b/contrib/llvm-project/clang/include/clang/AST/APValue.h index 4e22d6c8443..286c1a1b094 100644 --- a/contrib/llvm-project/clang/include/clang/AST/APValue.h +++ b/contrib/llvm-project/clang/include/clang/AST/APValue.h @@ -267,9 +267,9 @@ private: }; struct LV; struct Vec { - APValue *Elts; - unsigned NumElts; - Vec() : Elts(nullptr), NumElts(0) {} + APValue *Elts = nullptr; + unsigned NumElts = 0; + Vec() = default; ~Vec() { delete[] Elts; } }; struct Arr { diff --git a/contrib/llvm-project/clang/include/clang/AST/ASTConsumer.h b/contrib/llvm-project/clang/include/clang/AST/ASTConsumer.h index 21850e832ff..ebcd8059284 100644 --- a/contrib/llvm-project/clang/include/clang/AST/ASTConsumer.h +++ b/contrib/llvm-project/clang/include/clang/AST/ASTConsumer.h @@ -33,12 +33,12 @@ namespace clang { class ASTConsumer { /// Whether this AST consumer also requires information about /// semantic analysis. - bool SemaConsumer; + bool SemaConsumer = false; friend class SemaConsumer; public: - ASTConsumer() : SemaConsumer(false) { } + ASTConsumer() = default; virtual ~ASTConsumer() {} diff --git a/contrib/llvm-project/clang/include/clang/AST/ASTContext.h b/contrib/llvm-project/clang/include/clang/AST/ASTContext.h index 0238371927e..40cadd93158 100644 --- a/contrib/llvm-project/clang/include/clang/AST/ASTContext.h +++ b/contrib/llvm-project/clang/include/clang/AST/ASTContext.h @@ -447,8 +447,8 @@ class ASTContext : public RefCountedBase { }; llvm::DenseMap ModuleInitializers; - /// For module code-gen cases, this is the top-level module we are building. - Module *TopLevelModule = nullptr; + /// This is the top-level (C++20) Named module we are building. + Module *CurrentCXXNamedModule = nullptr; static constexpr unsigned ConstantArrayTypesLog2InitSize = 8; static constexpr unsigned GeneralTypesLog2InitSize = 9; @@ -1051,10 +1051,10 @@ public: ArrayRef getModuleInitializers(Module *M); /// Set the (C++20) module we are building. - void setModuleForCodeGen(Module *M) { TopLevelModule = M; } + void setCurrentNamedModule(Module *M); /// Get module under construction, nullptr if this is not a C++20 module. - Module *getModuleForCodeGen() const { return TopLevelModule; } + Module *getCurrentNamedModule() const { return CurrentCXXNamedModule; } TranslationUnitDecl *getTranslationUnitDecl() const { return TUDecl->getMostRecentDecl(); @@ -1126,6 +1126,8 @@ public: #define RVV_TYPE(Name, Id, SingletonId) \ CanQualType SingletonId; #include "clang/Basic/RISCVVTypes.def" +#define WASM_TYPE(Name, Id, SingletonId) CanQualType SingletonId; +#include "clang/Basic/WebAssemblyReferenceTypes.def" // Types for deductions in C++0x [stmt.ranged]'s desugaring. Built on demand. mutable QualType AutoDeductTy; // Deduction against 'auto'. @@ -1470,9 +1472,15 @@ public: /// Return the unique reference to a scalable vector type of the specified /// element type and scalable number of elements. + /// For RISC-V, number of fields is also provided when it fetching for + /// tuple type. /// /// \pre \p EltTy must be a built-in type. - QualType getScalableVectorType(QualType EltTy, unsigned NumElts) const; + QualType getScalableVectorType(QualType EltTy, unsigned NumElts, + unsigned NumFields = 1) const; + + /// Return a WebAssembly externref type. + QualType getWebAssemblyExternrefType() const; /// Return the unique reference to a vector type of the specified /// element type and size. @@ -1710,6 +1718,10 @@ public: /// C++11 deduction pattern for 'auto &&' type. QualType getAutoRRefDeductType() const; + /// Remove any type constraints from a template parameter type, for + /// equivalence comparison of template parameters. + QualType getUnconstrainedType(QualType T) const; + /// C++17 deduced class template specialization type. QualType getDeducedTemplateSpecializationType(TemplateName Template, QualType DeducedType, @@ -2243,6 +2255,17 @@ public: /// false otherwise. bool areLaxCompatibleSveTypes(QualType FirstType, QualType SecondType); + /// Return true if the given types are an RISC-V vector builtin type and a + /// VectorType that is a fixed-length representation of the RISC-V vector + /// builtin type for a specific vector-length. + bool areCompatibleRVVTypes(QualType FirstType, QualType SecondType); + + /// Return true if the given vector types are lax-compatible RISC-V vector + /// types as defined by -flax-vector-conversions=, which permits implicit + /// conversions between vectors with different number of elements and/or + /// incompatible element types, false otherwise. + bool areLaxCompatibleRVVTypes(QualType FirstType, QualType SecondType); + /// Return true if the type has been explicitly qualified with ObjC ownership. /// A type may be implicitly qualified with ownership under ObjC ARC, and in /// some cases the compiler treats these differently. @@ -2482,7 +2505,9 @@ public: /// Return true if the specified type has unique object representations /// according to (C++17 [meta.unary.prop]p9) - bool hasUniqueObjectRepresentations(QualType Ty) const; + bool + hasUniqueObjectRepresentations(QualType Ty, + bool CheckIfTriviallyCopyable = true) const; //===--------------------------------------------------------------------===// // Type Operators @@ -2647,11 +2672,6 @@ public: /// template. bool hasSameTemplateName(const TemplateName &X, const TemplateName &Y) const; - /// Determine whether two Friend functions are different because constraints - /// that refer to an enclosing template, according to [temp.friend] p9. - bool FriendsDifferByConstraints(const FunctionDecl *X, - const FunctionDecl *Y) const; - /// Determine whether the two declarations refer to the same entity. bool isSameEntity(const NamedDecl *X, const NamedDecl *Y) const; @@ -3042,7 +3062,7 @@ public: } GVALinkage GetGVALinkageForFunction(const FunctionDecl *FD) const; - GVALinkage GetGVALinkageForVariable(const VarDecl *VD); + GVALinkage GetGVALinkageForVariable(const VarDecl *VD) const; /// Determines if the decl can be CodeGen'ed or deserialized from PCH /// lazily, only when used; this is only relevant for function or file scoped @@ -3193,7 +3213,6 @@ private: public: ObjCEncOptions() : Bits(0) {} - ObjCEncOptions(const ObjCEncOptions &RHS) : Bits(RHS.Bits) {} #define OPT_LIST(V) \ V(ExpandPointedToStructures, 0) \ diff --git a/contrib/llvm-project/clang/include/clang/AST/ASTDiagnostic.h b/contrib/llvm-project/clang/include/clang/AST/ASTDiagnostic.h index 4cd90975172..ef222498286 100644 --- a/contrib/llvm-project/clang/include/clang/AST/ASTDiagnostic.h +++ b/contrib/llvm-project/clang/include/clang/AST/ASTDiagnostic.h @@ -34,7 +34,8 @@ namespace clang { ArrayRef QualTypeVals); /// Returns a desugared version of the QualType, and marks ShouldAKA as true - /// whenever we remove significant sugar from the type. + /// whenever we remove significant sugar from the type. Make sure ShouldAKA + /// is initialized before passing it in. QualType desugarForDiagnostic(ASTContext &Context, QualType QT, bool &ShouldAKA); } // end namespace clang diff --git a/contrib/llvm-project/clang/include/clang/AST/ASTImporter.h b/contrib/llvm-project/clang/include/clang/AST/ASTImporter.h index f851decd096..4ffd9138465 100644 --- a/contrib/llvm-project/clang/include/clang/AST/ASTImporter.h +++ b/contrib/llvm-project/clang/include/clang/AST/ASTImporter.h @@ -258,6 +258,7 @@ class TypeSourceInfo; FoundDeclsTy findDeclsInToCtx(DeclContext *DC, DeclarationName Name); void AddToLookupTable(Decl *ToD); + llvm::Error ImportAttrs(Decl *ToD, Decl *FromD); protected: /// Can be overwritten by subclasses to implement their own import logic. diff --git a/contrib/llvm-project/clang/include/clang/AST/ASTNodeTraverser.h b/contrib/llvm-project/clang/include/clang/AST/ASTNodeTraverser.h index a2c57aab89e..d649ef6816c 100644 --- a/contrib/llvm-project/clang/include/clang/AST/ASTNodeTraverser.h +++ b/contrib/llvm-project/clang/include/clang/AST/ASTNodeTraverser.h @@ -104,7 +104,8 @@ public: Visit(Comment, Comment); // Decls within functions are visited by the body. - if (!isa(*D) && !isa(*D)) { + if (!isa(*D) && !isa(*D) && + !isa(*D)) { if (Traversal != TK_AsIs) { if (const auto *CTSD = dyn_cast(D)) { auto SK = CTSD->getSpecializationKind(); @@ -384,7 +385,8 @@ public: } void VisitAttributedType(const AttributedType *T) { // FIXME: AttrKind - Visit(T->getModifiedType()); + if (T->getModifiedType() != T->getEquivalentType()) + Visit(T->getModifiedType()); } void VisitBTFTagAttributedType(const BTFTagAttributedType *T) { Visit(T->getWrappedType()); @@ -731,8 +733,11 @@ public: } void VisitGenericSelectionExpr(const GenericSelectionExpr *E) { - Visit(E->getControllingExpr()); - Visit(E->getControllingExpr()->getType()); // FIXME: remove + if (E->isExprPredicate()) { + Visit(E->getControllingExpr()); + Visit(E->getControllingExpr()->getType()); // FIXME: remove + } else + Visit(E->getControllingType()->getType()); for (const auto Assoc : E->associations()) { Visit(Assoc); diff --git a/contrib/llvm-project/clang/include/clang/AST/ASTTypeTraits.h b/contrib/llvm-project/clang/include/clang/AST/ASTTypeTraits.h index 8713221a737..78661823ca8 100644 --- a/contrib/llvm-project/clang/include/clang/AST/ASTTypeTraits.h +++ b/contrib/llvm-project/clang/include/clang/AST/ASTTypeTraits.h @@ -77,10 +77,13 @@ public: /// Returns \c true only for the default \c ASTNodeKind() constexpr bool isNone() const { return KindId == NKI_None; } + /// Returns \c true if \c this is a base kind of (or same as) \c Other. + bool isBaseOf(ASTNodeKind Other) const; + /// Returns \c true if \c this is a base kind of (or same as) \c Other. /// \param Distance If non-null, used to return the distance between \c this /// and \c Other in the class hierarchy. - bool isBaseOf(ASTNodeKind Other, unsigned *Distance = nullptr) const; + bool isBaseOf(ASTNodeKind Other, unsigned *Distance) const; /// String representation of the kind. StringRef asStringRef() const; @@ -166,6 +169,10 @@ private: /// Use getFromNodeKind() to construct the kind. constexpr ASTNodeKind(NodeKindId KindId) : KindId(KindId) {} + /// Returns \c true if \c Base is a base kind of (or same as) \c + /// Derived. + static bool isBaseOf(NodeKindId Base, NodeKindId Derived); + /// Returns \c true if \c Base is a base kind of (or same as) \c /// Derived. /// \param Distance If non-null, used to return the distance between \c Base diff --git a/contrib/llvm-project/clang/include/clang/AST/CXXInheritance.h b/contrib/llvm-project/clang/include/clang/AST/CXXInheritance.h index 946b9e318ba..eec2119f4a1 100644 --- a/contrib/llvm-project/clang/include/clang/AST/CXXInheritance.h +++ b/contrib/llvm-project/clang/include/clang/AST/CXXInheritance.h @@ -315,7 +315,7 @@ public: /// virtual function; in abstract classes, the final overrider for at /// least one virtual function is a pure virtual function. Due to /// multiple, virtual inheritance, it is possible for a class to have -/// more than one final overrider. Athough this is an error (per C++ +/// more than one final overrider. Although this is an error (per C++ /// [class.virtual]p2), it is not considered an error here: the final /// overrider map can represent multiple final overriders for a /// method, and it is up to the client to determine whether they are diff --git a/contrib/llvm-project/clang/include/clang/AST/CommentSema.h b/contrib/llvm-project/clang/include/clang/AST/CommentSema.h index 9c2ca5f8e60..5d8df7dbf38 100644 --- a/contrib/llvm-project/clang/include/clang/AST/CommentSema.h +++ b/contrib/llvm-project/clang/include/clang/AST/CommentSema.h @@ -193,7 +193,7 @@ private: void checkContainerDecl(const BlockCommandComment *Comment); /// Resolve parameter names to parameter indexes in function declaration. - /// Emit diagnostics about unknown parametrs. + /// Emit diagnostics about unknown parameters. void resolveParamCommandIndexes(const FullComment *FC); /// \returns \c true if the declaration that this comment is attached to diff --git a/contrib/llvm-project/clang/include/clang/AST/ComparisonCategories.h b/contrib/llvm-project/clang/include/clang/AST/ComparisonCategories.h index 1c94cee4b7c..b4ad37e394c 100644 --- a/contrib/llvm-project/clang/include/clang/AST/ComparisonCategories.h +++ b/contrib/llvm-project/clang/include/clang/AST/ComparisonCategories.h @@ -39,9 +39,8 @@ class NamespaceDecl; /// An enumeration representing the different comparison categories /// types. /// -/// C++2a [cmp.categories.pre] The types weak_equality, strong_equality, -/// partial_ordering, weak_ordering, and strong_ordering are collectively -/// termed the comparison category types. +/// C++20 [cmp.categories.pre] The types partial_ordering, weak_ordering, and +/// strong_ordering are collectively termed the comparison category types. enum class ComparisonCategoryType : unsigned char { PartialOrdering, WeakOrdering, diff --git a/contrib/llvm-project/clang/include/clang/AST/Decl.h b/contrib/llvm-project/clang/include/clang/AST/Decl.h index 32c5ab943e7..788f6ab97b1 100644 --- a/contrib/llvm-project/clang/include/clang/AST/Decl.h +++ b/contrib/llvm-project/clang/include/clang/AST/Decl.h @@ -395,9 +395,7 @@ public: /// Get the linkage from a semantic point of view. Entities in /// anonymous namespaces are external (in c++98). - Linkage getFormalLinkage() const { - return clang::getFormalLinkage(getLinkageInternal()); - } + Linkage getFormalLinkage() const; /// True if this decl has external linkage. bool hasExternalFormalLinkage() const { @@ -902,7 +900,7 @@ struct EvaluatedStmt { bool HasICEInit : 1; bool CheckedForICEInit : 1; - Stmt *Value; + LazyDeclStmtPtr Value; APValue Evaluated; EvaluatedStmt() @@ -1360,12 +1358,15 @@ public: EvaluatedStmt *getEvaluatedStmt() const; /// Attempt to evaluate the value of the initializer attached to this - /// declaration, and produce notes explaining why it cannot be evaluated or is - /// not a constant expression. Returns a pointer to the value if evaluation - /// succeeded, 0 otherwise. + /// declaration, and produce notes explaining why it cannot be evaluated. + /// Returns a pointer to the value if evaluation succeeded, 0 otherwise. APValue *evaluateValue() const; - APValue *evaluateValue(SmallVectorImpl &Notes) const; +private: + APValue *evaluateValueImpl(SmallVectorImpl &Notes, + bool IsConstantInitialization) const; + +public: /// Return the already-evaluated value of this variable's /// initializer, or NULL if the value is not yet known. Returns pointer /// to untyped APValue if the value could not be evaluated. @@ -2167,7 +2168,7 @@ public: /// declaration to the declaration that is a definition (if there is one). /// /// \param CheckForPendingFriendDefinition If \c true, also check for friend - /// declarations that were instantiataed from function definitions. + /// declarations that were instantiated from function definitions. /// Such a declaration behaves as if it is a definition for the /// purpose of redefinition checking, but isn't actually a "real" /// definition until its body is instantiated. @@ -2377,6 +2378,21 @@ public: return getConstexprKind() == ConstexprSpecKind::Consteval; } + void setBodyContainsImmediateEscalatingExpressions(bool Set) { + FunctionDeclBits.BodyContainsImmediateEscalatingExpression = Set; + } + + bool BodyContainsImmediateEscalatingExpressions() const { + return FunctionDeclBits.BodyContainsImmediateEscalatingExpression; + } + + bool isImmediateEscalating() const; + + // The function is a C++ immediate function. + // This can be either a consteval function, or an immediate escalating + // function containing an immediate escalating expression. + bool isImmediateFunction() const; + /// Whether the instantiation of this function is pending. /// This bit is set when the decision to instantiate this function is made /// and unset if and when the function body is created. That leaves out @@ -2536,6 +2552,10 @@ public: ->FunctionDeclBits.FriendConstraintRefersToEnclosingTemplate; } + /// Determine whether a function is a friend function that cannot be + /// redeclared outside of its class, per C++ [temp.friend]p9. + bool isMemberLikeConstrainedFriend() const; + /// Gets the kind of multiversioning attribute this declaration has. Note that /// this can return a value even if the function is not multiversion, such as /// the case of 'target'. @@ -2938,11 +2958,7 @@ public: /// Represents a member of a struct/union/class. class FieldDecl : public DeclaratorDecl, public Mergeable { - unsigned BitField : 1; - unsigned Mutable : 1; - mutable unsigned CachedFieldIndex : 30; - - /// The kinds of value we can store in InitializerOrBitWidth. + /// The kinds of value we can store in StorageKind. /// /// Note that this is compatible with InClassInitStyle except for /// ISK_CapturedVLAType. @@ -2965,10 +2981,15 @@ class FieldDecl : public DeclaratorDecl, public Mergeable { ISK_CapturedVLAType, }; + unsigned BitField : 1; + unsigned Mutable : 1; + unsigned StorageKind : 2; + mutable unsigned CachedFieldIndex : 28; + /// If this is a bitfield with a default member initializer, this /// structure is used to represent the two expressions. - struct InitAndBitWidth { - Expr *Init; + struct InitAndBitWidthStorage { + LazyDeclStmtPtr Init; Expr *BitWidth; }; @@ -2981,16 +3002,25 @@ class FieldDecl : public DeclaratorDecl, public Mergeable { /// and attached. // FIXME: Tail-allocate this to reduce the size of FieldDecl in the // overwhelmingly common case that we have none of these things. - llvm::PointerIntPair InitStorage; + union { + // Active member if ISK is not ISK_CapturedVLAType and BitField is false. + LazyDeclStmtPtr Init; + // Active member if ISK is ISK_NoInit and BitField is true. + Expr *BitWidth; + // Active member if ISK is ISK_InClass*Init and BitField is true. + InitAndBitWidthStorage *InitAndBitWidth; + // Active member if ISK is ISK_CapturedVLAType. + const VariableArrayType *CapturedVLAType; + }; protected: FieldDecl(Kind DK, DeclContext *DC, SourceLocation StartLoc, - SourceLocation IdLoc, IdentifierInfo *Id, - QualType T, TypeSourceInfo *TInfo, Expr *BW, bool Mutable, + SourceLocation IdLoc, IdentifierInfo *Id, QualType T, + TypeSourceInfo *TInfo, Expr *BW, bool Mutable, InClassInitStyle InitStyle) - : DeclaratorDecl(DK, DC, IdLoc, Id, T, TInfo, StartLoc), - BitField(false), Mutable(Mutable), CachedFieldIndex(0), - InitStorage(nullptr, (InitStorageKind) InitStyle) { + : DeclaratorDecl(DK, DC, IdLoc, Id, T, TInfo, StartLoc), BitField(false), + Mutable(Mutable), StorageKind((InitStorageKind)InitStyle), + CachedFieldIndex(0), Init() { if (BW) setBitWidth(BW); } @@ -3029,10 +3059,7 @@ public: Expr *getBitWidth() const { if (!BitField) return nullptr; - void *Ptr = InitStorage.getPointer(); - if (getInClassInitStyle()) - return static_cast(Ptr)->BitWidth; - return static_cast(Ptr); + return hasInClassInitializer() ? InitAndBitWidth->BitWidth : BitWidth; } unsigned getBitWidthValue(const ASTContext &Ctx) const; @@ -3043,11 +3070,11 @@ public: assert(!hasCapturedVLAType() && !BitField && "bit width or captured type already set"); assert(Width && "no bit width specified"); - InitStorage.setPointer( - InitStorage.getInt() - ? new (getASTContext()) - InitAndBitWidth{getInClassInitializer(), Width} - : static_cast(Width)); + if (hasInClassInitializer()) + InitAndBitWidth = + new (getASTContext()) InitAndBitWidthStorage{Init, Width}; + else + BitWidth = Width; BitField = true; } @@ -3055,7 +3082,11 @@ public: // Note: used by some clients (i.e., do not remove it). void removeBitWidth() { assert(isBitField() && "no bitfield width to remove"); - InitStorage.setPointer(getInClassInitializer()); + if (hasInClassInitializer()) { + // Read the old initializer before we change the active union member. + auto ExistingInit = InitAndBitWidth->Init; + Init = ExistingInit; + } BitField = false; } @@ -3069,11 +3100,14 @@ public: /// [[no_unique_address]] attribute. bool isZeroSize(const ASTContext &Ctx) const; + /// Determine if this field is of potentially-overlapping class type, that + /// is, subobject with the [[no_unique_address]] attribute + bool isPotentiallyOverlapping() const; + /// Get the kind of (C++11) default member initializer that this field has. InClassInitStyle getInClassInitStyle() const { - InitStorageKind storageKind = InitStorage.getInt(); - return (storageKind == ISK_CapturedVLAType - ? ICIS_NoInit : (InClassInitStyle) storageKind); + return (StorageKind == ISK_CapturedVLAType ? ICIS_NoInit + : (InClassInitStyle)StorageKind); } /// Determine whether this member has a C++11 default member initializer. @@ -3081,44 +3115,44 @@ public: return getInClassInitStyle() != ICIS_NoInit; } + /// Determine whether getInClassInitializer() would return a non-null pointer + /// without deserializing the initializer. + bool hasNonNullInClassInitializer() const { + return hasInClassInitializer() && (BitField ? InitAndBitWidth->Init : Init); + } + /// Get the C++11 default member initializer for this member, or null if one /// has not been set. If a valid declaration has a default member initializer, /// but this returns null, then we have not parsed and attached it yet. - Expr *getInClassInitializer() const { - if (!hasInClassInitializer()) - return nullptr; - void *Ptr = InitStorage.getPointer(); - if (BitField) - return static_cast(Ptr)->Init; - return static_cast(Ptr); - } + Expr *getInClassInitializer() const; /// Set the C++11 in-class initializer for this member. - void setInClassInitializer(Expr *Init) { - assert(hasInClassInitializer() && !getInClassInitializer()); - if (BitField) - static_cast(InitStorage.getPointer())->Init = Init; - else - InitStorage.setPointer(Init); - } + void setInClassInitializer(Expr *NewInit); +private: + void setLazyInClassInitializer(LazyDeclStmtPtr NewInit); + +public: /// Remove the C++11 in-class initializer from this member. void removeInClassInitializer() { assert(hasInClassInitializer() && "no initializer to remove"); - InitStorage.setPointerAndInt(getBitWidth(), ISK_NoInit); + StorageKind = ISK_NoInit; + if (BitField) { + // Read the bit width before we change the active union member. + Expr *ExistingBitWidth = InitAndBitWidth->BitWidth; + BitWidth = ExistingBitWidth; + } } /// Determine whether this member captures the variable length array /// type. bool hasCapturedVLAType() const { - return InitStorage.getInt() == ISK_CapturedVLAType; + return StorageKind == ISK_CapturedVLAType; } /// Get the captured variable length array type. const VariableArrayType *getCapturedVLAType() const { - return hasCapturedVLAType() ? static_cast( - InitStorage.getPointer()) - : nullptr; + return hasCapturedVLAType() ? CapturedVLAType : nullptr; } /// Set the captured variable length array type for this field. @@ -3691,6 +3725,7 @@ public: return getExtInfo()->TemplParamLists[i]; } + using TypeDecl::printName; void printName(raw_ostream &OS, const PrintingPolicy &Policy) const override; void setTemplateParameterListsInfo(ASTContext &Context, @@ -4305,6 +4340,7 @@ class TopLevelStmtDecl : public Decl { friend class ASTDeclWriter; Stmt *Statement = nullptr; + bool IsSemiMissing = false; TopLevelStmtDecl(DeclContext *DC, SourceLocation L, Stmt *S) : Decl(TopLevelStmt, DC, L), Statement(S) {} @@ -4318,6 +4354,12 @@ public: SourceRange getSourceRange() const override LLVM_READONLY; Stmt *getStmt() { return Statement; } const Stmt *getStmt() const { return Statement; } + void setStmt(Stmt *S) { + assert(IsSemiMissing && "Operation supported for printing values only!"); + Statement = S; + } + bool isSemiMissing() const { return IsSemiMissing; } + void setSemiMissing(bool Missing = true) { IsSemiMissing = Missing; } static bool classof(const Decl *D) { return classofKind(D->getKind()); } static bool classofKind(Kind K) { return K == TopLevelStmt; } @@ -4704,7 +4746,7 @@ public: static bool classofKind(Kind K) { return K == Import; } }; -/// Represents a C++ Modules TS module export declaration. +/// Represents a standard C++ module export declaration. /// /// For example: /// \code diff --git a/contrib/llvm-project/clang/include/clang/AST/DeclBase.h b/contrib/llvm-project/clang/include/clang/AST/DeclBase.h index 6134fdde8a2..1b99709ca90 100644 --- a/contrib/llvm-project/clang/include/clang/AST/DeclBase.h +++ b/contrib/llvm-project/clang/include/clang/AST/DeclBase.h @@ -644,6 +644,9 @@ public: return getModuleOwnershipKind() > ModuleOwnershipKind::VisibleWhenImported; } + /// Whether this declaration comes from another module unit. + bool isInAnotherModuleUnit() const; + /// FIXME: Implement discarding declarations actually in global module /// fragment. See [module.global.frag]p3,4 for details. bool isDiscardedInGlobalModuleFragment() const { return false; } @@ -810,7 +813,7 @@ public: } /// Get the module that owns this declaration for linkage purposes. - /// There only ever is such a module under the C++ Modules TS. + /// There only ever is such a standard C++ module. /// /// \param IgnoreLinkage Ignore the linkage of the entity; assume that /// all declarations in a global module fragment are unowned. @@ -1172,6 +1175,12 @@ public: } } + /// Clears the namespace of this declaration. + /// + /// This is useful if we want this declaration to be available for + /// redeclaration lookup but otherwise hidden for ordinary name lookups. + void clearIdentifierNamespace() { IdentifierNamespace = 0; } + enum FriendObjectKind { FOK_None, ///< Not a friend object. FOK_Declared, ///< A friend of a previously-declared entity. @@ -1227,6 +1236,10 @@ public: /// have a FunctionType. const FunctionType *getFunctionType(bool BlocksToo = true) const; + // Looks through the Decl's underlying type to determine if it's a + // function pointer type. + bool isFunctionPointerType() const; + private: void setAttrsImpl(const AttrVec& Attrs, ASTContext &Ctx); void setDeclContextsImpl(DeclContext *SemaDC, DeclContext *LexicalDC, @@ -1369,6 +1382,13 @@ public: } }; +/// Only used by CXXDeductionGuideDecl. +enum class DeductionCandidate : unsigned char { + Normal, + Copy, + Aggregate, +}; + /// DeclContext - This is used only as base class of specific decl types that /// can act as declaration contexts. These decls are (only the top classes /// that directly derive from DeclContext are mentioned, not their subclasses): @@ -1389,6 +1409,8 @@ public: class DeclContext { /// For makeDeclVisibleInContextImpl friend class ASTDeclReader; + /// For checking the new bits in the Serialization part. + friend class ASTDeclWriter; /// For reconcileExternalVisibleStorage, CreateStoredDeclsMap, /// hasNeedToReconcileExternalVisibleStorage friend class ExternalASTSource; @@ -1595,7 +1617,7 @@ class DeclContext { uint64_t : NumDeclContextBits; /// Kind of initializer, - /// function call or omp_priv initializtion. + /// function call or omp_priv initialization. uint64_t InitializerKind : 2; }; @@ -1605,10 +1627,10 @@ class DeclContext { /// Stores the bits used by FunctionDecl. /// If modified NumFunctionDeclBits and the accessor /// methods in FunctionDecl and CXXDeductionGuideDecl - /// (for IsCopyDeductionCandidate) should be updated appropriately. + /// (for DeductionCandidateKind) should be updated appropriately. class FunctionDeclBitfields { friend class FunctionDecl; - /// For IsCopyDeductionCandidate + /// For DeductionCandidateKind friend class CXXDeductionGuideDecl; /// For the bits in DeclContextBitfields. uint64_t : NumDeclContextBits; @@ -1644,6 +1666,8 @@ class DeclContext { /// Kind of contexpr specifier as defined by ConstexprSpecKind. uint64_t ConstexprKind : 2; + uint64_t BodyContainsImmediateEscalatingExpression : 1; + uint64_t InstantiationIsPending : 1; /// Indicates if the function uses __try. @@ -1661,10 +1685,10 @@ class DeclContext { /// function using attribute 'target'. uint64_t IsMultiVersion : 1; - /// [C++17] Only used by CXXDeductionGuideDecl. Indicates that - /// the Deduction Guide is the implicitly generated 'copy - /// deduction candidate' (is used during overload resolution). - uint64_t IsCopyDeductionCandidate : 1; + /// Only used by CXXDeductionGuideDecl. Indicates the kind + /// of the Deduction Guide that is implicitly generated + /// (used during overload resolution). + uint64_t DeductionCandidateKind : 2; /// Store the ODRHash after first calculation. uint64_t HasODRHash : 1; @@ -1678,7 +1702,7 @@ class DeclContext { }; /// Number of non-inherited bits in FunctionDeclBitfields. - enum { NumFunctionDeclBits = 29 }; + enum { NumFunctionDeclBits = 30 }; /// Stores the bits used by CXXConstructorDecl. If modified /// NumCXXConstructorDeclBits and the accessor @@ -1690,12 +1714,12 @@ class DeclContext { /// For the bits in FunctionDeclBitfields. uint64_t : NumFunctionDeclBits; - /// 22 bits to fit in the remaining available space. + /// 21 bits to fit in the remaining available space. /// Note that this makes CXXConstructorDeclBitfields take /// exactly 64 bits and thus the width of NumCtorInitializers /// will need to be shrunk if some bit is added to NumDeclContextBitfields, /// NumFunctionDeclBitfields or CXXConstructorDeclBitfields. - uint64_t NumCtorInitializers : 19; + uint64_t NumCtorInitializers : 18; uint64_t IsInheritingConstructor : 1; /// Whether this constructor has a trail-allocated explicit specifier. @@ -2525,10 +2549,8 @@ public: D == LastDecl); } - bool setUseQualifiedLookup(bool use = true) const { - bool old_value = DeclContextBits.UseQualifiedLookup; + void setUseQualifiedLookup(bool use = true) const { DeclContextBits.UseQualifiedLookup = use; - return old_value; } bool shouldUseQualifiedLookup() const { @@ -2589,14 +2611,6 @@ private: void reconcileExternalVisibleStorage() const; bool LoadLexicalDeclsFromExternalStorage() const; - /// Makes a declaration visible within this context, but - /// suppresses searches for external declarations with the same - /// name. - /// - /// Analogous to makeDeclVisibleInContext, but for the exclusive - /// use of addDeclInternal(). - void makeDeclVisibleInContextInternal(NamedDecl *D); - StoredDeclsMap *CreateStoredDeclsMap(ASTContext &C) const; void loadLazyLocalLexicalLookups(); diff --git a/contrib/llvm-project/clang/include/clang/AST/DeclCXX.h b/contrib/llvm-project/clang/include/clang/AST/DeclCXX.h index 11276c77490..afec8150c2c 100644 --- a/contrib/llvm-project/clang/include/clang/AST/DeclCXX.h +++ b/contrib/llvm-project/clang/include/clang/AST/DeclCXX.h @@ -395,7 +395,7 @@ private: unsigned NumCaptures : 15; /// The number of explicit captures in this lambda. - unsigned NumExplicitCaptures : 13; + unsigned NumExplicitCaptures : 12; /// Has known `internal` linkage. unsigned HasKnownInternalLinkage : 1; @@ -404,6 +404,10 @@ private: /// mangling in the Itanium C++ ABI. unsigned ManglingNumber : 31; + /// The index of this lambda within its context declaration. This is not in + /// general the same as the mangling number. + unsigned IndexInContext; + /// The declaration that provides context for this lambda, if the /// actual DeclContext does not suffice. This is used for lambdas that /// occur within default arguments of function parameters within the class @@ -424,7 +428,7 @@ private: : DefinitionData(D), DependencyKind(DK), IsGenericLambda(IsGeneric), CaptureDefault(CaptureDefault), NumCaptures(0), NumExplicitCaptures(0), HasKnownInternalLinkage(0), ManglingNumber(0), - MethodTyInfo(Info) { + IndexInContext(0), MethodTyInfo(Info) { IsLambda = true; // C++1z [expr.prim.lambda]p4: @@ -1092,6 +1096,11 @@ public: unsigned capture_size() const { return getLambdaData().NumCaptures; } + const LambdaCapture *getCapture(unsigned I) const { + assert(isLambda() && I < capture_size() && "invalid index for capture"); + return captures_begin() + I; + } + using conversion_iterator = UnresolvedSetIterator; conversion_iterator conversion_begin() const { @@ -1160,6 +1169,10 @@ public: /// /// \note This does NOT include a check for union-ness. bool isEmpty() const { return data().Empty; } + /// Marks this record as empty. This is used by DWARFASTParserClang + /// when parsing records with empty fields having [[no_unique_address]] + /// attribute + void markEmpty() { data().Empty = true; } void setInitMethod(bool Val) { data().HasInitMethod = Val; } bool hasInitMethod() const { return data().HasInitMethod; } @@ -1437,7 +1450,7 @@ public: } /// Notify the class that this destructor is now selected. - /// + /// /// Important properties of the class depend on destructor properties. Since /// C++20, it is possible to have multiple destructor declarations in a class /// out of which one will be selected at the end. @@ -1763,18 +1776,31 @@ public: /// the declaration context suffices. Decl *getLambdaContextDecl() const; - /// Set the mangling number and context declaration for a lambda - /// class. - void setLambdaMangling(unsigned ManglingNumber, Decl *ContextDecl, - bool HasKnownInternalLinkage = false) { + /// Retrieve the index of this lambda within the context declaration returned + /// by getLambdaContextDecl(). + unsigned getLambdaIndexInContext() const { assert(isLambda() && "Not a lambda closure type!"); - getLambdaData().ManglingNumber = ManglingNumber; - getLambdaData().ContextDecl = ContextDecl; - getLambdaData().HasKnownInternalLinkage = HasKnownInternalLinkage; + return getLambdaData().IndexInContext; } - /// Set the device side mangling number. - void setDeviceLambdaManglingNumber(unsigned Num) const; + /// Information about how a lambda is numbered within its context. + struct LambdaNumbering { + Decl *ContextDecl = nullptr; + unsigned IndexInContext = 0; + unsigned ManglingNumber = 0; + unsigned DeviceManglingNumber = 0; + bool HasKnownInternalLinkage = false; + }; + + /// Set the mangling numbers and context declaration for a lambda class. + void setLambdaNumbering(LambdaNumbering Numbering); + + // Get the mangling numbers and context declaration for a lambda class. + LambdaNumbering getLambdaNumbering() const { + return {getLambdaContextDecl(), getLambdaIndexInContext(), + getLambdaManglingNumber(), getDeviceLambdaManglingNumber(), + hasKnownLambdaInternalLinkage()}; + } /// Retrieve the device side mangling number. unsigned getDeviceLambdaManglingNumber() const; @@ -1826,6 +1852,20 @@ public: return getLambdaData().MethodTyInfo; } + void setLambdaTypeInfo(TypeSourceInfo *TS) { + assert(DefinitionData && DefinitionData->IsLambda && + "setting lambda property of non-lambda class"); + auto &DL = static_cast(*DefinitionData); + DL.MethodTyInfo = TS; + } + + void setLambdaIsGeneric(bool IsGeneric) { + assert(DefinitionData && DefinitionData->IsLambda && + "setting lambda property of non-lambda class"); + auto &DL = static_cast(*DefinitionData); + DL.IsGenericLambda = IsGeneric; + } + // Determine whether this type is an Interface Like type for // __interface inheritance purposes. bool isInterfaceLike() const; @@ -1902,13 +1942,13 @@ private: ExplicitSpecifier ES, const DeclarationNameInfo &NameInfo, QualType T, TypeSourceInfo *TInfo, SourceLocation EndLocation, - CXXConstructorDecl *Ctor) + CXXConstructorDecl *Ctor, DeductionCandidate Kind) : FunctionDecl(CXXDeductionGuide, C, DC, StartLoc, NameInfo, T, TInfo, SC_None, false, false, ConstexprSpecKind::Unspecified), Ctor(Ctor), ExplicitSpec(ES) { if (EndLocation.isValid()) setRangeEnd(EndLocation); - setIsCopyDeductionCandidate(false); + setDeductionCandidateKind(Kind); } CXXConstructorDecl *Ctor; @@ -1923,7 +1963,8 @@ public: Create(ASTContext &C, DeclContext *DC, SourceLocation StartLoc, ExplicitSpecifier ES, const DeclarationNameInfo &NameInfo, QualType T, TypeSourceInfo *TInfo, SourceLocation EndLocation, - CXXConstructorDecl *Ctor = nullptr); + CXXConstructorDecl *Ctor = nullptr, + DeductionCandidate Kind = DeductionCandidate::Normal); static CXXDeductionGuideDecl *CreateDeserialized(ASTContext &C, unsigned ID); @@ -1940,16 +1981,15 @@ public: /// Get the constructor from which this deduction guide was generated, if /// this is an implicit deduction guide. - CXXConstructorDecl *getCorrespondingConstructor() const { - return Ctor; + CXXConstructorDecl *getCorrespondingConstructor() const { return Ctor; } + + void setDeductionCandidateKind(DeductionCandidate K) { + FunctionDeclBits.DeductionCandidateKind = static_cast(K); } - void setIsCopyDeductionCandidate(bool isCDC = true) { - FunctionDeclBits.IsCopyDeductionCandidate = isCDC; - } - - bool isCopyDeductionCandidate() const { - return FunctionDeclBits.IsCopyDeductionCandidate; + DeductionCandidate getDeductionCandidateKind() const { + return static_cast( + FunctionDeclBits.DeductionCandidateKind); } // Implement isa/cast/dyncast/etc. @@ -3970,12 +4010,12 @@ public: /// Represents a C++11 static_assert declaration. class StaticAssertDecl : public Decl { llvm::PointerIntPair AssertExprAndFailed; - StringLiteral *Message; + Expr *Message; SourceLocation RParenLoc; StaticAssertDecl(DeclContext *DC, SourceLocation StaticAssertLoc, - Expr *AssertExpr, StringLiteral *Message, - SourceLocation RParenLoc, bool Failed) + Expr *AssertExpr, Expr *Message, SourceLocation RParenLoc, + bool Failed) : Decl(StaticAssert, DC, StaticAssertLoc), AssertExprAndFailed(AssertExpr, Failed), Message(Message), RParenLoc(RParenLoc) {} @@ -3987,15 +4027,15 @@ public: static StaticAssertDecl *Create(ASTContext &C, DeclContext *DC, SourceLocation StaticAssertLoc, - Expr *AssertExpr, StringLiteral *Message, + Expr *AssertExpr, Expr *Message, SourceLocation RParenLoc, bool Failed); static StaticAssertDecl *CreateDeserialized(ASTContext &C, unsigned ID); Expr *getAssertExpr() { return AssertExprAndFailed.getPointer(); } const Expr *getAssertExpr() const { return AssertExprAndFailed.getPointer(); } - StringLiteral *getMessage() { return Message; } - const StringLiteral *getMessage() const { return Message; } + Expr *getMessage() { return Message; } + const Expr *getMessage() const { return Message; } bool isFailed() const { return AssertExprAndFailed.getInt(); } diff --git a/contrib/llvm-project/clang/include/clang/AST/DeclObjC.h b/contrib/llvm-project/clang/include/clang/AST/DeclObjC.h index 3d650b82f2b..ee8ec7a6a01 100644 --- a/contrib/llvm-project/clang/include/clang/AST/DeclObjC.h +++ b/contrib/llvm-project/clang/include/clang/AST/DeclObjC.h @@ -172,7 +172,7 @@ private: Selector SelInfo, QualType T, TypeSourceInfo *ReturnTInfo, DeclContext *contextDecl, bool isInstance = true, bool isVariadic = false, bool isPropertyAccessor = false, - bool isSynthesizedAccessorStub = false, + bool isSynthesizedAccessorStub = false, bool isImplicitlyDeclared = false, bool isDefined = false, ImplementationControl impControl = None, bool HasRelatedResultType = false); diff --git a/contrib/llvm-project/clang/include/clang/AST/DeclTemplate.h b/contrib/llvm-project/clang/include/clang/AST/DeclTemplate.h index ae2542f4f23..7cd505218f2 100755 --- a/contrib/llvm-project/clang/include/clang/AST/DeclTemplate.h +++ b/contrib/llvm-project/clang/include/clang/AST/DeclTemplate.h @@ -117,6 +117,8 @@ public: SourceLocation RAngleLoc, Expr *RequiresClause); + void Profile(llvm::FoldingSetNodeID &ID, const ASTContext &C) const; + /// Iterates through the template parameters in this list. using iterator = NamedDecl **; @@ -616,7 +618,7 @@ public: static void Profile(llvm::FoldingSetNodeID &ID, ArrayRef TemplateArgs, - ASTContext &Context) { + const ASTContext &Context) { ID.AddInteger(TemplateArgs.size()); for (const TemplateArgument &TemplateArg : TemplateArgs) TemplateArg.Profile(ID, Context); @@ -850,7 +852,7 @@ protected: /// template. /// /// This pointer refers to the template arguments (there are as - /// many template arguments as template parameaters) for the + /// many template arguments as template parameters) for the /// template, and is allocated lazily, since most templates do not /// require the use of this information. TemplateArgument *InjectedArgs = nullptr; @@ -2081,7 +2083,7 @@ public: static void Profile(llvm::FoldingSetNodeID &ID, ArrayRef TemplateArgs, - ASTContext &Context) { + const ASTContext &Context) { ID.AddInteger(TemplateArgs.size()); for (const TemplateArgument &TemplateArg : TemplateArgs) TemplateArg.Profile(ID, Context); @@ -2257,7 +2259,7 @@ public: static void Profile(llvm::FoldingSetNodeID &ID, ArrayRef TemplateArgs, - TemplateParameterList *TPL, ASTContext &Context); + TemplateParameterList *TPL, const ASTContext &Context); static bool classof(const Decl *D) { return classofKind(D->getKind()); } @@ -2307,9 +2309,15 @@ protected: return static_cast(RedeclarableTemplateDecl::getCommonPtr()); } + void setCommonPtr(Common *C) { + RedeclarableTemplateDecl::Common = C; + } + public: + friend class ASTDeclReader; friend class ASTDeclWriter; + friend class TemplateDeclInstantiator; /// Load any lazily-loaded specializations from the external source. void LoadLazySpecializations() const; @@ -2926,13 +2934,7 @@ public: return ExplicitInfo ? ExplicitInfo->TemplateKeywordLoc : SourceLocation(); } - SourceRange getSourceRange() const override LLVM_READONLY { - if (isExplicitSpecialization()) { - if (const ASTTemplateArgumentListInfo *Info = getTemplateArgsInfo()) - return SourceRange(getOuterLocStart(), Info->getRAngleLoc()); - } - return VarDecl::getSourceRange(); - } + SourceRange getSourceRange() const override LLVM_READONLY; void Profile(llvm::FoldingSetNodeID &ID) const { Profile(ID, TemplateArgs->asArray(), getASTContext()); @@ -2940,7 +2942,7 @@ public: static void Profile(llvm::FoldingSetNodeID &ID, ArrayRef TemplateArgs, - ASTContext &Context) { + const ASTContext &Context) { ID.AddInteger(TemplateArgs.size()); for (const TemplateArgument &TemplateArg : TemplateArgs) TemplateArg.Profile(ID, Context); @@ -3091,13 +3093,7 @@ public: return First->InstantiatedFromMember.setInt(true); } - SourceRange getSourceRange() const override LLVM_READONLY { - if (isExplicitSpecialization()) { - if (const ASTTemplateArgumentListInfo *Info = getTemplateArgsAsWritten()) - return SourceRange(getOuterLocStart(), Info->getRAngleLoc()); - } - return VarDecl::getSourceRange(); - } + SourceRange getSourceRange() const override LLVM_READONLY; void Profile(llvm::FoldingSetNodeID &ID) const { Profile(ID, getTemplateArgs().asArray(), getTemplateParameters(), @@ -3106,7 +3102,7 @@ public: static void Profile(llvm::FoldingSetNodeID &ID, ArrayRef TemplateArgs, - TemplateParameterList *TPL, ASTContext &Context); + TemplateParameterList *TPL, const ASTContext &Context); static bool classof(const Decl *D) { return classofKind(D->getKind()); } diff --git a/contrib/llvm-project/clang/include/clang/AST/DeclarationName.h b/contrib/llvm-project/clang/include/clang/AST/DeclarationName.h index 1496e213dd7..b06931ea3e4 100644 --- a/contrib/llvm-project/clang/include/clang/AST/DeclarationName.h +++ b/contrib/llvm-project/clang/include/clang/AST/DeclarationName.h @@ -118,14 +118,14 @@ class alignas(IdentifierInfoAlignment) CXXLiteralOperatorIdName friend class clang::DeclarationName; friend class clang::DeclarationNameTable; - IdentifierInfo *ID; + const IdentifierInfo *ID; /// Extra information associated with this operator name that /// can be used by the front end. All bits are really needed /// so it is not possible to stash something in the low order bits. void *FETokenInfo; - CXXLiteralOperatorIdName(IdentifierInfo *II) + CXXLiteralOperatorIdName(const IdentifierInfo *II) : DeclarationNameExtra(CXXLiteralOperatorName), ID(II), FETokenInfo(nullptr) {} @@ -478,7 +478,7 @@ public: /// If this name is the name of a literal operator, /// retrieve the identifier associated with it. - IdentifierInfo *getCXXLiteralIdentifier() const { + const IdentifierInfo *getCXXLiteralIdentifier() const { if (getNameKind() == CXXLiteralOperatorName) { assert(getPtr() && "getCXXLiteralIdentifier on a null DeclarationName!"); return castAsCXXLiteralOperatorIdName()->ID; @@ -650,7 +650,7 @@ public: } /// Get the name of the literal operator function with II as the identifier. - DeclarationName getCXXLiteralOperatorName(IdentifierInfo *II); + DeclarationName getCXXLiteralOperatorName(const IdentifierInfo *II); }; /// DeclarationNameLoc - Additional source/type location info @@ -763,7 +763,7 @@ public: }; /// DeclarationNameInfo - A collector data type for bundling together -/// a DeclarationName and the correspnding source/type location info. +/// a DeclarationName and the corresponding source/type location info. struct DeclarationNameInfo { private: /// Name - The declaration name, also encoding name kind. diff --git a/contrib/llvm-project/clang/include/clang/AST/Expr.h b/contrib/llvm-project/clang/include/clang/AST/Expr.h index b47e2aa4688..f9795b6386c 100644 --- a/contrib/llvm-project/clang/include/clang/AST/Expr.h +++ b/contrib/llvm-project/clang/include/clang/AST/Expr.h @@ -135,8 +135,8 @@ protected: void setDependence(ExprDependence Deps) { ExprBits.Dependent = static_cast(Deps); } - friend class ASTImporter; // Sets dependence dircetly. - friend class ASTStmtReader; // Sets dependence dircetly. + friend class ASTImporter; // Sets dependence directly. + friend class ASTStmtReader; // Sets dependence directly. public: QualType getType() const { return TR; } @@ -171,7 +171,7 @@ public: } /// Determines whether the type of this expression depends on - /// - a template paramter (C++ [temp.dep.expr], which means that its type + /// - a template parameter (C++ [temp.dep.expr], which means that its type /// could change from one template instantiation to the next) /// - or an error /// @@ -593,12 +593,12 @@ public: struct EvalStatus { /// Whether the evaluated expression has side effects. /// For example, (f() && 0) can be folded, but it still has side effects. - bool HasSideEffects; + bool HasSideEffects = false; /// Whether the evaluation hit undefined behavior. /// For example, 1.0 / 0.0 can be folded to Inf, but has undefined behavior. /// Likewise, INT_MAX + 1 can be folded to INT_MIN, but has UB. - bool HasUndefinedBehavior; + bool HasUndefinedBehavior = false; /// Diag - If this is non-null, it will be filled in with a stack of notes /// indicating why evaluation failed (or why it failed to produce a constant @@ -607,10 +607,9 @@ public: /// foldable. If the expression is foldable, but not a constant expression, /// the notes will describes why it isn't a constant expression. If the /// expression *is* a constant expression, no notes will be produced. - SmallVectorImpl *Diag; + SmallVectorImpl *Diag = nullptr; - EvalStatus() - : HasSideEffects(false), HasUndefinedBehavior(false), Diag(nullptr) {} + EvalStatus() = default; // hasSideEffects - Return true if the evaluated expression has // side effects. @@ -665,8 +664,8 @@ public: SideEffectsKind AllowSideEffects = SE_NoSideEffects, bool InConstantContext = false) const; - /// EvaluateAsFloat - Return true if this is a constant which we can fold and - /// convert to a fixed point value. + /// EvaluateAsFixedPoint - Return true if this is a constant which we can fold + /// and convert to a fixed point value. bool EvaluateAsFixedPoint(EvalResult &Result, const ASTContext &Ctx, SideEffectsKind AllowSideEffects = SE_NoSideEffects, bool InConstantContext = false) const; @@ -714,7 +713,8 @@ public: /// notes will be produced if the expression is not a constant expression. bool EvaluateAsInitializer(APValue &Result, const ASTContext &Ctx, const VarDecl *VD, - SmallVectorImpl &Notes) const; + SmallVectorImpl &Notes, + bool IsConstantInitializer) const; /// EvaluateWithSubstitution - Evaluate an expression as if from the context /// of a call to the given function with the given arguments, inside an @@ -762,6 +762,11 @@ public: /// strlen, false otherwise. bool tryEvaluateStrLen(uint64_t &Result, ASTContext &Ctx) const; + bool EvaluateCharRangeAsString(std::string &Result, + const Expr *SizeExpression, + const Expr *PtrExpression, ASTContext &Ctx, + EvalResult &Status) const; + /// Enumeration used to describe the kind of Null pointer constant /// returned from \c isNullPointerConstant(). enum NullPointerConstantKind { @@ -819,7 +824,7 @@ public: /// member expression. static QualType findBoundMemberType(const Expr *expr); - /// Skip past any invisble AST nodes which might surround this + /// Skip past any invisible AST nodes which might surround this /// statement, such as ExprWithCleanups or ImplicitCastExpr nodes, /// but also injected CXXMemberExpr and CXXConstructExpr which represent /// implicit conversions. @@ -923,7 +928,7 @@ public: return const_cast(this)->IgnoreParenLValueCasts(); } - /// Skip past any parenthese and casts which do not change the value + /// Skip past any parentheses and casts which do not change the value /// (including ptr->int casts of the same size) until reaching a fixed point. /// Skips: /// * What IgnoreParens() skips @@ -1436,6 +1441,14 @@ public: return DeclRefExprBits.RefersToEnclosingVariableOrCapture; } + bool isImmediateEscalating() const { + return DeclRefExprBits.IsImmediateEscalating; + } + + void setIsImmediateEscalating(bool Set) { + DeclRefExprBits.IsImmediateEscalating = Set; + } + static bool classof(const Stmt *T) { return T->getStmtClass() == DeclRefExprClass; } @@ -1796,7 +1809,7 @@ class StringLiteral final /// * An array of getByteLength() char used to store the string data. public: - enum StringKind { Ordinary, Wide, UTF8, UTF16, UTF32 }; + enum StringKind { Ordinary, Wide, UTF8, UTF16, UTF32, Unevaluated }; private: unsigned numTrailingObjects(OverloadToken) const { return 1; } @@ -1858,7 +1871,7 @@ public: unsigned CharByteWidth); StringRef getString() const { - assert(getCharByteWidth() == 1 && + assert((isUnevaluated() || getCharByteWidth() == 1) && "This function is used in places that assume strings use char"); return StringRef(getStrDataAsChar(), getByteLength()); } @@ -1898,6 +1911,7 @@ public: bool isUTF8() const { return getKind() == UTF8; } bool isUTF16() const { return getKind() == UTF16; } bool isUTF32() const { return getKind() == UTF32; } + bool isUnevaluated() const { return getKind() == Unevaluated; } bool isPascal() const { return StringLiteralBits.IsPascal; } bool containsNonAscii() const { @@ -1992,7 +2006,7 @@ public: private: PredefinedExpr(SourceLocation L, QualType FNTy, IdentKind IK, - StringLiteral *SL); + bool IsTransparent, StringLiteral *SL); explicit PredefinedExpr(EmptyShell Empty, bool HasFunctionName); @@ -2007,8 +2021,12 @@ private: public: /// Create a PredefinedExpr. + /// + /// If IsTransparent, the PredefinedExpr is transparently handled as a + /// StringLiteral. static PredefinedExpr *Create(const ASTContext &Ctx, SourceLocation L, - QualType FNTy, IdentKind IK, StringLiteral *SL); + QualType FNTy, IdentKind IK, bool IsTransparent, + StringLiteral *SL); /// Create an empty PredefinedExpr. static PredefinedExpr *CreateEmpty(const ASTContext &Ctx, @@ -2018,6 +2036,8 @@ public: return static_cast(PredefinedExprBits.Kind); } + bool isTransparent() const { return PredefinedExprBits.IsTransparent; } + SourceLocation getLocation() const { return PredefinedExprBits.Loc; } void setLocation(SourceLocation L) { PredefinedExprBits.Loc = L; } @@ -2233,14 +2253,14 @@ public: bool canOverflow() const { return UnaryOperatorBits.CanOverflow; } void setCanOverflow(bool C) { UnaryOperatorBits.CanOverflow = C; } - // Get the FP contractability status of this operator. Only meaningful for - // operations on floating point types. + /// Get the FP contractability status of this operator. Only meaningful for + /// operations on floating point types. bool isFPContractableWithinStatement(const LangOptions &LO) const { return getFPFeaturesInEffect(LO).allowFPContractWithinStatement(); } - // Get the FENV_ACCESS status of this operator. Only meaningful for - // operations on floating point types. + /// Get the FENV_ACCESS status of this operator. Only meaningful for + /// operations on floating point types. bool isFEnvAccessOn(const LangOptions &LO) const { return getFPFeaturesInEffect(LO).getAllowFEnvAccess(); } @@ -2325,8 +2345,8 @@ protected: void setStoredFPFeatures(FPOptionsOverride F) { getTrailingFPFeatures() = F; } public: - // Get the FP features status of this operator. Only meaningful for - // operations on floating point types. + /// Get the FP features status of this operator. Only meaningful for + /// operations on floating point types. FPOptions getFPFeaturesInEffect(const LangOptions &LO) const { if (UnaryOperatorBits.HasFPFeatures) return getStoredFPFeatures().applyOverrides(LO); @@ -2814,7 +2834,7 @@ class CallExpr : public Expr { /// The number of arguments in the call expression. unsigned NumArgs; - /// The location of the right parenthese. This has a different meaning for + /// The location of the right parentheses. This has a different meaning for /// the derived classes of CallExpr. SourceLocation RParenLoc; @@ -3082,8 +3102,8 @@ public: *getTrailingFPFeatures() = F; } - // Get the FP features status of this operator. Only meaningful for - // operations on floating point types. + /// Get the FP features status of this operator. Only meaningful for + /// operations on floating point types. FPOptions getFPFeaturesInEffect(const LangOptions &LO) const { if (hasStoredFPFeatures()) return getStoredFPFeatures().applyOverrides(LO); @@ -3573,8 +3593,8 @@ public: return *getTrailingFPFeatures(); } - // Get the FP features status of this operation. Only meaningful for - // operations on floating point types. + /// Get the FP features status of this operation. Only meaningful for + /// operations on floating point types. FPOptions getFPFeaturesInEffect(const LangOptions &LO) const { if (hasStoredFPFeatures()) return getStoredFPFeatures().applyOverrides(LO); @@ -3971,11 +3991,12 @@ public: return isShiftAssignOp(getOpcode()); } - // Return true if a binary operator using the specified opcode and operands - // would match the 'p = (i8*)nullptr + n' idiom for casting a pointer-sized - // integer to a pointer. + /// Return true if a binary operator using the specified opcode and operands + /// would match the 'p = (i8*)nullptr + n' idiom for casting a pointer-sized + /// integer to a pointer. static bool isNullPointerArithmeticExtension(ASTContext &Ctx, Opcode Opc, - Expr *LHS, Expr *RHS); + const Expr *LHS, + const Expr *RHS); static bool classof(const Stmt *S) { return S->getStmtClass() >= firstBinaryOperatorConstant && @@ -4006,8 +4027,8 @@ public: *getTrailingFPFeatures() = F; } - // Get the FP features status of this operator. Only meaningful for - // operations on floating point types. + /// Get the FP features status of this operator. Only meaningful for + /// operations on floating point types. FPOptions getFPFeaturesInEffect(const LangOptions &LO) const { if (BinaryOperatorBits.HasFPFeatures) return getStoredFPFeatures().applyOverrides(LO); @@ -4021,14 +4042,14 @@ public: return FPOptionsOverride(); } - // Get the FP contractability status of this operator. Only meaningful for - // operations on floating point types. + /// Get the FP contractability status of this operator. Only meaningful for + /// operations on floating point types. bool isFPContractableWithinStatement(const LangOptions &LO) const { return getFPFeaturesInEffect(LO).allowFPContractWithinStatement(); } - // Get the FENV_ACCESS status of this operator. Only meaningful for - // operations on floating point types. + /// Get the FENV_ACCESS status of this operator. Only meaningful for + /// operations on floating point types. bool isFEnvAccessOn(const LangOptions &LO) const { return getFPFeaturesInEffect(LO).getAllowFEnvAccess(); } @@ -4124,17 +4145,17 @@ protected: : Expr(SC, Empty) { } public: - // getCond - Return the expression representing the condition for - // the ?: operator. + /// getCond - Return the expression representing the condition for + /// the ?: operator. Expr *getCond() const; - // getTrueExpr - Return the subexpression representing the value of - // the expression if the condition evaluates to true. + /// getTrueExpr - Return the subexpression representing the value of + /// the expression if the condition evaluates to true. Expr *getTrueExpr() const; - // getFalseExpr - Return the subexpression representing the value of - // the expression if the condition evaluates to false. This is - // the same as getRHS. + /// getFalseExpr - Return the subexpression representing the value of + /// the expression if the condition evaluates to false. This is + /// the same as getRHS. Expr *getFalseExpr() const; SourceLocation getQuestionLoc() const { return QuestionLoc; } @@ -4169,17 +4190,17 @@ public: explicit ConditionalOperator(EmptyShell Empty) : AbstractConditionalOperator(ConditionalOperatorClass, Empty) { } - // getCond - Return the expression representing the condition for - // the ?: operator. + /// getCond - Return the expression representing the condition for + /// the ?: operator. Expr *getCond() const { return cast(SubExprs[COND]); } - // getTrueExpr - Return the subexpression representing the value of - // the expression if the condition evaluates to true. + /// getTrueExpr - Return the subexpression representing the value of + /// the expression if the condition evaluates to true. Expr *getTrueExpr() const { return cast(SubExprs[LHS]); } - // getFalseExpr - Return the subexpression representing the value of - // the expression if the condition evaluates to false. This is - // the same as getRHS. + /// getFalseExpr - Return the subexpression representing the value of + /// the expression if the condition evaluates to false. This is + /// the same as getRHS. Expr *getFalseExpr() const { return cast(SubExprs[RHS]); } Expr *getLHS() const { return cast(SubExprs[LHS]); } @@ -4684,13 +4705,22 @@ public: }; /// Represents a function call to one of __builtin_LINE(), __builtin_COLUMN(), -/// __builtin_FUNCTION(), __builtin_FILE(), or __builtin_source_location(). +/// __builtin_FUNCTION(), __builtin_FUNCSIG(), __builtin_FILE(), +/// __builtin_FILE_NAME() or __builtin_source_location(). class SourceLocExpr final : public Expr { SourceLocation BuiltinLoc, RParenLoc; DeclContext *ParentContext; public: - enum IdentKind { Function, File, Line, Column, SourceLocStruct }; + enum IdentKind { + Function, + FuncSig, + File, + FileName, + Line, + Column, + SourceLocStruct + }; SourceLocExpr(const ASTContext &Ctx, IdentKind Type, QualType ResultTy, SourceLocation BLoc, SourceLocation RParenLoc, @@ -4714,7 +4744,9 @@ public: bool isIntType() const { switch (getIdentKind()) { case File: + case FileName: case Function: + case FuncSig: case SourceLocStruct: return false; case Line: @@ -4900,6 +4932,13 @@ public: /// has been set. bool hasArrayFiller() const { return getArrayFiller(); } + /// Determine whether this initializer list contains a designated initializer. + bool hasDesignatedInit() const { + return std::any_of(begin(), end(), [](const Stmt *S) { + return isa(S); + }); + } + /// If this initializes a union, specifies which field in the /// union to initialize. /// @@ -4928,8 +4967,8 @@ public: return LBraceLoc.isValid() && RBraceLoc.isValid(); } - // Is this an initializer for an array of characters, initialized by a string - // literal or an @encode? + /// Is this an initializer for an array of characters, initialized by a string + /// literal or an @encode? bool isStringLiteralInit() const; /// Is this a transparent initializer list (that is, an InitListExpr that is @@ -5068,37 +5107,6 @@ private: NumDesignators(0), NumSubExprs(NumSubExprs), Designators(nullptr) { } public: - /// A field designator, e.g., ".x". - struct FieldDesignator { - /// Refers to the field that is being initialized. The low bit - /// of this field determines whether this is actually a pointer - /// to an IdentifierInfo (if 1) or a FieldDecl (if 0). When - /// initially constructed, a field designator will store an - /// IdentifierInfo*. After semantic analysis has resolved that - /// name, the field designator will instead store a FieldDecl*. - uintptr_t NameOrField; - - /// The location of the '.' in the designated initializer. - SourceLocation DotLoc; - - /// The location of the field name in the designated initializer. - SourceLocation FieldLoc; - }; - - /// An array or GNU array-range designator, e.g., "[9]" or "[10..15]". - struct ArrayOrRangeDesignator { - /// Location of the first index expression within the designated - /// initializer expression's list of subexpressions. - unsigned Index; - /// The location of the '[' starting the array range designator. - SourceLocation LBracketLoc; - /// The location of the ellipsis separating the start and end - /// indices. Only valid for GNU array-range designators. - SourceLocation EllipsisLoc; - /// The location of the ']' terminating the array range designator. - SourceLocation RBracketLoc; - }; - /// Represents a single C99 designator. /// /// @todo This class is infuriatingly similar to clang::Designator, @@ -5106,118 +5114,177 @@ public: /// keep us from reusing it. Try harder, later, to rectify these /// differences. class Designator { + /// A field designator, e.g., ".x". + struct FieldDesignatorInfo { + /// Refers to the field that is being initialized. The low bit + /// of this field determines whether this is actually a pointer + /// to an IdentifierInfo (if 1) or a FieldDecl (if 0). When + /// initially constructed, a field designator will store an + /// IdentifierInfo*. After semantic analysis has resolved that + /// name, the field designator will instead store a FieldDecl*. + uintptr_t NameOrField; + + /// The location of the '.' in the designated initializer. + SourceLocation DotLoc; + + /// The location of the field name in the designated initializer. + SourceLocation FieldLoc; + + FieldDesignatorInfo(const IdentifierInfo *II, SourceLocation DotLoc, + SourceLocation FieldLoc) + : NameOrField(reinterpret_cast(II) | 0x1), DotLoc(DotLoc), + FieldLoc(FieldLoc) {} + }; + + /// An array or GNU array-range designator, e.g., "[9]" or "[10...15]". + struct ArrayOrRangeDesignatorInfo { + /// Location of the first index expression within the designated + /// initializer expression's list of subexpressions. + unsigned Index; + + /// The location of the '[' starting the array range designator. + SourceLocation LBracketLoc; + + /// The location of the ellipsis separating the start and end + /// indices. Only valid for GNU array-range designators. + SourceLocation EllipsisLoc; + + /// The location of the ']' terminating the array range designator. + SourceLocation RBracketLoc; + + ArrayOrRangeDesignatorInfo(unsigned Index, SourceLocation LBracketLoc, + SourceLocation RBracketLoc) + : Index(Index), LBracketLoc(LBracketLoc), RBracketLoc(RBracketLoc) {} + + ArrayOrRangeDesignatorInfo(unsigned Index, + SourceLocation LBracketLoc, + SourceLocation EllipsisLoc, + SourceLocation RBracketLoc) + : Index(Index), LBracketLoc(LBracketLoc), EllipsisLoc(EllipsisLoc), + RBracketLoc(RBracketLoc) {} + }; + /// The kind of designator this describes. - enum { + enum DesignatorKind { FieldDesignator, ArrayDesignator, ArrayRangeDesignator - } Kind; + }; + + DesignatorKind Kind; union { /// A field designator, e.g., ".x". - struct FieldDesignator Field; + struct FieldDesignatorInfo FieldInfo; + /// An array or GNU array-range designator, e.g., "[9]" or "[10..15]". - struct ArrayOrRangeDesignator ArrayOrRange; + struct ArrayOrRangeDesignatorInfo ArrayOrRangeInfo; }; - friend class DesignatedInitExpr; + + Designator(DesignatorKind Kind) : Kind(Kind) {} public: Designator() {} - /// Initializes a field designator. - Designator(const IdentifierInfo *FieldName, SourceLocation DotLoc, - SourceLocation FieldLoc) - : Kind(FieldDesignator) { - new (&Field) DesignatedInitExpr::FieldDesignator; - Field.NameOrField = reinterpret_cast(FieldName) | 0x01; - Field.DotLoc = DotLoc; - Field.FieldLoc = FieldLoc; - } - - /// Initializes an array designator. - Designator(unsigned Index, SourceLocation LBracketLoc, - SourceLocation RBracketLoc) - : Kind(ArrayDesignator) { - new (&ArrayOrRange) DesignatedInitExpr::ArrayOrRangeDesignator; - ArrayOrRange.Index = Index; - ArrayOrRange.LBracketLoc = LBracketLoc; - ArrayOrRange.EllipsisLoc = SourceLocation(); - ArrayOrRange.RBracketLoc = RBracketLoc; - } - - /// Initializes a GNU array-range designator. - Designator(unsigned Index, SourceLocation LBracketLoc, - SourceLocation EllipsisLoc, SourceLocation RBracketLoc) - : Kind(ArrayRangeDesignator) { - new (&ArrayOrRange) DesignatedInitExpr::ArrayOrRangeDesignator; - ArrayOrRange.Index = Index; - ArrayOrRange.LBracketLoc = LBracketLoc; - ArrayOrRange.EllipsisLoc = EllipsisLoc; - ArrayOrRange.RBracketLoc = RBracketLoc; - } - bool isFieldDesignator() const { return Kind == FieldDesignator; } bool isArrayDesignator() const { return Kind == ArrayDesignator; } bool isArrayRangeDesignator() const { return Kind == ArrayRangeDesignator; } - IdentifierInfo *getFieldName() const; + //===------------------------------------------------------------------===// + // FieldDesignatorInfo - FieldDecl *getField() const { - assert(Kind == FieldDesignator && "Only valid on a field designator"); - if (Field.NameOrField & 0x01) - return nullptr; - else - return reinterpret_cast(Field.NameOrField); + /// Creates a field designator. + static Designator CreateFieldDesignator(const IdentifierInfo *FieldName, + SourceLocation DotLoc, + SourceLocation FieldLoc) { + Designator D(FieldDesignator); + new (&D.FieldInfo) FieldDesignatorInfo(FieldName, DotLoc, FieldLoc); + return D; } - void setField(FieldDecl *FD) { - assert(Kind == FieldDesignator && "Only valid on a field designator"); - Field.NameOrField = reinterpret_cast(FD); + const IdentifierInfo *getFieldName() const; + + FieldDecl *getFieldDecl() const { + assert(isFieldDesignator() && "Only valid on a field designator"); + if (FieldInfo.NameOrField & 0x01) + return nullptr; + return reinterpret_cast(FieldInfo.NameOrField); + } + + void setFieldDecl(FieldDecl *FD) { + assert(isFieldDesignator() && "Only valid on a field designator"); + FieldInfo.NameOrField = reinterpret_cast(FD); } SourceLocation getDotLoc() const { - assert(Kind == FieldDesignator && "Only valid on a field designator"); - return Field.DotLoc; + assert(isFieldDesignator() && "Only valid on a field designator"); + return FieldInfo.DotLoc; } SourceLocation getFieldLoc() const { - assert(Kind == FieldDesignator && "Only valid on a field designator"); - return Field.FieldLoc; + assert(isFieldDesignator() && "Only valid on a field designator"); + return FieldInfo.FieldLoc; + } + + //===------------------------------------------------------------------===// + // ArrayOrRangeDesignator + + /// Creates an array designator. + static Designator CreateArrayDesignator(unsigned Index, + SourceLocation LBracketLoc, + SourceLocation RBracketLoc) { + Designator D(ArrayDesignator); + new (&D.ArrayOrRangeInfo) ArrayOrRangeDesignatorInfo(Index, LBracketLoc, + RBracketLoc); + return D; + } + + /// Creates a GNU array-range designator. + static Designator CreateArrayRangeDesignator(unsigned Index, + SourceLocation LBracketLoc, + SourceLocation EllipsisLoc, + SourceLocation RBracketLoc) { + Designator D(ArrayRangeDesignator); + new (&D.ArrayOrRangeInfo) ArrayOrRangeDesignatorInfo(Index, LBracketLoc, + EllipsisLoc, + RBracketLoc); + return D; + } + + unsigned getArrayIndex() const { + assert((isArrayDesignator() || isArrayRangeDesignator()) && + "Only valid on an array or array-range designator"); + return ArrayOrRangeInfo.Index; } SourceLocation getLBracketLoc() const { - assert((Kind == ArrayDesignator || Kind == ArrayRangeDesignator) && + assert((isArrayDesignator() || isArrayRangeDesignator()) && "Only valid on an array or array-range designator"); - return ArrayOrRange.LBracketLoc; - } - - SourceLocation getRBracketLoc() const { - assert((Kind == ArrayDesignator || Kind == ArrayRangeDesignator) && - "Only valid on an array or array-range designator"); - return ArrayOrRange.RBracketLoc; + return ArrayOrRangeInfo.LBracketLoc; } SourceLocation getEllipsisLoc() const { - assert(Kind == ArrayRangeDesignator && + assert(isArrayRangeDesignator() && "Only valid on an array-range designator"); - return ArrayOrRange.EllipsisLoc; + return ArrayOrRangeInfo.EllipsisLoc; } - unsigned getFirstExprIndex() const { - assert((Kind == ArrayDesignator || Kind == ArrayRangeDesignator) && + SourceLocation getRBracketLoc() const { + assert((isArrayDesignator() || isArrayRangeDesignator()) && "Only valid on an array or array-range designator"); - return ArrayOrRange.Index; + return ArrayOrRangeInfo.RBracketLoc; } SourceLocation getBeginLoc() const LLVM_READONLY { - if (Kind == FieldDesignator) - return getDotLoc().isInvalid()? getFieldLoc() : getDotLoc(); - else - return getLBracketLoc(); + if (isFieldDesignator()) + return getDotLoc().isInvalid() ? getFieldLoc() : getDotLoc(); + return getLBracketLoc(); } + SourceLocation getEndLoc() const LLVM_READONLY { - return Kind == FieldDesignator ? getFieldLoc() : getRBracketLoc(); + return isFieldDesignator() ? getFieldLoc() : getRBracketLoc(); } + SourceRange getSourceRange() const LLVM_READONLY { return SourceRange(getBeginLoc(), getEndLoc()); } @@ -5627,6 +5694,12 @@ public: /// which names a dependent type in its association list is result-dependent, /// which means that the choice of result expression is dependent. /// Result-dependent generic associations are both type- and value-dependent. +/// +/// We also allow an extended form in both C and C++ where the controlling +/// predicate for the selection expression is a type rather than an expression. +/// This type argument form does not perform any conversions for the +/// controlling type, which makes it suitable for use with qualified type +/// associations, which is not possible with the expression form. class GenericSelectionExpr final : public Expr, private llvm::TrailingObjects::max(), - ControllingIndex = 0, - AssocExprStartIndex = 1 + ResultDependentIndex = 0x7FFF }; + unsigned getIndexOfControllingExpression() const { + // If controlled by an expression, the first offset into the Stmt * + // trailing array is the controlling expression, the associated expressions + // follow this. + assert(isExprPredicate() && "Asking for the controlling expression of a " + "selection expr predicated by a type"); + return 0; + } + + unsigned getIndexOfControllingType() const { + // If controlled by a type, the first offset into the TypeSourceInfo * + // trailing array is the controlling type, the associated types follow this. + assert(isTypePredicate() && "Asking for the controlling type of a " + "selection expr predicated by an expression"); + return 0; + } + + unsigned getIndexOfStartOfAssociatedExprs() const { + // If the predicate is a type, then the associated expressions are the only + // Stmt * in the trailing array, otherwise we need to offset past the + // predicate expression. + return (int)isExprPredicate(); + } + + unsigned getIndexOfStartOfAssociatedTypes() const { + // If the predicate is a type, then the associated types follow it in the + // trailing array. Otherwise, the associated types are the only + // TypeSourceInfo * in the trailing array. + return (int)isTypePredicate(); + } + + /// The location of the "default" and of the right parenthesis. SourceLocation DefaultLoc, RParenLoc; // GenericSelectionExpr is followed by several trailing objects. // They are (in order): // - // * A single Stmt * for the controlling expression. + // * A single Stmt * for the controlling expression or a TypeSourceInfo * for + // the controlling type, depending on the result of isTypePredicate() or + // isExprPredicate(). // * An array of getNumAssocs() Stmt * for the association expressions. // * An array of getNumAssocs() TypeSourceInfo *, one for each of the // association expressions. unsigned numTrailingObjects(OverloadToken) const { // Add one to account for the controlling expression; the remainder // are the associated expressions. - return 1 + getNumAssocs(); + return getNumAssocs() + (int)isExprPredicate(); } unsigned numTrailingObjects(OverloadToken) const { - return getNumAssocs(); + // Add one to account for the controlling type predicate, the remainder + // are the associated types. + return getNumAssocs() + (int)isTypePredicate(); } template class AssociationIteratorTy; @@ -5744,7 +5853,8 @@ class GenericSelectionExpr final bool operator==(AssociationIteratorTy Other) const { return E == Other.E; } }; // class AssociationIterator - /// Build a non-result-dependent generic selection expression. + /// Build a non-result-dependent generic selection expression accepting an + /// expression predicate. GenericSelectionExpr(const ASTContext &Context, SourceLocation GenericLoc, Expr *ControllingExpr, ArrayRef AssocTypes, @@ -5753,7 +5863,8 @@ class GenericSelectionExpr final bool ContainsUnexpandedParameterPack, unsigned ResultIndex); - /// Build a result-dependent generic selection expression. + /// Build a result-dependent generic selection expression accepting an + /// expression predicate. GenericSelectionExpr(const ASTContext &Context, SourceLocation GenericLoc, Expr *ControllingExpr, ArrayRef AssocTypes, @@ -5761,11 +5872,31 @@ class GenericSelectionExpr final SourceLocation RParenLoc, bool ContainsUnexpandedParameterPack); + /// Build a non-result-dependent generic selection expression accepting a + /// type predicate. + GenericSelectionExpr(const ASTContext &Context, SourceLocation GenericLoc, + TypeSourceInfo *ControllingType, + ArrayRef AssocTypes, + ArrayRef AssocExprs, SourceLocation DefaultLoc, + SourceLocation RParenLoc, + bool ContainsUnexpandedParameterPack, + unsigned ResultIndex); + + /// Build a result-dependent generic selection expression accepting a type + /// predicate. + GenericSelectionExpr(const ASTContext &Context, SourceLocation GenericLoc, + TypeSourceInfo *ControllingType, + ArrayRef AssocTypes, + ArrayRef AssocExprs, SourceLocation DefaultLoc, + SourceLocation RParenLoc, + bool ContainsUnexpandedParameterPack); + /// Build an empty generic selection expression for deserialization. explicit GenericSelectionExpr(EmptyShell Empty, unsigned NumAssocs); public: - /// Create a non-result-dependent generic selection expression. + /// Create a non-result-dependent generic selection expression accepting an + /// expression predicate. static GenericSelectionExpr * Create(const ASTContext &Context, SourceLocation GenericLoc, Expr *ControllingExpr, ArrayRef AssocTypes, @@ -5773,13 +5904,31 @@ public: SourceLocation RParenLoc, bool ContainsUnexpandedParameterPack, unsigned ResultIndex); - /// Create a result-dependent generic selection expression. + /// Create a result-dependent generic selection expression accepting an + /// expression predicate. static GenericSelectionExpr * Create(const ASTContext &Context, SourceLocation GenericLoc, Expr *ControllingExpr, ArrayRef AssocTypes, ArrayRef AssocExprs, SourceLocation DefaultLoc, SourceLocation RParenLoc, bool ContainsUnexpandedParameterPack); + /// Create a non-result-dependent generic selection expression accepting a + /// type predicate. + static GenericSelectionExpr * + Create(const ASTContext &Context, SourceLocation GenericLoc, + TypeSourceInfo *ControllingType, ArrayRef AssocTypes, + ArrayRef AssocExprs, SourceLocation DefaultLoc, + SourceLocation RParenLoc, bool ContainsUnexpandedParameterPack, + unsigned ResultIndex); + + /// Create a result-dependent generic selection expression accepting a type + /// predicate + static GenericSelectionExpr * + Create(const ASTContext &Context, SourceLocation GenericLoc, + TypeSourceInfo *ControllingType, ArrayRef AssocTypes, + ArrayRef AssocExprs, SourceLocation DefaultLoc, + SourceLocation RParenLoc, bool ContainsUnexpandedParameterPack); + /// Create an empty generic selection expression for deserialization. static GenericSelectionExpr *CreateEmpty(const ASTContext &Context, unsigned NumAssocs); @@ -5807,32 +5956,56 @@ public: /// Whether this generic selection is result-dependent. bool isResultDependent() const { return ResultIndex == ResultDependentIndex; } + /// Whether this generic selection uses an expression as its controlling + /// argument. + bool isExprPredicate() const { return IsExprPredicate; } + /// Whether this generic selection uses a type as its controlling argument. + bool isTypePredicate() const { return !IsExprPredicate; } + /// Return the controlling expression of this generic selection expression. + /// Only valid to call if the selection expression used an expression as its + /// controlling argument. Expr *getControllingExpr() { - return cast(getTrailingObjects()[ControllingIndex]); + return cast( + getTrailingObjects()[getIndexOfControllingExpression()]); } const Expr *getControllingExpr() const { - return cast(getTrailingObjects()[ControllingIndex]); + return cast( + getTrailingObjects()[getIndexOfControllingExpression()]); + } + + /// Return the controlling type of this generic selection expression. Only + /// valid to call if the selection expression used a type as its controlling + /// argument. + TypeSourceInfo *getControllingType() { + return getTrailingObjects()[getIndexOfControllingType()]; + } + const TypeSourceInfo* getControllingType() const { + return getTrailingObjects()[getIndexOfControllingType()]; } /// Return the result expression of this controlling expression. Defined if /// and only if the generic selection expression is not result-dependent. Expr *getResultExpr() { return cast( - getTrailingObjects()[AssocExprStartIndex + getResultIndex()]); + getTrailingObjects()[getIndexOfStartOfAssociatedExprs() + + getResultIndex()]); } const Expr *getResultExpr() const { return cast( - getTrailingObjects()[AssocExprStartIndex + getResultIndex()]); + getTrailingObjects()[getIndexOfStartOfAssociatedExprs() + + getResultIndex()]); } ArrayRef getAssocExprs() const { return {reinterpret_cast(getTrailingObjects() + - AssocExprStartIndex), + getIndexOfStartOfAssociatedExprs()), NumAssocs}; } ArrayRef getAssocTypeSourceInfos() const { - return {getTrailingObjects(), NumAssocs}; + return {getTrailingObjects() + + getIndexOfStartOfAssociatedTypes(), + NumAssocs}; } /// Return the Ith association expression with its TypeSourceInfo, @@ -5841,23 +6014,30 @@ public: assert(I < getNumAssocs() && "Out-of-range index in GenericSelectionExpr::getAssociation!"); return Association( - cast(getTrailingObjects()[AssocExprStartIndex + I]), - getTrailingObjects()[I], + cast( + getTrailingObjects()[getIndexOfStartOfAssociatedExprs() + + I]), + getTrailingObjects< + TypeSourceInfo *>()[getIndexOfStartOfAssociatedTypes() + I], !isResultDependent() && (getResultIndex() == I)); } ConstAssociation getAssociation(unsigned I) const { assert(I < getNumAssocs() && "Out-of-range index in GenericSelectionExpr::getAssociation!"); return ConstAssociation( - cast(getTrailingObjects()[AssocExprStartIndex + I]), - getTrailingObjects()[I], + cast( + getTrailingObjects()[getIndexOfStartOfAssociatedExprs() + + I]), + getTrailingObjects< + TypeSourceInfo *>()[getIndexOfStartOfAssociatedTypes() + I], !isResultDependent() && (getResultIndex() == I)); } association_range associations() { AssociationIterator Begin(getTrailingObjects() + - AssocExprStartIndex, - getTrailingObjects(), + getIndexOfStartOfAssociatedExprs(), + getTrailingObjects() + + getIndexOfStartOfAssociatedTypes(), /*Offset=*/0, ResultIndex); AssociationIterator End(Begin.E + NumAssocs, Begin.TSI + NumAssocs, /*Offset=*/NumAssocs, ResultIndex); @@ -5866,8 +6046,9 @@ public: const_association_range associations() const { ConstAssociationIterator Begin(getTrailingObjects() + - AssocExprStartIndex, - getTrailingObjects(), + getIndexOfStartOfAssociatedExprs(), + getTrailingObjects() + + getIndexOfStartOfAssociatedTypes(), /*Offset=*/0, ResultIndex); ConstAssociationIterator End(Begin.E + NumAssocs, Begin.TSI + NumAssocs, /*Offset=*/NumAssocs, ResultIndex); @@ -6180,11 +6361,11 @@ public: return getSubExprsBuffer() + getNumSubExprs(); } - llvm::iterator_range semantics() { - return llvm::make_range(semantics_begin(), semantics_end()); + ArrayRef semantics() { + return ArrayRef(semantics_begin(), semantics_end()); } - llvm::iterator_range semantics() const { - return llvm::make_range(semantics_begin(), semantics_end()); + ArrayRef semantics() const { + return ArrayRef(semantics_begin(), semantics_end()); } Expr *getSemanticExpr(unsigned index) { diff --git a/contrib/llvm-project/clang/include/clang/AST/ExprCXX.h b/contrib/llvm-project/clang/include/clang/AST/ExprCXX.h index 032fd199b03..f5e805257ce 100644 --- a/contrib/llvm-project/clang/include/clang/AST/ExprCXX.h +++ b/contrib/llvm-project/clang/include/clang/AST/ExprCXX.h @@ -1681,6 +1681,14 @@ public: getArgs()[Arg] = ArgExpr; } + bool isImmediateEscalating() const { + return CXXConstructExprBits.IsImmediateEscalating; + } + + void setIsImmediateEscalating(bool Set) { + CXXConstructExprBits.IsImmediateEscalating = Set; + } + SourceLocation getBeginLoc() const LLVM_READONLY; SourceLocation getEndLoc() const LLVM_READONLY; SourceRange getParenOrBraceRange() const { return ParenOrBraceRange; } @@ -2321,7 +2329,7 @@ public: /// This might return std::nullopt even if isArray() returns true, /// since there might not be an array size expression. - /// If the result is not-None, it will never wrap a nullptr. + /// If the result is not std::nullopt, it will never wrap a nullptr. std::optional getArraySize() { if (!isArray()) return std::nullopt; @@ -2335,7 +2343,7 @@ public: /// This might return std::nullopt even if isArray() returns true, /// since there might not be an array size expression. - /// If the result is not-None, it will never wrap a nullptr. + /// If the result is not std::nullopt, it will never wrap a nullptr. std::optional getArraySize() const { if (!isArray()) return std::nullopt; @@ -3504,8 +3512,9 @@ class CXXUnresolvedConstructExpr final friend class ASTStmtReader; friend TrailingObjects; - /// The type being constructed. - TypeSourceInfo *TSI; + /// The type being constructed, and whether the construct expression models + /// list initialization or not. + llvm::PointerIntPair TypeAndInitForm; /// The location of the left parentheses ('('). SourceLocation LParenLoc; @@ -3515,30 +3524,31 @@ class CXXUnresolvedConstructExpr final CXXUnresolvedConstructExpr(QualType T, TypeSourceInfo *TSI, SourceLocation LParenLoc, ArrayRef Args, - SourceLocation RParenLoc); + SourceLocation RParenLoc, bool IsListInit); CXXUnresolvedConstructExpr(EmptyShell Empty, unsigned NumArgs) - : Expr(CXXUnresolvedConstructExprClass, Empty), TSI(nullptr) { + : Expr(CXXUnresolvedConstructExprClass, Empty) { CXXUnresolvedConstructExprBits.NumArgs = NumArgs; } public: - static CXXUnresolvedConstructExpr *Create(const ASTContext &Context, - QualType T, TypeSourceInfo *TSI, - SourceLocation LParenLoc, - ArrayRef Args, - SourceLocation RParenLoc); + static CXXUnresolvedConstructExpr * + Create(const ASTContext &Context, QualType T, TypeSourceInfo *TSI, + SourceLocation LParenLoc, ArrayRef Args, + SourceLocation RParenLoc, bool IsListInit); static CXXUnresolvedConstructExpr *CreateEmpty(const ASTContext &Context, unsigned NumArgs); /// Retrieve the type that is being constructed, as specified /// in the source code. - QualType getTypeAsWritten() const { return TSI->getType(); } + QualType getTypeAsWritten() const { return getTypeSourceInfo()->getType(); } /// Retrieve the type source information for the type being /// constructed. - TypeSourceInfo *getTypeSourceInfo() const { return TSI; } + TypeSourceInfo *getTypeSourceInfo() const { + return TypeAndInitForm.getPointer(); + } /// Retrieve the location of the left parentheses ('(') that /// precedes the argument list. @@ -3553,7 +3563,7 @@ public: /// Determine whether this expression models list-initialization. /// If so, there will be exactly one subexpression, which will be /// an InitListExpr. - bool isListInitialization() const { return LParenLoc.isInvalid(); } + bool isListInitialization() const { return TypeAndInitForm.getInt(); } /// Retrieve the number of arguments. unsigned getNumArgs() const { return CXXUnresolvedConstructExprBits.NumArgs; } diff --git a/contrib/llvm-project/clang/include/clang/AST/ExprConcepts.h b/contrib/llvm-project/clang/include/clang/AST/ExprConcepts.h index 746a5b2fbfc..d900e980852 100644 --- a/contrib/llvm-project/clang/include/clang/AST/ExprConcepts.h +++ b/contrib/llvm-project/clang/include/clang/AST/ExprConcepts.h @@ -80,12 +80,6 @@ public: ImplicitConceptSpecializationDecl *SpecDecl, const ConstraintSatisfaction *Satisfaction); - static ConceptSpecializationExpr * - Create(const ASTContext &C, ConceptDecl *NamedConcept, - ImplicitConceptSpecializationDecl *SpecDecl, - const ConstraintSatisfaction *Satisfaction, bool Dependent, - bool ContainsUnexpandedParameterPack); - static ConceptSpecializationExpr * Create(const ASTContext &C, ConceptDecl *NamedConcept, const ASTTemplateArgumentListInfo *ArgsAsWritten, diff --git a/contrib/llvm-project/clang/include/clang/AST/ExternalASTSource.h b/contrib/llvm-project/clang/include/clang/AST/ExternalASTSource.h index 65f8ae61fe4..8e573965b0a 100644 --- a/contrib/llvm-project/clang/include/clang/AST/ExternalASTSource.h +++ b/contrib/llvm-project/clang/include/clang/AST/ExternalASTSource.h @@ -371,7 +371,7 @@ public: /// \param Source the external AST source. /// /// \returns a pointer to the AST node. - T* get(ExternalASTSource *Source) const { + T *get(ExternalASTSource *Source) const { if (isOffset()) { assert(Source && "Cannot deserialize a lazy pointer without an AST source"); @@ -379,6 +379,14 @@ public: } return reinterpret_cast(Ptr); } + + /// Retrieve the address of the AST node pointer. Deserializes the pointee if + /// necessary. + T **getAddressOfPointer(ExternalASTSource *Source) const { + // Ensure the integer is in pointer form. + (void)get(Source); + return reinterpret_cast(&Ptr); + } }; /// A lazy value (of type T) that is within an AST node of type Owner, diff --git a/contrib/llvm-project/clang/include/clang/AST/IgnoreExpr.h b/contrib/llvm-project/clang/include/clang/AST/IgnoreExpr.h index a7e9b07bef6..917bada61fa 100644 --- a/contrib/llvm-project/clang/include/clang/AST/IgnoreExpr.h +++ b/contrib/llvm-project/clang/include/clang/AST/IgnoreExpr.h @@ -23,7 +23,8 @@ namespace detail { inline Expr *IgnoreExprNodesImpl(Expr *E) { return E; } template Expr *IgnoreExprNodesImpl(Expr *E, FnTy &&Fn, FnTys &&... Fns) { - return IgnoreExprNodesImpl(Fn(E), std::forward(Fns)...); + return IgnoreExprNodesImpl(std::forward(Fn)(E), + std::forward(Fns)...); } } // namespace detail @@ -165,6 +166,11 @@ inline Expr *IgnoreParensSingleStep(Expr *E) { return CE->getChosenSubExpr(); } + else if (auto *PE = dyn_cast(E)) { + if (PE->isTransparent() && PE->getFunctionName()) + return PE->getFunctionName(); + } + return E; } diff --git a/contrib/llvm-project/clang/include/clang/AST/Mangle.h b/contrib/llvm-project/clang/include/clang/AST/Mangle.h index 9662a33c61c..c04bcc7f01c 100644 --- a/contrib/llvm-project/clang/include/clang/AST/Mangle.h +++ b/contrib/llvm-project/clang/include/clang/AST/Mangle.h @@ -140,7 +140,8 @@ public: unsigned ManglingNumber, raw_ostream &) = 0; virtual void mangleCXXRTTI(QualType T, raw_ostream &) = 0; - virtual void mangleCXXRTTIName(QualType T, raw_ostream &) = 0; + virtual void mangleCXXRTTIName(QualType T, raw_ostream &, + bool NormalizeIntegers = false) = 0; virtual void mangleStringLiteral(const StringLiteral *SL, raw_ostream &) = 0; virtual void mangleMSGuidDecl(const MSGuidDecl *GD, raw_ostream&); @@ -177,7 +178,8 @@ public: /// or type uniquing. /// TODO: Extend this to internal types by generating names that are unique /// across translation units so it can be used with LTO. - virtual void mangleTypeName(QualType T, raw_ostream &) = 0; + virtual void mangleTypeName(QualType T, raw_ostream &, + bool NormalizeIntegers = false) = 0; /// @} }; diff --git a/contrib/llvm-project/clang/include/clang/AST/MangleNumberingContext.h b/contrib/llvm-project/clang/include/clang/AST/MangleNumberingContext.h index a4a6ce4c270..1313c94eb12 100644 --- a/contrib/llvm-project/clang/include/clang/AST/MangleNumberingContext.h +++ b/contrib/llvm-project/clang/include/clang/AST/MangleNumberingContext.h @@ -27,6 +27,9 @@ class VarDecl; /// Keeps track of the mangled names of lambda expressions and block /// literals within a particular context. class MangleNumberingContext { + // The index of the next lambda we encounter in this context. + unsigned LambdaIndex = 0; + public: virtual ~MangleNumberingContext() {} @@ -55,6 +58,11 @@ public: /// given call operator within the device context. No device number is /// assigned if there's no device numbering context is associated. virtual unsigned getDeviceManglingNumber(const CXXMethodDecl *) { return 0; } + + // Retrieve the index of the next lambda appearing in this context, which is + // used for deduplicating lambdas across modules. Note that this is a simple + // sequence number and is not ABI-dependent. + unsigned getNextLambdaIndex() { return LambdaIndex++; } }; } // end namespace clang diff --git a/contrib/llvm-project/clang/include/clang/AST/OpenMPClause.h b/contrib/llvm-project/clang/include/clang/AST/OpenMPClause.h index 627e9025c11..0bea2127069 100644 --- a/contrib/llvm-project/clang/include/clang/AST/OpenMPClause.h +++ b/contrib/llvm-project/clang/include/clang/AST/OpenMPClause.h @@ -9046,6 +9046,132 @@ public: Expr *getSize() const { return getStmtAs(); } }; +/// This represents the 'doacross' clause for the '#pragma omp ordered' +/// directive. +/// +/// \code +/// #pragma omp ordered doacross(sink: i-1, j-1) +/// \endcode +/// In this example directive '#pragma omp ordered' with clause 'doacross' with +/// a dependence-type 'sink' and loop-iteration vector expressions i-1 and j-1. +class OMPDoacrossClause final + : public OMPVarListClause, + private llvm::TrailingObjects { + friend class OMPClauseReader; + friend OMPVarListClause; + friend TrailingObjects; + + /// Dependence type (sink or source). + OpenMPDoacrossClauseModifier DepType = OMPC_DOACROSS_unknown; + + /// Dependence type location. + SourceLocation DepLoc; + + /// Colon location. + SourceLocation ColonLoc; + + /// Number of loops, associated with the doacross clause. + unsigned NumLoops = 0; + + /// Build clause with number of expressions \a N. + /// + /// \param StartLoc Starting location of the clause. + /// \param LParenLoc Location of '('. + /// \param EndLoc Ending location of the clause. + /// \param N Number of expressions in the clause. + /// \param NumLoops Number of loops associated with the clause. + OMPDoacrossClause(SourceLocation StartLoc, SourceLocation LParenLoc, + SourceLocation EndLoc, unsigned N, unsigned NumLoops) + : OMPVarListClause(llvm::omp::OMPC_doacross, StartLoc, + LParenLoc, EndLoc, N), + NumLoops(NumLoops) {} + + /// Build an empty clause. + /// + /// \param N Number of expressions in the clause. + /// \param NumLoops Number of loops associated with the clause. + explicit OMPDoacrossClause(unsigned N, unsigned NumLoops) + : OMPVarListClause(llvm::omp::OMPC_doacross, + SourceLocation(), SourceLocation(), + SourceLocation(), N), + NumLoops(NumLoops) {} + + /// Set dependence type. + void setDependenceType(OpenMPDoacrossClauseModifier M) { DepType = M; } + + /// Set dependence type location. + void setDependenceLoc(SourceLocation Loc) { DepLoc = Loc; } + + /// Set colon location. + void setColonLoc(SourceLocation Loc) { ColonLoc = Loc; } + +public: + /// Creates clause with a list of expressions \a VL. + /// + /// \param C AST context. + /// \param StartLoc Starting location of the clause. + /// \param LParenLoc Location of '('. + /// \param EndLoc Ending location of the clause. + /// \param DepType The dependence type. + /// \param DepLoc Location of the dependence type. + /// \param ColonLoc Location of ':'. + /// \param VL List of references to the expressions. + /// \param NumLoops Number of loops that associated with the clause. + static OMPDoacrossClause * + Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation LParenLoc, + SourceLocation EndLoc, OpenMPDoacrossClauseModifier DepType, + SourceLocation DepLoc, SourceLocation ColonLoc, ArrayRef VL, + unsigned NumLoops); + + /// Creates an empty clause with \a N expressions. + /// + /// \param C AST context. + /// \param N The number of expressions. + /// \param NumLoops Number of loops that is associated with this clause. + static OMPDoacrossClause *CreateEmpty(const ASTContext &C, unsigned N, + unsigned NumLoops); + + /// Get dependence type. + OpenMPDoacrossClauseModifier getDependenceType() const { return DepType; } + + /// Get dependence type location. + SourceLocation getDependenceLoc() const { return DepLoc; } + + /// Get colon location. + SourceLocation getColonLoc() const { return ColonLoc; } + + /// Get number of loops associated with the clause. + unsigned getNumLoops() const { return NumLoops; } + + /// Set the loop data. + void setLoopData(unsigned NumLoop, Expr *Cnt); + + /// Get the loop data. + Expr *getLoopData(unsigned NumLoop); + const Expr *getLoopData(unsigned NumLoop) const; + + child_range children() { + return child_range(reinterpret_cast(varlist_begin()), + reinterpret_cast(varlist_end())); + } + + const_child_range children() const { + auto Children = const_cast(this)->children(); + return const_child_range(Children.begin(), Children.end()); + } + + child_range used_children() { + return child_range(child_iterator(), child_iterator()); + } + const_child_range used_children() const { + return const_child_range(const_child_iterator(), const_child_iterator()); + } + + static bool classof(const OMPClause *T) { + return T->getClauseKind() == llvm::omp::OMPC_doacross; + } +}; + } // namespace clang #endif // LLVM_CLANG_AST_OPENMPCLAUSE_H diff --git a/contrib/llvm-project/clang/include/clang/AST/OperationKinds.def b/contrib/llvm-project/clang/include/clang/AST/OperationKinds.def index b05b9d81569..96b5a4db55e 100644 --- a/contrib/llvm-project/clang/include/clang/AST/OperationKinds.def +++ b/contrib/llvm-project/clang/include/clang/AST/OperationKinds.def @@ -362,8 +362,8 @@ CAST_OPERATION(IntToOCLSampler) //===- Binary Operations -------------------------------------------------===// // Operators listed in order of precedence. -// Note that additions to this should also update the StmtVisitor class and -// BinaryOperator::getOverloadedOperator. +// Note that additions to this should also update the StmtVisitor class, +// BinaryOperator::getOverloadedOperator and CXBinaryOperatorKind enum. // [C++ 5.5] Pointer-to-member operators. BINARY_OPERATION(PtrMemD, ".*") @@ -415,8 +415,8 @@ BINARY_OPERATION(Comma, ",") //===- Unary Operations ---------------------------------------------------===// -// Note that additions to this should also update the StmtVisitor class and -// UnaryOperator::getOverloadedOperator. +// Note that additions to this should also update the StmtVisitor class, +// UnaryOperator::getOverloadedOperator and CXUnaryOperatorKind enum. // [C99 6.5.2.4] Postfix increment and decrement UNARY_OPERATION(PostInc, "++") diff --git a/contrib/llvm-project/clang/include/clang/AST/PrettyPrinter.h b/contrib/llvm-project/clang/include/clang/AST/PrettyPrinter.h index 5aeaca7beda..8a0bc6dfb57 100644 --- a/contrib/llvm-project/clang/include/clang/AST/PrettyPrinter.h +++ b/contrib/llvm-project/clang/include/clang/AST/PrettyPrinter.h @@ -60,14 +60,15 @@ struct PrintingPolicy { : Indentation(2), SuppressSpecifiers(false), SuppressTagKeyword(LO.CPlusPlus), IncludeTagDefinition(false), SuppressScope(false), SuppressUnwrittenScope(false), - SuppressInlineNamespace(true), SuppressInitializers(false), - ConstantArraySizeAsWritten(false), AnonymousTagLocations(true), - SuppressStrongLifetime(false), SuppressLifetimeQualifiers(false), + SuppressInlineNamespace(true), SuppressElaboration(false), + SuppressInitializers(false), ConstantArraySizeAsWritten(false), + AnonymousTagLocations(true), SuppressStrongLifetime(false), + SuppressLifetimeQualifiers(false), SuppressTemplateArgsInCXXConstructors(false), SuppressDefaultTemplateArgs(true), Bool(LO.Bool), Nullptr(LO.CPlusPlus11 || LO.C2x), NullptrTypeInNamespace(LO.CPlusPlus), - Restrict(LO.C99), Alignof(LO.CPlusPlus11), - UnderscoreAlignof(LO.C11), UseVoidForZeroParams(!LO.CPlusPlus), + Restrict(LO.C99), Alignof(LO.CPlusPlus11), UnderscoreAlignof(LO.C11), + UseVoidForZeroParams(!LO.CPlusPlus), SplitTemplateClosers(!LO.CPlusPlus11), TerseOutput(false), PolishForDeclaration(false), Half(LO.Half), MSWChar(LO.MicrosoftExt && !LO.WChar), IncludeNewlines(true), @@ -139,6 +140,10 @@ struct PrintingPolicy { /// removed. unsigned SuppressInlineNamespace : 1; + /// Ignore qualifiers and tag keywords as specified by elaborated type sugar, + /// instead letting the underlying type print as normal. + unsigned SuppressElaboration : 1; + /// Suppress printing of variable initializers. /// /// This flag is used when printing the loop variable in a for-range diff --git a/contrib/llvm-project/clang/include/clang/AST/PropertiesBase.td b/contrib/llvm-project/clang/include/clang/AST/PropertiesBase.td index c2823c660f3..c6fe790e196 100644 --- a/contrib/llvm-project/clang/include/clang/AST/PropertiesBase.td +++ b/contrib/llvm-project/clang/include/clang/AST/PropertiesBase.td @@ -450,10 +450,13 @@ let Class = PropertyTypeCase in { lvalueBase ? lvalueBase.dyn_cast() : nullptr; bool lvalueBaseIsExpr = (bool) expr; bool lvalueBaseIsTypeInfo = lvalueBase.is(); + bool lvalueBaseIsDynamicAlloc = lvalueBase.is(); QualType elemTy; if (lvalueBase) { if (lvalueBaseIsTypeInfo) { elemTy = lvalueBase.getTypeInfoType(); + } else if (lvalueBaseIsDynamicAlloc) { + elemTy = lvalueBase.getDynamicAllocType(); } else if (lvalueBaseIsExpr) { elemTy = expr->getType(); } else { @@ -473,6 +476,9 @@ let Class = PropertyTypeCase in { def : Property<"isTypeInfo", Bool> { let Read = [{ lvalueBaseIsTypeInfo }]; } + def : Property<"isDynamicAlloc", Bool> { + let Read = [{ lvalueBaseIsDynamicAlloc }]; + } def : Property<"hasBase", Bool> { let Read = [{ static_cast(lvalueBase) }]; } @@ -485,9 +491,17 @@ let Class = PropertyTypeCase in { QualType(node.getLValueBase().get().getType(), 0) }]; } + def : Property<"dynamicAlloc", UInt32> { + let Conditional = [{ hasBase && isDynamicAlloc }]; + let Read = [{ node.getLValueBase().get().getIndex() }]; + } def : Property<"type", QualType> { - let Conditional = [{ hasBase && isTypeInfo }]; - let Read = [{ node.getLValueBase().getTypeInfoType() }]; + let Conditional = [{ hasBase && (isTypeInfo || isDynamicAlloc) }]; + let Read = [{ + isTypeInfo + ? node.getLValueBase().getTypeInfoType() + : node.getLValueBase().getDynamicAllocType() + }]; } def : Property<"callIndex", UInt32> { let Conditional = [{ hasBase && !isTypeInfo }]; @@ -502,7 +516,7 @@ let Class = PropertyTypeCase in { let Read = [{ const_cast(expr) }]; } def : Property<"decl", DeclRef> { - let Conditional = [{ hasBase && !isTypeInfo && !isExpr }]; + let Conditional = [{ hasBase && !isTypeInfo && !isDynamicAlloc && !isExpr }]; let Read = [{ lvalueBase.get() }]; } def : Property<"offsetQuantity", UInt32> { @@ -521,6 +535,9 @@ let Class = PropertyTypeCase in { if (isTypeInfo) { base = APValue::LValueBase::getTypeInfo( TypeInfoLValue(typeInfo->getTypePtr()), *type); + } else if (isDynamicAlloc) { + base = APValue::LValueBase::getDynamicAlloc( + DynamicAllocLValue(*dynamicAlloc), *type); } else if (isExpr) { base = APValue::LValueBase(cast(*stmt), *callIndex, *version); @@ -745,8 +762,11 @@ let Class = PropertyTypeCase in { def : Property<"type", QualType> { let Read = [{ node.getAsType() }]; } + def : Property<"isDefaulted", Bool> { + let Read = [{ node.getIsDefaulted() }]; + } def : Creator<[{ - return TemplateArgument(type); + return TemplateArgument(type, /* isNullPtr */ false, isDefaulted); }]>; } let Class = PropertyTypeCase in { @@ -756,16 +776,22 @@ let Class = PropertyTypeCase in { def : Property<"parameterType", QualType> { let Read = [{ node.getParamTypeForDecl() }]; } + def : Property<"isDefaulted", Bool> { + let Read = [{ node.getIsDefaulted() }]; + } def : Creator<[{ - return TemplateArgument(declaration, parameterType); + return TemplateArgument(declaration, parameterType, isDefaulted); }]>; } let Class = PropertyTypeCase in { def : Property<"type", QualType> { let Read = [{ node.getNullPtrType() }]; } + def : Property<"isDefaulted", Bool> { + let Read = [{ node.getIsDefaulted() }]; + } def : Creator<[{ - return TemplateArgument(type, /*nullptr*/ true); + return TemplateArgument(type, /*nullptr*/ true, isDefaulted); }]>; } let Class = PropertyTypeCase in { @@ -775,16 +801,22 @@ let Class = PropertyTypeCase in { def : Property<"type", QualType> { let Read = [{ node.getIntegralType() }]; } + def : Property<"isDefaulted", Bool> { + let Read = [{ node.getIsDefaulted() }]; + } def : Creator<[{ - return TemplateArgument(ctx, value, type); + return TemplateArgument(ctx, value, type, isDefaulted); }]>; } let Class = PropertyTypeCase in { def : Property<"name", TemplateName> { let Read = [{ node.getAsTemplateOrTemplatePattern() }]; } + def : Property<"isDefaulted", Bool> { + let Read = [{ node.getIsDefaulted() }]; + } def : Creator<[{ - return TemplateArgument(name); + return TemplateArgument(name, isDefaulted); }]>; } let Class = PropertyTypeCase in { @@ -798,19 +830,25 @@ let Class = PropertyTypeCase in { [](unsigned i) { return uint32_t(i); }) }]; } + def : Property<"isDefaulted", Bool> { + let Read = [{ node.getIsDefaulted() }]; + } def : Creator<[{ auto numExpansionsUnsigned = llvm::transformOptional( numExpansions, [](uint32_t i) { return unsigned(i); }); - return TemplateArgument(name, numExpansionsUnsigned); + return TemplateArgument(name, numExpansionsUnsigned, isDefaulted); }]>; } let Class = PropertyTypeCase in { def : Property<"expression", ExprRef> { let Read = [{ node.getAsExpr() }]; } + def : Property<"isDefaulted", Bool> { + let Read = [{ node.getIsDefaulted() }]; + } def : Creator<[{ - return TemplateArgument(expression); + return TemplateArgument(expression, isDefaulted); }]>; } let Class = PropertyTypeCase in { diff --git a/contrib/llvm-project/clang/include/clang/AST/RawCommentList.h b/contrib/llvm-project/clang/include/clang/AST/RawCommentList.h index 1bb8d7ce40a..2f44a77d450 100644 --- a/contrib/llvm-project/clang/include/clang/AST/RawCommentList.h +++ b/contrib/llvm-project/clang/include/clang/AST/RawCommentList.h @@ -115,6 +115,17 @@ public: return extractBriefText(Context); } + bool hasUnsupportedSplice(const SourceManager &SourceMgr) const { + if (!isInvalid()) + return false; + StringRef Text = getRawText(SourceMgr); + if (Text.size() < 6 || Text[0] != '/') + return false; + if (Text[1] == '*') + return Text[Text.size() - 1] != '/' || Text[Text.size() - 2] != '*'; + return Text[1] != '/'; + } + /// Returns sanitized comment text, suitable for presentation in editor UIs. /// E.g. will transform: /// // This is a long multiline comment. @@ -162,7 +173,7 @@ private: SourceRange Range; mutable StringRef RawText; - mutable const char *BriefText; + mutable const char *BriefText = nullptr; mutable bool RawTextValid : 1; ///< True if RawText is valid mutable bool BriefTextValid : 1; ///< True if BriefText is valid diff --git a/contrib/llvm-project/clang/include/clang/AST/RecursiveASTVisitor.h b/contrib/llvm-project/clang/include/clang/AST/RecursiveASTVisitor.h index 5802e905be4..604875cd633 100644 --- a/contrib/llvm-project/clang/include/clang/AST/RecursiveASTVisitor.h +++ b/contrib/llvm-project/clang/include/clang/AST/RecursiveASTVisitor.h @@ -2553,7 +2553,11 @@ bool RecursiveASTVisitor::TraverseInitListExpr( // are interleaved. We also need to watch out for null types (default // generic associations). DEF_TRAVERSE_STMT(GenericSelectionExpr, { - TRY_TO(TraverseStmt(S->getControllingExpr())); + if (S->isExprPredicate()) + TRY_TO(TraverseStmt(S->getControllingExpr())); + else + TRY_TO(TraverseTypeLoc(S->getControllingType()->getTypeLoc())); + for (const GenericSelectionExpr::Association Assoc : S->associations()) { if (TypeSourceInfo *TSI = Assoc.getTypeSourceInfo()) TRY_TO(TraverseTypeLoc(TSI->getTypeLoc())); @@ -2723,7 +2727,11 @@ DEF_TRAVERSE_STMT(CXXDefaultArgExpr, { TRY_TO(TraverseStmt(S->getExpr())); }) -DEF_TRAVERSE_STMT(CXXDefaultInitExpr, {}) +DEF_TRAVERSE_STMT(CXXDefaultInitExpr, { + if (getDerived().shouldVisitImplicitCode()) + TRY_TO(TraverseStmt(S->getExpr())); +}) + DEF_TRAVERSE_STMT(CXXDeleteExpr, {}) DEF_TRAVERSE_STMT(ExprWithCleanups, {}) DEF_TRAVERSE_STMT(CXXInheritedCtorInitExpr, {}) @@ -3860,6 +3868,13 @@ bool RecursiveASTVisitor::VisitOMPXDynCGroupMemClause( return true; } +template +bool RecursiveASTVisitor::VisitOMPDoacrossClause( + OMPDoacrossClause *C) { + TRY_TO(VisitOMPClauseList(C)); + return true; +} + // FIXME: look at the following tricky-seeming exprs to see if we // need to recurse on anything. These are ones that have methods // returning decls or qualtypes or nestednamespecifier -- though I'm diff --git a/contrib/llvm-project/clang/include/clang/AST/Redeclarable.h b/contrib/llvm-project/clang/include/clang/AST/Redeclarable.h index 58ec0797392..091bb886f2d 100644 --- a/contrib/llvm-project/clang/include/clang/AST/Redeclarable.h +++ b/contrib/llvm-project/clang/include/clang/AST/Redeclarable.h @@ -240,7 +240,7 @@ public: class redecl_iterator { /// Current - The current declaration. decl_type *Current = nullptr; - decl_type *Starter; + decl_type *Starter = nullptr; bool PassedFirst = false; public: diff --git a/contrib/llvm-project/clang/include/clang/AST/Stmt.h b/contrib/llvm-project/clang/include/clang/AST/Stmt.h index b70cf3aec5d..87ffebc00d7 100644 --- a/contrib/llvm-project/clang/include/clang/AST/Stmt.h +++ b/contrib/llvm-project/clang/include/clang/AST/Stmt.h @@ -364,6 +364,10 @@ protected: /// for the predefined identifier. unsigned HasFunctionName : 1; + /// True if this PredefinedExpr should be treated as a StringLiteral (for + /// MSVC compatibility). + unsigned IsTransparent : 1; + /// The location of this PredefinedExpr. SourceLocation Loc; }; @@ -380,6 +384,7 @@ protected: unsigned HadMultipleCandidates : 1; unsigned RefersToEnclosingVariableOrCapture : 1; unsigned NonOdrUseReason : 2; + unsigned IsImmediateEscalating : 1; /// The location of the declaration name itself. SourceLocation Loc; @@ -588,10 +593,8 @@ protected: unsigned : NumExprBits; - // These don't need to be particularly wide, because they're - // strictly limited by the forms of expressions we permit. - unsigned NumSubExprs : 8; - unsigned ResultIndex : 32 - 8 - NumExprBits; + unsigned NumSubExprs : 16; + unsigned ResultIndex : 16; }; class SourceLocExprBitfields { @@ -823,6 +826,7 @@ protected: unsigned StdInitListInitialization : 1; unsigned ZeroInitialization : 1; unsigned ConstructionKind : 3; + unsigned IsImmediateEscalating : 1; SourceLocation Loc; }; @@ -978,7 +982,7 @@ protected: SourceLocation RequiresKWLoc; }; - //===--- C++ Coroutines TS bitfields classes ---===// + //===--- C++ Coroutines bitfields classes ---===// class CoawaitExprBitfields { friend class CoawaitExpr; @@ -1082,7 +1086,7 @@ protected: LambdaExprBitfields LambdaExprBits; RequiresExprBitfields RequiresExprBits; - // C++ Coroutines TS expressions + // C++ Coroutines expressions CoawaitExprBitfields CoawaitBits; // Obj-C Expressions @@ -1291,8 +1295,13 @@ public: /// parameters are identified by index/level rather than their /// declaration pointers) or the exact representation of the statement as /// written in the source. + /// \param ProfileLambdaExpr whether or not to profile lambda expressions. + /// When false, the lambda expressions are never considered to be equal to + /// other lambda expressions. When true, the lambda expressions with the same + /// implementation will be considered to be the same. ProfileLambdaExpr should + /// only be true when we try to merge two declarations within modules. void Profile(llvm::FoldingSetNodeID &ID, const ASTContext &Context, - bool Canonical) const; + bool Canonical, bool ProfileLambdaExpr = false) const; /// Calculate a unique representation for a statement that is /// stable across compiler invocations. @@ -2092,6 +2101,11 @@ public: : nullptr; } + void setConditionVariableDeclStmt(DeclStmt *CondVar) { + assert(hasVarStorage()); + getTrailingObjects()[varOffset()] = CondVar; + } + Stmt *getInit() { return hasInitStorage() ? getTrailingObjects()[initOffset()] : nullptr; @@ -2324,6 +2338,11 @@ public: : nullptr; } + void setConditionVariableDeclStmt(DeclStmt *CondVar) { + assert(hasVarStorage()); + getTrailingObjects()[varOffset()] = CondVar; + } + SwitchCase *getSwitchCaseList() { return FirstCase; } const SwitchCase *getSwitchCaseList() const { return FirstCase; } void setSwitchCaseList(SwitchCase *SC) { FirstCase = SC; } @@ -2487,6 +2506,11 @@ public: : nullptr; } + void setConditionVariableDeclStmt(DeclStmt *CondVar) { + assert(hasVarStorage()); + getTrailingObjects()[varOffset()] = CondVar; + } + SourceLocation getWhileLoc() const { return WhileStmtBits.WhileLoc; } void setWhileLoc(SourceLocation L) { WhileStmtBits.WhileLoc = L; } @@ -2576,6 +2600,8 @@ public: /// the init/cond/inc parts of the ForStmt will be null if they were not /// specified in the source. class ForStmt : public Stmt { + friend class ASTStmtReader; + enum { INIT, CONDVAR, COND, INC, BODY, END_EXPR }; Stmt* SubExprs[END_EXPR]; // SubExprs[INIT] is an expression or declstmt. SourceLocation LParenLoc, RParenLoc; @@ -2603,10 +2629,18 @@ public: /// If this ForStmt has a condition variable, return the faux DeclStmt /// associated with the creation of that condition variable. + DeclStmt *getConditionVariableDeclStmt() { + return reinterpret_cast(SubExprs[CONDVAR]); + } + const DeclStmt *getConditionVariableDeclStmt() const { return reinterpret_cast(SubExprs[CONDVAR]); } + void setConditionVariableDeclStmt(DeclStmt *CondVar) { + SubExprs[CONDVAR] = CondVar; + } + Expr *getCond() { return reinterpret_cast(SubExprs[COND]); } Expr *getInc() { return reinterpret_cast(SubExprs[INC]); } Stmt *getBody() { return SubExprs[BODY]; } @@ -3558,8 +3592,11 @@ public: llvm::PointerIntPair VarAndKind; SourceLocation Loc; + Capture() = default; + public: friend class ASTStmtReader; + friend class CapturedStmt; /// Create a new capture. /// diff --git a/contrib/llvm-project/clang/include/clang/AST/StmtCXX.h b/contrib/llvm-project/clang/include/clang/AST/StmtCXX.h index 2c71f867689..8b4ef24ed37 100644 --- a/contrib/llvm-project/clang/include/clang/AST/StmtCXX.h +++ b/contrib/llvm-project/clang/include/clang/AST/StmtCXX.h @@ -75,7 +75,8 @@ class CXXTryStmt final : public Stmt, unsigned NumHandlers; size_t numTrailingObjects(OverloadToken) const { return NumHandlers; } - CXXTryStmt(SourceLocation tryLoc, Stmt *tryBlock, ArrayRef handlers); + CXXTryStmt(SourceLocation tryLoc, CompoundStmt *tryBlock, + ArrayRef handlers); CXXTryStmt(EmptyShell Empty, unsigned numHandlers) : Stmt(CXXTryStmtClass), NumHandlers(numHandlers) { } @@ -84,7 +85,7 @@ class CXXTryStmt final : public Stmt, public: static CXXTryStmt *Create(const ASTContext &C, SourceLocation tryLoc, - Stmt *tryBlock, ArrayRef handlers); + CompoundStmt *tryBlock, ArrayRef handlers); static CXXTryStmt *Create(const ASTContext &C, EmptyShell Empty, unsigned numHandlers); @@ -326,6 +327,7 @@ class CoroutineBodyStmt final OnFallthrough, ///< Handler for control flow falling off the body. Allocate, ///< Coroutine frame memory allocation. Deallocate, ///< Coroutine frame memory deallocation. + ResultDecl, ///< Declaration holding the result of get_return_object. ReturnValue, ///< Return value for thunk function: p.get_return_object(). ReturnStmt, ///< Return statement for the thunk function. ReturnStmtOnAllocFailure, ///< Return statement if allocation failed. @@ -352,6 +354,7 @@ public: Stmt *OnFallthrough = nullptr; Expr *Allocate = nullptr; Expr *Deallocate = nullptr; + Stmt *ResultDecl = nullptr; Expr *ReturnValue = nullptr; Stmt *ReturnStmt = nullptr; Stmt *ReturnStmtOnAllocFailure = nullptr; @@ -372,9 +375,10 @@ public: } /// Retrieve the body of the coroutine as written. This will be either - /// a CompoundStmt or a TryStmt. - Stmt *getBody() const { - return getStoredStmts()[SubStmt::Body]; + /// a CompoundStmt. If the coroutine is in function-try-block, we will + /// wrap the CXXTryStmt into a CompoundStmt to keep consistency. + CompoundStmt *getBody() const { + return cast(getStoredStmts()[SubStmt::Body]); } Stmt *getPromiseDeclStmt() const { @@ -404,13 +408,13 @@ public: Expr *getDeallocate() const { return cast_or_null(getStoredStmts()[SubStmt::Deallocate]); } + Stmt *getResultDecl() const { return getStoredStmts()[SubStmt::ResultDecl]; } Expr *getReturnValueInit() const { return cast(getStoredStmts()[SubStmt::ReturnValue]); } Expr *getReturnValue() const { - assert(getReturnStmt()); - auto *RS = cast(getReturnStmt()); - return RS->getRetValue(); + auto *RS = dyn_cast_or_null(getReturnStmt()); + return RS ? RS->getRetValue() : nullptr; } Stmt *getReturnStmt() const { return getStoredStmts()[SubStmt::ReturnStmt]; } Stmt *getReturnStmtOnAllocFailure() const { @@ -439,6 +443,17 @@ public: NumParams); } + child_range childrenExclBody() { + return child_range(getStoredStmts() + SubStmt::Body + 1, + getStoredStmts() + SubStmt::FirstParamMove + NumParams); + } + + const_child_range childrenExclBody() const { + return const_child_range(getStoredStmts() + SubStmt::Body + 1, + getStoredStmts() + SubStmt::FirstParamMove + + NumParams); + } + static bool classof(const Stmt *T) { return T->getStmtClass() == CoroutineBodyStmtClass; } diff --git a/contrib/llvm-project/clang/include/clang/AST/TemplateBase.h b/contrib/llvm-project/clang/include/clang/AST/TemplateBase.h index 66aef2121d8..8e6b4d81974 100644 --- a/contrib/llvm-project/clang/include/clang/AST/TemplateBase.h +++ b/contrib/llvm-project/clang/include/clang/AST/TemplateBase.h @@ -103,12 +103,14 @@ private: /// The kind of template argument we're storing. struct DA { - unsigned Kind; + unsigned Kind : 31; + unsigned IsDefaulted : 1; void *QT; ValueDecl *D; }; struct I { - unsigned Kind; + unsigned Kind : 31; + unsigned IsDefaulted : 1; // We store a decomposed APSInt with the data allocated by ASTContext if // BitWidth > 64. The memory may be shared between multiple // TemplateArgument instances. @@ -124,17 +126,20 @@ private: void *Type; }; struct A { - unsigned Kind; + unsigned Kind : 31; + unsigned IsDefaulted : 1; unsigned NumArgs; const TemplateArgument *Args; }; struct TA { - unsigned Kind; + unsigned Kind : 31; + unsigned IsDefaulted : 1; unsigned NumExpansions; void *Name; }; struct TV { - unsigned Kind; + unsigned Kind : 31; + unsigned IsDefaulted : 1; uintptr_t V; }; union { @@ -147,27 +152,31 @@ private: public: /// Construct an empty, invalid template argument. - constexpr TemplateArgument() : TypeOrValue({Null, 0}) {} + constexpr TemplateArgument() : TypeOrValue({Null, 0, /* IsDefaulted */ 0}) {} /// Construct a template type argument. - TemplateArgument(QualType T, bool isNullPtr = false) { + TemplateArgument(QualType T, bool isNullPtr = false, + bool IsDefaulted = false) { TypeOrValue.Kind = isNullPtr ? NullPtr : Type; + TypeOrValue.IsDefaulted = IsDefaulted; TypeOrValue.V = reinterpret_cast(T.getAsOpaquePtr()); } /// Construct a template argument that refers to a /// declaration, which is either an external declaration or a /// template declaration. - TemplateArgument(ValueDecl *D, QualType QT) { + TemplateArgument(ValueDecl *D, QualType QT, bool IsDefaulted = false) { assert(D && "Expected decl"); DeclArg.Kind = Declaration; + DeclArg.IsDefaulted = IsDefaulted; DeclArg.QT = QT.getAsOpaquePtr(); DeclArg.D = D; } /// Construct an integral constant template argument. The memory to /// store the value is allocated with Ctx. - TemplateArgument(ASTContext &Ctx, const llvm::APSInt &Value, QualType Type); + TemplateArgument(ASTContext &Ctx, const llvm::APSInt &Value, QualType Type, + bool IsDefaulted = false); /// Construct an integral constant template argument with the same /// value as Other but a different type. @@ -184,8 +193,12 @@ public: /// is taken. /// /// \param Name The template name. - TemplateArgument(TemplateName Name) { + /// + /// \param IsDefaulted If 'true', implies that this TemplateArgument + /// corresponds to a default template parameter + TemplateArgument(TemplateName Name, bool IsDefaulted = false) { TemplateArg.Kind = Template; + TemplateArg.IsDefaulted = IsDefaulted; TemplateArg.Name = Name.getAsVoidPointer(); TemplateArg.NumExpansions = 0; } @@ -201,8 +214,13 @@ public: /// /// \param NumExpansions The number of expansions that will be generated by /// instantiating - TemplateArgument(TemplateName Name, std::optional NumExpansions) { + /// + /// \param IsDefaulted If 'true', implies that this TemplateArgument + /// corresponds to a default template parameter + TemplateArgument(TemplateName Name, std::optional NumExpansions, + bool IsDefaulted = false) { TemplateArg.Kind = TemplateExpansion; + TemplateArg.IsDefaulted = IsDefaulted; TemplateArg.Name = Name.getAsVoidPointer(); if (NumExpansions) TemplateArg.NumExpansions = *NumExpansions + 1; @@ -215,8 +233,9 @@ public: /// This form of template argument only occurs in template argument /// lists used for dependent types and for expression; it will not /// occur in a non-dependent, canonical template argument list. - TemplateArgument(Expr *E) { + TemplateArgument(Expr *E, bool IsDefaulted = false) { TypeOrValue.Kind = Expression; + TypeOrValue.IsDefaulted = IsDefaulted; TypeOrValue.V = reinterpret_cast(E); } @@ -226,12 +245,11 @@ public: /// outlives the TemplateArgument itself. explicit TemplateArgument(ArrayRef Args) { this->Args.Kind = Pack; + this->Args.IsDefaulted = false; this->Args.Args = Args.data(); this->Args.NumArgs = Args.size(); } - TemplateArgument(TemplateName, bool) = delete; - static TemplateArgument getEmptyPack() { return TemplateArgument(std::nullopt); } @@ -334,6 +352,14 @@ public: Integer.Type = T.getAsOpaquePtr(); } + /// Set to 'true' if this TemplateArgument corresponds to a + /// default template parameter. + void setIsDefaulted(bool v) { TypeOrValue.IsDefaulted = v; } + + /// If returns 'true', this TemplateArgument corresponds to a + /// default template parameter. + bool getIsDefaulted() const { return (bool)TypeOrValue.IsDefaulted; } + /// If this is a non-type template argument, get its type. Otherwise, /// returns a null QualType. QualType getNonTypeTemplateArgumentType() const; diff --git a/contrib/llvm-project/clang/include/clang/AST/TemplateName.h b/contrib/llvm-project/clang/include/clang/AST/TemplateName.h index 2f108ea0072..d56361b5005 100644 --- a/contrib/llvm-project/clang/include/clang/AST/TemplateName.h +++ b/contrib/llvm-project/clang/include/clang/AST/TemplateName.h @@ -351,9 +351,7 @@ public: /// error. void dump() const; - void Profile(llvm::FoldingSetNodeID &ID) { - ID.AddPointer(Storage.getOpaqueValue()); - } + void Profile(llvm::FoldingSetNodeID &ID); /// Retrieve the template name as a void pointer. void *getAsVoidPointer() const { return Storage.getOpaqueValue(); } diff --git a/contrib/llvm-project/clang/include/clang/AST/Type.h b/contrib/llvm-project/clang/include/clang/AST/Type.h index 180251d7f6b..8d20d088bb6 100644 --- a/contrib/llvm-project/clang/include/clang/AST/Type.h +++ b/contrib/llvm-project/clang/include/clang/AST/Type.h @@ -899,12 +899,24 @@ public: /// Return true if this is a trivially relocatable type. bool isTriviallyRelocatableType(const ASTContext &Context) const; + /// Return true if this is a trivially equality comparable type. + bool isTriviallyEqualityComparableType(const ASTContext &Context) const; + /// Returns true if it is a class and it might be dynamic. bool mayBeDynamicClass() const; /// Returns true if it is not a class or if the class might not be dynamic. bool mayBeNotDynamicClass() const; + /// Returns true if it is a WebAssembly Reference Type. + bool isWebAssemblyReferenceType() const; + + /// Returns true if it is a WebAssembly Externref Type. + bool isWebAssemblyExternrefType() const; + + /// Returns true if it is a WebAssembly Funcref Type. + bool isWebAssemblyFuncrefType() const; + // Don't promise in the API that anything besides 'const' can be // easily added. @@ -945,7 +957,6 @@ public: void removeLocalConst(); void removeLocalVolatile(); void removeLocalRestrict(); - void removeLocalCVRQualifiers(unsigned Mask); void removeLocalFastQualifiers() { Value.setInt(0); } void removeLocalFastQualifiers(unsigned Mask) { @@ -1647,7 +1658,8 @@ protected: unsigned : NumTypeBits; /// The kind (BuiltinType::Kind) of builtin type this is. - unsigned Kind : 8; + static constexpr unsigned NumOfBuiltinTypeBits = 9; + unsigned Kind : NumOfBuiltinTypeBits; }; /// FunctionTypeBitfields store various bits belonging to FunctionProtoType. @@ -1767,7 +1779,7 @@ protected: /// The kind of vector, either a generic vector type or some /// target-specific vector type such as for AltiVec or Neon. - unsigned VecKind : 3; + unsigned VecKind : 4; /// The number of elements in the vector. uint32_t NumElements; }; @@ -2029,6 +2041,17 @@ public: /// Returns true for SVE scalable vector types. bool isSVESizelessBuiltinType() const; + /// Returns true for RVV scalable vector types. + bool isRVVSizelessBuiltinType() const; + + /// Check if this is a WebAssembly Externref Type. + bool isWebAssemblyExternrefType() const; + + /// Returns true if this is a WebAssembly table type: either an array of + /// reference types, or a pointer to a reference type (which can only be + /// created by array to pointer decay). + bool isWebAssemblyTableType() const; + /// Determines if this is a sizeless type supported by the /// 'arm_sve_vector_bits' type attribute, which can be applied to a single /// SVE vector or predicate, excluding tuple types such as svint32x4_t. @@ -2039,6 +2062,16 @@ public: /// 'arm_sve_vector_bits' type attribute as VectorType. QualType getSveEltType(const ASTContext &Ctx) const; + /// Determines if this is a sizeless type supported by the + /// 'riscv_rvv_vector_bits' type attribute, which can be applied to a single + /// RVV vector or mask. + bool isRVVVLSBuiltinType() const; + + /// Returns the representative type for the element of an RVV builtin type. + /// This is used to represent fixed-length RVV vectors created with the + /// 'riscv_rvv_vector_bits' type attribute as VectorType. + QualType getRVVEltType(const ASTContext &Ctx) const; + /// Types are partitioned into 3 broad categories (C99 6.2.5p1): /// object types, function types, and incomplete types. @@ -2273,8 +2306,12 @@ public: /// Check if the type is the CUDA device builtin texture type. bool isCUDADeviceBuiltinTextureType() const; + bool isRVVType(unsigned ElementCount) const; + bool isRVVType() const; + bool isRVVType(unsigned Bitwidth, bool IsFloat) const; + /// Return the implicit lifetime for this type, which must not be dependent. Qualifiers::ObjCLifetime getObjCARCImplicitLifetime() const; @@ -2640,6 +2677,9 @@ public: // RVV Types #define RVV_TYPE(Name, Id, SingletonId) Id, #include "clang/Basic/RISCVVTypes.def" +// WebAssembly reference types +#define WASM_TYPE(Name, Id, SingletonId) Id, +#include "clang/Basic/WebAssemblyReferenceTypes.def" // All other builtin types #define BUILTIN_TYPE(Id, SingletonId) Id, #define LAST_BUILTIN_TYPE(Id) LastKind = Id @@ -2653,6 +2693,10 @@ private: : Type(Builtin, QualType(), K == Dependent ? TypeDependence::DependentInstantiation : TypeDependence::None) { + static_assert(Kind::LastKind < + (1 << BuiltinTypeBitfields::NumOfBuiltinTypeBits) && + "Defined builtin type exceeds the allocated space for serial " + "numbering"); BuiltinTypeBits.Kind = K; } @@ -2688,6 +2732,8 @@ public: bool isSVEBool() const { return getKind() == Kind::SveBool; } + bool isSVECount() const { return getKind() == Kind::SveCount; } + /// Determines whether the given kind corresponds to a placeholder type. static bool isPlaceholderTypeKind(Kind K) { return K >= Overload; @@ -3385,7 +3431,10 @@ public: SveFixedLengthDataVector, /// is AArch64 SVE fixed-length predicate vector - SveFixedLengthPredicateVector + SveFixedLengthPredicateVector, + + /// is RISC-V RVV fixed-length data vector + RVVFixedLengthDataVector, }; protected: @@ -3924,7 +3973,7 @@ public: /// The number of types in the exception specification. /// A whole unsigned is not needed here and according to /// [implimits] 8 bits would be enough here. - unsigned NumExceptionType = 0; + uint16_t NumExceptionType = 0; }; protected: @@ -4920,6 +4969,8 @@ public: bool isMSTypeSpec() const; + bool isWebAssemblyFuncrefSpec() const; + bool isCallingConv() const; std::optional getImmediateNullability() const; @@ -6608,7 +6659,7 @@ class alignas(8) TypeSourceInfo { QualType Ty; - TypeSourceInfo(QualType ty) : Ty(ty) {} + TypeSourceInfo(QualType ty, size_t DataSize); // implemented in TypeLoc.h public: /// Return the type wrapped by this type source info. @@ -6749,15 +6800,6 @@ inline void QualType::removeLocalVolatile() { removeLocalFastQualifiers(Qualifiers::Volatile); } -inline void QualType::removeLocalCVRQualifiers(unsigned Mask) { - assert(!(Mask & ~Qualifiers::CVRMask) && "mask has non-CVR bits"); - static_assert((int)Qualifiers::CVRMask == (int)Qualifiers::FastMask, - "Fast bits differ from CVR bits!"); - - // Fast path: we don't need to touch the slow qualifiers. - removeLocalFastQualifiers(Mask); -} - /// Check if this type has any address space qualifier. inline bool QualType::hasAddressSpace() const { return getQualifiers().hasAddressSpace(); @@ -7153,6 +7195,27 @@ inline bool Type::isRVVType() const { false; // end of boolean or operation. } +inline bool Type::isRVVType(unsigned ElementCount) const { + bool Ret = false; +#define RVV_VECTOR_TYPE(Name, Id, SingletonId, NumEls, ElBits, NF, IsSigned, \ + IsFP) \ + if (NumEls == ElementCount) \ + Ret |= isSpecificBuiltinType(BuiltinType::Id); +#include "clang/Basic/RISCVVTypes.def" + return Ret; +} + +inline bool Type::isRVVType(unsigned Bitwidth, bool IsFloat) const { + bool Ret = false; +#define RVV_TYPE(Name, Id, SingletonId) +#define RVV_VECTOR_TYPE(Name, Id, SingletonId, NumEls, ElBits, NF, IsSigned, \ + IsFP) \ + if (ElBits == Bitwidth && IsFloat == IsFP) \ + Ret |= isSpecificBuiltinType(BuiltinType::Id); +#include "clang/Basic/RISCVVTypes.def" + return Ret; +} + inline bool Type::isTemplateTypeParmType() const { return isa(CanonicalType); } diff --git a/contrib/llvm-project/clang/include/clang/AST/TypeLoc.h b/contrib/llvm-project/clang/include/clang/AST/TypeLoc.h index 72ed3cb752e..27f714b7c98 100644 --- a/contrib/llvm-project/clang/include/clang/AST/TypeLoc.h +++ b/contrib/llvm-project/clang/include/clang/AST/TypeLoc.h @@ -240,6 +240,11 @@ private: static SourceRange getLocalSourceRangeImpl(TypeLoc TL); }; +inline TypeSourceInfo::TypeSourceInfo(QualType ty, size_t DataSize) : Ty(ty) { + // Init data attached to the object. See getTypeLoc. + memset(this + 1, 0, DataSize); +} + /// Return the TypeLoc for a type source info. inline TypeLoc TypeSourceInfo::getTypeLoc() const { // TODO: is this alignment already sufficient? @@ -2102,7 +2107,7 @@ struct AutoTypeLocInfo : TypeSpecLocInfo { NestedNameSpecifierLoc NestedNameSpec; SourceLocation TemplateKWLoc; SourceLocation ConceptNameLoc; - NamedDecl *FoundDecl; + NamedDecl *FoundDecl = nullptr; SourceLocation LAngleLoc; SourceLocation RAngleLoc; diff --git a/contrib/llvm-project/clang/include/clang/AST/TypeProperties.td b/contrib/llvm-project/clang/include/clang/AST/TypeProperties.td index aca445fbe6c..3cc826c1463 100644 --- a/contrib/llvm-project/clang/include/clang/AST/TypeProperties.td +++ b/contrib/llvm-project/clang/include/clang/AST/TypeProperties.td @@ -11,7 +11,7 @@ include "clang/Basic/TypeNodes.td" let Class = ComplexType in { def : Property<"elementType", QualType> { - let Read = [{ node->getElementType() }]; + let Read = [{ node->getElementType() }]; } def : Creator<[{ return ctx.getComplexType(elementType); }]>; @@ -591,7 +591,7 @@ let Class = ParenType in { def : Creator<[{ return ctx.getParenType(innerType); - }]>; + }]>; } let Class = MacroQualifiedType in { @@ -813,6 +813,10 @@ let Class = BuiltinType in { case BuiltinType::ID: return ctx.SINGLETON_ID; #include "clang/Basic/RISCVVTypes.def" +#define WASM_TYPE(NAME, ID, SINGLETON_ID) \ + case BuiltinType::ID: return ctx.SINGLETON_ID; +#include "clang/Basic/WebAssemblyReferenceTypes.def" + #define BUILTIN_TYPE(ID, SINGLETON_ID) \ case BuiltinType::ID: return ctx.SINGLETON_ID; #include "clang/AST/BuiltinTypes.def" @@ -889,7 +893,7 @@ let Class = ObjCInterfaceType in { let Class = ObjCTypeParamType in { def : Property<"declaration", ObjCTypeParamDeclRef> { let Read = [{ node->getDecl() }]; - } + } def : Property<"qualifiers", Array> { let Read = [{ node->getProtocols() }]; } diff --git a/contrib/llvm-project/clang/include/clang/AST/UnresolvedSet.h b/contrib/llvm-project/clang/include/clang/AST/UnresolvedSet.h index 17b47f6ab96..ee31be969b6 100644 --- a/contrib/llvm-project/clang/include/clang/AST/UnresolvedSet.h +++ b/contrib/llvm-project/clang/include/clang/AST/UnresolvedSet.h @@ -114,9 +114,17 @@ public: I.I->set(New, AS); } - void erase(unsigned I) { decls()[I] = decls().pop_back_val(); } + void erase(unsigned I) { + auto val = decls().pop_back_val(); + if (I < size()) + decls()[I] = val; + } - void erase(iterator I) { *I.I = decls().pop_back_val(); } + void erase(iterator I) { + auto val = decls().pop_back_val(); + if (I != end()) + *I.I = val; + } void setAccess(iterator I, AccessSpecifier AS) { I.I->setAccess(AS); } diff --git a/contrib/llvm-project/clang/include/clang/AST/VTableBuilder.h b/contrib/llvm-project/clang/include/clang/AST/VTableBuilder.h index e451f3f861b..1bf7d0467aa 100644 --- a/contrib/llvm-project/clang/include/clang/AST/VTableBuilder.h +++ b/contrib/llvm-project/clang/include/clang/AST/VTableBuilder.h @@ -563,8 +563,6 @@ private: llvm::DenseMap> VBaseInfo; - void enumerateVFPtrs(const CXXRecordDecl *ForClass, VPtrInfoVector &Result); - void computeVTableRelatedInformation(const CXXRecordDecl *RD) override; void dumpMethodLocations(const CXXRecordDecl *RD, diff --git a/contrib/llvm-project/clang/include/clang/ASTMatchers/ASTMatchers.h b/contrib/llvm-project/clang/include/clang/ASTMatchers/ASTMatchers.h index 98b727e6940..f49204a3d90 100644 --- a/contrib/llvm-project/clang/include/clang/ASTMatchers/ASTMatchers.h +++ b/contrib/llvm-project/clang/include/clang/ASTMatchers/ASTMatchers.h @@ -81,6 +81,7 @@ #include "clang/Basic/TypeTraits.h" #include "llvm/ADT/ArrayRef.h" #include "llvm/ADT/SmallVector.h" +#include "llvm/ADT/StringExtras.h" #include "llvm/ADT/StringRef.h" #include "llvm/Support/Casting.h" #include "llvm/Support/Compiler.h" @@ -1333,6 +1334,16 @@ extern const internal::VariadicDynCastAllOfMatcher extern const internal::VariadicDynCastAllOfMatcher cxxDeductionGuideDecl; +/// Matches concept declarations. +/// +/// Example matches integral +/// \code +/// template +/// concept integral = std::is_integral_v; +/// \endcode +extern const internal::VariadicDynCastAllOfMatcher + conceptDecl; + /// Matches variable declarations. /// /// Note: this does not match declarations of member variables, which are @@ -1970,6 +1981,45 @@ extern const internal::VariadicDynCastAllOfMatcher extern const internal::VariadicDynCastAllOfMatcher cxxNoexceptExpr; +/// Matches a loop initializing the elements of an array in a number of contexts: +/// * in the implicit copy/move constructor for a class with an array member +/// * when a lambda-expression captures an array by value +/// * when a decomposition declaration decomposes an array +/// +/// Given +/// \code +/// void testLambdaCapture() { +/// int a[10]; +/// auto Lam1 = [a]() { +/// return; +/// }; +/// } +/// \endcode +/// arrayInitLoopExpr() matches the implicit loop that initializes each element of +/// the implicit array field inside the lambda object, that represents the array `a` +/// captured by value. +extern const internal::VariadicDynCastAllOfMatcher + arrayInitLoopExpr; + +/// The arrayInitIndexExpr consists of two subexpressions: a common expression +/// (the source array) that is evaluated once up-front, and a per-element initializer +/// that runs once for each array element. Within the per-element initializer, +/// the current index may be obtained via an ArrayInitIndexExpr. +/// +/// Given +/// \code +/// void testStructBinding() { +/// int a[2] = {1, 2}; +/// auto [x, y] = a; +/// } +/// \endcode +/// arrayInitIndexExpr() matches the array index that implicitly iterates +/// over the array `a` to copy each element to the anonymous array +/// that backs the structured binding `[x, y]` elements of which are +/// referred to by their aliases `x` and `y`. +extern const internal::VariadicDynCastAllOfMatcher + arrayInitIndexExpr; + /// Matches array subscript expressions. /// /// Given @@ -2450,6 +2500,17 @@ extern const internal::VariadicDynCastAllOfMatcher extern const internal::VariadicDynCastAllOfMatcher coyieldExpr; +/// Matches coroutine body statements. +/// +/// coroutineBodyStmt() matches the coroutine below +/// \code +/// generator gen() { +/// co_return; +/// } +/// \endcode +extern const internal::VariadicDynCastAllOfMatcher + coroutineBodyStmt; + /// Matches nullptr literal. extern const internal::VariadicDynCastAllOfMatcher cxxNullPtrLiteralExpr; @@ -4419,6 +4480,33 @@ AST_POLYMORPHIC_MATCHER_P(argumentCountIs, return NumArgs == N; } +/// Checks that a call expression or a constructor call expression has at least +/// the specified number of arguments (including absent default arguments). +/// +/// Example matches f(0, 0) and g(0, 0, 0) +/// (matcher = callExpr(argumentCountAtLeast(2))) +/// \code +/// void f(int x, int y); +/// void g(int x, int y, int z); +/// f(0, 0); +/// g(0, 0, 0); +/// \endcode +AST_POLYMORPHIC_MATCHER_P(argumentCountAtLeast, + AST_POLYMORPHIC_SUPPORTED_TYPES( + CallExpr, CXXConstructExpr, + CXXUnresolvedConstructExpr, ObjCMessageExpr), + unsigned, N) { + unsigned NumArgs = Node.getNumArgs(); + if (!Finder->isTraversalIgnoringImplicitNodes()) + return NumArgs >= N; + while (NumArgs) { + if (!isa(Node.getArg(NumArgs - 1))) + break; + --NumArgs; + } + return NumArgs >= N; +} + /// Matches the n'th argument of a call expression or a constructor /// call expression. /// @@ -5460,9 +5548,10 @@ AST_MATCHER_P(ArraySubscriptExpr, hasBase, return false; } -/// Matches a 'for', 'while', 'do' statement or a function definition that has -/// a given body. Note that in case of functions this matcher only matches the -/// definition itself and not the other declarations of the same function. +/// Matches a 'for', 'while', 'while' statement or a function or coroutine +/// definition that has a given body. Note that in case of functions or +/// coroutines this matcher only matches the definition itself and not the +/// other declarations of the same function or coroutine. /// /// Given /// \code @@ -5483,12 +5572,11 @@ AST_MATCHER_P(ArraySubscriptExpr, hasBase, /// with compoundStmt() /// matching '{}' /// but does not match 'void f();' -AST_POLYMORPHIC_MATCHER_P(hasBody, - AST_POLYMORPHIC_SUPPORTED_TYPES(DoStmt, ForStmt, - WhileStmt, - CXXForRangeStmt, - FunctionDecl), - internal::Matcher, InnerMatcher) { +AST_POLYMORPHIC_MATCHER_P( + hasBody, + AST_POLYMORPHIC_SUPPORTED_TYPES(DoStmt, ForStmt, WhileStmt, CXXForRangeStmt, + FunctionDecl, CoroutineBodyStmt), + internal::Matcher, InnerMatcher) { if (Finder->isTraversalIgnoringImplicitNodes() && isDefaultedHelper(&Node)) return false; const Stmt *const Statement = internal::GetBodyMatcher::get(Node); diff --git a/contrib/llvm-project/clang/include/clang/ASTMatchers/Dynamic/Diagnostics.h b/contrib/llvm-project/clang/include/clang/ASTMatchers/Dynamic/Diagnostics.h index 3f6f364d650..960d59a747f 100644 --- a/contrib/llvm-project/clang/include/clang/ASTMatchers/Dynamic/Diagnostics.h +++ b/contrib/llvm-project/clang/include/clang/ASTMatchers/Dynamic/Diagnostics.h @@ -28,9 +28,9 @@ namespace ast_matchers { namespace dynamic { struct SourceLocation { - SourceLocation() : Line(), Column() {} - unsigned Line; - unsigned Column; + SourceLocation() = default; + unsigned Line = 0; + unsigned Column = 0; }; struct SourceRange { diff --git a/contrib/llvm-project/clang/include/clang/Analysis/Analyses/CalledOnceCheck.h b/contrib/llvm-project/clang/include/clang/Analysis/Analyses/CalledOnceCheck.h index b65a3967cd5..6a1528a2da2 100644 --- a/contrib/llvm-project/clang/include/clang/Analysis/Analyses/CalledOnceCheck.h +++ b/contrib/llvm-project/clang/include/clang/Analysis/Analyses/CalledOnceCheck.h @@ -28,7 +28,7 @@ class Stmt; /// \enum IfThen -- then branch of the if statement has no call. /// \enum IfElse -- else branch of the if statement has no call. /// \enum Switch -- one of the switch cases doesn't have a call. -/// \enum SwitchSkipped -- there is no call if none of the cases appies. +/// \enum SwitchSkipped -- there is no call if none of the cases applies. /// \enum LoopEntered -- no call when the loop is entered. /// \enum LoopSkipped -- no call when the loop is not entered. /// \enum FallbackReason -- fallback case when we were not able to figure out diff --git a/contrib/llvm-project/clang/include/clang/Analysis/Analyses/Consumed.h b/contrib/llvm-project/clang/include/clang/Analysis/Analyses/Consumed.h index 24702567ab6..3e2788cac3c 100644 --- a/contrib/llvm-project/clang/include/clang/Analysis/Analyses/Consumed.h +++ b/contrib/llvm-project/clang/include/clang/Analysis/Analyses/Consumed.h @@ -155,6 +155,10 @@ namespace consumed { ConsumedStateMap(const ConsumedStateMap &Other) : Reachable(Other.Reachable), From(Other.From), VarMap(Other.VarMap) {} + // The copy assignment operator is defined as deleted pending further + // motivation. + ConsumedStateMap &operator=(const ConsumedStateMap &) = delete; + /// Warn if any of the parameters being tracked are not in the state /// they were declared to be in upon return from a function. void checkParamsForReturnTypestate(SourceLocation BlameLoc, @@ -240,7 +244,7 @@ namespace consumed { ConsumedBlockInfo BlockInfo; std::unique_ptr CurrStates; - ConsumedState ExpectedReturnState; + ConsumedState ExpectedReturnState = CS_None; void determineExpectedReturnState(AnalysisDeclContext &AC, const FunctionDecl *D); @@ -258,7 +262,7 @@ namespace consumed { /// Check a function's CFG for consumed violations. /// /// We traverse the blocks in the CFG, keeping track of the state of each - /// value who's type has uniquness annotations. If methods are invoked in + /// value who's type has uniqueness annotations. If methods are invoked in /// the wrong state a warning is issued. Each block in the CFG is traversed /// exactly once. void run(AnalysisDeclContext &AC); diff --git a/contrib/llvm-project/clang/include/clang/Analysis/Analyses/IntervalPartition.h b/contrib/llvm-project/clang/include/clang/Analysis/Analyses/IntervalPartition.h new file mode 100644 index 00000000000..cc04bab7bf6 --- /dev/null +++ b/contrib/llvm-project/clang/include/clang/Analysis/Analyses/IntervalPartition.h @@ -0,0 +1,50 @@ +//===- IntervalPartition.h - CFG Partitioning into Intervals -----*- C++-*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +// +// This file defines functionality for partitioning a CFG into intervals. The +// concepts and implementations are based on the presentation in "Compilers" by +// Aho, Sethi and Ullman (the "dragon book"), pages 664-666. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CLANG_ANALYSIS_ANALYSES_INTERVALPARTITION_H +#define LLVM_CLANG_ANALYSIS_ANALYSES_INTERVALPARTITION_H + +#include "clang/Analysis/CFG.h" +#include "llvm/ADT/DenseSet.h" +#include + +namespace clang { + +// An interval is a strongly-connected component of the CFG along with a +// trailing acyclic structure. The _header_ of the interval is either the CFG +// entry block or has at least one predecessor outside of the interval. All +// other blocks in the interval have only predecessors also in the interval. +struct CFGInterval { + CFGInterval(const CFGBlock *Header) : Header(Header), Blocks({Header}) {} + + // The block from which the interval was constructed. Is either the CFG entry + // block or has at least one predecessor outside the interval. + const CFGBlock *Header; + + llvm::SmallDenseSet Blocks; + + // Successor blocks of the *interval*: blocks outside the interval for + // reachable (in one edge) from within the interval. + llvm::SmallDenseSet Successors; +}; + +CFGInterval buildInterval(const CFG &Cfg, const CFGBlock &Header); + +// Partitions `Cfg` into intervals and constructs a graph of the intervals, +// based on the edges between nodes in these intervals. +std::vector partitionIntoIntervals(const CFG &Cfg); + +} // namespace clang + +#endif // LLVM_CLANG_ANALYSIS_ANALYSES_INTERVALPARTITION_H diff --git a/contrib/llvm-project/clang/include/clang/Analysis/Analyses/ReachableCode.h b/contrib/llvm-project/clang/include/clang/Analysis/Analyses/ReachableCode.h index 514b9458d33..f1b63f74b6c 100644 --- a/contrib/llvm-project/clang/include/clang/Analysis/Analyses/ReachableCode.h +++ b/contrib/llvm-project/clang/include/clang/Analysis/Analyses/ReachableCode.h @@ -48,11 +48,9 @@ class Callback { virtual void anchor(); public: virtual ~Callback() {} - virtual void HandleUnreachable(UnreachableKind UK, - SourceLocation L, - SourceRange ConditionVal, - SourceRange R1, - SourceRange R2) = 0; + virtual void HandleUnreachable(UnreachableKind UK, SourceLocation L, + SourceRange ConditionVal, SourceRange R1, + SourceRange R2, bool HasFallThroughAttr) = 0; }; /// ScanReachableFromBlock - Mark all blocks reachable from Start. diff --git a/contrib/llvm-project/clang/include/clang/Analysis/Analyses/ThreadSafetyCommon.h b/contrib/llvm-project/clang/include/clang/Analysis/Analyses/ThreadSafetyCommon.h index 9c73d65db26..9d28325c1ea 100644 --- a/contrib/llvm-project/clang/include/clang/Analysis/Analyses/ThreadSafetyCommon.h +++ b/contrib/llvm-project/clang/include/clang/Analysis/Analyses/ThreadSafetyCommon.h @@ -484,8 +484,6 @@ private: SMap.insert(std::make_pair(S, E)); } - til::SExpr *getCurrentLVarDefinition(const ValueDecl *VD); - til::SExpr *addStatement(til::SExpr *E, const Stmt *S, const ValueDecl *VD = nullptr); til::SExpr *lookupVarDecl(const ValueDecl *VD); diff --git a/contrib/llvm-project/clang/include/clang/Analysis/Analyses/ThreadSafetyTIL.h b/contrib/llvm-project/clang/include/clang/Analysis/Analyses/ThreadSafetyTIL.h index eac402a7910..65dd66ee093 100644 --- a/contrib/llvm-project/clang/include/clang/Analysis/Analyses/ThreadSafetyTIL.h +++ b/contrib/llvm-project/clang/include/clang/Analysis/Analyses/ThreadSafetyTIL.h @@ -319,6 +319,7 @@ public: protected: SExpr(TIL_Opcode Op) : Opcode(Op) {} SExpr(const SExpr &E) : Opcode(E.Opcode), Flags(E.Flags) {} + SExpr &operator=(const SExpr &) = delete; const TIL_Opcode Opcode; unsigned char Reserved = 0; @@ -488,6 +489,10 @@ public: Undefined(const Stmt *S = nullptr) : SExpr(COP_Undefined), Cstmt(S) {} Undefined(const Undefined &U) : SExpr(U), Cstmt(U.Cstmt) {} + // The copy assignment operator is defined as deleted pending further + // motivation. + Undefined &operator=(const Undefined &) = delete; + static bool classof(const SExpr *E) { return E->opcode() == COP_Undefined; } template @@ -566,6 +571,10 @@ public: LiteralT(T Dat) : Literal(ValueType::getValueType()), Val(Dat) {} LiteralT(const LiteralT &L) : Literal(L), Val(L.Val) {} + // The copy assignment operator is defined as deleted pending further + // motivation. + LiteralT &operator=(const LiteralT &) = delete; + T value() const { return Val;} T& value() { return Val; } diff --git a/contrib/llvm-project/clang/include/clang/Analysis/Analyses/ThreadSafetyUtil.h b/contrib/llvm-project/clang/include/clang/Analysis/Analyses/ThreadSafetyUtil.h index 7792707e502..ac7b24cdb4a 100644 --- a/contrib/llvm-project/clang/include/clang/Analysis/Analyses/ThreadSafetyUtil.h +++ b/contrib/llvm-project/clang/include/clang/Analysis/Analyses/ThreadSafetyUtil.h @@ -240,6 +240,10 @@ class CopyOnWriteVector { VectorData() = default; VectorData(const VectorData &VD) : Vect(VD.Vect) {} + + // The copy assignment operator is defined as deleted pending further + // motivation. + VectorData &operator=(const VectorData &) = delete; }; public: diff --git a/contrib/llvm-project/clang/include/clang/Analysis/Analyses/UnsafeBufferUsage.h b/contrib/llvm-project/clang/include/clang/Analysis/Analyses/UnsafeBufferUsage.h index e3f87cd0f36..6766ba8ec27 100644 --- a/contrib/llvm-project/clang/include/clang/Analysis/Analyses/UnsafeBufferUsage.h +++ b/contrib/llvm-project/clang/include/clang/Analysis/Analyses/UnsafeBufferUsage.h @@ -19,6 +19,8 @@ namespace clang { +using DefMapTy = llvm::DenseMap>; + /// The interface that lets the caller handle unsafe buffer usage analysis /// results by overriding this class's handle... methods. class UnsafeBufferUsageHandler { @@ -34,15 +36,32 @@ public: virtual void handleUnsafeOperation(const Stmt *Operation, bool IsRelatedToDecl) = 0; - /// Invoked when a fix is suggested against a variable. - virtual void handleFixableVariable(const VarDecl *Variable, - FixItList &&List) = 0; + /// Invoked when a fix is suggested against a variable. This function groups + /// all variables that must be fixed together (i.e their types must be changed to the + /// same target type to prevent type mismatches) into a single fixit. + virtual void handleUnsafeVariableGroup(const VarDecl *Variable, + const DefMapTy &VarGrpMap, + FixItList &&Fixes) = 0; + + /// Returns a reference to the `Preprocessor`: + virtual bool isSafeBufferOptOut(const SourceLocation &Loc) const = 0; + + virtual std::string + getUnsafeBufferUsageAttributeTextAt(SourceLocation Loc, + StringRef WSSuffix = "") const = 0; }; // This function invokes the analysis and allows the caller to react to it // through the handler class. -void checkUnsafeBufferUsage(const Decl *D, UnsafeBufferUsageHandler &Handler); +void checkUnsafeBufferUsage(const Decl *D, UnsafeBufferUsageHandler &Handler, + bool EmitSuggestions); +namespace internal { +// Tests if any two `FixItHint`s in `FixIts` conflict. Two `FixItHint`s +// conflict if they have overlapping source ranges. +bool anyConflict(const llvm::SmallVectorImpl &FixIts, + const SourceManager &SM); +} // namespace internal } // end namespace clang #endif /* LLVM_CLANG_ANALYSIS_ANALYSES_UNSAFEBUFFERUSAGE_H */ diff --git a/contrib/llvm-project/clang/include/clang/Analysis/Analyses/UnsafeBufferUsageGadgets.def b/contrib/llvm-project/clang/include/clang/Analysis/Analyses/UnsafeBufferUsageGadgets.def index d10d95e5b1b..ff687a0d178 100644 --- a/contrib/llvm-project/clang/include/clang/Analysis/Analyses/UnsafeBufferUsageGadgets.def +++ b/contrib/llvm-project/clang/include/clang/Analysis/Analyses/UnsafeBufferUsageGadgets.def @@ -29,6 +29,15 @@ WARNING_GADGET(Increment) WARNING_GADGET(Decrement) WARNING_GADGET(ArraySubscript) WARNING_GADGET(PointerArithmetic) +WARNING_GADGET(UnsafeBufferUsageAttr) +FIXABLE_GADGET(ULCArraySubscript) // `DRE[any]` in an Unspecified Lvalue Context +FIXABLE_GADGET(DerefSimplePtrArithFixable) +FIXABLE_GADGET(PointerDereference) +FIXABLE_GADGET(UPCAddressofArraySubscript) // '&DRE[any]' in an Unspecified Pointer Context +FIXABLE_GADGET(UPCStandalonePointer) +FIXABLE_GADGET(UPCPreIncrement) // '++Ptr' in an Unspecified Pointer Context +FIXABLE_GADGET(PointerAssignment) +FIXABLE_GADGET(PointerInit) #undef FIXABLE_GADGET #undef WARNING_GADGET diff --git a/contrib/llvm-project/clang/include/clang/Analysis/AnalysisDeclContext.h b/contrib/llvm-project/clang/include/clang/Analysis/AnalysisDeclContext.h index ce60ad56af4..a517a4e757c 100644 --- a/contrib/llvm-project/clang/include/clang/Analysis/AnalysisDeclContext.h +++ b/contrib/llvm-project/clang/include/clang/Analysis/AnalysisDeclContext.h @@ -331,7 +331,7 @@ public: unsigned getIndex() const { return Index; } CFGElement getCallSiteCFGElement() const { return (*Block)[Index]; } - + void Profile(llvm::FoldingSetNodeID &ID) override; static void Profile(llvm::FoldingSetNodeID &ID, AnalysisDeclContext *ADC, diff --git a/contrib/llvm-project/clang/include/clang/Analysis/BodyFarm.h b/contrib/llvm-project/clang/include/clang/Analysis/BodyFarm.h index eaa6472433d..52be29cb788 100644 --- a/contrib/llvm-project/clang/include/clang/Analysis/BodyFarm.h +++ b/contrib/llvm-project/clang/include/clang/Analysis/BodyFarm.h @@ -40,6 +40,9 @@ public: /// Remove copy constructor to avoid accidental copying. BodyFarm(const BodyFarm &other) = delete; + /// Delete copy assignment operator. + BodyFarm &operator=(const BodyFarm &other) = delete; + private: typedef llvm::DenseMap> BodyMap; diff --git a/contrib/llvm-project/clang/include/clang/Analysis/CFG.h b/contrib/llvm-project/clang/include/clang/Analysis/CFG.h index bd5658cbdea..eacebe176dd 100644 --- a/contrib/llvm-project/clang/include/clang/Analysis/CFG.h +++ b/contrib/llvm-project/clang/include/clang/Analysis/CFG.h @@ -1122,19 +1122,10 @@ public: Elements.push_back(CFGScopeBegin(VD, S), C); } - void prependScopeBegin(const VarDecl *VD, const Stmt *S, - BumpVectorContext &C) { - Elements.insert(Elements.rbegin(), 1, CFGScopeBegin(VD, S), C); - } - void appendScopeEnd(const VarDecl *VD, const Stmt *S, BumpVectorContext &C) { Elements.push_back(CFGScopeEnd(VD, S), C); } - void prependScopeEnd(const VarDecl *VD, const Stmt *S, BumpVectorContext &C) { - Elements.insert(Elements.rbegin(), 1, CFGScopeEnd(VD, S), C); - } - void appendBaseDtor(const CXXBaseSpecifier *BS, BumpVectorContext &C) { Elements.push_back(CFGBaseDtor(BS), C); } @@ -1162,44 +1153,6 @@ public: void appendDeleteDtor(CXXRecordDecl *RD, CXXDeleteExpr *DE, BumpVectorContext &C) { Elements.push_back(CFGDeleteDtor(RD, DE), C); } - - // Destructors must be inserted in reversed order. So insertion is in two - // steps. First we prepare space for some number of elements, then we insert - // the elements beginning at the last position in prepared space. - iterator beginAutomaticObjDtorsInsert(iterator I, size_t Cnt, - BumpVectorContext &C) { - return iterator(Elements.insert(I.base(), Cnt, - CFGAutomaticObjDtor(nullptr, nullptr), C)); - } - iterator insertAutomaticObjDtor(iterator I, VarDecl *VD, Stmt *S) { - *I = CFGAutomaticObjDtor(VD, S); - return ++I; - } - - // Scope leaving must be performed in reversed order. So insertion is in two - // steps. First we prepare space for some number of elements, then we insert - // the elements beginning at the last position in prepared space. - iterator beginLifetimeEndsInsert(iterator I, size_t Cnt, - BumpVectorContext &C) { - return iterator( - Elements.insert(I.base(), Cnt, CFGLifetimeEnds(nullptr, nullptr), C)); - } - iterator insertLifetimeEnds(iterator I, VarDecl *VD, Stmt *S) { - *I = CFGLifetimeEnds(VD, S); - return ++I; - } - - // Scope leaving must be performed in reversed order. So insertion is in two - // steps. First we prepare space for some number of elements, then we insert - // the elements beginning at the last position in prepared space. - iterator beginScopeEndInsert(iterator I, size_t Cnt, BumpVectorContext &C) { - return iterator( - Elements.insert(I.base(), Cnt, CFGScopeEnd(nullptr, nullptr), C)); - } - iterator insertScopeEnd(iterator I, VarDecl *VD, Stmt *S) { - *I = CFGScopeEnd(VD, S); - return ++I; - } }; /// CFGCallback defines methods that should be called when a logical diff --git a/contrib/llvm-project/clang/include/clang/Analysis/CallGraph.h b/contrib/llvm-project/clang/include/clang/Analysis/CallGraph.h index 999ac5da8ac..78f8d115550 100644 --- a/contrib/llvm-project/clang/include/clang/Analysis/CallGraph.h +++ b/contrib/llvm-project/clang/include/clang/Analysis/CallGraph.h @@ -66,7 +66,7 @@ public: /// Determine if a declaration should be included in the graph. static bool includeInGraph(const Decl *D); - /// Determine if a declaration should be included in the graph for the + /// Determine if a declaration should be included in the graph for the /// purposes of being a callee. This is similar to includeInGraph except /// it permits declarations, not just definitions. static bool includeCalleeInGraph(const Decl *D); diff --git a/contrib/llvm-project/clang/include/clang/Analysis/FlowSensitive/Arena.h b/contrib/llvm-project/clang/include/clang/Analysis/FlowSensitive/Arena.h new file mode 100644 index 00000000000..373697dc737 --- /dev/null +++ b/contrib/llvm-project/clang/include/clang/Analysis/FlowSensitive/Arena.h @@ -0,0 +1,147 @@ +//===-- Arena.h -------------------------------*- C++ -------------------*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +#ifndef LLVM_CLANG_ANALYSIS_FLOWSENSITIVE__ARENA_H +#define LLVM_CLANG_ANALYSIS_FLOWSENSITIVE__ARENA_H + +#include "clang/Analysis/FlowSensitive/Formula.h" +#include "clang/Analysis/FlowSensitive/StorageLocation.h" +#include "clang/Analysis/FlowSensitive/Value.h" +#include + +namespace clang::dataflow { + +/// The Arena owns the objects that model data within an analysis. +/// For example, `Value`, `StorageLocation`, `Atom`, and `Formula`. +class Arena { +public: + Arena() : True(makeAtom()), False(makeAtom()) {} + Arena(const Arena &) = delete; + Arena &operator=(const Arena &) = delete; + + /// Creates a `T` (some subclass of `StorageLocation`), forwarding `args` to + /// the constructor, and returns a reference to it. + /// + /// The `DataflowAnalysisContext` takes ownership of the created object. The + /// object will be destroyed when the `DataflowAnalysisContext` is destroyed. + template + std::enable_if_t::value, T &> + create(Args &&...args) { + // Note: If allocation of individual `StorageLocation`s turns out to be + // costly, consider creating specializations of `create` for commonly + // used `StorageLocation` subclasses and make them use a `BumpPtrAllocator`. + return *cast( + Locs.emplace_back(std::make_unique(std::forward(args)...)) + .get()); + } + + /// Creates a `T` (some subclass of `Value`), forwarding `args` to the + /// constructor, and returns a reference to it. + /// + /// The `DataflowAnalysisContext` takes ownership of the created object. The + /// object will be destroyed when the `DataflowAnalysisContext` is destroyed. + template + std::enable_if_t::value, T &> + create(Args &&...args) { + // Note: If allocation of individual `Value`s turns out to be costly, + // consider creating specializations of `create` for commonly used + // `Value` subclasses and make them use a `BumpPtrAllocator`. + return *cast( + Vals.emplace_back(std::make_unique(std::forward(args)...)) + .get()); + } + + /// Creates a BoolValue wrapping a particular formula. + /// + /// Passing in the same formula will result in the same BoolValue. + /// FIXME: Interning BoolValues but not other Values is inconsistent. + /// Decide whether we want Value interning or not. + BoolValue &makeBoolValue(const Formula &); + + /// Creates a fresh atom and wraps in in an AtomicBoolValue. + /// FIXME: For now, identical-address AtomicBoolValue <=> identical atom. + /// Stop relying on pointer identity and remove this guarantee. + AtomicBoolValue &makeAtomValue() { + return cast(makeBoolValue(makeAtomRef(makeAtom()))); + } + + /// Creates a fresh Top boolean value. + TopBoolValue &makeTopValue() { + // No need for deduplicating: there's no way to create aliasing Tops. + return create(makeAtomRef(makeAtom())); + } + + /// Returns a symbolic integer value that models an integer literal equal to + /// `Value`. These literals are the same every time. + /// Integer literals are not typed; the type is determined by the `Expr` that + /// an integer literal is associated with. + IntegerValue &makeIntLiteral(llvm::APInt Value); + + // Factories for boolean formulas. + // Formulas are interned: passing the same arguments return the same result. + // For commutative operations like And/Or, interning ignores order. + // Simplifications are applied: makeOr(X, X) => X, etc. + + /// Returns a formula for the conjunction of `LHS` and `RHS`. + const Formula &makeAnd(const Formula &LHS, const Formula &RHS); + + /// Returns a formula for the disjunction of `LHS` and `RHS`. + const Formula &makeOr(const Formula &LHS, const Formula &RHS); + + /// Returns a formula for the negation of `Val`. + const Formula &makeNot(const Formula &Val); + + /// Returns a formula for `LHS => RHS`. + const Formula &makeImplies(const Formula &LHS, const Formula &RHS); + + /// Returns a formula for `LHS <=> RHS`. + const Formula &makeEquals(const Formula &LHS, const Formula &RHS); + + /// Returns a formula for the variable A. + const Formula &makeAtomRef(Atom A); + + /// Returns a formula for a literal true/false. + const Formula &makeLiteral(bool Value) { + return makeAtomRef(Value ? True : False); + } + + /// Returns a new atomic boolean variable, distinct from any other. + Atom makeAtom() { return static_cast(NextAtom++); }; + + /// Creates a fresh flow condition and returns a token that identifies it. The + /// token can be used to perform various operations on the flow condition such + /// as adding constraints to it, forking it, joining it with another flow + /// condition, or checking implications. + Atom makeFlowConditionToken() { return makeAtom(); } + +private: + llvm::BumpPtrAllocator Alloc; + + // Storage for the state of a program. + std::vector> Locs; + std::vector> Vals; + + // Indices that are used to avoid recreating the same integer literals and + // composite boolean values. + llvm::DenseMap IntegerLiterals; + using FormulaPair = std::pair; + llvm::DenseMap Ands; + llvm::DenseMap Ors; + llvm::DenseMap Nots; + llvm::DenseMap Implies; + llvm::DenseMap Equals; + llvm::DenseMap AtomRefs; + + llvm::DenseMap FormulaValues; + unsigned NextAtom = 0; + + Atom True, False; +}; + +} // namespace clang::dataflow + +#endif // LLVM_CLANG_ANALYSIS_FLOWSENSITIVE__ARENA_H diff --git a/contrib/llvm-project/clang/include/clang/Analysis/FlowSensitive/ControlFlowContext.h b/contrib/llvm-project/clang/include/clang/Analysis/FlowSensitive/ControlFlowContext.h index e641468f77d..bb36ed237c1 100644 --- a/contrib/llvm-project/clang/include/clang/Analysis/FlowSensitive/ControlFlowContext.h +++ b/contrib/llvm-project/clang/include/clang/Analysis/FlowSensitive/ControlFlowContext.h @@ -18,6 +18,7 @@ #include "clang/AST/Decl.h" #include "clang/AST/Stmt.h" #include "clang/Analysis/CFG.h" +#include "llvm/ADT/BitVector.h" #include "llvm/ADT/DenseMap.h" #include "llvm/Support/Error.h" #include @@ -30,8 +31,18 @@ namespace dataflow { /// analysis. class ControlFlowContext { public: + /// Builds a ControlFlowContext from a `FunctionDecl`. + /// `Func.hasBody()` must be true, and `Func.isTemplated()` must be false. + static llvm::Expected build(const FunctionDecl &Func); + /// Builds a ControlFlowContext from an AST node. `D` is the function in which - /// `S` resides and must not be null. + /// `S` resides. `D.isTemplated()` must be false. + static llvm::Expected build(const Decl &D, Stmt &S, + ASTContext &C); + + /// Builds a ControlFlowContext from an AST node. `D` is the function in which + /// `S` resides. `D` must not be null and `D->isTemplated()` must be false. + LLVM_DEPRECATED("Use the version that takes a const Decl & instead", "") static llvm::Expected build(const Decl *D, Stmt &S, ASTContext &C); @@ -47,18 +58,26 @@ public: return StmtToBlock; } + /// Returns whether `B` is reachable from the entry block. + bool isBlockReachable(const CFGBlock &B) const { + return BlockReachable[B.getBlockID()]; + } + private: // FIXME: Once the deprecated `build` method is removed, mark `D` as "must not // be null" and add an assertion. ControlFlowContext(const Decl *D, std::unique_ptr Cfg, - llvm::DenseMap StmtToBlock) + llvm::DenseMap StmtToBlock, + llvm::BitVector BlockReachable) : ContainingDecl(D), Cfg(std::move(Cfg)), - StmtToBlock(std::move(StmtToBlock)) {} + StmtToBlock(std::move(StmtToBlock)), + BlockReachable(std::move(BlockReachable)) {} /// The `Decl` containing the statement used to construct the CFG. const Decl *ContainingDecl; std::unique_ptr Cfg; llvm::DenseMap StmtToBlock; + llvm::BitVector BlockReachable; }; } // namespace dataflow diff --git a/contrib/llvm-project/clang/include/clang/Analysis/FlowSensitive/DataflowAnalysis.h b/contrib/llvm-project/clang/include/clang/Analysis/FlowSensitive/DataflowAnalysis.h index 517dd3c9997..33eb42897b8 100644 --- a/contrib/llvm-project/clang/include/clang/Analysis/FlowSensitive/DataflowAnalysis.h +++ b/contrib/llvm-project/clang/include/clang/Analysis/FlowSensitive/DataflowAnalysis.h @@ -41,7 +41,7 @@ namespace dataflow { /// must provide the following public members: /// * `LatticeT initialElement()` - returns a lattice element that models the /// initial state of a basic block; -/// * `void transfer(const CFGElement *, LatticeT &, Environment &)` - applies +/// * `void transfer(const CFGElement &, LatticeT &, Environment &)` - applies /// the analysis transfer function for a given CFG element and lattice /// element. /// @@ -61,6 +61,7 @@ namespace dataflow { /// argument by computing their least upper bound, modifies the object if /// necessary, and returns an effect indicating whether any changes were /// made to it; +/// FIXME: make it `static LatticeT join(const LatticeT&, const LatticeT&)` /// * `bool operator==(const LatticeT &) const` - returns true if and only if /// the object is equal to the argument. /// @@ -98,11 +99,13 @@ public: return {static_cast(this)->initialElement()}; } - LatticeJoinEffect joinTypeErased(TypeErasedLattice &E1, + TypeErasedLattice joinTypeErased(const TypeErasedLattice &E1, const TypeErasedLattice &E2) final { - Lattice &L1 = llvm::any_cast(E1.Value); + // FIXME: change the signature of join() to avoid copying here. + Lattice L1 = llvm::any_cast(E1.Value); const Lattice &L2 = llvm::any_cast(E2.Value); - return L1.join(L2); + L1.join(L2); + return {std::move(L1)}; } LatticeJoinEffect widenTypeErased(TypeErasedLattice &Current, @@ -119,7 +122,7 @@ public: return L1 == L2; } - void transferTypeErased(const CFGElement *Element, TypeErasedLattice &E, + void transferTypeErased(const CFGElement &Element, TypeErasedLattice &E, Environment &Env) final { Lattice &L = llvm::any_cast(E.Value); static_cast(this)->transfer(Element, L, Env); @@ -205,8 +208,10 @@ runDataflowAnalysis( const TypeErasedDataflowAnalysisState &State) { auto *Lattice = llvm::any_cast(&State.Lattice.Value); + // FIXME: we should not be copying the environment here! + // Ultimately the PostVisitCFG only gets a const reference anyway. PostVisitCFG(Element, DataflowAnalysisState{ - *Lattice, State.Env}); + *Lattice, State.Env.fork()}); }; } @@ -222,14 +227,15 @@ runDataflowAnalysis( llvm::transform( std::move(*TypeErasedBlockStates), std::back_inserter(BlockStates), [](auto &OptState) { - return llvm::transformOptional(std::move(OptState), [](auto &&State) { - return DataflowAnalysisState{ - llvm::any_cast( - std::move(State.Lattice.Value)), - std::move(State.Env)}; - }); + return llvm::transformOptional( + std::move(OptState), [](TypeErasedDataflowAnalysisState &&State) { + return DataflowAnalysisState{ + llvm::any_cast( + std::move(State.Lattice.Value)), + std::move(State.Env)}; + }); }); - return BlockStates; + return std::move(BlockStates); } /// Abstract base class for dataflow "models": reusable analysis components that @@ -238,7 +244,7 @@ runDataflowAnalysis( class DataflowModel : public Environment::ValueModel { public: /// Return value indicates whether the model processed the `Element`. - virtual bool transfer(const CFGElement *Element, Environment &Env) = 0; + virtual bool transfer(const CFGElement &Element, Environment &Env) = 0; }; } // namespace dataflow diff --git a/contrib/llvm-project/clang/include/clang/Analysis/FlowSensitive/DataflowAnalysisContext.h b/contrib/llvm-project/clang/include/clang/Analysis/FlowSensitive/DataflowAnalysisContext.h index 74748c8723c..e5c325b876b 100644 --- a/contrib/llvm-project/clang/include/clang/Analysis/FlowSensitive/DataflowAnalysisContext.h +++ b/contrib/llvm-project/clang/include/clang/Analysis/FlowSensitive/DataflowAnalysisContext.h @@ -18,12 +18,14 @@ #include "clang/AST/Decl.h" #include "clang/AST/Expr.h" #include "clang/AST/TypeOrdering.h" +#include "clang/Analysis/FlowSensitive/Arena.h" #include "clang/Analysis/FlowSensitive/ControlFlowContext.h" #include "clang/Analysis/FlowSensitive/Solver.h" #include "clang/Analysis/FlowSensitive/StorageLocation.h" #include "clang/Analysis/FlowSensitive/Value.h" #include "llvm/ADT/DenseMap.h" #include "llvm/ADT/DenseSet.h" +#include "llvm/ADT/SetVector.h" #include "llvm/Support/Compiler.h" #include #include @@ -34,6 +36,7 @@ namespace clang { namespace dataflow { +class Logger; /// Skip past nodes that the CFG does not emit. These nodes are invisible to /// flow-sensitive analysis, and should be ignored as they will effectively not @@ -48,8 +51,12 @@ namespace dataflow { const Expr &ignoreCFGOmittedNodes(const Expr &E); const Stmt &ignoreCFGOmittedNodes(const Stmt &S); +/// A set of `FieldDecl *`. Use `SmallSetVector` to guarantee deterministic +/// iteration order. +using FieldSet = llvm::SmallSetVector; + /// Returns the set of all fields in the type. -llvm::DenseSet getObjectFields(QualType Type); +FieldSet getObjectFields(QualType Type); struct ContextSensitiveOptions { /// The maximum depth to analyze. A value of zero is equivalent to disabling @@ -67,6 +74,11 @@ public: /// fundamentally limited: some constructs, such as recursion, are /// explicitly unsupported. std::optional ContextSensitiveOpts; + + /// If provided, analysis details will be recorded here. + /// (This is always non-null within an AnalysisContext, the framework + /// provides a fallback no-op logger). + Logger *Log = nullptr; }; /// Constructs a dataflow analysis context. @@ -76,37 +88,9 @@ public: /// `S` must not be null. DataflowAnalysisContext(std::unique_ptr S, Options Opts = Options{ - /*ContextSensitiveOpts=*/std::nullopt}) - : S(std::move(S)), TrueVal(createAtomicBoolValue()), - FalseVal(createAtomicBoolValue()), Opts(Opts) { - assert(this->S != nullptr); - } - - /// Takes ownership of `Loc` and returns a reference to it. - /// - /// Requirements: - /// - /// `Loc` must not be null. - template - std::enable_if_t::value, T &> - takeOwnership(std::unique_ptr Loc) { - assert(Loc != nullptr); - Locs.push_back(std::move(Loc)); - return *cast(Locs.back().get()); - } - - /// Takes ownership of `Val` and returns a reference to it. - /// - /// Requirements: - /// - /// `Val` must not be null. - template - std::enable_if_t::value, T &> - takeOwnership(std::unique_ptr Val) { - assert(Val != nullptr); - Vals.push_back(std::move(Val)); - return *cast(Vals.back().get()); - } + /*ContextSensitiveOpts=*/std::nullopt, + /*Logger=*/nullptr}); + ~DataflowAnalysisContext(); /// Returns a new storage location appropriate for `Type`. /// @@ -125,15 +109,14 @@ public: /// /// `D` must not be assigned a storage location. void setStorageLocation(const ValueDecl &D, StorageLocation &Loc) { - assert(DeclToLoc.find(&D) == DeclToLoc.end()); + assert(!DeclToLoc.contains(&D)); DeclToLoc[&D] = &Loc; } /// Returns the storage location assigned to `D` or null if `D` has no /// assigned storage location. StorageLocation *getStorageLocation(const ValueDecl &D) const { - auto It = DeclToLoc.find(&D); - return It == DeclToLoc.end() ? nullptr : It->second; + return DeclToLoc.lookup(&D); } /// Assigns `Loc` as the storage location of `E`. @@ -143,15 +126,14 @@ public: /// `E` must not be assigned a storage location. void setStorageLocation(const Expr &E, StorageLocation &Loc) { const Expr &CanonE = ignoreCFGOmittedNodes(E); - assert(ExprToLoc.find(&CanonE) == ExprToLoc.end()); + assert(!ExprToLoc.contains(&CanonE)); ExprToLoc[&CanonE] = &Loc; } /// Returns the storage location assigned to `E` or null if `E` has no /// assigned storage location. StorageLocation *getStorageLocation(const Expr &E) const { - auto It = ExprToLoc.find(&ignoreCFGOmittedNodes(E)); - return It == ExprToLoc.end() ? nullptr : It->second; + return ExprToLoc.lookup(&ignoreCFGOmittedNodes(E)); } /// Returns a pointer value that represents a null pointer. Calls with @@ -159,112 +141,33 @@ public: /// A null `PointeeType` can be used for the pointee of `std::nullptr_t`. PointerValue &getOrCreateNullPointerValue(QualType PointeeType); - /// Returns a symbolic boolean value that models a boolean literal equal to - /// `Value`. - AtomicBoolValue &getBoolLiteralValue(bool Value) const { - return Value ? TrueVal : FalseVal; - } - - /// Creates an atomic boolean value. - AtomicBoolValue &createAtomicBoolValue() { - return takeOwnership(std::make_unique()); - } - - /// Creates a Top value for booleans. Each instance is unique and can be - /// assigned a distinct truth value during solving. - /// - /// FIXME: `Top iff Top` is true when both Tops are identical (by pointer - /// equality), but not when they are distinct values. We should improve the - /// implementation so that `Top iff Top` has a consistent meaning, regardless - /// of the identity of `Top`. Moreover, I think the meaning should be - /// `false`. - TopBoolValue &createTopBoolValue() { - return takeOwnership(std::make_unique()); - } - - /// Returns a boolean value that represents the conjunction of `LHS` and - /// `RHS`. Subsequent calls with the same arguments, regardless of their - /// order, will return the same result. If the given boolean values represent - /// the same value, the result will be the value itself. - BoolValue &getOrCreateConjunction(BoolValue &LHS, BoolValue &RHS); - - /// Returns a boolean value that represents the disjunction of `LHS` and - /// `RHS`. Subsequent calls with the same arguments, regardless of their - /// order, will return the same result. If the given boolean values represent - /// the same value, the result will be the value itself. - BoolValue &getOrCreateDisjunction(BoolValue &LHS, BoolValue &RHS); - - /// Returns a boolean value that represents the negation of `Val`. Subsequent - /// calls with the same argument will return the same result. - BoolValue &getOrCreateNegation(BoolValue &Val); - - /// Returns a boolean value that represents `LHS => RHS`. Subsequent calls - /// with the same arguments, will return the same result. If the given boolean - /// values represent the same value, the result will be a value that - /// represents the true boolean literal. - BoolValue &getOrCreateImplication(BoolValue &LHS, BoolValue &RHS); - - /// Returns a boolean value that represents `LHS <=> RHS`. Subsequent calls - /// with the same arguments, regardless of their order, will return the same - /// result. If the given boolean values represent the same value, the result - /// will be a value that represents the true boolean literal. - BoolValue &getOrCreateIff(BoolValue &LHS, BoolValue &RHS); - - /// Creates a fresh flow condition and returns a token that identifies it. The - /// token can be used to perform various operations on the flow condition such - /// as adding constraints to it, forking it, joining it with another flow - /// condition, or checking implications. - AtomicBoolValue &makeFlowConditionToken(); - /// Adds `Constraint` to the flow condition identified by `Token`. - void addFlowConditionConstraint(AtomicBoolValue &Token, - BoolValue &Constraint); + void addFlowConditionConstraint(Atom Token, const Formula &Constraint); /// Creates a new flow condition with the same constraints as the flow /// condition identified by `Token` and returns its token. - AtomicBoolValue &forkFlowCondition(AtomicBoolValue &Token); + Atom forkFlowCondition(Atom Token); /// Creates a new flow condition that represents the disjunction of the flow /// conditions identified by `FirstToken` and `SecondToken`, and returns its /// token. - AtomicBoolValue &joinFlowConditions(AtomicBoolValue &FirstToken, - AtomicBoolValue &SecondToken); - - // FIXME: This function returns the flow condition expressed directly as its - // constraints: (C1 AND C2 AND ...). This differs from the general approach in - // the framework where a flow condition is represented as a token (an atomic - // boolean) with dependencies and constraints tracked in `FlowConditionDeps` - // and `FlowConditionConstraints`: (FC <=> C1 AND C2 AND ...). - // Consider if we should make the representation of flow condition consistent, - // returning an atomic boolean token with separate constraints instead. - // - /// Builds and returns the logical formula defining the flow condition - /// identified by `Token`. If a value in the formula is present as a key in - /// `Substitutions`, it will be substituted with the value it maps to. - /// As an example, say we have flow condition tokens FC1, FC2, FC3 and - /// FlowConditionConstraints: { FC1: C1, - /// FC2: C2, - /// FC3: (FC1 v FC2) ^ C3 } - /// buildAndSubstituteFlowCondition(FC3, {{C1 -> C1'}}) will return a value - /// corresponding to (C1' v C2) ^ C3. - BoolValue &buildAndSubstituteFlowCondition( - AtomicBoolValue &Token, - llvm::DenseMap Substitutions); + Atom joinFlowConditions(Atom FirstToken, Atom SecondToken); /// Returns true if and only if the constraints of the flow condition /// identified by `Token` imply that `Val` is true. - bool flowConditionImplies(AtomicBoolValue &Token, BoolValue &Val); + bool flowConditionImplies(Atom Token, const Formula &); /// Returns true if and only if the constraints of the flow condition /// identified by `Token` are always true. - bool flowConditionIsTautology(AtomicBoolValue &Token); + bool flowConditionIsTautology(Atom Token); /// Returns true if `Val1` is equivalent to `Val2`. /// Note: This function doesn't take into account constraints on `Val1` and /// `Val2` imposed by the flow condition. - bool equivalentBoolValues(BoolValue &Val1, BoolValue &Val2); + bool equivalentFormulas(const Formula &Val1, const Formula &Val2); - LLVM_DUMP_METHOD void dumpFlowCondition(AtomicBoolValue &Token); + LLVM_DUMP_METHOD void dumpFlowCondition(Atom Token, + llvm::raw_ostream &OS = llvm::dbgs()); /// Returns the `ControlFlowContext` registered for `F`, if any. Otherwise, /// returns null. @@ -272,6 +175,20 @@ public: const Options &getOptions() { return Opts; } + Arena &arena() { return *A; } + + /// Returns the outcome of satisfiability checking on `Constraints`. + /// + /// Flow conditions are not incorporated, so they may need to be manually + /// included in `Constraints` to provide contextually-accurate results, e.g. + /// if any definitions or relationships of the values in `Constraints` have + /// been stored in flow conditions. + Solver::Result querySolver(llvm::SetVector Constraints); + + /// Returns the fields of `Type`, limited to the set of fields modeled by this + /// context. + FieldSet getModeledFields(QualType Type); + private: friend class Environment; @@ -287,56 +204,25 @@ private: }; // Extends the set of modeled field declarations. - void addModeledFields(const llvm::DenseSet &Fields); - - /// Returns the fields of `Type`, limited to the set of fields modeled by this - /// context. - llvm::DenseSet getReferencedFields(QualType Type); + void addModeledFields(const FieldSet &Fields); /// Adds all constraints of the flow condition identified by `Token` and all /// of its transitive dependencies to `Constraints`. `VisitedTokens` is used /// to track tokens of flow conditions that were already visited by recursive /// calls. void addTransitiveFlowConditionConstraints( - AtomicBoolValue &Token, llvm::DenseSet &Constraints, - llvm::DenseSet &VisitedTokens); - - /// Returns the outcome of satisfiability checking on `Constraints`. - /// Possible outcomes are: - /// - `Satisfiable`: A satisfying assignment exists and is returned. - /// - `Unsatisfiable`: A satisfying assignment does not exist. - /// - `TimedOut`: The search for a satisfying assignment was not completed. - Solver::Result querySolver(llvm::DenseSet Constraints); + Atom Token, llvm::SetVector &Constraints, + llvm::DenseSet &VisitedTokens); /// Returns true if the solver is able to prove that there is no satisfying /// assignment for `Constraints` - bool isUnsatisfiable(llvm::DenseSet Constraints) { + bool isUnsatisfiable(llvm::SetVector Constraints) { return querySolver(std::move(Constraints)).getStatus() == Solver::Result::Status::Unsatisfiable; } - /// Returns a boolean value as a result of substituting `Val` and its sub - /// values based on entries in `SubstitutionsCache`. Intermediate results are - /// stored in `SubstitutionsCache` to avoid reprocessing values that have - /// already been visited. - BoolValue &substituteBoolValue( - BoolValue &Val, - llvm::DenseMap &SubstitutionsCache); - - /// Builds and returns the logical formula defining the flow condition - /// identified by `Token`, sub values may be substituted based on entries in - /// `SubstitutionsCache`. Intermediate results are stored in - /// `SubstitutionsCache` to avoid reprocessing values that have already been - /// visited. - BoolValue &buildAndSubstituteFlowConditionWithCache( - AtomicBoolValue &Token, - llvm::DenseMap &SubstitutionsCache); - std::unique_ptr S; - - // Storage for the state of a program. - std::vector> Locs; - std::vector> Vals; + std::unique_ptr A; // Maps from program declarations and statements to storage locations that are // assigned to them. These assignments are global (aggregated across all basic @@ -355,23 +241,8 @@ private: llvm::DenseMap NullPointerVals; - AtomicBoolValue &TrueVal; - AtomicBoolValue &FalseVal; - Options Opts; - // Indices that are used to avoid recreating the same composite boolean - // values. - llvm::DenseMap, ConjunctionValue *> - ConjunctionVals; - llvm::DenseMap, DisjunctionValue *> - DisjunctionVals; - llvm::DenseMap NegationVals; - llvm::DenseMap, ImplicationValue *> - ImplicationVals; - llvm::DenseMap, BiconditionalValue *> - BiconditionalVals; - // Flow conditions are tracked symbolically: each unique flow condition is // associated with a fresh symbolic variable (token), bound to the clause that // defines the flow condition. Conceptually, each binding corresponds to an @@ -384,14 +255,15 @@ private: // Flow conditions depend on other flow conditions if they are created using // `forkFlowCondition` or `joinFlowConditions`. The graph of flow condition // dependencies is stored in the `FlowConditionDeps` map. - llvm::DenseMap> - FlowConditionDeps; - llvm::DenseMap FlowConditionConstraints; + llvm::DenseMap> FlowConditionDeps; + llvm::DenseMap FlowConditionConstraints; llvm::DenseMap FunctionContexts; // Fields modeled by environments covered by this context. - llvm::DenseSet ModeledFields; + FieldSet ModeledFields; + + std::unique_ptr LogOwner; // If created via flags. }; } // namespace dataflow diff --git a/contrib/llvm-project/clang/include/clang/Analysis/FlowSensitive/DataflowEnvironment.h b/contrib/llvm-project/clang/include/clang/Analysis/FlowSensitive/DataflowEnvironment.h index e457430a5e6..5cf52ad3d72 100644 --- a/contrib/llvm-project/clang/include/clang/Analysis/FlowSensitive/DataflowEnvironment.h +++ b/contrib/llvm-project/clang/include/clang/Analysis/FlowSensitive/DataflowEnvironment.h @@ -22,10 +22,14 @@ #include "clang/Analysis/FlowSensitive/ControlFlowContext.h" #include "clang/Analysis/FlowSensitive/DataflowAnalysisContext.h" #include "clang/Analysis/FlowSensitive/DataflowLattice.h" +#include "clang/Analysis/FlowSensitive/Formula.h" +#include "clang/Analysis/FlowSensitive/Logger.h" #include "clang/Analysis/FlowSensitive/StorageLocation.h" #include "clang/Analysis/FlowSensitive/Value.h" #include "llvm/ADT/DenseMap.h" #include "llvm/ADT/DenseSet.h" +#include "llvm/ADT/MapVector.h" +#include "llvm/Support/Compiler.h" #include "llvm/Support/ErrorHandling.h" #include #include @@ -44,9 +48,6 @@ enum class SkipPast { None, /// An optional reference should be skipped past. Reference, - /// An optional reference should be skipped past, then an optional pointer - /// should be skipped past. - ReferenceThenPointer, }; /// Indicates the result of a tentative comparison. @@ -161,8 +162,8 @@ public: /// the state of a program. explicit Environment(DataflowAnalysisContext &DACtx); - Environment(const Environment &Other); - Environment &operator=(const Environment &Other); + // Copy-constructor is private, Environments should not be copied. See fork(). + Environment &operator=(const Environment &Other) = delete; Environment(Environment &&Other) = default; Environment &operator=(Environment &&Other) = default; @@ -177,9 +178,15 @@ public: /// with a symbolic representation of the `this` pointee. Environment(DataflowAnalysisContext &DACtx, const DeclContext &DeclCtx); - const DataflowAnalysisContext::Options &getAnalysisOptions() { - return DACtx->getOptions(); - } + /// Returns a new environment that is a copy of this one. + /// + /// The state of the program is initially the same, but can be mutated without + /// affecting the original. + /// + /// However the original should not be further mutated, as this may interfere + /// with the fork. (In practice, values are stored independently, but the + /// forked flow condition references the original). + Environment fork() const; /// Creates and returns an environment to use for an inline analysis of the /// callee. Uses the storage location from each argument in the `Call` as the @@ -197,7 +204,8 @@ public: /// Moves gathered information back into `this` from a `CalleeEnv` created via /// `pushCall`. - void popCall(const Environment &CalleeEnv); + void popCall(const CallExpr *Call, const Environment &CalleeEnv); + void popCall(const CXXConstructExpr *Call, const Environment &CalleeEnv); /// Returns true if and only if the environment is equivalent to `Other`, i.e /// the two environments: @@ -212,17 +220,15 @@ public: bool equivalentTo(const Environment &Other, Environment::ValueModel &Model) const; - /// Joins the environment with `Other` by taking the intersection of storage - /// locations and values that are stored in them. Distinct values that are - /// assigned to the same storage locations in the environment and `Other` are - /// merged using `Model`. + /// Joins two environments by taking the intersection of storage locations and + /// values that are stored in them. Distinct values that are assigned to the + /// same storage locations in `EnvA` and `EnvB` are merged using `Model`. /// /// Requirements: /// - /// `Other` and `this` must use the same `DataflowAnalysisContext`. - LatticeJoinEffect join(const Environment &Other, - Environment::ValueModel &Model); - + /// `EnvA` and `EnvB` must use the same `DataflowAnalysisContext`. + static Environment join(const Environment &EnvA, const Environment &EnvB, + Environment::ValueModel &Model); /// Widens the environment point-wise, using `PrevEnv` as needed to inform the /// approximation. @@ -259,101 +265,290 @@ public: /// /// Requirements: /// - /// `D` must not be assigned a storage location in the environment. + /// `D` must not already have a storage location in the environment. + /// + /// If `D` has reference type, `Loc` must refer directly to the referenced + /// object (if any), not to a `ReferenceValue`, and it is not permitted to + /// later change `Loc` to refer to a `ReferenceValue.` void setStorageLocation(const ValueDecl &D, StorageLocation &Loc); - /// Returns the storage location assigned to `D` in the environment, applying - /// the `SP` policy for skipping past indirections, or null if `D` isn't - /// assigned a storage location in the environment. - StorageLocation *getStorageLocation(const ValueDecl &D, SkipPast SP) const; + /// Returns the storage location assigned to `D` in the environment, or null + /// if `D` isn't assigned a storage location in the environment. + /// + /// Note that if `D` has reference type, the storage location that is returned + /// refers directly to the referenced object, not a `ReferenceValue`. + StorageLocation *getStorageLocation(const ValueDecl &D) const; /// Assigns `Loc` as the storage location of `E` in the environment. /// + /// This function is deprecated; prefer `setStorageLocationStrict()`. + /// For details, see https://discourse.llvm.org/t/70086. + /// /// Requirements: /// /// `E` must not be assigned a storage location in the environment. void setStorageLocation(const Expr &E, StorageLocation &Loc); + /// Assigns `Loc` as the storage location of the glvalue `E` in the + /// environment. + /// + /// This function is the preferred alternative to + /// `setStorageLocation(const Expr &, StorageLocation &)`. Once the migration + /// to strict handling of value categories is complete (see + /// https://discourse.llvm.org/t/70086), `setStorageLocation()` will be + /// removed and this function will be renamed to `setStorageLocation()`. + /// + /// Requirements: + /// + /// `E` must not be assigned a storage location in the environment. + /// `E` must be a glvalue or a `BuiltinType::BuiltinFn` + void setStorageLocationStrict(const Expr &E, StorageLocation &Loc); + /// Returns the storage location assigned to `E` in the environment, applying /// the `SP` policy for skipping past indirections, or null if `E` isn't /// assigned a storage location in the environment. + /// + /// This function is deprecated; prefer `getStorageLocationStrict()`. + /// For details, see https://discourse.llvm.org/t/70086. StorageLocation *getStorageLocation(const Expr &E, SkipPast SP) const; + /// Returns the storage location assigned to the glvalue `E` in the + /// environment, or null if `E` isn't assigned a storage location in the + /// environment. + /// + /// If the storage location for `E` is associated with a + /// `ReferenceValue RefVal`, returns `RefVal.getReferentLoc()` instead. + /// + /// This function is the preferred alternative to + /// `getStorageLocation(const Expr &, SkipPast)`. Once the migration + /// to strict handling of value categories is complete (see + /// https://discourse.llvm.org/t/70086), `getStorageLocation()` will be + /// removed and this function will be renamed to `getStorageLocation()`. + /// + /// Requirements: + /// `E` must be a glvalue or a `BuiltinType::BuiltinFn` + StorageLocation *getStorageLocationStrict(const Expr &E) const; + /// Returns the storage location assigned to the `this` pointee in the /// environment or null if the `this` pointee has no assigned storage location /// in the environment. - StorageLocation *getThisPointeeStorageLocation() const; + AggregateStorageLocation *getThisPointeeStorageLocation() const; - /// Returns the storage location of the return value or null, if unset. - StorageLocation *getReturnStorageLocation() const; + /// Returns the location of the result object for a record-type prvalue. + /// + /// In C++, prvalues of record type serve only a limited purpose: They can + /// only be used to initialize a result object (e.g. a variable or a + /// temporary). This function returns the location of that result object. + /// + /// When creating a prvalue of record type, we already need the storage + /// location of the result object to pass in `this`, even though prvalues are + /// otherwise not associated with storage locations. + /// + /// FIXME: Currently, this simply returns a stable storage location for `E`, + /// but this doesn't do the right thing in scenarios like the following: + /// ``` + /// MyClass c = some_condition()? MyClass(foo) : MyClass(bar); + /// ``` + /// Here, `MyClass(foo)` and `MyClass(bar)` will have two different storage + /// locations, when in fact their storage locations should be the same. + /// Eventually, we want to propagate storage locations from result objects + /// down to the prvalues that initialize them, similar to the way that this is + /// done in Clang's CodeGen. + /// + /// Requirements: + /// `E` must be a prvalue of record type. + AggregateStorageLocation &getResultObjectLocation(const Expr &RecordPRValue); + + /// Returns the return value of the current function. This can be null if: + /// - The function has a void return type + /// - No return value could be determined for the function, for example + /// because it calls a function without a body. + /// + /// Requirements: + /// The current function must have a non-reference return type. + Value *getReturnValue() const { + assert(getCurrentFunc() != nullptr && + !getCurrentFunc()->getReturnType()->isReferenceType()); + return ReturnVal; + } + + /// Returns the storage location for the reference returned by the current + /// function. This can be null if function doesn't return a single consistent + /// reference. + /// + /// Requirements: + /// The current function must have a reference return type. + StorageLocation *getReturnStorageLocation() const { + assert(getCurrentFunc() != nullptr && + getCurrentFunc()->getReturnType()->isReferenceType()); + return ReturnLoc; + } + + /// Sets the return value of the current function. + /// + /// Requirements: + /// The current function must have a non-reference return type. + void setReturnValue(Value *Val) { + assert(getCurrentFunc() != nullptr && + !getCurrentFunc()->getReturnType()->isReferenceType()); + ReturnVal = Val; + } + + /// Sets the storage location for the reference returned by the current + /// function. + /// + /// Requirements: + /// The current function must have a reference return type. + void setReturnStorageLocation(StorageLocation *Loc) { + assert(getCurrentFunc() != nullptr && + getCurrentFunc()->getReturnType()->isReferenceType()); + ReturnLoc = Loc; + } /// Returns a pointer value that represents a null pointer. Calls with /// `PointeeType` that are canonically equivalent will return the same result. PointerValue &getOrCreateNullPointerValue(QualType PointeeType); /// Creates a value appropriate for `Type`, if `Type` is supported, otherwise - /// return null. If `Type` is a pointer or reference type, creates all the - /// necessary storage locations and values for indirections until it finds a + /// returns null. + /// + /// If `Type` is a pointer or reference type, creates all the necessary + /// storage locations and values for indirections until it finds a /// non-pointer/non-reference type. /// + /// If `Type` is a class, struct, or union type, calls `setValue()` to + /// associate the `StructValue` with its storage location + /// (`StructValue::getAggregateLoc()`). + /// + /// If `Type` is one of the following types, this function will always return + /// a non-null pointer: + /// - `bool` + /// - Any integer type + /// - Any class, struct, or union type + /// /// Requirements: /// /// `Type` must not be null. Value *createValue(QualType Type); + /// Creates an object (i.e. a storage location with an associated value) of + /// type `Ty`. If `InitExpr` is non-null and has a value associated with it, + /// initializes the object with this value. Otherwise, initializes the object + /// with a value created using `createValue()`. + StorageLocation &createObject(QualType Ty, const Expr *InitExpr = nullptr) { + return createObjectInternal(nullptr, Ty, InitExpr); + } + + /// Creates an object for the variable declaration `D`. If `D` has an + /// initializer and this initializer is associated with a value, initializes + /// the object with this value. Otherwise, initializes the object with a + /// value created using `createValue()`. Uses the storage location returned by + /// `DataflowAnalysisContext::getStableStorageLocation(D)`. + StorageLocation &createObject(const VarDecl &D) { + return createObjectInternal(&D, D.getType(), D.getInit()); + } + + /// Creates an object for the variable declaration `D`. If `InitExpr` is + /// non-null and has a value associated with it, initializes the object with + /// this value. Otherwise, initializes the object with a value created using + /// `createValue()`. Uses the storage location returned by + /// `DataflowAnalysisContext::getStableStorageLocation(D)`. + StorageLocation &createObject(const VarDecl &D, const Expr *InitExpr) { + return createObjectInternal(&D, D.getType(), InitExpr); + } + /// Assigns `Val` as the value of `Loc` in the environment. void setValue(const StorageLocation &Loc, Value &Val); + /// Clears any association between `Loc` and a value in the environment. + void clearValue(const StorageLocation &Loc) { LocToVal.erase(&Loc); } + + /// Assigns `Val` as the value of the prvalue `E` in the environment. + /// + /// If `E` is not yet associated with a storage location, associates it with + /// a newly created storage location. In any case, associates the storage + /// location of `E` with `Val`. + /// + /// Once the migration to strict handling of value categories is complete + /// (see https://discourse.llvm.org/t/70086), this function will be renamed to + /// `setValue()`. At this point, prvalue expressions will be associated + /// directly with `Value`s, and the legacy behavior of associating prvalue + /// expressions with storage locations (as described above) will be + /// eliminated. + /// + /// Requirements: + /// + /// `E` must be a prvalue + /// `Val` must not be a `ReferenceValue` + /// If `Val` is a `StructValue`, its `AggregateStorageLocation` must be the + /// same as that of any `StructValue` that has already been associated with + /// `E`. This is to guarantee that the result object initialized by a prvalue + /// `StructValue` has a durable storage location. + void setValueStrict(const Expr &E, Value &Val); + /// Returns the value assigned to `Loc` in the environment or null if `Loc` /// isn't assigned a value in the environment. Value *getValue(const StorageLocation &Loc) const; /// Equivalent to `getValue(getStorageLocation(D, SP), SkipPast::None)` if `D` /// is assigned a storage location in the environment, otherwise returns null. - Value *getValue(const ValueDecl &D, SkipPast SP) const; + Value *getValue(const ValueDecl &D) const; /// Equivalent to `getValue(getStorageLocation(E, SP), SkipPast::None)` if `E` /// is assigned a storage location in the environment, otherwise returns null. + /// + /// This function is deprecated; prefer `getValueStrict()`. For details, see + /// https://discourse.llvm.org/t/70086. Value *getValue(const Expr &E, SkipPast SP) const; - /// Transfers ownership of `Loc` to the analysis context and returns a - /// reference to it. + /// Returns the `Value` assigned to the prvalue `E` in the environment, or + /// null if `E` isn't assigned a value in the environment. + /// + /// This function is the preferred alternative to + /// `getValue(const Expr &, SkipPast)`. Once the migration to strict handling + /// of value categories is complete (see https://discourse.llvm.org/t/70086), + /// `getValue()` will be removed and this function will be renamed to + /// `getValue()`. /// /// Requirements: /// - /// `Loc` must not be null. - template - std::enable_if_t::value, T &> - takeOwnership(std::unique_ptr Loc) { - return DACtx->takeOwnership(std::move(Loc)); + /// `E` must be a prvalue + Value *getValueStrict(const Expr &E) const; + + // FIXME: should we deprecate the following & call arena().create() directly? + + /// Creates a `T` (some subclass of `Value`), forwarding `args` to the + /// constructor, and returns a reference to it. + /// + /// The analysis context takes ownership of the created object. The object + /// will be destroyed when the analysis context is destroyed. + template + std::enable_if_t::value, T &> + create(Args &&...args) { + return arena().create(std::forward(args)...); } - /// Transfers ownership of `Val` to the analysis context and returns a - /// reference to it. - /// - /// Requirements: - /// - /// `Val` must not be null. - template - std::enable_if_t::value, T &> - takeOwnership(std::unique_ptr Val) { - return DACtx->takeOwnership(std::move(Val)); + /// Returns a symbolic integer value that models an integer literal equal to + /// `Value` + IntegerValue &getIntLiteralValue(llvm::APInt Value) const { + return arena().makeIntLiteral(Value); } /// Returns a symbolic boolean value that models a boolean literal equal to /// `Value` AtomicBoolValue &getBoolLiteralValue(bool Value) const { - return DACtx->getBoolLiteralValue(Value); + return cast( + arena().makeBoolValue(arena().makeLiteral(Value))); } /// Returns an atomic boolean value. BoolValue &makeAtomicBoolValue() const { - return DACtx->createAtomicBoolValue(); + return arena().makeAtomValue(); } /// Returns a unique instance of boolean Top. BoolValue &makeTopBoolValue() const { - return DACtx->createTopBoolValue(); + return arena().makeTopValue(); } /// Returns a boolean value that represents the conjunction of `LHS` and @@ -361,7 +556,8 @@ public: /// order, will return the same result. If the given boolean values represent /// the same value, the result will be the value itself. BoolValue &makeAnd(BoolValue &LHS, BoolValue &RHS) const { - return DACtx->getOrCreateConjunction(LHS, RHS); + return arena().makeBoolValue( + arena().makeAnd(LHS.formula(), RHS.formula())); } /// Returns a boolean value that represents the disjunction of `LHS` and @@ -369,13 +565,14 @@ public: /// order, will return the same result. If the given boolean values represent /// the same value, the result will be the value itself. BoolValue &makeOr(BoolValue &LHS, BoolValue &RHS) const { - return DACtx->getOrCreateDisjunction(LHS, RHS); + return arena().makeBoolValue( + arena().makeOr(LHS.formula(), RHS.formula())); } /// Returns a boolean value that represents the negation of `Val`. Subsequent /// calls with the same argument will return the same result. BoolValue &makeNot(BoolValue &Val) const { - return DACtx->getOrCreateNegation(Val); + return arena().makeBoolValue(arena().makeNot(Val.formula())); } /// Returns a boolean value represents `LHS` => `RHS`. Subsequent calls with @@ -383,7 +580,8 @@ public: /// values represent the same value, the result will be a value that /// represents the true boolean literal. BoolValue &makeImplication(BoolValue &LHS, BoolValue &RHS) const { - return DACtx->getOrCreateImplication(LHS, RHS); + return arena().makeBoolValue( + arena().makeImplies(LHS.formula(), RHS.formula())); } /// Returns a boolean value represents `LHS` <=> `RHS`. Subsequent calls with @@ -391,48 +589,61 @@ public: /// result. If the given boolean values represent the same value, the result /// will be a value that represents the true boolean literal. BoolValue &makeIff(BoolValue &LHS, BoolValue &RHS) const { - return DACtx->getOrCreateIff(LHS, RHS); + return arena().makeBoolValue( + arena().makeEquals(LHS.formula(), RHS.formula())); } - /// Returns the token that identifies the flow condition of the environment. - AtomicBoolValue &getFlowConditionToken() const { return *FlowConditionToken; } + /// Returns a boolean variable that identifies the flow condition (FC). + /// + /// The flow condition is a set of facts that are necessarily true when the + /// program reaches the current point, expressed as boolean formulas. + /// The flow condition token is equivalent to the AND of these facts. + /// + /// These may e.g. constrain the value of certain variables. A pointer + /// variable may have a consistent modeled PointerValue throughout, but at a + /// given point the Environment may tell us that the value must be non-null. + /// + /// The FC is necessary but not sufficient for this point to be reachable. + /// In particular, where the FC token appears in flow conditions of successor + /// environments, it means "point X may have been reached", not + /// "point X was reached". + Atom getFlowConditionToken() const { return FlowConditionToken; } - /// Builds and returns the logical formula defining the flow condition - /// identified by `Token`. If a value in the formula is present as a key in - /// `Substitutions`, it will be substituted with the value it maps to. - BoolValue &buildAndSubstituteFlowCondition( - AtomicBoolValue &Token, - llvm::DenseMap Substitutions) { - return DACtx->buildAndSubstituteFlowCondition(Token, - std::move(Substitutions)); - } + /// Record a fact that must be true if this point in the program is reached. + void addToFlowCondition(const Formula &); - /// Adds `Val` to the set of clauses that constitute the flow condition. - void addToFlowCondition(BoolValue &Val); - - /// Returns true if and only if the clauses that constitute the flow condition - /// imply that `Val` is true. - bool flowConditionImplies(BoolValue &Val) const; + /// Returns true if the formula is always true when this point is reached. + /// Returns false if the formula may be false, or if the flow condition isn't + /// sufficiently precise to prove that it is true. + bool flowConditionImplies(const Formula &) const; /// Returns the `DeclContext` of the block being analysed, if any. Otherwise, /// returns null. const DeclContext *getDeclCtx() const { return CallStack.back(); } + /// Returns the function currently being analyzed, or null if the code being + /// analyzed isn't part of a function. + const FunctionDecl *getCurrentFunc() const { + return dyn_cast(getDeclCtx()); + } + /// Returns whether this `Environment` can be extended to analyze the given /// `Callee` (i.e. if `pushCall` can be used), with recursion disallowed and a /// given `MaxDepth`. bool canDescend(unsigned MaxDepth, const DeclContext *Callee) const; - /// Returns the `ControlFlowContext` registered for `F`, if any. Otherwise, - /// returns null. - const ControlFlowContext *getControlFlowContext(const FunctionDecl *F) { - return DACtx->getControlFlowContext(F); - } + /// Returns the `DataflowAnalysisContext` used by the environment. + DataflowAnalysisContext &getDataflowAnalysisContext() const { return *DACtx; } + + Arena &arena() const { return DACtx->arena(); } LLVM_DUMP_METHOD void dump() const; LLVM_DUMP_METHOD void dump(raw_ostream &OS) const; private: + // The copy-constructor is for use in fork() only. + Environment(const Environment &) = default; + /// Creates a value appropriate for `Type`, if `Type` is supported, otherwise /// return null. /// @@ -448,6 +659,19 @@ private: llvm::DenseSet &Visited, int Depth, int &CreatedValuesCount); + /// Creates a storage location for `Ty`. Also creates and associates a value + /// with the storage location, unless values of this type are not supported or + /// we hit one of the limits at which we stop producing values (controlled by + /// `Visited`, `Depth`, and `CreatedValuesCount`). + StorageLocation &createLocAndMaybeValue(QualType Ty, + llvm::DenseSet &Visited, + int Depth, int &CreatedValuesCount); + + /// Shared implementation of `createObject()` overloads. + /// `D` and `InitExpr` may be null. + StorageLocation &createObjectInternal(const VarDecl *D, QualType Ty, + const Expr *InitExpr); + StorageLocation &skip(StorageLocation &Loc, SkipPast SP) const; const StorageLocation &skip(const StorageLocation &Loc, SkipPast SP) const; @@ -457,26 +681,29 @@ private: void pushCallInternal(const FunctionDecl *FuncDecl, ArrayRef Args); - /// Assigns storage locations and values to all variables in `Vars`. - void initVars(llvm::DenseSet Vars); + /// Assigns storage locations and values to all global variables, fields + /// and functions referenced in `FuncDecl`. `FuncDecl` must have a body. + void initFieldsGlobalsAndFuncs(const FunctionDecl *FuncDecl); // `DACtx` is not null and not owned by this object. DataflowAnalysisContext *DACtx; - - // FIXME: move the fields `CallStack`, `ReturnLoc` and `ThisPointeeLoc` into a - // separate call-context object, shared between environments in the same call. + // FIXME: move the fields `CallStack`, `ReturnVal`, `ReturnLoc` and + // `ThisPointeeLoc` into a separate call-context object, shared between + // environments in the same call. // https://github.com/llvm/llvm-project/issues/59005 // `DeclContext` of the block being analysed if provided. std::vector CallStack; - // In a properly initialized `Environment`, `ReturnLoc` should only be null if - // its `DeclContext` could not be cast to a `FunctionDecl`. + // Value returned by the function (if it has non-reference return type). + Value *ReturnVal = nullptr; + // Storage location of the reference returned by the function (if it has + // reference return type). StorageLocation *ReturnLoc = nullptr; // The storage location of the `this` pointee. Should only be null if the // function being analyzed is only a function and not a method. - StorageLocation *ThisPointeeLoc = nullptr; + AggregateStorageLocation *ThisPointeeLoc = nullptr; // Maps from program declarations and statements to storage locations that are // assigned to them. Unlike the maps in `DataflowAnalysisContext`, these @@ -484,18 +711,48 @@ private: // block. llvm::DenseMap DeclToLoc; llvm::DenseMap ExprToLoc; + // We preserve insertion order so that join/widen process values in + // deterministic sequence. This in turn produces deterministic SAT formulas. + llvm::MapVector LocToVal; - llvm::DenseMap LocToVal; - - // Maps locations of struct members to symbolic values of the structs that own - // them and the decls of the struct members. - llvm::DenseMap> - MemberLocToStruct; - - AtomicBoolValue *FlowConditionToken; + Atom FlowConditionToken; }; +/// Returns the storage location for the implicit object of a +/// `CXXMemberCallExpr`, or null if none is defined in the environment. +/// Dereferences the pointer if the member call expression was written using +/// `->`. +AggregateStorageLocation * +getImplicitObjectLocation(const CXXMemberCallExpr &MCE, const Environment &Env); + +/// Returns the storage location for the base object of a `MemberExpr`, or null +/// if none is defined in the environment. Dereferences the pointer if the +/// member expression was written using `->`. +AggregateStorageLocation *getBaseObjectLocation(const MemberExpr &ME, + const Environment &Env); + +/// Returns the fields of `RD` that are initialized by an `InitListExpr`, in the +/// order in which they appear in `InitListExpr::inits()`. +std::vector getFieldsForInitListExpr(const RecordDecl *RD); + +/// Associates a new `StructValue` with `Loc` and returns the new value. +/// It is not defined whether the field values remain the same or not. +/// +/// This function is primarily intended for use by checks that set custom +/// properties on `StructValue`s to model the state of these values. Such checks +/// should avoid modifying the properties of an existing `StructValue` because +/// these changes would be visible to other `Environment`s that share the same +/// `StructValue`. Instead, call `refreshStructValue()`, then set the properties +/// on the new `StructValue` that it returns. Typical usage: +/// +/// refreshStructValue(Loc, Env).setProperty("my_prop", MyPropValue); +StructValue &refreshStructValue(AggregateStorageLocation &Loc, + Environment &Env); + +/// Associates a new `StructValue` with `Expr` and returns the new value. +/// See also documentation for the overload above. +StructValue &refreshStructValue(const Expr &Expr, Environment &Env); + } // namespace dataflow } // namespace clang diff --git a/contrib/llvm-project/clang/include/clang/Analysis/FlowSensitive/DebugSupport.h b/contrib/llvm-project/clang/include/clang/Analysis/FlowSensitive/DebugSupport.h index ca50ffc5f5c..6b9f3681490 100644 --- a/contrib/llvm-project/clang/include/clang/Analysis/FlowSensitive/DebugSupport.h +++ b/contrib/llvm-project/clang/include/clang/Analysis/FlowSensitive/DebugSupport.h @@ -19,7 +19,6 @@ #include "clang/Analysis/FlowSensitive/Solver.h" #include "clang/Analysis/FlowSensitive/Value.h" -#include "llvm/ADT/DenseMap.h" #include "llvm/ADT/StringRef.h" namespace clang { @@ -28,60 +27,9 @@ namespace dataflow { /// Returns a string representation of a value kind. llvm::StringRef debugString(Value::Kind Kind); -/// Returns a string representation of a boolean assignment to true or false. -llvm::StringRef debugString(Solver::Result::Assignment Assignment); - /// Returns a string representation of the result status of a SAT check. llvm::StringRef debugString(Solver::Result::Status Status); -/// Returns a string representation for the boolean value `B`. -/// -/// Atomic booleans appearing in the boolean value `B` are assigned to labels -/// either specified in `AtomNames` or created by default rules as B0, B1, ... -/// -/// Requirements: -/// -/// Names assigned to atoms should not be repeated in `AtomNames`. -std::string debugString( - const BoolValue &B, - llvm::DenseMap AtomNames = {{}}); - -/// Returns a string representation for `Constraints` - a collection of boolean -/// formulas. -/// -/// Atomic booleans appearing in the boolean value `Constraints` are assigned to -/// labels either specified in `AtomNames` or created by default rules as B0, -/// B1, ... -/// -/// Requirements: -/// -/// Names assigned to atoms should not be repeated in `AtomNames`. -std::string debugString( - const llvm::DenseSet &Constraints, - llvm::DenseMap AtomNames = {{}}); - -/// Returns a string representation for `Constraints` - a collection of boolean -/// formulas and the `Result` of satisfiability checking. -/// -/// Atomic booleans appearing in `Constraints` and `Result` are assigned to -/// labels either specified in `AtomNames` or created by default rules as B0, -/// B1, ... -/// -/// Requirements: -/// -/// Names assigned to atoms should not be repeated in `AtomNames`. -std::string debugString( - ArrayRef Constraints, const Solver::Result &Result, - llvm::DenseMap AtomNames = {{}}); -inline std::string debugString( - const llvm::DenseSet &Constraints, - const Solver::Result &Result, - llvm::DenseMap AtomNames = {{}}) { - std::vector ConstraintsVec(Constraints.begin(), - Constraints.end()); - return debugString(ConstraintsVec, Result, std::move(AtomNames)); -} - } // namespace dataflow } // namespace clang diff --git a/contrib/llvm-project/clang/include/clang/Analysis/FlowSensitive/Formula.h b/contrib/llvm-project/clang/include/clang/Analysis/FlowSensitive/Formula.h new file mode 100644 index 00000000000..64fe8f5b630 --- /dev/null +++ b/contrib/llvm-project/clang/include/clang/Analysis/FlowSensitive/Formula.h @@ -0,0 +1,138 @@ +//===- Formula.h - Boolean formulas -----------------------------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CLANG_ANALYSIS_FLOWSENSITIVE_FORMULA_H +#define LLVM_CLANG_ANALYSIS_FLOWSENSITIVE_FORMULA_H + +#include "clang/Basic/LLVM.h" +#include "llvm/ADT/ArrayRef.h" +#include "llvm/ADT/DenseMap.h" +#include "llvm/ADT/DenseMapInfo.h" +#include "llvm/ADT/STLFunctionalExtras.h" +#include "llvm/Support/Allocator.h" +#include "llvm/Support/raw_ostream.h" +#include +#include +#include + +namespace clang::dataflow { + +/// Identifies an atomic boolean variable such as "V1". +/// +/// This often represents an assertion that is interesting to the analysis but +/// cannot immediately be proven true or false. For example: +/// - V1 may mean "the program reaches this point", +/// - V2 may mean "the parameter was null" +/// +/// We can use these variables in formulas to describe relationships we know +/// to be true: "if the parameter was null, the program reaches this point". +/// We also express hypotheses as formulas, and use a SAT solver to check +/// whether they are consistent with the known facts. +enum class Atom : unsigned {}; + +/// A boolean expression such as "true" or "V1 & !V2". +/// Expressions may refer to boolean atomic variables. These should take a +/// consistent true/false value across the set of formulas being considered. +/// +/// (Formulas are always expressions in terms of boolean variables rather than +/// e.g. integers because our underlying model is SAT rather than e.g. SMT). +/// +/// Simple formulas such as "true" and "V1" are self-contained. +/// Compound formulas connect other formulas, e.g. "(V1 & V2) || V3" is an 'or' +/// formula, with pointers to its operands "(V1 & V2)" and "V3" stored as +/// trailing objects. +/// For this reason, Formulas are Arena-allocated and over-aligned. +class Formula; +class alignas(const Formula *) Formula { +public: + enum Kind : unsigned { + /// A reference to an atomic boolean variable. + /// We name these e.g. "V3", where 3 == atom identity == Value. + AtomRef, + // FIXME: add const true/false rather than modeling them as variables + + Not, /// True if its only operand is false + + // These kinds connect two operands LHS and RHS + And, /// True if LHS and RHS are both true + Or, /// True if either LHS or RHS is true + Implies, /// True if LHS is false or RHS is true + Equal, /// True if LHS and RHS have the same truth value + }; + Kind kind() const { return FormulaKind; } + + Atom getAtom() const { + assert(kind() == AtomRef); + return static_cast(Value); + } + + ArrayRef operands() const { + return ArrayRef(reinterpret_cast(this + 1), + numOperands(kind())); + } + + using AtomNames = llvm::DenseMap; + // Produce a stable human-readable representation of this formula. + // For example: (V3 | !(V1 & V2)) + // If AtomNames is provided, these override the default V0, V1... names. + void print(llvm::raw_ostream &OS, const AtomNames * = nullptr) const; + + // Allocate Formulas using Arena rather than calling this function directly. + static Formula &create(llvm::BumpPtrAllocator &Alloc, Kind K, + ArrayRef Operands, + unsigned Value = 0); + +private: + Formula() = default; + Formula(const Formula &) = delete; + Formula &operator=(const Formula &) = delete; + + static unsigned numOperands(Kind K) { + switch (K) { + case AtomRef: + return 0; + case Not: + return 1; + case And: + case Or: + case Implies: + case Equal: + return 2; + } + llvm_unreachable("Unhandled Formula::Kind enum"); + } + + Kind FormulaKind; + // Some kinds of formula have scalar values, e.g. AtomRef's atom number. + unsigned Value; +}; + +// The default names of atoms are V0, V1 etc in order of creation. +inline llvm::raw_ostream &operator<<(llvm::raw_ostream &OS, Atom A) { + return OS << 'V' << static_cast(A); +} +inline llvm::raw_ostream &operator<<(llvm::raw_ostream &OS, const Formula &F) { + F.print(OS); + return OS; +} + +} // namespace clang::dataflow +namespace llvm { +template <> struct DenseMapInfo { + using Atom = clang::dataflow::Atom; + using Underlying = std::underlying_type_t; + + static inline Atom getEmptyKey() { return Atom(Underlying(-1)); } + static inline Atom getTombstoneKey() { return Atom(Underlying(-2)); } + static unsigned getHashValue(const Atom &Val) { + return DenseMapInfo::getHashValue(Underlying(Val)); + } + static bool isEqual(const Atom &LHS, const Atom &RHS) { return LHS == RHS; } +}; +} // namespace llvm +#endif diff --git a/contrib/llvm-project/clang/include/clang/Analysis/FlowSensitive/Logger.h b/contrib/llvm-project/clang/include/clang/Analysis/FlowSensitive/Logger.h new file mode 100644 index 00000000000..6836488003a --- /dev/null +++ b/contrib/llvm-project/clang/include/clang/Analysis/FlowSensitive/Logger.h @@ -0,0 +1,89 @@ +//===-- Logger.h ------------------------------------------------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CLANG_ANALYSIS_FLOWSENSITIVE_LOGGER_H +#define LLVM_CLANG_ANALYSIS_FLOWSENSITIVE_LOGGER_H + +#include "clang/Analysis/CFG.h" +#include "llvm/Support/raw_ostream.h" +#include + +namespace clang::dataflow { +// Forward declarations so we can use Logger anywhere in the framework. +class ControlFlowContext; +class TypeErasedDataflowAnalysis; +struct TypeErasedDataflowAnalysisState; + +/// A logger is notified as the analysis progresses. +/// It can produce a report of the analysis's findings and how it came to them. +/// +/// The framework reports key structural events (e.g. traversal of blocks). +/// The specific analysis can add extra details to be presented in context. +class Logger { +public: + /// Returns a dummy logger that does nothing. + static Logger &null(); + /// A logger that simply writes messages to the specified ostream in real + /// time. + static std::unique_ptr textual(llvm::raw_ostream &); + /// A logger that builds an HTML UI to inspect the analysis results. + /// Each function's analysis is written to a stream obtained from the factory. + static std::unique_ptr + html(std::function()>); + + virtual ~Logger() = default; + + /// Called by the framework as we start analyzing a new function or statement. + /// Forms a pair with endAnalysis(). + virtual void beginAnalysis(const ControlFlowContext &, + TypeErasedDataflowAnalysis &) {} + virtual void endAnalysis() {} + + // At any time during the analysis, we're computing the state for some target + // program point. + + /// Called when we start (re-)processing a block in the CFG. + /// The target program point is the entry to the specified block. + /// Calls to log() describe transferBranch(), join() etc. + virtual void enterBlock(const CFGBlock &) {} + /// Called when we start processing an element in the current CFG block. + /// The target program point is after the specified element. + /// Calls to log() describe the transfer() function. + virtual void enterElement(const CFGElement &) {} + + /// Records the analysis state computed for the current program point. + virtual void recordState(TypeErasedDataflowAnalysisState &) {} + /// Records that the analysis state for the current block is now final. + virtual void blockConverged() {} + + /// Called by the framework or user code to report some event. + /// The event is associated with the current context (program point). + /// The Emit function produces the log message. It may or may not be called, + /// depending on if the logger is interested; it should have no side effects. + void log(llvm::function_ref Emit) { + if (!ShouldLogText) + return; + std::string S; + llvm::raw_string_ostream OS(S); + Emit(OS); + logText(S); + } + +protected: + /// ShouldLogText should be false for trivial loggers that ignore logText(). + /// This allows log() to skip evaluating its Emit function. + Logger(bool ShouldLogText = true) : ShouldLogText(ShouldLogText) {} + +private: + bool ShouldLogText; + virtual void logText(llvm::StringRef) {} +}; + +} // namespace clang::dataflow + +#endif diff --git a/contrib/llvm-project/clang/include/clang/Analysis/FlowSensitive/MatchSwitch.h b/contrib/llvm-project/clang/include/clang/Analysis/FlowSensitive/MatchSwitch.h index 37894ab37dd..9a298478c51 100644 --- a/contrib/llvm-project/clang/include/clang/Analysis/FlowSensitive/MatchSwitch.h +++ b/contrib/llvm-project/clang/include/clang/Analysis/FlowSensitive/MatchSwitch.h @@ -6,7 +6,7 @@ // //===----------------------------------------------------------------------===// // -// This file defines the `MatchSwitch` abstraction for building a "switch" +// This file defines the `ASTMatchSwitch` abstraction for building a "switch" // statement, where each case of the switch is defined by an AST matcher. The // cases are considered in order, like pattern matching in functional // languages. @@ -17,8 +17,7 @@ // //===----------------------------------------------------------------------===// // -// FIXME: Rename to ASTMatchSwitch.h and update documentation when all usages of -// `MatchSwitch` are updated to `ASTMatchSwitch` +// FIXME: Rename to ASTMatchSwitch.h #ifndef LLVM_CLANG_ANALYSIS_FLOWSENSITIVE_MATCHSWITCH_H_ #define LLVM_CLANG_ANALYSIS_FLOWSENSITIVE_MATCHSWITCH_H_ @@ -69,11 +68,6 @@ template using ASTMatchSwitch = std::function; -// FIXME: Remove this alias when all usages of `MatchSwitch` are updated to -// `ASTMatchSwitch`. -template -using MatchSwitch = ASTMatchSwitch; - /// Collects cases of a "match switch": a collection of matchers paired with /// callbacks, which together define a switch that can be applied to a node /// whose type derives from `BaseT`. This structure can simplify the definition @@ -171,11 +165,6 @@ private: std::vector> Actions; }; -// FIXME: Remove this alias when all usages of `MatchSwitchBuilder` are updated -// to `ASTMatchSwitchBuilder`. -template -using MatchSwitchBuilder = ASTMatchSwitchBuilder; - } // namespace dataflow } // namespace clang #endif // LLVM_CLANG_ANALYSIS_FLOWSENSITIVE_MATCHSWITCH_H_ diff --git a/contrib/llvm-project/clang/include/clang/Analysis/FlowSensitive/Models/ChromiumCheckModel.h b/contrib/llvm-project/clang/include/clang/Analysis/FlowSensitive/Models/ChromiumCheckModel.h index e65f40b0b72..b4315e41d79 100644 --- a/contrib/llvm-project/clang/include/clang/Analysis/FlowSensitive/Models/ChromiumCheckModel.h +++ b/contrib/llvm-project/clang/include/clang/Analysis/FlowSensitive/Models/ChromiumCheckModel.h @@ -13,7 +13,6 @@ #define CLANG_ANALYSIS_FLOWSENSITIVE_MODELS_CHROMIUMCHECKMODEL_H #include "clang/AST/DeclCXX.h" -#include "clang/AST/Stmt.h" #include "clang/Analysis/FlowSensitive/DataflowAnalysis.h" #include "clang/Analysis/FlowSensitive/DataflowEnvironment.h" #include "llvm/ADT/DenseSet.h" @@ -26,7 +25,7 @@ namespace dataflow { class ChromiumCheckModel : public DataflowModel { public: ChromiumCheckModel() = default; - bool transfer(const CFGElement *Element, Environment &Env) override; + bool transfer(const CFGElement &Element, Environment &Env) override; private: /// Declarations for `::logging::CheckError::.*Check`, lazily initialized. diff --git a/contrib/llvm-project/clang/include/clang/Analysis/FlowSensitive/Models/UncheckedOptionalAccessModel.h b/contrib/llvm-project/clang/include/clang/Analysis/FlowSensitive/Models/UncheckedOptionalAccessModel.h index 2d52ee5fc84..23dfdd49e94 100644 --- a/contrib/llvm-project/clang/include/clang/Analysis/FlowSensitive/Models/UncheckedOptionalAccessModel.h +++ b/contrib/llvm-project/clang/include/clang/Analysis/FlowSensitive/Models/UncheckedOptionalAccessModel.h @@ -52,7 +52,7 @@ public: static NoopLattice initialElement() { return {}; } - void transfer(const CFGElement *Elt, NoopLattice &L, Environment &Env); + void transfer(const CFGElement &Elt, NoopLattice &L, Environment &Env); ComparisonResult compare(QualType Type, const Value &Val1, const Environment &Env1, const Value &Val2, diff --git a/contrib/llvm-project/clang/include/clang/Analysis/FlowSensitive/NoopAnalysis.h b/contrib/llvm-project/clang/include/clang/Analysis/FlowSensitive/NoopAnalysis.h index bf27ec3a58d..e28a7f902fa 100644 --- a/contrib/llvm-project/clang/include/clang/Analysis/FlowSensitive/NoopAnalysis.h +++ b/contrib/llvm-project/clang/include/clang/Analysis/FlowSensitive/NoopAnalysis.h @@ -38,7 +38,7 @@ public: static NoopLattice initialElement() { return {}; } - void transfer(const CFGElement *E, NoopLattice &L, Environment &Env) {} + void transfer(const CFGElement &E, NoopLattice &L, Environment &Env) {} }; } // namespace dataflow diff --git a/contrib/llvm-project/clang/include/clang/Analysis/FlowSensitive/RecordOps.h b/contrib/llvm-project/clang/include/clang/Analysis/FlowSensitive/RecordOps.h new file mode 100644 index 00000000000..c9c302b9199 --- /dev/null +++ b/contrib/llvm-project/clang/include/clang/Analysis/FlowSensitive/RecordOps.h @@ -0,0 +1,76 @@ +//===-- RecordOps.h ---------------------------------------------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +// +// Operations on records (structs, classes, and unions). +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CLANG_ANALYSIS_FLOWSENSITIVE_RECORDOPS_H +#define LLVM_CLANG_ANALYSIS_FLOWSENSITIVE_RECORDOPS_H + +#include "clang/Analysis/FlowSensitive/DataflowEnvironment.h" +#include "clang/Analysis/FlowSensitive/StorageLocation.h" + +namespace clang { +namespace dataflow { + +/// Copies a record (struct, class, or union) from `Src` to `Dst`. +/// +/// This performs a deep copy, i.e. it copies every field and recurses on +/// fields of record type. It also copies properties from the `StructValue` +/// associated with `Src` to the `StructValue` associated with `Dst` (if these +/// `StructValue`s exist). +/// +/// If there is a `StructValue` associated with `Dst` in the environment, this +/// function creates a new `StructValue` and associates it with `Dst`; clients +/// need to be aware of this and must not assume that the `StructValue` +/// associated with `Dst` remains the same after the call. +/// +/// We create a new `StructValue` rather than modifying properties on the old +/// `StructValue` because the old `StructValue` may be shared with other +/// `Environment`s, and we don't want changes to properties to be visible there. +/// +/// Requirements: +/// +/// `Src` and `Dst` must have the same canonical unqualified type. +void copyRecord(AggregateStorageLocation &Src, AggregateStorageLocation &Dst, + Environment &Env); + +/// Returns whether the records `Loc1` and `Loc2` are equal. +/// +/// Values for `Loc1` are retrieved from `Env1`, and values for `Loc2` are +/// retrieved from `Env2`. A convenience overload retrieves values for `Loc1` +/// and `Loc2` from the same environment. +/// +/// This performs a deep comparison, i.e. it compares every field and recurses +/// on fields of record type. Fields of reference type compare equal if they +/// refer to the same storage location. If `StructValue`s are associated with +/// `Loc1` and `Loc2`, it also compares the properties on those `StructValue`s. +/// +/// Note on how to interpret the result: +/// - If this returns true, the records are guaranteed to be equal at runtime. +/// - If this returns false, the records may still be equal at runtime; our +/// analysis merely cannot guarantee that they will be equal. +/// +/// Requirements: +/// +/// `Src` and `Dst` must have the same canonical unqualified type. +bool recordsEqual(const AggregateStorageLocation &Loc1, const Environment &Env1, + const AggregateStorageLocation &Loc2, + const Environment &Env2); + +inline bool recordsEqual(const AggregateStorageLocation &Loc1, + const AggregateStorageLocation &Loc2, + const Environment &Env) { + return recordsEqual(Loc1, Env, Loc2, Env); +} + +} // namespace dataflow +} // namespace clang + +#endif // LLVM_CLANG_ANALYSIS_FLOWSENSITIVE_RECORDOPS_H diff --git a/contrib/llvm-project/clang/include/clang/Analysis/FlowSensitive/Solver.h b/contrib/llvm-project/clang/include/clang/Analysis/FlowSensitive/Solver.h index e4d450c8d12..079f6802f24 100644 --- a/contrib/llvm-project/clang/include/clang/Analysis/FlowSensitive/Solver.h +++ b/contrib/llvm-project/clang/include/clang/Analysis/FlowSensitive/Solver.h @@ -14,10 +14,12 @@ #ifndef LLVM_CLANG_ANALYSIS_FLOWSENSITIVE_SOLVER_H #define LLVM_CLANG_ANALYSIS_FLOWSENSITIVE_SOLVER_H -#include "clang/Analysis/FlowSensitive/Value.h" +#include "clang/Analysis/FlowSensitive/Formula.h" +#include "clang/Basic/LLVM.h" +#include "llvm/ADT/ArrayRef.h" #include "llvm/ADT/DenseMap.h" -#include "llvm/ADT/DenseSet.h" #include +#include namespace clang { namespace dataflow { @@ -45,8 +47,7 @@ public: /// Constructs a result indicating that the queried boolean formula is /// satisfiable. The result will hold a solution found by the solver. - static Result - Satisfiable(llvm::DenseMap Solution) { + static Result Satisfiable(llvm::DenseMap Solution) { return Result(Status::Satisfiable, std::move(Solution)); } @@ -64,19 +65,17 @@ public: /// Returns a truth assignment to boolean values that satisfies the queried /// boolean formula if available. Otherwise, an empty optional is returned. - std::optional> - getSolution() const { + std::optional> getSolution() const { return Solution; } private: - Result( - enum Status SATCheckStatus, - std::optional> Solution) + Result(Status SATCheckStatus, + std::optional> Solution) : SATCheckStatus(SATCheckStatus), Solution(std::move(Solution)) {} Status SATCheckStatus; - std::optional> Solution; + std::optional> Solution; }; virtual ~Solver() = default; @@ -87,9 +86,12 @@ public: /// Requirements: /// /// All elements in `Vals` must not be null. - virtual Result solve(llvm::DenseSet Vals) = 0; + virtual Result solve(llvm::ArrayRef Vals) = 0; }; +llvm::raw_ostream &operator<<(llvm::raw_ostream &, const Solver::Result &); +llvm::raw_ostream &operator<<(llvm::raw_ostream &, Solver::Result::Assignment); + } // namespace dataflow } // namespace clang diff --git a/contrib/llvm-project/clang/include/clang/Analysis/FlowSensitive/StorageLocation.h b/contrib/llvm-project/clang/include/clang/Analysis/FlowSensitive/StorageLocation.h index f7ea7eb174c..62e3d5e59c6 100644 --- a/contrib/llvm-project/clang/include/clang/Analysis/FlowSensitive/StorageLocation.h +++ b/contrib/llvm-project/clang/include/clang/Analysis/FlowSensitive/StorageLocation.h @@ -17,6 +17,10 @@ #include "clang/AST/Decl.h" #include "clang/AST/Type.h" #include "llvm/ADT/DenseMap.h" +#include "llvm/Support/Debug.h" +#include + +#define DEBUG_TYPE "dataflow" namespace clang { namespace dataflow { @@ -29,7 +33,9 @@ class StorageLocation { public: enum class Kind { Scalar, Aggregate }; - StorageLocation(Kind LocKind, QualType Type) : LocKind(LocKind), Type(Type) {} + StorageLocation(Kind LocKind, QualType Type) : LocKind(LocKind), Type(Type) { + assert(Type.isNull() || !Type->isReferenceType()); + } // Non-copyable because addresses of storage locations are used as their // identities throughout framework and user code. The framework is responsible @@ -65,36 +71,89 @@ public: /// struct with public members. The child map is flat, so when used for a struct /// or class type, all accessible members of base struct and class types are /// directly accesible as children of this location. +/// +/// The storage location for a field of reference type may be null. This +/// typically occurs in one of two situations: +/// - The record has not been fully initialized. +/// - The maximum depth for modelling a self-referential data structure has been +/// reached. +/// Storage locations for fields of all other types must be non-null. +/// /// FIXME: Currently, the storage location of unions is modelled the same way as /// that of structs or classes. Eventually, we need to change this modelling so /// that all of the members of a given union have the same storage location. class AggregateStorageLocation final : public StorageLocation { public: - explicit AggregateStorageLocation(QualType Type) - : AggregateStorageLocation( - Type, llvm::DenseMap()) {} + using FieldToLoc = llvm::DenseMap; - AggregateStorageLocation( - QualType Type, - llvm::DenseMap Children) - : StorageLocation(Kind::Aggregate, Type), Children(std::move(Children)) {} + explicit AggregateStorageLocation(QualType Type) + : AggregateStorageLocation(Type, FieldToLoc()) {} + + AggregateStorageLocation(QualType Type, FieldToLoc TheChildren) + : StorageLocation(Kind::Aggregate, Type), + Children(std::move(TheChildren)) { + assert(!Type.isNull()); + assert(Type->isRecordType()); + assert([this] { + for (auto [Field, Loc] : Children) { + if (!Field->getType()->isReferenceType() && Loc == nullptr) + return false; + } + return true; + }()); + } static bool classof(const StorageLocation *Loc) { return Loc->getKind() == Kind::Aggregate; } /// Returns the child storage location for `D`. - StorageLocation &getChild(const ValueDecl &D) const { + /// + /// May return null if `D` has reference type; guaranteed to return non-null + /// in all other cases. + /// + /// Note that it is an error to call this with a field that does not exist. + /// The function does not return null in this case. + StorageLocation *getChild(const ValueDecl &D) const { auto It = Children.find(&D); + LLVM_DEBUG({ + if (It == Children.end()) { + llvm::dbgs() << "Couldn't find child " << D.getNameAsString() + << " on StorageLocation " << this << " of type " + << getType() << "\n"; + llvm::dbgs() << "Existing children:\n"; + for ([[maybe_unused]] auto [Field, Loc] : Children) { + llvm::dbgs() << Field->getNameAsString() << "\n"; + } + } + }); assert(It != Children.end()); - return *It->second; + return It->second; + } + + /// Changes the child storage location for a field `D` of reference type. + /// All other fields cannot change their storage location and always retain + /// the storage location passed to the `AggregateStorageLocation` constructor. + /// + /// Requirements: + /// + /// `D` must have reference type. + void setChild(const ValueDecl &D, StorageLocation *Loc) { + assert(D.getType()->isReferenceType()); + Children[&D] = Loc; + } + + llvm::iterator_range children() const { + return {Children.begin(), Children.end()}; } private: - llvm::DenseMap Children; + FieldToLoc Children; }; } // namespace dataflow } // namespace clang +#undef DEBUG_TYPE + #endif // LLVM_CLANG_ANALYSIS_FLOWSENSITIVE_STORAGELOCATION_H diff --git a/contrib/llvm-project/clang/include/clang/Analysis/FlowSensitive/Transfer.h b/contrib/llvm-project/clang/include/clang/Analysis/FlowSensitive/Transfer.h index 78a426ed94d..58bb77c4905 100644 --- a/contrib/llvm-project/clang/include/clang/Analysis/FlowSensitive/Transfer.h +++ b/contrib/llvm-project/clang/include/clang/Analysis/FlowSensitive/Transfer.h @@ -17,6 +17,7 @@ #include "clang/AST/Stmt.h" #include "clang/Analysis/FlowSensitive/DataflowAnalysisContext.h" #include "clang/Analysis/FlowSensitive/DataflowEnvironment.h" +#include "clang/Analysis/FlowSensitive/TypeErasedDataflowAnalysis.h" namespace clang { namespace dataflow { @@ -24,12 +25,18 @@ namespace dataflow { /// Maps statements to the environments of basic blocks that contain them. class StmtToEnvMap { public: - virtual ~StmtToEnvMap() = default; + StmtToEnvMap(const ControlFlowContext &CFCtx, + llvm::ArrayRef> + BlockToState) + : CFCtx(CFCtx), BlockToState(BlockToState) {} - /// Returns the environment of the basic block that contains `S` or nullptr if - /// there isn't one. - /// FIXME: Ensure that the result can't be null and return a const reference. - virtual const Environment *getEnvironment(const Stmt &S) const = 0; + /// Returns the environment of the basic block that contains `S`. + /// The result is guaranteed never to be null. + const Environment *getEnvironment(const Stmt &S) const; + +private: + const ControlFlowContext &CFCtx; + llvm::ArrayRef> BlockToState; }; /// Evaluates `S` and updates `Env` accordingly. diff --git a/contrib/llvm-project/clang/include/clang/Analysis/FlowSensitive/TypeErasedDataflowAnalysis.h b/contrib/llvm-project/clang/include/clang/Analysis/FlowSensitive/TypeErasedDataflowAnalysis.h index 1d7962e9f67..88a33d19f7d 100644 --- a/contrib/llvm-project/clang/include/clang/Analysis/FlowSensitive/TypeErasedDataflowAnalysis.h +++ b/contrib/llvm-project/clang/include/clang/Analysis/FlowSensitive/TypeErasedDataflowAnalysis.h @@ -72,7 +72,7 @@ public: /// Joins two type-erased lattice elements by computing their least upper /// bound. Places the join result in the left element and returns an effect /// indicating whether any changes were made to it. - virtual LatticeJoinEffect joinTypeErased(TypeErasedLattice &, + virtual TypeErasedLattice joinTypeErased(const TypeErasedLattice &, const TypeErasedLattice &) = 0; /// Chooses a lattice element that approximates the current element at a @@ -96,7 +96,7 @@ public: /// Applies the analysis transfer function for a given control flow graph /// element and type-erased lattice element. - virtual void transferTypeErased(const CFGElement *, TypeErasedLattice &, + virtual void transferTypeErased(const CFGElement &, TypeErasedLattice &, Environment &) = 0; /// Applies the analysis transfer function for a given edge from a CFG block @@ -104,6 +104,7 @@ public: /// @param Stmt The condition which is responsible for the split in the CFG. /// @param Branch True if the edge goes to the basic block where the /// condition is true. + // FIXME: Change `Stmt` argument to a reference. virtual void transferBranchTypeErased(bool Branch, const Stmt *, TypeErasedLattice &, Environment &) = 0; @@ -125,6 +126,10 @@ struct TypeErasedDataflowAnalysisState { TypeErasedDataflowAnalysisState(TypeErasedLattice Lattice, Environment Env) : Lattice(std::move(Lattice)), Env(std::move(Env)) {} + + TypeErasedDataflowAnalysisState fork() const { + return TypeErasedDataflowAnalysisState(Lattice, Env.fork()); + } }; /// Transfers the state of a basic block by evaluating each of its elements in diff --git a/contrib/llvm-project/clang/include/clang/Analysis/FlowSensitive/Value.h b/contrib/llvm-project/clang/include/clang/Analysis/FlowSensitive/Value.h index 32d10a34894..7d9a7b7d282 100644 --- a/contrib/llvm-project/clang/include/clang/Analysis/FlowSensitive/Value.h +++ b/contrib/llvm-project/clang/include/clang/Analysis/FlowSensitive/Value.h @@ -15,11 +15,11 @@ #define LLVM_CLANG_ANALYSIS_FLOWSENSITIVE_VALUE_H #include "clang/AST/Decl.h" +#include "clang/Analysis/FlowSensitive/Formula.h" #include "clang/Analysis/FlowSensitive/StorageLocation.h" #include "llvm/ADT/DenseMap.h" #include "llvm/ADT/StringMap.h" #include "llvm/ADT/StringRef.h" -#include "llvm/Support/raw_ostream.h" #include #include @@ -38,14 +38,10 @@ public: Pointer, Struct, - // Synthetic boolean values are either atomic values or logical connectives. + // TODO: Top values should not be need to be type-specific. TopBool, AtomicBool, - Conjunction, - Disjunction, - Negation, - Implication, - Biconditional, + FormulaBool, }; explicit Value(Kind ValKind) : ValKind(ValKind) {} @@ -63,8 +59,7 @@ public: /// Returns the value of the synthetic property with the given `Name` or null /// if the property isn't assigned a value. Value *getProperty(llvm::StringRef Name) const { - auto It = Properties.find(Name); - return It == Properties.end() ? nullptr : It->second; + return Properties.lookup(Name); } /// Assigns `Val` as the value of the synthetic property with the given @@ -73,6 +68,11 @@ public: Properties.insert_or_assign(Name, &Val); } + llvm::iterator_range::const_iterator> + properties() const { + return {Properties.begin(), Properties.end()}; + } + private: Kind ValKind; llvm::StringMap Properties; @@ -91,151 +91,68 @@ bool areEquivalentValues(const Value &Val1, const Value &Val2); /// Models a boolean. class BoolValue : public Value { + const Formula *F; + public: - explicit BoolValue(Kind ValueKind) : Value(ValueKind) {} + explicit BoolValue(Kind ValueKind, const Formula &F) + : Value(ValueKind), F(&F) {} static bool classof(const Value *Val) { return Val->getKind() == Kind::TopBool || Val->getKind() == Kind::AtomicBool || - Val->getKind() == Kind::Conjunction || - Val->getKind() == Kind::Disjunction || - Val->getKind() == Kind::Negation || - Val->getKind() == Kind::Implication || - Val->getKind() == Kind::Biconditional; + Val->getKind() == Kind::FormulaBool; } + + const Formula &formula() const { return *F; } }; -/// Models the trivially true formula, which is Top in the lattice of boolean -/// formulas. +/// A TopBoolValue represents a boolean that is explicitly unconstrained. +/// +/// This is equivalent to an AtomicBoolValue that does not appear anywhere +/// else in a system of formula. +/// Knowing the value is unconstrained is useful when e.g. reasoning about +/// convergence. class TopBoolValue final : public BoolValue { public: - TopBoolValue() : BoolValue(Kind::TopBool) {} + TopBoolValue(const Formula &F) : BoolValue(Kind::TopBool, F) { + assert(F.kind() == Formula::AtomRef); + } static bool classof(const Value *Val) { return Val->getKind() == Kind::TopBool; } + + Atom getAtom() const { return formula().getAtom(); } }; /// Models an atomic boolean. -class AtomicBoolValue : public BoolValue { +/// +/// FIXME: Merge this class into FormulaBoolValue. +/// When we want to specify atom identity, use Atom. +class AtomicBoolValue final : public BoolValue { public: - explicit AtomicBoolValue() : BoolValue(Kind::AtomicBool) {} + explicit AtomicBoolValue(const Formula &F) : BoolValue(Kind::AtomicBool, F) { + assert(F.kind() == Formula::AtomRef); + } static bool classof(const Value *Val) { return Val->getKind() == Kind::AtomicBool; } + + Atom getAtom() const { return formula().getAtom(); } }; -/// Models a boolean conjunction. -// FIXME: Consider representing binary and unary boolean operations similar -// to how they are represented in the AST. This might become more pressing -// when such operations need to be added for other data types. -class ConjunctionValue : public BoolValue { +/// Models a compound boolean formula. +class FormulaBoolValue final : public BoolValue { public: - explicit ConjunctionValue(BoolValue &LeftSubVal, BoolValue &RightSubVal) - : BoolValue(Kind::Conjunction), LeftSubVal(LeftSubVal), - RightSubVal(RightSubVal) {} - - static bool classof(const Value *Val) { - return Val->getKind() == Kind::Conjunction; + explicit FormulaBoolValue(const Formula &F) + : BoolValue(Kind::FormulaBool, F) { + assert(F.kind() != Formula::AtomRef && "For now, use AtomicBoolValue"); } - /// Returns the left sub-value of the conjunction. - BoolValue &getLeftSubValue() const { return LeftSubVal; } - - /// Returns the right sub-value of the conjunction. - BoolValue &getRightSubValue() const { return RightSubVal; } - -private: - BoolValue &LeftSubVal; - BoolValue &RightSubVal; -}; - -/// Models a boolean disjunction. -class DisjunctionValue : public BoolValue { -public: - explicit DisjunctionValue(BoolValue &LeftSubVal, BoolValue &RightSubVal) - : BoolValue(Kind::Disjunction), LeftSubVal(LeftSubVal), - RightSubVal(RightSubVal) {} - static bool classof(const Value *Val) { - return Val->getKind() == Kind::Disjunction; + return Val->getKind() == Kind::FormulaBool; } - - /// Returns the left sub-value of the disjunction. - BoolValue &getLeftSubValue() const { return LeftSubVal; } - - /// Returns the right sub-value of the disjunction. - BoolValue &getRightSubValue() const { return RightSubVal; } - -private: - BoolValue &LeftSubVal; - BoolValue &RightSubVal; -}; - -/// Models a boolean negation. -class NegationValue : public BoolValue { -public: - explicit NegationValue(BoolValue &SubVal) - : BoolValue(Kind::Negation), SubVal(SubVal) {} - - static bool classof(const Value *Val) { - return Val->getKind() == Kind::Negation; - } - - /// Returns the sub-value of the negation. - BoolValue &getSubVal() const { return SubVal; } - -private: - BoolValue &SubVal; -}; - -/// Models a boolean implication. -/// -/// Equivalent to `!LHS v RHS`. -class ImplicationValue : public BoolValue { -public: - explicit ImplicationValue(BoolValue &LeftSubVal, BoolValue &RightSubVal) - : BoolValue(Kind::Implication), LeftSubVal(LeftSubVal), - RightSubVal(RightSubVal) {} - - static bool classof(const Value *Val) { - return Val->getKind() == Kind::Implication; - } - - /// Returns the left sub-value of the implication. - BoolValue &getLeftSubValue() const { return LeftSubVal; } - - /// Returns the right sub-value of the implication. - BoolValue &getRightSubValue() const { return RightSubVal; } - -private: - BoolValue &LeftSubVal; - BoolValue &RightSubVal; -}; - -/// Models a boolean biconditional. -/// -/// Equivalent to `(LHS ^ RHS) v (!LHS ^ !RHS)`. -class BiconditionalValue : public BoolValue { -public: - explicit BiconditionalValue(BoolValue &LeftSubVal, BoolValue &RightSubVal) - : BoolValue(Kind::Biconditional), LeftSubVal(LeftSubVal), - RightSubVal(RightSubVal) {} - - static bool classof(const Value *Val) { - return Val->getKind() == Kind::Biconditional; - } - - /// Returns the left sub-value of the biconditional. - BoolValue &getLeftSubValue() const { return LeftSubVal; } - - /// Returns the right sub-value of the biconditional. - BoolValue &getRightSubValue() const { return RightSubVal; } - -private: - BoolValue &LeftSubVal; - BoolValue &RightSubVal; }; /// Models an integer. @@ -281,34 +198,59 @@ private: StorageLocation &PointeeLoc; }; -/// Models a value of `struct` or `class` type, with a flat map of fields to -/// child storage locations, containing all accessible members of base struct -/// and class types. +/// Models a value of `struct` or `class` type. +/// In C++, prvalues of class type serve only a limited purpose: They can only +/// be used to initialize a result object. It is not possible to access member +/// variables or call member functions on a prvalue of class type. +/// Correspondingly, `StructValue` also serves only two limited purposes: +/// - It conveys a prvalue of class type from the place where the object is +/// constructed to the result object that it initializes. +/// +/// When creating a prvalue of class type, we already need a storage location +/// for `this`, even though prvalues are otherwise not associated with storage +/// locations. `StructValue` is therefore essentially a wrapper for a storage +/// location, which is then used to set the storage location for the result +/// object when we process the AST node for that result object. +/// +/// For example: +/// MyStruct S = MyStruct(3); +/// +/// In this example, `MyStruct(3) is a prvalue, which is modeled as a +/// `StructValue` that wraps an `AbstractStorageLocation`. This +// `AbstractStorageLocation` is then used as the storage location for `S`. +/// +/// - It allows properties to be associated with an object of class type. +/// Note that when doing so, you should avoid mutating the properties of an +/// existing `StructValue` in place, as these changes would be visible to +/// other `Environment`s that share the same `StructValue`. Instead, associate +/// a new `StructValue` with the `AggregateStorageLocation` and set the +/// properties on this new `StructValue`. (See also `refreshStructValue()` in +/// DataflowEnvironment.h, which makes this easy.) +/// Note also that this implies that it is common for the same +/// `AggregateStorageLocation` to be associated with different `StructValue`s +/// in different environments. +/// Over time, we may eliminate `StructValue` entirely. See also the discussion +/// here: https://reviews.llvm.org/D155204#inline-1503204 class StructValue final : public Value { public: - StructValue() : StructValue(llvm::DenseMap()) {} - - explicit StructValue(llvm::DenseMap Children) - : Value(Kind::Struct), Children(std::move(Children)) {} + explicit StructValue(AggregateStorageLocation &Loc) + : Value(Kind::Struct), Loc(Loc) {} static bool classof(const Value *Val) { return Val->getKind() == Kind::Struct; } - /// Returns the child value that is assigned for `D` or null if the child is - /// not initialized. - Value *getChild(const ValueDecl &D) const { - auto It = Children.find(&D); - if (It == Children.end()) - return nullptr; - return It->second; + /// Returns the storage location that this `StructValue` is associated with. + AggregateStorageLocation &getAggregateLoc() const { return Loc; } + + /// Convenience function that returns the child storage location for `Field`. + /// See also the documentation for `AggregateStorageLocation::getChild()`. + StorageLocation *getChild(const ValueDecl &Field) const { + return Loc.getChild(Field); } - /// Assigns `Val` as the child value for `D`. - void setChild(const ValueDecl &D, Value &Val) { Children[&D] = &Val; } - private: - llvm::DenseMap Children; + AggregateStorageLocation &Loc; }; raw_ostream &operator<<(raw_ostream &OS, const Value &Val); diff --git a/contrib/llvm-project/clang/include/clang/Analysis/FlowSensitive/WatchedLiteralsSolver.h b/contrib/llvm-project/clang/include/clang/Analysis/FlowSensitive/WatchedLiteralsSolver.h index 702da97349d..5448eecf6d4 100644 --- a/contrib/llvm-project/clang/include/clang/Analysis/FlowSensitive/WatchedLiteralsSolver.h +++ b/contrib/llvm-project/clang/include/clang/Analysis/FlowSensitive/WatchedLiteralsSolver.h @@ -14,9 +14,10 @@ #ifndef LLVM_CLANG_ANALYSIS_FLOWSENSITIVE_WATCHEDLITERALSSOLVER_H #define LLVM_CLANG_ANALYSIS_FLOWSENSITIVE_WATCHEDLITERALSSOLVER_H +#include "clang/Analysis/FlowSensitive/Formula.h" #include "clang/Analysis/FlowSensitive/Solver.h" -#include "clang/Analysis/FlowSensitive/Value.h" -#include "llvm/ADT/DenseSet.h" +#include "llvm/ADT/ArrayRef.h" +#include namespace clang { namespace dataflow { @@ -27,8 +28,28 @@ namespace dataflow { /// single "watched" literal per clause, and uses a set of "active" variables /// for unit propagation. class WatchedLiteralsSolver : public Solver { + // Count of the iterations of the main loop of the solver. This spans *all* + // calls to the underlying solver across the life of this object. It is + // reduced with every (non-trivial) call to the solver. + // + // We give control over the abstract count of iterations instead of concrete + // measurements like CPU cycles or time to ensure deterministic results. + std::int64_t MaxIterations = std::numeric_limits::max(); + public: - Result solve(llvm::DenseSet Vals) override; + WatchedLiteralsSolver() = default; + + // `Work` specifies a computational limit on the solver. Units of "work" + // roughly correspond to attempts to assign a value to a single + // variable. Since the algorithm is exponential in the number of variables, + // this is the most direct (abstract) unit to target. + explicit WatchedLiteralsSolver(std::int64_t WorkLimit) + : MaxIterations(WorkLimit) {} + + Result solve(llvm::ArrayRef Vals) override; + + // The solver reached its maximum number of iterations. + bool reachedLimit() const { return MaxIterations == 0; } }; } // namespace dataflow diff --git a/contrib/llvm-project/clang/include/clang/Analysis/ProgramPoint.h b/contrib/llvm-project/clang/include/clang/Analysis/ProgramPoint.h index 6dba0582c8d..b9339570e1a 100644 --- a/contrib/llvm-project/clang/include/clang/Analysis/ProgramPoint.h +++ b/contrib/llvm-project/clang/include/clang/Analysis/ProgramPoint.h @@ -95,35 +95,33 @@ private: llvm::PointerIntPair Tag; + CFGBlock::ConstCFGElementRef ElemRef = {nullptr, 0}; + protected: ProgramPoint() = default; - ProgramPoint(const void *P, - Kind k, - const LocationContext *l, - const ProgramPointTag *tag = nullptr) - : Data1(P), - Data2(nullptr, (((unsigned) k) >> 0) & 0x3), - L(l, (((unsigned) k) >> 2) & 0x3), - Tag(tag, (((unsigned) k) >> 4) & 0x3) { - assert(getKind() == k); - assert(getLocationContext() == l); - assert(getData1() == P); - } + ProgramPoint(const void *P, Kind k, const LocationContext *l, + const ProgramPointTag *tag = nullptr, + CFGBlock::ConstCFGElementRef ElemRef = {nullptr, 0}) + : Data1(P), Data2(nullptr, (((unsigned)k) >> 0) & 0x3), + L(l, (((unsigned)k) >> 2) & 0x3), Tag(tag, (((unsigned)k) >> 4) & 0x3), + ElemRef(ElemRef) { + assert(getKind() == k); + assert(getLocationContext() == l); + assert(getData1() == P); + } - ProgramPoint(const void *P1, - const void *P2, - Kind k, - const LocationContext *l, - const ProgramPointTag *tag = nullptr) - : Data1(P1), - Data2(P2, (((unsigned) k) >> 0) & 0x3), - L(l, (((unsigned) k) >> 2) & 0x3), - Tag(tag, (((unsigned) k) >> 4) & 0x3) {} + ProgramPoint(const void *P1, const void *P2, Kind k, const LocationContext *l, + const ProgramPointTag *tag = nullptr, + CFGBlock::ConstCFGElementRef ElemRef = {nullptr, 0}) + : Data1(P1), Data2(P2, (((unsigned)k) >> 0) & 0x3), + L(l, (((unsigned)k) >> 2) & 0x3), Tag(tag, (((unsigned)k) >> 4) & 0x3), + ElemRef(ElemRef) {} protected: const void *getData1() const { return Data1; } const void *getData2() const { return Data2.getPointer(); } void setData2(const void *d) { Data2.setPointer(d); } + CFGBlock::ConstCFGElementRef getElementRef() const { return ElemRef; } public: /// Create a new ProgramPoint object that is the same as the original @@ -190,17 +188,13 @@ public: } bool operator==(const ProgramPoint & RHS) const { - return Data1 == RHS.Data1 && - Data2 == RHS.Data2 && - L == RHS.L && - Tag == RHS.Tag; + return Data1 == RHS.Data1 && Data2 == RHS.Data2 && L == RHS.L && + Tag == RHS.Tag && ElemRef == RHS.ElemRef; } bool operator!=(const ProgramPoint &RHS) const { - return Data1 != RHS.Data1 || - Data2 != RHS.Data2 || - L != RHS.L || - Tag != RHS.Tag; + return Data1 != RHS.Data1 || Data2 != RHS.Data2 || L != RHS.L || + Tag != RHS.Tag || ElemRef != RHS.ElemRef; } void Profile(llvm::FoldingSetNodeID& ID) const { @@ -209,6 +203,8 @@ public: ID.AddPointer(getData2()); ID.AddPointer(getLocationContext()); ID.AddPointer(getTag()); + ID.AddPointer(ElemRef.getParent()); + ID.AddInteger(ElemRef.getIndexInBlock()); } void printJson(llvm::raw_ostream &Out, const char *NL = "\n") const; @@ -266,6 +262,7 @@ private: } }; +// FIXME: Eventually we want to take a CFGElementRef as parameter here too. class StmtPoint : public ProgramPoint { public: StmtPoint(const Stmt *S, const void *p2, Kind k, const LocationContext *L, @@ -557,8 +554,9 @@ private: class ImplicitCallPoint : public ProgramPoint { public: ImplicitCallPoint(const Decl *D, SourceLocation Loc, Kind K, - const LocationContext *L, const ProgramPointTag *Tag) - : ProgramPoint(Loc.getPtrEncoding(), D, K, L, Tag) {} + const LocationContext *L, const ProgramPointTag *Tag, + CFGBlock::ConstCFGElementRef ElemRef) + : ProgramPoint(Loc.getPtrEncoding(), D, K, L, Tag, ElemRef) {} const Decl *getDecl() const { return static_cast(getData2()); } SourceLocation getLocation() const { @@ -581,8 +579,9 @@ private: class PreImplicitCall : public ImplicitCallPoint { public: PreImplicitCall(const Decl *D, SourceLocation Loc, const LocationContext *L, + CFGBlock::ConstCFGElementRef ElemRef, const ProgramPointTag *Tag = nullptr) - : ImplicitCallPoint(D, Loc, PreImplicitCallKind, L, Tag) {} + : ImplicitCallPoint(D, Loc, PreImplicitCallKind, L, Tag, ElemRef) {} private: friend class ProgramPoint; @@ -598,8 +597,9 @@ private: class PostImplicitCall : public ImplicitCallPoint { public: PostImplicitCall(const Decl *D, SourceLocation Loc, const LocationContext *L, + CFGBlock::ConstCFGElementRef ElemRef, const ProgramPointTag *Tag = nullptr) - : ImplicitCallPoint(D, Loc, PostImplicitCallKind, L, Tag) {} + : ImplicitCallPoint(D, Loc, PostImplicitCallKind, L, Tag, ElemRef) {} private: friend class ProgramPoint; diff --git a/contrib/llvm-project/clang/include/clang/Analysis/Support/BumpVector.h b/contrib/llvm-project/clang/include/clang/Analysis/Support/BumpVector.h index 74092dabbfd..6c3f11e9930 100644 --- a/contrib/llvm-project/clang/include/clang/Analysis/Support/BumpVector.h +++ b/contrib/llvm-project/clang/include/clang/Analysis/Support/BumpVector.h @@ -42,6 +42,15 @@ public: Other.Alloc.setPointer(nullptr); } + // The move assignment operator is defined as deleted pending further + // motivation. + BumpVectorContext &operator=(BumpVectorContext &&) = delete; + + // The copy constrcutor and copy assignment operator is defined as deleted + // pending further motivation. + BumpVectorContext(const BumpVectorContext &) = delete; + BumpVectorContext &operator=(const BumpVectorContext &) = delete; + /// Construct a new BumpVectorContext that reuses an existing /// BumpPtrAllocator. This BumpPtrAllocator is not destroyed when the /// BumpVectorContext object is destroyed. diff --git a/contrib/llvm-project/clang/include/clang/Basic/AArch64SVEACLETypes.def b/contrib/llvm-project/clang/include/clang/Basic/AArch64SVEACLETypes.def index b98a07436e9..56af270e1d1 100644 --- a/contrib/llvm-project/clang/include/clang/Basic/AArch64SVEACLETypes.def +++ b/contrib/llvm-project/clang/include/clang/Basic/AArch64SVEACLETypes.def @@ -49,6 +49,11 @@ SVE_TYPE(Name, Id, SingletonId) #endif +#ifndef SVE_OPAQUE_TYPE +#define SVE_OPAQUE_TYPE(Name, MangledName, Id, SingletonId) \ + SVE_TYPE(Name, Id, SingletonId) +#endif + //===- Vector point types -----------------------------------------------===// @@ -124,7 +129,12 @@ SVE_VECTOR_TYPE("__clang_svfloat64x4_t", "svfloat64x4_t", SveFloat64x4, SveFloat SVE_VECTOR_TYPE("__clang_svbfloat16x4_t", "svbfloat16x4_t", SveBFloat16x4, SveBFloat16x4Ty, 32, 16, true, false, true) SVE_PREDICATE_TYPE("__SVBool_t", "__SVBool_t", SveBool, SveBoolTy, 16) +SVE_PREDICATE_TYPE("__clang_svboolx2_t", "svboolx2_t", SveBoolx2, SveBoolx2Ty, 32) +SVE_PREDICATE_TYPE("__clang_svboolx4_t", "svboolx4_t", SveBoolx4, SveBoolx4Ty, 64) + +SVE_OPAQUE_TYPE("__SVCount_t", "__SVCount_t", SveCount, SveCountTy) #undef SVE_VECTOR_TYPE #undef SVE_PREDICATE_TYPE +#undef SVE_OPAQUE_TYPE #undef SVE_TYPE diff --git a/contrib/llvm-project/clang/include/clang/Basic/AddressSpaces.h b/contrib/llvm-project/clang/include/clang/Basic/AddressSpaces.h index 2f2c5d5826b..7b723d508ff 100644 --- a/contrib/llvm-project/clang/include/clang/Basic/AddressSpaces.h +++ b/contrib/llvm-project/clang/include/clang/Basic/AddressSpaces.h @@ -59,6 +59,9 @@ enum class LangAS : unsigned { // HLSL specific address spaces. hlsl_groupshared, + // Wasm specific address spaces. + wasm_funcref, + // This denotes the count of language-specific address spaces and also // the offset added to the target-specific address spaces, which are usually // specified by address space attributes __attribute__(address_space(n))). diff --git a/contrib/llvm-project/clang/include/clang/Basic/AlignedAllocation.h b/contrib/llvm-project/clang/include/clang/Basic/AlignedAllocation.h index 949e54c8c03..ac26eb4a276 100644 --- a/contrib/llvm-project/clang/include/clang/Basic/AlignedAllocation.h +++ b/contrib/llvm-project/clang/include/clang/Basic/AlignedAllocation.h @@ -15,9 +15,9 @@ #ifndef LLVM_CLANG_BASIC_ALIGNEDALLOCATION_H #define LLVM_CLANG_BASIC_ALIGNEDALLOCATION_H -#include "llvm/ADT/Triple.h" #include "llvm/Support/ErrorHandling.h" #include "llvm/Support/VersionTuple.h" +#include "llvm/TargetParser/Triple.h" namespace clang { diff --git a/contrib/llvm-project/clang/include/clang/Basic/Attr.td b/contrib/llvm-project/clang/include/clang/Basic/Attr.td index d449a2fe7f8..d5204b28696 100644 --- a/contrib/llvm-project/clang/include/clang/Basic/Attr.td +++ b/contrib/llvm-project/clang/include/clang/Basic/Attr.td @@ -168,6 +168,12 @@ def FunctionLike : SubsetSubjectgetFunctionType(false) != nullptr}], "functions, function pointers">; +// Function Pointer is a stricter version of FunctionLike that only allows function +// pointers. +def FunctionPointer : SubsetSubjectisFunctionPointerType()}], + "functions pointers">; + def OpenCLKernelFunction : SubsetSubjecthasAttr()}], "kernel functions">; @@ -287,26 +293,38 @@ class VariadicEnumArgument values, } // This handles one spelling of an attribute. -class Spelling { +class Spelling { string Name = name; string Variety = variety; + int Version = version; } class GNU : Spelling; class Declspec : Spelling; class Microsoft : Spelling; class CXX11 - : Spelling { + : Spelling { string Namespace = namespace; - int Version = version; } class C2x - : Spelling { + : Spelling { string Namespace = namespace; - int Version = version; } -class Keyword : Spelling; +class Keyword + : Spelling { + bit HasOwnParseRules = hasOwnParseRules; +} + +// A keyword that can appear wherever a standard attribute can appear, +// and that appertains to whatever a standard attribute would appertain to. +// This is useful for things that affect semantics but that should otherwise +// be treated like standard attributes. +class RegularKeyword : Keyword {} + +// A keyword that has its own individual parsing rules. +class CustomKeyword : Keyword {} + class Pragma : Spelling { string Namespace = namespace; } @@ -321,7 +339,8 @@ class GCC : Spelling { // The Clang spelling implies GNU, CXX11<"clang", name>, and optionally, // C2x<"clang", name>. This spelling should be used for any Clang-specific // attributes. -class Clang : Spelling { +class Clang + : Spelling { bit AllowInC = allowInC; } @@ -408,6 +427,7 @@ def TargetRISCV : TargetArch<["riscv32", "riscv64"]>; def TargetX86 : TargetArch<["x86"]>; def TargetAnyX86 : TargetArch<["x86", "x86_64"]>; def TargetWebAssembly : TargetArch<["wasm32", "wasm64"]>; +def TargetNVPTX : TargetArch<["nvptx", "nvptx64"]>; def TargetWindows : TargetSpec { let OSes = ["Win32"]; } @@ -702,13 +722,13 @@ def ArmBuiltinAlias : InheritableAttr, TargetSpecificAttr { } def Aligned : InheritableAttr { - let Spellings = [GCC<"aligned">, Declspec<"align">, Keyword<"alignas">, - Keyword<"_Alignas">]; + let Spellings = [GCC<"aligned">, Declspec<"align">, CustomKeyword<"alignas">, + CustomKeyword<"_Alignas">]; let Args = [AlignedArgument<"Alignment", 1>]; let Accessors = [Accessor<"isGNU", [GCC<"aligned">]>, - Accessor<"isC11", [Keyword<"_Alignas">]>, - Accessor<"isAlignas", [Keyword<"alignas">, - Keyword<"_Alignas">]>, + Accessor<"isC11", [CustomKeyword<"_Alignas">]>, + Accessor<"isAlignas", [CustomKeyword<"alignas">, + CustomKeyword<"_Alignas">]>, Accessor<"isDeclspec",[Declspec<"align">]>]; let Documentation = [Undocumented]; } @@ -749,7 +769,7 @@ def AlignNatural : InheritableAttr { def AlwaysInline : DeclOrStmtAttr { let Spellings = [GCC<"always_inline">, CXX11<"clang", "always_inline">, - C2x<"clang", "always_inline">, Keyword<"__forceinline">]; + C2x<"clang", "always_inline">, CustomKeyword<"__forceinline">]; let Accessors = [Accessor<"isClangAlwaysInline", [CXX11<"clang", "always_inline">, C2x<"clang", "always_inline">]>]; let Subjects = SubjectList<[Function, Stmt], WarnDiag, @@ -792,7 +812,8 @@ def XRayLogArgs : InheritableAttr { def PatchableFunctionEntry : InheritableAttr, TargetSpecificAttr> { + ["aarch64", "aarch64_be", "loongarch32", "loongarch64", "riscv32", + "riscv64", "x86", "x86_64"]>> { let Spellings = [GCC<"patchable_function_entry">]; let Subjects = SubjectList<[Function, ObjCMethod]>; let Args = [UnsignedArgument<"Count">, DefaultIntArgument<"Offset", 0>]; @@ -826,7 +847,7 @@ def Annotate : InheritableParamAttr { return AnnotateAttr::Create(Ctx, Annotation, nullptr, 0, CommonInfo); } static AnnotateAttr *CreateImplicit(ASTContext &Ctx, llvm::StringRef Annotation, \ - const AttributeCommonInfo &CommonInfo = {SourceRange{}}) { + const AttributeCommonInfo &CommonInfo) { return AnnotateAttr::CreateImplicit(Ctx, Annotation, nullptr, 0, CommonInfo); } }]; @@ -871,7 +892,7 @@ def AVRSignal : InheritableAttr, TargetSpecificAttr { } def AsmLabel : InheritableAttr { - let Spellings = [Keyword<"asm">, Keyword<"__asm__">]; + let Spellings = [CustomKeyword<"asm">, CustomKeyword<"__asm__">]; let Args = [ // Label specifies the mangled name for the decl. StringArgument<"Label">, @@ -918,6 +939,7 @@ def Availability : InheritableAttr { .Case("maccatalyst_app_extension", "macCatalyst (App Extension)") .Case("swift", "Swift") .Case("shadermodel", "HLSL ShaderModel") + .Case("ohos", "OpenHarmony OS") .Default(llvm::StringRef()); } static llvm::StringRef getPlatformNameSourceSpelling(llvm::StringRef Platform) { @@ -958,10 +980,12 @@ static llvm::StringRef canonicalizePlatformName(llvm::StringRef Platform) { } def ExternalSourceSymbol : InheritableAttr { - let Spellings = [Clang<"external_source_symbol">]; + let Spellings = [Clang<"external_source_symbol", /*allowInC=*/1, + /*version=*/20230206>]; let Args = [StringArgument<"language", 1>, StringArgument<"definedIn", 1>, - BoolArgument<"generatedDeclaration", 1>]; + BoolArgument<"generatedDeclaration", 1>, + StringArgument<"USR", 1>]; let HasCustomParsing = 1; let Subjects = SubjectList<[Named]>; let Documentation = [ExternalSourceSymbolDocs]; @@ -986,7 +1010,7 @@ def CarriesDependency : InheritableParamAttr { } def CDecl : DeclOrTypeAttr { - let Spellings = [GCC<"cdecl">, Keyword<"__cdecl">, Keyword<"_cdecl">]; + let Spellings = [GCC<"cdecl">, CustomKeyword<"__cdecl">, CustomKeyword<"_cdecl">]; // let Subjects = [Function, ObjCMethod]; let Documentation = [Undocumented]; } @@ -1073,7 +1097,7 @@ def Cleanup : InheritableAttr { let Spellings = [GCC<"cleanup">]; let Args = [DeclArgument]; let Subjects = SubjectList<[LocalVar]>; - let Documentation = [Undocumented]; + let Documentation = [CleanupDocs]; } def CmseNSEntry : InheritableAttr, TargetSpecificAttr { @@ -1111,10 +1135,10 @@ def Const : InheritableAttr { def ConstInit : InheritableAttr { // This attribute does not have a C [[]] spelling because it requires the // CPlusPlus language option. - let Spellings = [Keyword<"constinit">, + let Spellings = [CustomKeyword<"constinit">, Clang<"require_constant_initialization", 0>]; let Subjects = SubjectList<[GlobalVar], ErrorDiag>; - let Accessors = [Accessor<"isConstinit", [Keyword<"constinit">]>]; + let Accessors = [Accessor<"isConstinit", [CustomKeyword<"constinit">]>]; let Documentation = [ConstInitDocs]; let LangOpts = [CPlusPlus]; let SimpleHandler = 1; @@ -1211,6 +1235,12 @@ def CUDAHost : InheritableAttr { } def : MutualExclusions<[CUDAGlobal, CUDAHost]>; +def NVPTXKernel : InheritableAttr, TargetSpecificAttr { + let Spellings = [Clang<"nvptx_kernel">]; + let Subjects = SubjectList<[Function]>; + let Documentation = [Undocumented]; +} + def HIPManaged : InheritableAttr { let Spellings = [GNU<"managed">, Declspec<"__managed__">]; let Subjects = SubjectList<[Var]>; @@ -1259,7 +1289,7 @@ def SYCLSpecialClass: InheritableAttr { } def C11NoReturn : InheritableAttr { - let Spellings = [Keyword<"_Noreturn">]; + let Spellings = [CustomKeyword<"_Noreturn">]; let Subjects = SubjectList<[Function], ErrorDiag>; let SemaHandler = 0; let Documentation = [C11NoReturnDocs]; @@ -1275,7 +1305,7 @@ def CXX11NoReturn : InheritableAttr { // Similar to CUDA, OpenCL attributes do not receive a [[]] spelling because // the specification does not expose them with one currently. def OpenCLKernel : InheritableAttr { - let Spellings = [Keyword<"__kernel">, Keyword<"kernel">]; + let Spellings = [CustomKeyword<"__kernel">, CustomKeyword<"kernel">]; let Subjects = SubjectList<[Function], ErrorDiag>; let Documentation = [Undocumented]; let SimpleHandler = 1; @@ -1299,26 +1329,28 @@ def OpenCLIntelReqdSubGroupSize: InheritableAttr { // This attribute is both a type attribute, and a declaration attribute (for // parameter variables). def OpenCLAccess : Attr { - let Spellings = [Keyword<"__read_only">, Keyword<"read_only">, - Keyword<"__write_only">, Keyword<"write_only">, - Keyword<"__read_write">, Keyword<"read_write">]; + let Spellings = [CustomKeyword<"__read_only">, CustomKeyword<"read_only">, + CustomKeyword<"__write_only">, CustomKeyword<"write_only">, + CustomKeyword<"__read_write">, CustomKeyword<"read_write">]; let Subjects = SubjectList<[ParmVar, TypedefName], ErrorDiag>; - let Accessors = [Accessor<"isReadOnly", [Keyword<"__read_only">, - Keyword<"read_only">]>, - Accessor<"isReadWrite", [Keyword<"__read_write">, - Keyword<"read_write">]>, - Accessor<"isWriteOnly", [Keyword<"__write_only">, - Keyword<"write_only">]>]; + let Accessors = [Accessor<"isReadOnly", [CustomKeyword<"__read_only">, + CustomKeyword<"read_only">]>, + Accessor<"isReadWrite", [CustomKeyword<"__read_write">, + CustomKeyword<"read_write">]>, + Accessor<"isWriteOnly", [CustomKeyword<"__write_only">, + CustomKeyword<"write_only">]>]; let Documentation = [OpenCLAccessDocs]; } def OpenCLPrivateAddressSpace : TypeAttr { - let Spellings = [Keyword<"__private">, Keyword<"private">, Clang<"opencl_private">]; + let Spellings = [CustomKeyword<"__private">, CustomKeyword<"private">, + Clang<"opencl_private">]; let Documentation = [OpenCLAddressSpacePrivateDocs]; } def OpenCLGlobalAddressSpace : TypeAttr { - let Spellings = [Keyword<"__global">, Keyword<"global">, Clang<"opencl_global">]; + let Spellings = [CustomKeyword<"__global">, CustomKeyword<"global">, + Clang<"opencl_global">]; let Documentation = [OpenCLAddressSpaceGlobalDocs]; } @@ -1333,17 +1365,20 @@ def OpenCLGlobalHostAddressSpace : TypeAttr { } def OpenCLLocalAddressSpace : TypeAttr { - let Spellings = [Keyword<"__local">, Keyword<"local">, Clang<"opencl_local">]; + let Spellings = [CustomKeyword<"__local">, CustomKeyword<"local">, + Clang<"opencl_local">]; let Documentation = [OpenCLAddressSpaceLocalDocs]; } def OpenCLConstantAddressSpace : TypeAttr { - let Spellings = [Keyword<"__constant">, Keyword<"constant">, Clang<"opencl_constant">]; + let Spellings = [CustomKeyword<"__constant">, CustomKeyword<"constant">, + Clang<"opencl_constant">]; let Documentation = [OpenCLAddressSpaceConstantDocs]; } def OpenCLGenericAddressSpace : TypeAttr { - let Spellings = [Keyword<"__generic">, Keyword<"generic">, Clang<"opencl_generic">]; + let Spellings = [CustomKeyword<"__generic">, CustomKeyword<"generic">, + Clang<"opencl_generic">]; let Documentation = [OpenCLAddressSpaceGenericDocs]; } @@ -1447,9 +1482,8 @@ def : MutualExclusions<[Likely, Unlikely]>; def NoMerge : DeclOrStmtAttr { let Spellings = [Clang<"nomerge">]; let Documentation = [NoMergeDocs]; - let Subjects = SubjectList<[Function, Stmt], ErrorDiag, - "functions and statements">; - let SimpleHandler = 1; + let Subjects = SubjectList<[Function, Stmt, Var], ErrorDiag, + "functions, statements and variables">; } def MustTail : StmtAttr { @@ -1459,20 +1493,20 @@ def MustTail : StmtAttr { } def FastCall : DeclOrTypeAttr { - let Spellings = [GCC<"fastcall">, Keyword<"__fastcall">, - Keyword<"_fastcall">]; + let Spellings = [GCC<"fastcall">, CustomKeyword<"__fastcall">, + CustomKeyword<"_fastcall">]; // let Subjects = [Function, ObjCMethod]; let Documentation = [FastCallDocs]; } def RegCall : DeclOrTypeAttr { - let Spellings = [GCC<"regcall">, Keyword<"__regcall">]; + let Spellings = [GCC<"regcall">, CustomKeyword<"__regcall">]; let Documentation = [RegCallDocs]; } def Final : InheritableAttr { - let Spellings = [Keyword<"final">, Keyword<"sealed">]; - let Accessors = [Accessor<"isSpelledAsSealed", [Keyword<"sealed">]>]; + let Spellings = [CustomKeyword<"final">, CustomKeyword<"sealed">]; + let Accessors = [Accessor<"isSpelledAsSealed", [CustomKeyword<"sealed">]>]; let SemaHandler = 0; // Omitted from docs, since this is language syntax, not an attribute, as far // as users are concerned. @@ -1818,7 +1852,7 @@ def Convergent : InheritableAttr { } def NoInline : DeclOrStmtAttr { - let Spellings = [Keyword<"__noinline__">, GCC<"noinline">, + let Spellings = [CustomKeyword<"__noinline__">, GCC<"noinline">, CXX11<"clang", "noinline">, C2x<"clang", "noinline">, Declspec<"noinline">]; let Accessors = [Accessor<"isClangNoInline", [CXX11<"clang", "noinline">, @@ -1847,13 +1881,23 @@ def RISCVInterrupt : InheritableAttr, TargetSpecificAttr { let Spellings = [GCC<"interrupt">]; let Subjects = SubjectList<[Function]>; let Args = [EnumArgument<"Interrupt", "InterruptType", - ["user", "supervisor", "machine"], - ["user", "supervisor", "machine"], + ["supervisor", "machine"], + ["supervisor", "machine"], 1>]; let ParseKind = "Interrupt"; let Documentation = [RISCVInterruptDocs]; } +def RISCVRVVVectorBits : TypeAttr { + let Spellings = [GNU<"riscv_rvv_vector_bits">]; + let Subjects = SubjectList<[TypedefName], ErrorDiag>; + let Args = [UnsignedArgument<"NumBits">]; + let Documentation = [RISCVRVVVectorBitsDocs]; + let PragmaAttributeSupport = 0; + // Represented as VectorType instead. + let ASTNode = 0; +} + // This is not a TargetSpecificAttr so that is silently accepted and // ignored on other targets as encouraged by the OpenCL spec. // @@ -2004,22 +2048,22 @@ def PassObjectSize : InheritableParamAttr { // Nullability type attributes. def TypeNonNull : TypeAttr { - let Spellings = [Keyword<"_Nonnull">]; + let Spellings = [CustomKeyword<"_Nonnull">]; let Documentation = [TypeNonNullDocs]; } def TypeNullable : TypeAttr { - let Spellings = [Keyword<"_Nullable">]; + let Spellings = [CustomKeyword<"_Nullable">]; let Documentation = [TypeNullableDocs]; } def TypeNullableResult : TypeAttr { - let Spellings = [Keyword<"_Nullable_result">]; + let Spellings = [CustomKeyword<"_Nullable_result">]; let Documentation = [TypeNullableResultDocs]; } def TypeNullUnspecified : TypeAttr { - let Spellings = [Keyword<"_Null_unspecified">]; + let Spellings = [CustomKeyword<"_Null_unspecified">]; let Documentation = [TypeNullUnspecifiedDocs]; } @@ -2027,12 +2071,12 @@ def TypeNullUnspecified : TypeAttr { // ignored because ARC is not enabled. The usual representation for this // qualifier is as an ObjCOwnership attribute with Kind == "none". def ObjCInertUnsafeUnretained : TypeAttr { - let Spellings = [Keyword<"__unsafe_unretained">]; + let Spellings = [CustomKeyword<"__unsafe_unretained">]; let Documentation = [InternalOnly]; } def ObjCKindOf : TypeAttr { - let Spellings = [Keyword<"__kindof">]; + let Spellings = [CustomKeyword<"__kindof">]; let Documentation = [Undocumented]; } @@ -2331,7 +2375,7 @@ def Overloadable : Attr { } def Override : InheritableAttr { - let Spellings = [Keyword<"override">]; + let Spellings = [CustomKeyword<"override">]; let SemaHandler = 0; // Omitted from docs, since this is language syntax, not an attribute, as far // as users are concerned. @@ -2389,6 +2433,11 @@ def AArch64SVEPcs: DeclOrTypeAttr { let Documentation = [AArch64SVEPcsDocs]; } +def ArmStreaming : TypeAttr, TargetSpecificAttr { + let Spellings = [RegularKeyword<"__arm_streaming">]; + let Documentation = [ArmStreamingDocs]; +} + def Pure : InheritableAttr { let Spellings = [GCC<"pure">]; let Documentation = [Undocumented]; @@ -2576,7 +2625,8 @@ def Sentinel : InheritableAttr { } def StdCall : DeclOrTypeAttr { - let Spellings = [GCC<"stdcall">, Keyword<"__stdcall">, Keyword<"_stdcall">]; + let Spellings = [GCC<"stdcall">, CustomKeyword<"__stdcall">, + CustomKeyword<"_stdcall">]; // let Subjects = [Function, ObjCMethod]; let Documentation = [StdCallDocs]; } @@ -2645,15 +2695,15 @@ def SysVABI : DeclOrTypeAttr { } def ThisCall : DeclOrTypeAttr { - let Spellings = [GCC<"thiscall">, Keyword<"__thiscall">, - Keyword<"_thiscall">]; + let Spellings = [GCC<"thiscall">, CustomKeyword<"__thiscall">, + CustomKeyword<"_thiscall">]; // let Subjects = [Function, ObjCMethod]; let Documentation = [ThisCallDocs]; } def VectorCall : DeclOrTypeAttr { - let Spellings = [Clang<"vectorcall">, Keyword<"__vectorcall">, - Keyword<"_vectorcall">]; + let Spellings = [Clang<"vectorcall">, CustomKeyword<"__vectorcall">, + CustomKeyword<"_vectorcall">]; // let Subjects = [Function, ObjCMethod]; let Documentation = [VectorCallDocs]; } @@ -2672,7 +2722,8 @@ def ZeroCallUsedRegs : InheritableAttr { } def Pascal : DeclOrTypeAttr { - let Spellings = [Clang<"pascal">, Keyword<"__pascal">, Keyword<"_pascal">]; + let Spellings = [Clang<"pascal">, CustomKeyword<"__pascal">, + CustomKeyword<"_pascal">]; // let Subjects = [Function, ObjCMethod]; let Documentation = [Undocumented]; } @@ -2831,6 +2882,7 @@ def Unavailable : InheritableAttr { "IR_ARCInitReturnsUnrelated", "IR_ARCFieldWithOwnership"], 1, /*fake*/ 1>]; let Documentation = [Undocumented]; + let MeaningfulToClassTemplateDefinition = 1; } def DiagnoseIf : InheritableAttr { @@ -3568,37 +3620,37 @@ def Thread : Attr { } def Win64 : IgnoredAttr { - let Spellings = [Keyword<"__w64">]; + let Spellings = [CustomKeyword<"__w64">]; let LangOpts = [MicrosoftExt]; } def Ptr32 : TypeAttr { - let Spellings = [Keyword<"__ptr32">]; + let Spellings = [CustomKeyword<"__ptr32">]; let Documentation = [Ptr32Docs]; } def Ptr64 : TypeAttr { - let Spellings = [Keyword<"__ptr64">]; + let Spellings = [CustomKeyword<"__ptr64">]; let Documentation = [Ptr64Docs]; } def SPtr : TypeAttr { - let Spellings = [Keyword<"__sptr">]; + let Spellings = [CustomKeyword<"__sptr">]; let Documentation = [SPtrDocs]; } def UPtr : TypeAttr { - let Spellings = [Keyword<"__uptr">]; + let Spellings = [CustomKeyword<"__uptr">]; let Documentation = [UPtrDocs]; } def MSInheritance : InheritableAttr { let LangOpts = [MicrosoftExt]; let Args = [DefaultBoolArgument<"BestCase", /*default*/1, /*fake*/1>]; - let Spellings = [Keyword<"__single_inheritance">, - Keyword<"__multiple_inheritance">, - Keyword<"__virtual_inheritance">, - Keyword<"__unspecified_inheritance">]; + let Spellings = [CustomKeyword<"__single_inheritance">, + CustomKeyword<"__multiple_inheritance">, + CustomKeyword<"__virtual_inheritance">, + CustomKeyword<"__unspecified_inheritance">]; let AdditionalMembers = [{ MSInheritanceModel getInheritanceModel() const { // The spelling enum should agree with MSInheritanceModel. @@ -3966,6 +4018,12 @@ def ReleaseHandle : InheritableParamAttr { let Documentation = [ReleaseHandleDocs]; } +def UnsafeBufferUsage : InheritableAttr { + let Spellings = [Clang<"unsafe_buffer_usage">]; + let Subjects = SubjectList<[Function]>; + let Documentation = [UnsafeBufferUsageDocs]; +} + def DiagnoseAsBuiltin : InheritableAttr { let Spellings = [Clang<"diagnose_as_builtin">]; let Args = [DeclArgument, @@ -4092,7 +4150,7 @@ def HLSLResource : InheritableAttr { } def HLSLGroupSharedAddressSpace : TypeAttr { - let Spellings = [Keyword<"groupshared">]; + let Spellings = [CustomKeyword<"groupshared">]; let Subjects = SubjectList<[Var]>; let Documentation = [HLSLGroupSharedAddressSpaceDocs]; } @@ -4122,8 +4180,22 @@ def FunctionReturnThunks : InheritableAttr, let Subjects = SubjectList<[Function]>; let Documentation = [FunctionReturnThunksDocs]; } + +def WebAssemblyFuncref : TypeAttr, TargetSpecificAttr { + let Spellings = [CustomKeyword<"__funcref">]; + let Documentation = [WebAssemblyExportNameDocs]; + let Subjects = SubjectList<[FunctionPointer], ErrorDiag>; +} + def ReadOnlyPlacement : InheritableAttr { let Spellings = [Clang<"enforce_read_only_placement">]; let Subjects = SubjectList<[Record]>; let Documentation = [ReadOnlyPlacementDocs]; } + +def AvailableOnlyInDefaultEvalMethod : InheritableAttr { + let Spellings = [Clang<"available_only_in_default_eval_method">]; + let Subjects = SubjectList<[TypedefName], ErrorDiag>; + let Documentation = [Undocumented]; +} + diff --git a/contrib/llvm-project/clang/include/clang/Basic/AttrDocs.td b/contrib/llvm-project/clang/include/clang/Basic/AttrDocs.td index 6d7a3ffd2d5..2c950231255 100644 --- a/contrib/llvm-project/clang/include/clang/Basic/AttrDocs.td +++ b/contrib/llvm-project/clang/include/clang/Basic/AttrDocs.td @@ -539,17 +539,41 @@ def NoMergeDocs : Documentation { let Category = DocCatStmt; let Content = [{ If a statement is marked ``nomerge`` and contains call expressions, those call -expressions inside the statement will not be merged during optimization. This +expressions inside the statement will not be merged during optimization. This attribute can be used to prevent the optimizer from obscuring the source location of certain calls. For example, it will prevent tail merging otherwise identical code sequences that raise an exception or terminate the program. Tail merging normally reduces the precision of source location information, making stack traces less useful for debugging. This attribute gives the user control -over the tradeoff between code size and debug information precision. +over the tradeoff between code size and debug information precision. -``nomerge`` attribute can also be used as function attribute to prevent all -calls to the specified function from merging. It has no effect on indirect -calls. +``nomerge`` attribute can also be used as function attribute to prevent all +calls to the specified function from merging. It has no effect on indirect +calls to such functions. For example: + +.. code-block:: c++ + + [[clang::nomerge]] void foo(int) {} + + void bar(int x) { + auto *ptr = foo; + if (x) foo(1); else foo(2); // will not be merged + if (x) ptr(1); else ptr(2); // indirect call, can be merged + } + +``nomerge`` attribute can also be used for pointers to functions to +prevent calls through such pointer from merging. In such case the +effect applies only to a specific function pointer. For example: + +.. code-block:: c++ + + [[clang::nomerge]] void (*foo)(int); + + void bar(int x) { + auto *ptr = foo; + if (x) foo(1); else foo(2); // will not be merged + if (x) ptr(1); else ptr(2); // 'ptr' has no 'nomerge' attribute, can be merged + } }]; } @@ -603,6 +627,9 @@ Any variables in scope, including all arguments to the function and the return value must be trivially destructible. The calling convention of the caller and callee must match, and they must not be variadic functions or have old style K&R C function declarations. + +``clang::musttail`` provides assurances that the tail call can be optimized on +all targets, not just one. }]; } @@ -1581,7 +1608,7 @@ attributes are ignored. Supported platforms are: ``watchos`` Apple's watchOS operating system. The minimum deployment target is specified by the ``-mwatchos-version-min=*version*`` command-line argument. - + ``driverkit`` Apple's DriverKit userspace kernel extensions. The minimum deployment target is specified as part of the triple. @@ -1750,6 +1777,19 @@ defined_in=\ *string-literal* source containers are modules, so ``defined_in`` should specify the Swift module name. +USR=\ *string-literal* + String that specifies a unified symbol resolution (USR) value for this + declaration. USR string uniquely identifies this particular declaration, and + is typically used when constructing an index of a codebase. + The USR value in this attribute is expected to be generated by an external + compiler that compiled the native declaration using its original source + language. The exact format of the USR string and its other attributes + are determined by the specification of this declaration's source language. + When not specified, Clang's indexer will use the Clang USR for this symbol. + User can query to see if Clang supports the use of the ``USR`` clause in + the ``external_source_symbol`` attribute with + ``__has_attribute(external_source_symbol) >= 20230206``. + generated_declaration This declaration was automatically generated by some tool. @@ -2280,7 +2320,7 @@ as ``-mlong-calls`` and ``-mno-long-calls``. def RISCVInterruptDocs : Documentation { let Category = DocCatFunction; - let Heading = "interrupt (RISCV)"; + let Heading = "interrupt (RISC-V)"; let Content = [{ Clang supports the GNU style ``__attribute__((interrupt))`` attribute on RISCV targets. This attribute may be attached to a function definition and instructs @@ -2301,6 +2341,40 @@ Version 1.10. }]; } +def RISCVRVVVectorBitsDocs : Documentation { + let Category = DocCatType; + let Content = [{ +On RISC-V targets, the ``riscv_rvv_vector_bits(N)`` attribute is used to define +fixed-length variants of sizeless types. + +For example: + +.. code-block:: c + + #include + + #if defined(__riscv_v_fixed_vlen) + typedef vint8m1_t fixed_vint8m1_t __attribute__((riscv_rvv_vector_bits(__riscv_v_fixed_vlen))); + #endif + +Creates a type ``fixed_vint8m1_t_t`` that is a fixed-length variant of +``vint8m1_t`` that contains exactly 512 bits. Unlike ``vint8m1_t``, this type +can be used in globals, structs, unions, and arrays, all of which are +unsupported for sizeless types. + +The attribute can be attached to a single RVV vector (such as ``vint8m1_t``). +The attribute will be rejected unless +``N==(__riscv_v_fixed_vlen*LMUL)``, the implementation defined feature macro that +is enabled under the ``-mrvv-vector-bits`` flag. ``__riscv_v_fixed_vlen`` can +only be a power of 2 between 64 and 65536. + +For types where LMUL!=1, ``__riscv_v_fixed_vlen`` needs to be scaled by the LMUL +of the type before passing to the attribute. + +``vbool*_t`` types are not supported at this time. +}]; +} + def AVRInterruptDocs : Documentation { let Category = DocCatFunction; let Heading = "interrupt (AVR)"; @@ -3883,7 +3957,7 @@ Whether a particular pointer may be "null" is an important concern when working with pointers in the C family of languages. The various nullability attributes indicate whether a particular pointer can be null or not, which makes APIs more expressive and can help static analysis tools identify bugs involving null -pointers. Clang supports several kinds of nullability attributes: the +pointers. Clang supports several kinds of nullability attributes: the ``nonnull`` and ``returns_nonnull`` attributes indicate which function or method parameters and result types can never be null, while nullability type qualifiers indicate which pointer types can be null (``_Nullable``) or cannot @@ -4059,7 +4133,7 @@ memory is not available rather than returning a null pointer: The ``returns_nonnull`` attribute implies that returning a null pointer is undefined behavior, which the optimizer may take advantage of. The ``_Nonnull`` type qualifier indicates that a pointer cannot be null in a more general manner -(because it is part of the type system) and does not imply undefined behavior, +(because it is part of the type system) and does not imply undefined behavior, making it more widely applicable }]; } @@ -5166,6 +5240,9 @@ apply for values returned in callee-saved registers. R11. R11 can be used as a scratch register. Floating-point registers (XMMs/YMMs) are not preserved and need to be saved by the caller. +- On AArch64 the callee preserve all general purpose registers, except X0-X8 and + X16-X18. + The idea behind this convention is to support calls to runtime functions that have a hot path and a cold path. The hot path is usually a small piece of code that doesn't use many registers. The cold path might need to call out to @@ -5206,6 +5283,10 @@ returned in callee-saved registers. R11. R11 can be used as a scratch register. Furthermore it also preserves all floating-point registers (XMMs/YMMs). +- On AArch64 the callee preserve all general purpose registers, except X0-X8 and + X16-X18. Furthermore it also preserves lower 128 bits of V8-V31 SIMD - floating + point registers. + The idea behind this convention is to support calls to runtime functions that don't need to call out to any other functions. @@ -5315,7 +5396,7 @@ takes precedence over the command line option ``-fpatchable-function-entry=N,M`` ``M`` defaults to 0 if omitted. This attribute is only supported on -aarch64/aarch64-be/riscv32/riscv64/i386/x86-64 targets. +aarch64/aarch64-be/loongarch32/loongarch64/riscv32/riscv64/i386/x86-64 targets. }]; } @@ -6008,15 +6089,15 @@ def CFGuardDocs : Documentation { let Content = [{ Code can indicate CFG checks are not wanted with the ``__declspec(guard(nocf))`` attribute. This directs the compiler to not insert any CFG checks for the entire -function. This approach is typically used only sparingly in specific situations -where the programmer has manually inserted "CFG-equivalent" protection. The -programmer knows that they are calling through some read-only function table -whose address is obtained through read-only memory references and for which the -index is masked to the function table limit. This approach may also be applied -to small wrapper functions that are not inlined and that do nothing more than -make a call through a function pointer. Since incorrect usage of this directive -can compromise the security of CFG, the programmer must be very careful using -the directive. Typically, this usage is limited to very small functions that +function. This approach is typically used only sparingly in specific situations +where the programmer has manually inserted "CFG-equivalent" protection. The +programmer knows that they are calling through some read-only function table +whose address is obtained through read-only memory references and for which the +index is masked to the function table limit. This approach may also be applied +to small wrapper functions that are not inlined and that do nothing more than +make a call through a function pointer. Since incorrect usage of this directive +can compromise the security of CFG, the programmer must be very careful using +the directive. Typically, this usage is limited to very small functions that only call one function. `Control Flow Guard documentation ` @@ -6274,6 +6355,84 @@ attribute requires a string literal argument to identify the handle being releas }]; } +def UnsafeBufferUsageDocs : Documentation { + let Category = DocCatFunction; + let Content = [{ +The attribute ``[[clang::unsafe_buffer_usage]]`` should be placed on functions +that need to be avoided as they are prone to buffer overflows. It is designed to +work together with the off-by-default compiler warning ``-Wunsafe-buffer-usage`` +to help codebases transition away from raw pointer based buffer management, +in favor of safer abstractions such as C++20 ``std::span``. The attribute causes +``-Wunsafe-buffer-usage`` to warn on every use of the function, and it may +enable ``-Wunsafe-buffer-usage`` to emit automatic fix-it hints +which would help the user replace such unsafe functions with safe +alternatives, though the attribute can be used even when the fix can't be automated. + +The attribute does not suppress ``-Wunsafe-buffer-usage`` inside the function +to which it is attached. These warnings still need to be addressed. + +The attribute is warranted even if the only way a function can overflow +the buffer is by violating the function's preconditions. For example, it +would make sense to put the attribute on function ``foo()`` below because +passing an incorrect size parameter would cause a buffer overflow: + +.. code-block:: c++ + + [[clang::unsafe_buffer_usage]] + void foo(int *buf, size_t size) { + for (size_t i = 0; i < size; ++i) { + buf[i] = i; + } + } + +The attribute is NOT warranted when the function uses safe abstractions, +assuming that these abstractions weren't misused outside the function. +For example, function ``bar()`` below doesn't need the attribute, +because assuming that the container ``buf`` is well-formed (has size that +fits the original buffer it refers to), overflow cannot occur: + +.. code-block:: c++ + + void bar(std::span buf) { + for (size_t i = 0; i < buf.size(); ++i) { + buf[i] = i; + } + } + +In this case function ``bar()`` enables the user to keep the buffer +"containerized" in a span for as long as possible. On the other hand, +Function ``foo()`` in the previous example may have internal +consistency, but by accepting a raw buffer it requires the user to unwrap +their span, which is undesirable according to the programming model +behind ``-Wunsafe-buffer-usage``. + +The attribute is warranted when a function accepts a raw buffer only to +immediately put it into a span: + +.. code-block:: c++ + + [[clang::unsafe_buffer_usage]] + void baz(int *buf, size_t size) { + std::span sp{ buf, size }; + for (size_t i = 0; i < sp.size(); ++i) { + sp[i] = i; + } + } + +In this case ``baz()`` does not contain any unsafe operations, but the awkward +parameter type causes the caller to unwrap the span unnecessarily. +Note that regardless of the attribute, code inside ``baz()`` isn't flagged +by ``-Wunsafe-buffer-usage`` as unsafe. It is definitely undesirable, +but if ``baz()`` is on an API surface, there is no way to improve it +to make it as safe as ``bar()`` without breaking the source and binary +compatibility with existing users of the function. In such cases +the proper solution would be to create a different function (possibly +an overload of ``baz()``) that accepts a safe container like ``bar()``, +and then use the attribute on the original ``baz()`` to help the users +update their code to use the new function. + }]; +} + def DiagnoseAsBuiltinDocs : Documentation { let Category = DocCatFunction; let Content = [{ @@ -6419,6 +6578,41 @@ Requirements on Development Tools - Engineering Specification Documentation }]; } +def ArmStreamingDocs : Documentation { + let Category = DocCatType; + let Content = [{ +.. Note:: This attribute has not been implemented yet, but once it is + implemented, it will behave as described below. + +The ``__arm_streaming`` keyword is only available on AArch64 targets. +It applies to function types and specifies that the function has a +"streaming interface". This means that: + +* the function requires the Scalable Matrix Extension (SME) + +* the function must be entered in streaming mode (that is, with PSTATE.SM + set to 1) + +* the function must return in streaming mode + +See `Procedure Call Standard for the Arm® 64-bit Architecture (AArch64) +`_ for more details about +streaming-interface functions. + +Clang manages PSTATE.SM automatically; it is not the source code's +responsibility to do this. For example, if a normal non-streaming +function calls an ``__arm_streaming`` function, Clang generates code +that switches into streaming mode before calling the function and +switches back to non-streaming mode on return. + +``__arm_streaming`` can appear anywhere that a standard ``[[...]]`` type +attribute can appear. + +See `Arm C Language Extensions `_ +for more details about this extension, and for other related SME features. + }]; +} + def AlwaysInlineDocs : Documentation { let Category = DocCatFunction; let Content = [{ @@ -6847,3 +7041,39 @@ def ReadOnlyPlacementDocs : Documentation { ``enforce_read_only_placement`` attribute. }]; } + +def WebAssemblyFuncrefDocs : Documentation { + let Category = DocCatType; + let Content = [{ +Clang supports the ``__funcref`` attribute for the WebAssembly target. +This attribute may be attached to a function pointer type, where it modifies +its underlying representation to be a WebAssembly ``funcref``. + }]; +} + +def CleanupDocs : Documentation { + let Category = DocCatType; + let Content = [{ +This attribute allows a function to be run when a local variable goes out of +scope. The attribute takes the identifier of a function with a parameter type +that is a pointer to the type with the attribute. + +.. code-block:: c + + static void foo (int *) { ... } + static void bar (int *) { ... } + void baz (void) { + int x __attribute__((cleanup(foo))); + { + int y __attribute__((cleanup(bar))); + } + } + +The above example will result in a call to ``bar`` being passed the address of +`y`` when ``y`` goes out of scope, then a call to ``foo`` being passed the +address of ``x`` when ``x`` goes out of scope. If two or more variables share +the same scope, their ``cleanup`` callbacks are invoked in the reverse order +the variables were declared in. It is not possible to check the return value +(if any) of these ``cleanup`` callback functions. +}]; +} diff --git a/contrib/llvm-project/clang/include/clang/Basic/AttributeCommonInfo.h b/contrib/llvm-project/clang/include/clang/Basic/AttributeCommonInfo.h index 81a8d213419..6396c0dc6ef 100644 --- a/contrib/llvm-project/clang/include/clang/Basic/AttributeCommonInfo.h +++ b/contrib/llvm-project/clang/include/clang/Basic/AttributeCommonInfo.h @@ -14,6 +14,7 @@ #ifndef LLVM_CLANG_BASIC_ATTRIBUTECOMMONINFO_H #define LLVM_CLANG_BASIC_ATTRIBUTECOMMONINFO_H #include "clang/Basic/SourceLocation.h" +#include "clang/Basic/TokenKinds.h" namespace clang { class IdentifierInfo; @@ -24,7 +25,7 @@ public: /// The style used to specify an attribute. enum Syntax { /// __attribute__((...)) - AS_GNU, + AS_GNU = 1, /// [[...]] AS_CXX11, @@ -51,6 +52,10 @@ public: /// : AS_HLSLSemantic, + + /// The attibute has no source code manifestation and is only created + /// implicitly. + AS_Implicit }; enum Kind { #define PARSED_ATTR(NAME) AT_##NAME, @@ -71,63 +76,96 @@ private: /// Corresponds to the Syntax enum. unsigned SyntaxUsed : 4; unsigned SpellingIndex : 4; + unsigned IsAlignas : 1; + unsigned IsRegularKeywordAttribute : 1; protected: static constexpr unsigned SpellingNotCalculated = 0xf; public: - AttributeCommonInfo(SourceRange AttrRange) - : AttrRange(AttrRange), ScopeLoc(), AttrKind(0), SyntaxUsed(0), - SpellingIndex(SpellingNotCalculated) {} + /// Combines information about the source-code form of an attribute, + /// including its syntax and spelling. + class Form { + public: + constexpr Form(Syntax SyntaxUsed, unsigned SpellingIndex, bool IsAlignas, + bool IsRegularKeywordAttribute) + : SyntaxUsed(SyntaxUsed), SpellingIndex(SpellingIndex), + IsAlignas(IsAlignas), + IsRegularKeywordAttribute(IsRegularKeywordAttribute) {} + constexpr Form(tok::TokenKind Tok) + : SyntaxUsed(AS_Keyword), SpellingIndex(SpellingNotCalculated), + IsAlignas(Tok == tok::kw_alignas), + IsRegularKeywordAttribute(tok::isRegularKeywordAttribute(Tok)) {} - AttributeCommonInfo(SourceLocation AttrLoc) - : AttrRange(AttrLoc), ScopeLoc(), AttrKind(0), SyntaxUsed(0), - SpellingIndex(SpellingNotCalculated) {} + Syntax getSyntax() const { return Syntax(SyntaxUsed); } + unsigned getSpellingIndex() const { return SpellingIndex; } + bool isAlignas() const { return IsAlignas; } + bool isRegularKeywordAttribute() const { return IsRegularKeywordAttribute; } + + static Form GNU() { return AS_GNU; } + static Form CXX11() { return AS_CXX11; } + static Form C2x() { return AS_C2x; } + static Form Declspec() { return AS_Declspec; } + static Form Microsoft() { return AS_Microsoft; } + static Form Keyword(bool IsAlignas, bool IsRegularKeywordAttribute) { + return Form(AS_Keyword, SpellingNotCalculated, IsAlignas, + IsRegularKeywordAttribute); + } + static Form Pragma() { return AS_Pragma; } + static Form ContextSensitiveKeyword() { return AS_ContextSensitiveKeyword; } + static Form HLSLSemantic() { return AS_HLSLSemantic; } + static Form Implicit() { return AS_Implicit; } + + private: + constexpr Form(Syntax SyntaxUsed) + : SyntaxUsed(SyntaxUsed), SpellingIndex(SpellingNotCalculated), + IsAlignas(0), IsRegularKeywordAttribute(0) {} + + unsigned SyntaxUsed : 4; + unsigned SpellingIndex : 4; + unsigned IsAlignas : 1; + unsigned IsRegularKeywordAttribute : 1; + }; AttributeCommonInfo(const IdentifierInfo *AttrName, const IdentifierInfo *ScopeName, SourceRange AttrRange, - SourceLocation ScopeLoc, Syntax SyntaxUsed) + SourceLocation ScopeLoc, Kind AttrKind, Form FormUsed) : AttrName(AttrName), ScopeName(ScopeName), AttrRange(AttrRange), - ScopeLoc(ScopeLoc), - AttrKind(getParsedKind(AttrName, ScopeName, SyntaxUsed)), - SyntaxUsed(SyntaxUsed), SpellingIndex(SpellingNotCalculated) {} + ScopeLoc(ScopeLoc), AttrKind(AttrKind), + SyntaxUsed(FormUsed.getSyntax()), + SpellingIndex(FormUsed.getSpellingIndex()), + IsAlignas(FormUsed.isAlignas()), + IsRegularKeywordAttribute(FormUsed.isRegularKeywordAttribute()) { + assert(SyntaxUsed >= AS_GNU && SyntaxUsed <= AS_Implicit && + "Invalid syntax!"); + } AttributeCommonInfo(const IdentifierInfo *AttrName, const IdentifierInfo *ScopeName, SourceRange AttrRange, - SourceLocation ScopeLoc, Kind AttrKind, Syntax SyntaxUsed) - : AttrName(AttrName), ScopeName(ScopeName), AttrRange(AttrRange), - ScopeLoc(ScopeLoc), AttrKind(AttrKind), SyntaxUsed(SyntaxUsed), - SpellingIndex(SpellingNotCalculated) {} - - AttributeCommonInfo(const IdentifierInfo *AttrName, - const IdentifierInfo *ScopeName, SourceRange AttrRange, - SourceLocation ScopeLoc, Kind AttrKind, Syntax SyntaxUsed, - unsigned Spelling) - : AttrName(AttrName), ScopeName(ScopeName), AttrRange(AttrRange), - ScopeLoc(ScopeLoc), AttrKind(AttrKind), SyntaxUsed(SyntaxUsed), - SpellingIndex(Spelling) {} + SourceLocation ScopeLoc, Form FormUsed) + : AttributeCommonInfo( + AttrName, ScopeName, AttrRange, ScopeLoc, + getParsedKind(AttrName, ScopeName, FormUsed.getSyntax()), + FormUsed) {} AttributeCommonInfo(const IdentifierInfo *AttrName, SourceRange AttrRange, - Syntax SyntaxUsed) - : AttrName(AttrName), ScopeName(nullptr), AttrRange(AttrRange), - ScopeLoc(), AttrKind(getParsedKind(AttrName, ScopeName, SyntaxUsed)), - SyntaxUsed(SyntaxUsed), SpellingIndex(SpellingNotCalculated) {} + Form FormUsed) + : AttributeCommonInfo(AttrName, nullptr, AttrRange, SourceLocation(), + FormUsed) {} - AttributeCommonInfo(SourceRange AttrRange, Kind K, Syntax SyntaxUsed) - : AttrName(nullptr), ScopeName(nullptr), AttrRange(AttrRange), ScopeLoc(), - AttrKind(K), SyntaxUsed(SyntaxUsed), - SpellingIndex(SpellingNotCalculated) {} - - AttributeCommonInfo(SourceRange AttrRange, Kind K, Syntax SyntaxUsed, - unsigned Spelling) - : AttrName(nullptr), ScopeName(nullptr), AttrRange(AttrRange), ScopeLoc(), - AttrKind(K), SyntaxUsed(SyntaxUsed), SpellingIndex(Spelling) {} + AttributeCommonInfo(SourceRange AttrRange, Kind K, Form FormUsed) + : AttributeCommonInfo(nullptr, nullptr, AttrRange, SourceLocation(), K, + FormUsed) {} AttributeCommonInfo(AttributeCommonInfo &&) = default; AttributeCommonInfo(const AttributeCommonInfo &) = default; Kind getParsedKind() const { return Kind(AttrKind); } Syntax getSyntax() const { return Syntax(SyntaxUsed); } + Form getForm() const { + return Form(getSyntax(), SpellingIndex, IsAlignas, + IsRegularKeywordAttribute); + } const IdentifierInfo *getAttrName() const { return AttrName; } SourceLocation getLoc() const { return AttrRange.getBegin(); } SourceRange getRange() const { return AttrRange; } @@ -148,29 +186,7 @@ public: bool isGNUScope() const; bool isClangScope() const; - bool isAlignasAttribute() const { - // FIXME: Use a better mechanism to determine this. - // We use this in `isCXX11Attribute` below, so it _should_ only return - // true for the `alignas` spelling, but it currently also returns true - // for the `_Alignas` spelling, which only exists in C11. Distinguishing - // between the two is important because they behave differently: - // - `alignas` may only appear in the attribute-specifier-seq before - // the decl-specifier-seq and is therefore associated with the - // declaration. - // - `_Alignas` may appear anywhere within the declaration-specifiers - // and is therefore associated with the `DeclSpec`. - // It's not clear how best to fix this: - // - We have the necessary information in the form of the `SpellingIndex`, - // but we would need to compare against AlignedAttr::Keyword_alignas, - // and we can't depend on clang/AST/Attr.h here. - // - We could test `getAttrName()->getName() == "alignas"`, but this is - // inefficient. - return getParsedKind() == AT_Aligned && isKeywordAttribute(); - } - - bool isCXX11Attribute() const { - return SyntaxUsed == AS_CXX11 || isAlignasAttribute(); - } + bool isCXX11Attribute() const { return SyntaxUsed == AS_CXX11 || IsAlignas; } bool isC2xAttribute() const { return SyntaxUsed == AS_C2x; } @@ -186,6 +202,8 @@ public: return SyntaxUsed == AS_Keyword || SyntaxUsed == AS_ContextSensitiveKeyword; } + bool isRegularKeywordAttribute() const { return IsRegularKeywordAttribute; } + bool isContextSensitiveKeywordAttribute() const { return SyntaxUsed == AS_ContextSensitiveKeyword; } diff --git a/contrib/llvm-project/clang/include/clang/Basic/Builtins.def b/contrib/llvm-project/clang/include/clang/Basic/Builtins.def index 41f12455644..6dad8b512bd 100644 --- a/contrib/llvm-project/clang/include/clang/Basic/Builtins.def +++ b/contrib/llvm-project/clang/include/clang/Basic/Builtins.def @@ -39,6 +39,8 @@ // A -> "reference" to __builtin_va_list // V -> Vector, followed by the number of elements and the base type. // q -> Scalable vector, followed by the number of elements and the base type. +// Q -> target builtin type, followed by a character to distinguish the builtin type +// Qa -> AArch64 svcount_t builtin type. // E -> ext_vector, followed by the number of elements and the base type. // X -> _Complex, followed by the base type. // Y -> ptrdiff_t @@ -141,6 +143,7 @@ BUILTIN(__builtin_frexp , "ddi*" , "Fn") BUILTIN(__builtin_frexpf, "ffi*" , "Fn") BUILTIN(__builtin_frexpl, "LdLdi*", "Fn") BUILTIN(__builtin_frexpf128, "LLdLLdi*", "Fn") +BUILTIN(__builtin_frexpf16, "hhi*" , "Fn") BUILTIN(__builtin_huge_val, "d", "ncE") BUILTIN(__builtin_huge_valf, "f", "ncE") BUILTIN(__builtin_huge_vall, "Ld", "ncE") @@ -157,6 +160,7 @@ BUILTIN(__builtin_ldexp , "ddi" , "Fne") BUILTIN(__builtin_ldexpf, "ffi" , "Fne") BUILTIN(__builtin_ldexpl, "LdLdi", "Fne") BUILTIN(__builtin_ldexpf128, "LLdLLdi", "Fne") +BUILTIN(__builtin_ldexpf16, "hhi", "Fne") BUILTIN(__builtin_modf , "ddd*" , "Fn") BUILTIN(__builtin_modff, "fff*" , "Fn") BUILTIN(__builtin_modfl, "LdLdLd*", "Fn") @@ -350,6 +354,11 @@ BUILTIN(__builtin_roundf, "ff" , "Fnc") BUILTIN(__builtin_roundf16, "hh" , "Fnc") BUILTIN(__builtin_roundl, "LdLd" , "Fnc") BUILTIN(__builtin_roundf128, "LLdLLd" , "Fnc") +BUILTIN(__builtin_roundeven, "dd" , "Fnc") +BUILTIN(__builtin_roundevenf, "ff" , "Fnc") +BUILTIN(__builtin_roundevenf16, "hh" , "Fnc") +BUILTIN(__builtin_roundevenl, "LdLd" , "Fnc") +BUILTIN(__builtin_roundevenf128, "LLdLLd" , "Fnc") BUILTIN(__builtin_scalbln , "ddLi", "Fne") BUILTIN(__builtin_scalblnf, "ffLi", "Fne") BUILTIN(__builtin_scalblnl, "LdLdLi", "Fne") @@ -392,6 +401,7 @@ BUILTIN(__builtin_truncf16, "hh", "Fnc") // Access to floating point environment BUILTIN(__builtin_flt_rounds, "i", "n") +BUILTIN(__builtin_set_flt_rounds, "vi", "n") // C99 complex builtins BUILTIN(__builtin_cabs, "dXd", "Fne") @@ -479,6 +489,7 @@ BUILTIN(__builtin_isinf, "i.", "FnctE") BUILTIN(__builtin_isinf_sign, "i.", "FnctE") BUILTIN(__builtin_isnan, "i.", "FnctE") BUILTIN(__builtin_isnormal, "i.", "FnctE") +BUILTIN(__builtin_isfpclass, "i.", "nctE") // FP signbit builtins BUILTIN(__builtin_signbit, "i.", "Fnct") @@ -551,7 +562,6 @@ BUILTIN(__builtin_assume_aligned, "v*vC*z.", "nctE") BUILTIN(__builtin_bcmp, "ivC*vC*z", "FnE") BUILTIN(__builtin_bcopy, "vv*v*z", "n") BUILTIN(__builtin_bzero, "vv*z", "nF") -BUILTIN(__builtin_fprintf, "iP*cC*.", "Fp:1:") BUILTIN(__builtin_free, "vv*", "nF") BUILTIN(__builtin_malloc, "v*z", "nF") BUILTIN(__builtin_memchr, "v*vC*iz", "nFE") @@ -562,7 +572,6 @@ BUILTIN(__builtin_memmove, "v*v*vC*z", "nFE") BUILTIN(__builtin_mempcpy, "v*v*vC*z", "nF") BUILTIN(__builtin_memset, "v*v*iz", "nF") BUILTIN(__builtin_memset_inline, "vv*iIz", "n") -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") @@ -599,10 +608,20 @@ BUILTIN(__builtin_setjmp, "iv**", "j") BUILTIN(__builtin_longjmp, "vv**i", "r") BUILTIN(__builtin_unwind_init, "v", "") BUILTIN(__builtin_eh_return_data_regno, "iIi", "ncE") -BUILTIN(__builtin_snprintf, "ic*zcC*.", "nFp:2:") -BUILTIN(__builtin_sprintf, "ic*cC*.", "nFP:1:") -BUILTIN(__builtin_vsnprintf, "ic*zcC*a", "nFP:2:") -BUILTIN(__builtin_vsprintf, "ic*cC*a", "nFP:1:") +BUILTIN(__builtin_fprintf, "iP*RcC*R.", "nFp:1:") +BUILTIN(__builtin_printf, "icC*R.", "nFp:0:") +BUILTIN(__builtin_sprintf, "ic*RcC*R.", "nFp:1:") +BUILTIN(__builtin_snprintf, "ic*RzcC*R.", "nFp:2:") +BUILTIN(__builtin_vprintf, "icC*Ra", "nFP:0:") +BUILTIN(__builtin_vfprintf, "iP*RcC*Ra", "nFP:1:") +BUILTIN(__builtin_vsprintf, "ic*RcC*Ra", "nFP:1:") +BUILTIN(__builtin_vsnprintf, "ic*RzcC*Ra", "nFP:2:") +BUILTIN(__builtin_fscanf, "iP*RcC*R.", "Fs:1:") +BUILTIN(__builtin_scanf, "icC*R.", "Fs:0:") +BUILTIN(__builtin_sscanf, "icC*RcC*R.", "Fs:1:") +BUILTIN(__builtin_vfscanf, "iP*RcC*Ra", "FS:1:") +BUILTIN(__builtin_vscanf, "icC*Ra", "FS:0:") +BUILTIN(__builtin_vsscanf, "icC*RcC*Ra", "FS:1:") BUILTIN(__builtin_thread_pointer, "v*", "nc") BUILTIN(__builtin_launder, "v*v*", "ntE") LANGBUILTIN(__builtin_is_constant_evaluated, "b", "nE", CXX_LANG) @@ -631,14 +650,14 @@ 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___snprintf_chk, "ic*RzizcC*R.", "Fp:4:") +BUILTIN(__builtin___sprintf_chk, "ic*RizcC*R.", "Fp:3:") +BUILTIN(__builtin___vsnprintf_chk, "ic*RzizcC*Ra", "FP:4:") +BUILTIN(__builtin___vsprintf_chk, "ic*RizcC*Ra", "FP:3:") +BUILTIN(__builtin___fprintf_chk, "iP*RicC*R.", "Fp:2:") +BUILTIN(__builtin___printf_chk, "iicC*R.", "Fp:1:") +BUILTIN(__builtin___vfprintf_chk, "iP*RicC*Ra", "FP:2:") +BUILTIN(__builtin___vprintf_chk, "iicC*Ra", "FP:1:") BUILTIN(__builtin_unpredictable, "LiLi" , "nc") BUILTIN(__builtin_expect, "LiLiLi" , "ncE") @@ -655,18 +674,29 @@ BUILTIN(__builtin_alloca_uninitialized, "v*z", "Fn") BUILTIN(__builtin_alloca_with_align, "v*zIz", "Fn") BUILTIN(__builtin_alloca_with_align_uninitialized, "v*zIz", "Fn") BUILTIN(__builtin_call_with_static_chain, "v.", "nt") +BUILTIN(__builtin_nondeterministic_value, "v.", "nt") BUILTIN(__builtin_elementwise_abs, "v.", "nct") BUILTIN(__builtin_elementwise_max, "v.", "nct") BUILTIN(__builtin_elementwise_min, "v.", "nct") BUILTIN(__builtin_elementwise_ceil, "v.", "nct") BUILTIN(__builtin_elementwise_cos, "v.", "nct") +BUILTIN(__builtin_elementwise_exp, "v.", "nct") +BUILTIN(__builtin_elementwise_exp2, "v.", "nct") BUILTIN(__builtin_elementwise_floor, "v.", "nct") +BUILTIN(__builtin_elementwise_log, "v.", "nct") +BUILTIN(__builtin_elementwise_log2, "v.", "nct") +BUILTIN(__builtin_elementwise_log10, "v.", "nct") +BUILTIN(__builtin_elementwise_pow, "v.", "nct") BUILTIN(__builtin_elementwise_roundeven, "v.", "nct") +BUILTIN(__builtin_elementwise_round, "v.", "nct") +BUILTIN(__builtin_elementwise_rint, "v.", "nct") +BUILTIN(__builtin_elementwise_nearbyint, "v.", "nct") BUILTIN(__builtin_elementwise_sin, "v.", "nct") BUILTIN(__builtin_elementwise_trunc, "v.", "nct") BUILTIN(__builtin_elementwise_canonicalize, "v.", "nct") BUILTIN(__builtin_elementwise_copysign, "v.", "nct") +BUILTIN(__builtin_elementwise_fma, "v.", "nct") BUILTIN(__builtin_elementwise_add_sat, "v.", "nct") BUILTIN(__builtin_elementwise_sub_sat, "v.", "nct") BUILTIN(__builtin_reduce_max, "v.", "nct") @@ -889,6 +919,7 @@ ATOMIC_BUILTIN(__hip_atomic_compare_exchange_weak, "v.", "t") ATOMIC_BUILTIN(__hip_atomic_compare_exchange_strong, "v.", "t") ATOMIC_BUILTIN(__hip_atomic_exchange, "v.", "t") ATOMIC_BUILTIN(__hip_atomic_fetch_add, "v.", "t") +ATOMIC_BUILTIN(__hip_atomic_fetch_sub, "v.", "t") ATOMIC_BUILTIN(__hip_atomic_fetch_and, "v.", "t") ATOMIC_BUILTIN(__hip_atomic_fetch_or, "v.", "t") ATOMIC_BUILTIN(__hip_atomic_fetch_xor, "v.", "t") @@ -1415,6 +1446,10 @@ 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(roundeven, "dd", "fnc", MATH_H, ALL_LANGUAGES) +LIBBUILTIN(roundevenf, "ff", "fnc", MATH_H, ALL_LANGUAGES) +LIBBUILTIN(roundevenl, "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) @@ -1565,6 +1600,7 @@ LIBBUILTIN(addressof, "v*v&", "zfncThE", MEMORY, CXX_LANG) LANGBUILTIN(__addressof, "v*v&", "zfncTE", CXX_LANG) LIBBUILTIN(as_const, "v&v&", "zfncThE", UTILITY, CXX_LANG) LIBBUILTIN(forward, "v&v&", "zfncThE", UTILITY, CXX_LANG) +LIBBUILTIN(forward_like, "v&v&", "zfncThE", UTILITY, CXX_LANG) LIBBUILTIN(move, "v&v&", "zfncThE", UTILITY, CXX_LANG) LIBBUILTIN(move_if_noexcept, "v&v&", "zfncThE", UTILITY, CXX_LANG) @@ -1573,6 +1609,7 @@ BUILTIN(__builtin_annotation, "v.", "tn") // Invariants BUILTIN(__builtin_assume, "vb", "nE") +BUILTIN(__builtin_assume_separate_storage, "vvCD*vCD*", "nE") // Multiprecision Arithmetic Builtins. BUILTIN(__builtin_addcb, "UcUcCUcCUcCUc*", "n") diff --git a/contrib/llvm-project/clang/include/clang/Basic/BuiltinsAArch64.def b/contrib/llvm-project/clang/include/clang/Basic/BuiltinsAArch64.def index e6672a1702e..eaae6c9ad84 100644 --- a/contrib/llvm-project/clang/include/clang/Basic/BuiltinsAArch64.def +++ b/contrib/llvm-project/clang/include/clang/Basic/BuiltinsAArch64.def @@ -39,6 +39,8 @@ BUILTIN(__builtin_arm_rbit, "UiUi", "nc") BUILTIN(__builtin_arm_rbit64, "WUiWUi", "nc") BUILTIN(__builtin_arm_cls, "UiZUi", "nc") BUILTIN(__builtin_arm_cls64, "UiWUi", "nc") +BUILTIN(__builtin_arm_clz, "UiZUi", "nc") +BUILTIN(__builtin_arm_clz64, "UiWUi", "nc") // HINT BUILTIN(__builtin_arm_nop, "v", "") @@ -257,16 +259,18 @@ TARGET_HEADER_BUILTIN(__umulh, "ULLiULLiULLi", "nh", INTRIN_H, ALL_MS_LANGUAGES, TARGET_HEADER_BUILTIN(__break, "vi", "nh", INTRIN_H, ALL_MS_LANGUAGES, "") -TARGET_HEADER_BUILTIN(__writex18byte, "vULiUc", "nh", INTRIN_H, ALL_MS_LANGUAGES, "") -TARGET_HEADER_BUILTIN(__writex18word, "vULiUs", "nh", INTRIN_H, ALL_MS_LANGUAGES, "") -TARGET_HEADER_BUILTIN(__writex18dword, "vULiULi", "nh", INTRIN_H, ALL_MS_LANGUAGES, "") -TARGET_HEADER_BUILTIN(__writex18qword, "vULiULLi", "nh", INTRIN_H, ALL_MS_LANGUAGES, "") -TARGET_HEADER_BUILTIN(__readx18byte, "UcULi", "nh", INTRIN_H, ALL_MS_LANGUAGES, "") -TARGET_HEADER_BUILTIN(__readx18word, "UsULi", "nh", INTRIN_H, ALL_MS_LANGUAGES, "") -TARGET_HEADER_BUILTIN(__readx18dword, "ULiULi", "nh", INTRIN_H, ALL_MS_LANGUAGES, "") -TARGET_HEADER_BUILTIN(__readx18qword, "ULLiULi", "nh", INTRIN_H, ALL_MS_LANGUAGES, "") +TARGET_HEADER_BUILTIN(__writex18byte, "vUNiUc", "nh", INTRIN_H, ALL_MS_LANGUAGES, "") +TARGET_HEADER_BUILTIN(__writex18word, "vUNiUs", "nh", INTRIN_H, ALL_MS_LANGUAGES, "") +TARGET_HEADER_BUILTIN(__writex18dword, "vUNiUNi", "nh", INTRIN_H, ALL_MS_LANGUAGES, "") +TARGET_HEADER_BUILTIN(__writex18qword, "vUNiULLi", "nh", INTRIN_H, ALL_MS_LANGUAGES, "") + +TARGET_HEADER_BUILTIN(__readx18byte, "UcUNi", "nh", INTRIN_H, ALL_MS_LANGUAGES, "") +TARGET_HEADER_BUILTIN(__readx18word, "UsUNi", "nh", INTRIN_H, ALL_MS_LANGUAGES, "") +TARGET_HEADER_BUILTIN(__readx18dword, "UNiUNi", "nh", INTRIN_H, ALL_MS_LANGUAGES, "") +TARGET_HEADER_BUILTIN(__readx18qword, "ULLiUNi", "nh", INTRIN_H, ALL_MS_LANGUAGES, "") #undef BUILTIN #undef LANGBUILTIN +#undef TARGET_BUILTIN #undef TARGET_HEADER_BUILTIN diff --git a/contrib/llvm-project/clang/include/clang/Basic/BuiltinsAMDGPU.def b/contrib/llvm-project/clang/include/clang/Basic/BuiltinsAMDGPU.def index c14237227cd..29aa9ca7552 100644 --- a/contrib/llvm-project/clang/include/clang/Basic/BuiltinsAMDGPU.def +++ b/contrib/llvm-project/clang/include/clang/Basic/BuiltinsAMDGPU.def @@ -100,6 +100,8 @@ BUILTIN(__builtin_amdgcn_rsq_clamp, "dd", "nc") BUILTIN(__builtin_amdgcn_rsq_clampf, "ff", "nc") BUILTIN(__builtin_amdgcn_sinf, "ff", "nc") BUILTIN(__builtin_amdgcn_cosf, "ff", "nc") +BUILTIN(__builtin_amdgcn_logf, "ff", "nc") +BUILTIN(__builtin_amdgcn_exp2f, "ff", "nc") BUILTIN(__builtin_amdgcn_log_clampf, "ff", "nc") BUILTIN(__builtin_amdgcn_ldexp, "ddi", "nc") BUILTIN(__builtin_amdgcn_ldexpf, "ffi", "nc") @@ -214,8 +216,8 @@ TARGET_BUILTIN(__builtin_amdgcn_perm, "UiUiUiUi", "nc", "gfx8-insts") TARGET_BUILTIN(__builtin_amdgcn_fmed3h, "hhhh", "nc", "gfx9-insts") TARGET_BUILTIN(__builtin_amdgcn_global_atomic_fadd_f64, "dd*1d", "t", "gfx90a-insts") -TARGET_BUILTIN(__builtin_amdgcn_global_atomic_fadd_f32, "ff*1f", "t", "gfx90a-insts") -TARGET_BUILTIN(__builtin_amdgcn_global_atomic_fadd_v2f16, "V2hV2h*1V2h", "t", "gfx90a-insts") +TARGET_BUILTIN(__builtin_amdgcn_global_atomic_fadd_f32, "ff*1f", "t", "atomic-fadd-rtn-insts") +TARGET_BUILTIN(__builtin_amdgcn_global_atomic_fadd_v2f16, "V2hV2h*1V2h", "t", "atomic-buffer-global-pk-add-f16-insts") TARGET_BUILTIN(__builtin_amdgcn_global_atomic_fmin_f64, "dd*1d", "t", "gfx90a-insts") TARGET_BUILTIN(__builtin_amdgcn_global_atomic_fmax_f64, "dd*1d", "t", "gfx90a-insts") @@ -227,16 +229,17 @@ TARGET_BUILTIN(__builtin_amdgcn_ds_atomic_fadd_f64, "dd*3d", "t", "gfx90a-insts" TARGET_BUILTIN(__builtin_amdgcn_ds_atomic_fadd_f32, "ff*3f", "t", "gfx8-insts") TARGET_BUILTIN(__builtin_amdgcn_flat_atomic_fadd_f32, "ff*0f", "t", "gfx940-insts") -TARGET_BUILTIN(__builtin_amdgcn_flat_atomic_fadd_v2f16, "V2hV2h*0V2h", "t", "gfx940-insts") -TARGET_BUILTIN(__builtin_amdgcn_flat_atomic_fadd_v2bf16, "V2sV2s*0V2s", "t", "gfx940-insts") -TARGET_BUILTIN(__builtin_amdgcn_global_atomic_fadd_v2bf16, "V2sV2s*1V2s", "t", "gfx940-insts") -TARGET_BUILTIN(__builtin_amdgcn_ds_atomic_fadd_v2bf16, "V2sV2s*3V2s", "t", "gfx940-insts") +TARGET_BUILTIN(__builtin_amdgcn_flat_atomic_fadd_v2f16, "V2hV2h*0V2h", "t", "atomic-flat-pk-add-16-insts") +TARGET_BUILTIN(__builtin_amdgcn_flat_atomic_fadd_v2bf16, "V2sV2s*0V2s", "t", "atomic-flat-pk-add-16-insts") +TARGET_BUILTIN(__builtin_amdgcn_global_atomic_fadd_v2bf16, "V2sV2s*1V2s", "t", "atomic-global-pk-add-bf16-inst") +TARGET_BUILTIN(__builtin_amdgcn_ds_atomic_fadd_v2bf16, "V2sV2s*3V2s", "t", "atomic-ds-pk-add-16-insts") +TARGET_BUILTIN(__builtin_amdgcn_ds_atomic_fadd_v2f16, "V2hV2h*3V2h", "t", "atomic-ds-pk-add-16-insts") //===----------------------------------------------------------------------===// // Deep learning builtins. //===----------------------------------------------------------------------===// -TARGET_BUILTIN(__builtin_amdgcn_fdot2, "fV2hV2hfIb", "nc", "dot7-insts") +TARGET_BUILTIN(__builtin_amdgcn_fdot2, "fV2hV2hfIb", "nc", "dot10-insts") TARGET_BUILTIN(__builtin_amdgcn_fdot2_f16_f16, "hV2hV2hh", "nc", "dot9-insts") TARGET_BUILTIN(__builtin_amdgcn_fdot2_bf16_bf16, "sV2sV2ss", "nc", "dot9-insts") TARGET_BUILTIN(__builtin_amdgcn_fdot2_f32_bf16, "fV2sV2sfIb", "nc", "dot9-insts") diff --git a/contrib/llvm-project/clang/include/clang/Basic/BuiltinsARM.def b/contrib/llvm-project/clang/include/clang/Basic/BuiltinsARM.def index eabf830b359..9ee918cb214 100644 --- a/contrib/llvm-project/clang/include/clang/Basic/BuiltinsARM.def +++ b/contrib/llvm-project/clang/include/clang/Basic/BuiltinsARM.def @@ -119,6 +119,8 @@ BUILTIN(__builtin_arm_smusdx, "iii", "nc") // Bit manipulation BUILTIN(__builtin_arm_rbit, "UiUi", "nc") +BUILTIN(__builtin_arm_clz, "UiZUi", "nc") +BUILTIN(__builtin_arm_clz64, "UiWUi", "nc") BUILTIN(__builtin_arm_cls, "UiZUi", "nc") BUILTIN(__builtin_arm_cls64, "UiWUi", "nc") @@ -343,4 +345,5 @@ TARGET_HEADER_BUILTIN(_InterlockedDecrement64_rel, "LLiLLiD*", "nh", INTRIN_H, A #undef BUILTIN #undef LANGBUILTIN +#undef TARGET_BUILTIN #undef TARGET_HEADER_BUILTIN diff --git a/contrib/llvm-project/clang/include/clang/Basic/BuiltinsNEON.def b/contrib/llvm-project/clang/include/clang/Basic/BuiltinsNEON.def index b8eb5a7b617..9627005ba98 100644 --- a/contrib/llvm-project/clang/include/clang/Basic/BuiltinsNEON.def +++ b/contrib/llvm-project/clang/include/clang/Basic/BuiltinsNEON.def @@ -19,3 +19,4 @@ #undef GET_NEON_BUILTINS #undef BUILTIN +#undef TARGET_BUILTIN diff --git a/contrib/llvm-project/clang/include/clang/Basic/BuiltinsNVPTX.def b/contrib/llvm-project/clang/include/clang/Basic/BuiltinsNVPTX.def index ea0cd8c3e84..f645ad25cbd 100644 --- a/contrib/llvm-project/clang/include/clang/Basic/BuiltinsNVPTX.def +++ b/contrib/llvm-project/clang/include/clang/Basic/BuiltinsNVPTX.def @@ -54,7 +54,11 @@ #pragma push_macro("PTX76") #pragma push_macro("PTX77") #pragma push_macro("PTX78") -#define PTX78 "ptx78" +#pragma push_macro("PTX80") +#pragma push_macro("PTX81") +#define PTX81 "ptx81" +#define PTX80 "ptx80|" PTX81 +#define PTX78 "ptx78|" PTX80 #define PTX77 "ptx77|" PTX78 #define PTX76 "ptx76|" PTX77 #define PTX75 "ptx75|" PTX76 @@ -95,6 +99,31 @@ BUILTIN(__nvvm_read_ptx_sreg_nctaid_y, "i", "nc") BUILTIN(__nvvm_read_ptx_sreg_nctaid_z, "i", "nc") BUILTIN(__nvvm_read_ptx_sreg_nctaid_w, "i", "nc") +TARGET_BUILTIN(__nvvm_read_ptx_sreg_clusterid_x, "i", "nc", AND(SM_90, PTX78)) +TARGET_BUILTIN(__nvvm_read_ptx_sreg_clusterid_y, "i", "nc", AND(SM_90, PTX78)) +TARGET_BUILTIN(__nvvm_read_ptx_sreg_clusterid_z, "i", "nc", AND(SM_90, PTX78)) +TARGET_BUILTIN(__nvvm_read_ptx_sreg_clusterid_w, "i", "nc", AND(SM_90, PTX78)) + +TARGET_BUILTIN(__nvvm_read_ptx_sreg_nclusterid_x, "i", "nc", AND(SM_90, PTX78)) +TARGET_BUILTIN(__nvvm_read_ptx_sreg_nclusterid_y, "i", "nc", AND(SM_90, PTX78)) +TARGET_BUILTIN(__nvvm_read_ptx_sreg_nclusterid_z, "i", "nc", AND(SM_90, PTX78)) +TARGET_BUILTIN(__nvvm_read_ptx_sreg_nclusterid_w, "i", "nc", AND(SM_90, PTX78)) + +TARGET_BUILTIN(__nvvm_read_ptx_sreg_cluster_ctaid_x, "i", "nc", AND(SM_90, PTX78)) +TARGET_BUILTIN(__nvvm_read_ptx_sreg_cluster_ctaid_y, "i", "nc", AND(SM_90, PTX78)) +TARGET_BUILTIN(__nvvm_read_ptx_sreg_cluster_ctaid_z, "i", "nc", AND(SM_90, PTX78)) +TARGET_BUILTIN(__nvvm_read_ptx_sreg_cluster_ctaid_w, "i", "nc", AND(SM_90, PTX78)) + +TARGET_BUILTIN(__nvvm_read_ptx_sreg_cluster_nctaid_x, "i", "nc", AND(SM_90, PTX78)) +TARGET_BUILTIN(__nvvm_read_ptx_sreg_cluster_nctaid_y, "i", "nc", AND(SM_90, PTX78)) +TARGET_BUILTIN(__nvvm_read_ptx_sreg_cluster_nctaid_z, "i", "nc", AND(SM_90, PTX78)) +TARGET_BUILTIN(__nvvm_read_ptx_sreg_cluster_nctaid_w, "i", "nc", AND(SM_90, PTX78)) + +TARGET_BUILTIN(__nvvm_read_ptx_sreg_cluster_ctarank, "i", "nc", AND(SM_90, PTX78)) +TARGET_BUILTIN(__nvvm_read_ptx_sreg_cluster_nctarank, "i", "nc", AND(SM_90, PTX78)) + +TARGET_BUILTIN(__nvvm_is_explicit_cluster, "b", "nc", AND(SM_90, PTX78)) + BUILTIN(__nvvm_read_ptx_sreg_laneid, "i", "nc") BUILTIN(__nvvm_read_ptx_sreg_warpid, "i", "nc") BUILTIN(__nvvm_read_ptx_sreg_nwarpid, "i", "nc") @@ -144,16 +173,20 @@ TARGET_BUILTIN(__nvvm_fmin_nan_xorsign_abs_f16x2, "V2hV2hV2h", "", AND(SM_86, PTX72)) TARGET_BUILTIN(__nvvm_fmin_ftz_nan_xorsign_abs_f16x2, "V2hV2hV2h", "", AND(SM_86, PTX72)) -TARGET_BUILTIN(__nvvm_fmin_bf16, "UsUsUs", "", AND(SM_80, PTX70)) -TARGET_BUILTIN(__nvvm_fmin_nan_bf16, "UsUsUs", "", AND(SM_80, PTX70)) -TARGET_BUILTIN(__nvvm_fmin_xorsign_abs_bf16, "UsUsUs", "", AND(SM_86, PTX72)) -TARGET_BUILTIN(__nvvm_fmin_nan_xorsign_abs_bf16, "UsUsUs", "", +TARGET_BUILTIN(__nvvm_fmin_bf16, "yyy", "", AND(SM_80, PTX70)) +TARGET_BUILTIN(__nvvm_fmin_ftz_bf16, "yyy", "", AND(SM_80, PTX70)) +TARGET_BUILTIN(__nvvm_fmin_nan_bf16, "yyy", "", AND(SM_80, PTX70)) +TARGET_BUILTIN(__nvvm_fmin_ftz_nan_bf16, "yyy", "", AND(SM_80, PTX70)) +TARGET_BUILTIN(__nvvm_fmin_xorsign_abs_bf16, "yyy", "", AND(SM_86, PTX72)) +TARGET_BUILTIN(__nvvm_fmin_nan_xorsign_abs_bf16, "yyy", "", AND(SM_86, PTX72)) -TARGET_BUILTIN(__nvvm_fmin_bf16x2, "ZUiZUiZUi", "", AND(SM_80, PTX70)) -TARGET_BUILTIN(__nvvm_fmin_nan_bf16x2, "ZUiZUiZUi", "", AND(SM_80, PTX70)) -TARGET_BUILTIN(__nvvm_fmin_xorsign_abs_bf16x2, "ZUiZUiZUi", "", +TARGET_BUILTIN(__nvvm_fmin_bf16x2, "V2yV2yV2y", "", AND(SM_80, PTX70)) +TARGET_BUILTIN(__nvvm_fmin_ftz_bf16x2, "V2yV2yV2y", "", AND(SM_80, PTX70)) +TARGET_BUILTIN(__nvvm_fmin_nan_bf16x2, "V2yV2yV2y", "", AND(SM_80, PTX70)) +TARGET_BUILTIN(__nvvm_fmin_ftz_nan_bf16x2, "V2yV2yV2y", "", AND(SM_80, PTX70)) +TARGET_BUILTIN(__nvvm_fmin_xorsign_abs_bf16x2, "V2yV2yV2y", "", AND(SM_86, PTX72)) -TARGET_BUILTIN(__nvvm_fmin_nan_xorsign_abs_bf16x2, "ZUiZUiZUi", "", +TARGET_BUILTIN(__nvvm_fmin_nan_xorsign_abs_bf16x2, "V2yV2yV2y", "", AND(SM_86, PTX72)) BUILTIN(__nvvm_fmin_f, "fff", "") BUILTIN(__nvvm_fmin_ftz_f, "fff", "") @@ -186,16 +219,20 @@ TARGET_BUILTIN(__nvvm_fmax_nan_xorsign_abs_f16x2, "V2hV2hV2h", "", AND(SM_86, PTX72)) TARGET_BUILTIN(__nvvm_fmax_ftz_nan_xorsign_abs_f16x2, "V2hV2hV2h", "", AND(SM_86, PTX72)) -TARGET_BUILTIN(__nvvm_fmax_bf16, "UsUsUs", "", AND(SM_80, PTX70)) -TARGET_BUILTIN(__nvvm_fmax_nan_bf16, "UsUsUs", "", AND(SM_80, PTX70)) -TARGET_BUILTIN(__nvvm_fmax_xorsign_abs_bf16, "UsUsUs", "", AND(SM_86, PTX72)) -TARGET_BUILTIN(__nvvm_fmax_nan_xorsign_abs_bf16, "UsUsUs", "", +TARGET_BUILTIN(__nvvm_fmax_bf16, "yyy", "", AND(SM_80, PTX70)) +TARGET_BUILTIN(__nvvm_fmax_ftz_bf16, "yyy", "", AND(SM_80, PTX70)) +TARGET_BUILTIN(__nvvm_fmax_nan_bf16, "yyy", "", AND(SM_80, PTX70)) +TARGET_BUILTIN(__nvvm_fmax_ftz_nan_bf16, "yyy", "", AND(SM_80, PTX70)) +TARGET_BUILTIN(__nvvm_fmax_xorsign_abs_bf16, "yyy", "", AND(SM_86, PTX72)) +TARGET_BUILTIN(__nvvm_fmax_nan_xorsign_abs_bf16, "yyy", "", AND(SM_86, PTX72)) -TARGET_BUILTIN(__nvvm_fmax_bf16x2, "ZUiZUiZUi", "", AND(SM_80, PTX70)) -TARGET_BUILTIN(__nvvm_fmax_nan_bf16x2, "ZUiZUiZUi", "", AND(SM_80, PTX70)) -TARGET_BUILTIN(__nvvm_fmax_xorsign_abs_bf16x2, "ZUiZUiZUi", "", +TARGET_BUILTIN(__nvvm_fmax_bf16x2, "V2yV2yV2y", "", AND(SM_80, PTX70)) +TARGET_BUILTIN(__nvvm_fmax_ftz_bf16x2, "V2yV2yV2y", "", AND(SM_80, PTX70)) +TARGET_BUILTIN(__nvvm_fmax_nan_bf16x2, "V2yV2yV2y", "", AND(SM_80, PTX70)) +TARGET_BUILTIN(__nvvm_fmax_ftz_nan_bf16x2, "V2yV2yV2y", "", AND(SM_80, PTX70)) +TARGET_BUILTIN(__nvvm_fmax_xorsign_abs_bf16x2, "V2yV2yV2y", "", AND(SM_86, PTX72)) -TARGET_BUILTIN(__nvvm_fmax_nan_xorsign_abs_bf16x2, "ZUiZUiZUi", "", +TARGET_BUILTIN(__nvvm_fmax_nan_xorsign_abs_bf16x2, "V2yV2yV2y", "", AND(SM_86, PTX72)) BUILTIN(__nvvm_fmax_f, "fff", "") BUILTIN(__nvvm_fmax_ftz_f, "fff", "") @@ -323,10 +360,10 @@ TARGET_BUILTIN(__nvvm_fma_rn_sat_f16x2, "V2hV2hV2hV2h", "", AND(SM_53, PTX42)) TARGET_BUILTIN(__nvvm_fma_rn_ftz_sat_f16x2, "V2hV2hV2hV2h", "", AND(SM_53, PTX42)) TARGET_BUILTIN(__nvvm_fma_rn_relu_f16x2, "V2hV2hV2hV2h", "", AND(SM_80, PTX70)) TARGET_BUILTIN(__nvvm_fma_rn_ftz_relu_f16x2, "V2hV2hV2hV2h", "", AND(SM_80, PTX70)) -TARGET_BUILTIN(__nvvm_fma_rn_bf16, "UsUsUsUs", "", AND(SM_80, PTX70)) -TARGET_BUILTIN(__nvvm_fma_rn_relu_bf16, "UsUsUsUs", "", AND(SM_80, PTX70)) -TARGET_BUILTIN(__nvvm_fma_rn_bf16x2, "ZUiZUiZUiZUi", "", AND(SM_80, PTX70)) -TARGET_BUILTIN(__nvvm_fma_rn_relu_bf16x2, "ZUiZUiZUiZUi", "", AND(SM_80, PTX70)) +TARGET_BUILTIN(__nvvm_fma_rn_bf16, "yyyy", "", AND(SM_80, PTX70)) +TARGET_BUILTIN(__nvvm_fma_rn_relu_bf16, "yyyy", "", AND(SM_80, PTX70)) +TARGET_BUILTIN(__nvvm_fma_rn_bf16x2, "V2yV2yV2yV2y", "", AND(SM_80, PTX70)) +TARGET_BUILTIN(__nvvm_fma_rn_relu_bf16x2, "V2yV2yV2yV2y", "", AND(SM_80, PTX70)) BUILTIN(__nvvm_fma_rn_ftz_f, "ffff", "") BUILTIN(__nvvm_fma_rn_f, "ffff", "") BUILTIN(__nvvm_fma_rz_ftz_f, "ffff", "") @@ -514,20 +551,20 @@ BUILTIN(__nvvm_ull2d_rp, "dULLi", "") BUILTIN(__nvvm_f2h_rn_ftz, "Usf", "") BUILTIN(__nvvm_f2h_rn, "Usf", "") -TARGET_BUILTIN(__nvvm_ff2bf16x2_rn, "ZUiff", "", AND(SM_80,PTX70)) -TARGET_BUILTIN(__nvvm_ff2bf16x2_rn_relu, "ZUiff", "", AND(SM_80,PTX70)) -TARGET_BUILTIN(__nvvm_ff2bf16x2_rz, "ZUiff", "", AND(SM_80,PTX70)) -TARGET_BUILTIN(__nvvm_ff2bf16x2_rz_relu, "ZUiff", "", AND(SM_80,PTX70)) +TARGET_BUILTIN(__nvvm_ff2bf16x2_rn, "V2yff", "", AND(SM_80,PTX70)) +TARGET_BUILTIN(__nvvm_ff2bf16x2_rn_relu, "V2yff", "", AND(SM_80,PTX70)) +TARGET_BUILTIN(__nvvm_ff2bf16x2_rz, "V2yff", "", AND(SM_80,PTX70)) +TARGET_BUILTIN(__nvvm_ff2bf16x2_rz_relu, "V2yff", "", AND(SM_80,PTX70)) TARGET_BUILTIN(__nvvm_ff2f16x2_rn, "V2hff", "", AND(SM_80,PTX70)) TARGET_BUILTIN(__nvvm_ff2f16x2_rn_relu, "V2hff", "", AND(SM_80,PTX70)) TARGET_BUILTIN(__nvvm_ff2f16x2_rz, "V2hff", "", AND(SM_80,PTX70)) TARGET_BUILTIN(__nvvm_ff2f16x2_rz_relu, "V2hff", "", AND(SM_80,PTX70)) -TARGET_BUILTIN(__nvvm_f2bf16_rn, "ZUsf", "", AND(SM_80,PTX70)) -TARGET_BUILTIN(__nvvm_f2bf16_rn_relu, "ZUsf", "", AND(SM_80,PTX70)) -TARGET_BUILTIN(__nvvm_f2bf16_rz, "ZUsf", "", AND(SM_80,PTX70)) -TARGET_BUILTIN(__nvvm_f2bf16_rz_relu, "ZUsf", "", AND(SM_80,PTX70)) +TARGET_BUILTIN(__nvvm_f2bf16_rn, "yf", "", AND(SM_80,PTX70)) +TARGET_BUILTIN(__nvvm_f2bf16_rn_relu, "yf", "", AND(SM_80,PTX70)) +TARGET_BUILTIN(__nvvm_f2bf16_rz, "yf", "", AND(SM_80,PTX70)) +TARGET_BUILTIN(__nvvm_f2bf16_rz_relu, "yf", "", AND(SM_80,PTX70)) TARGET_BUILTIN(__nvvm_f2tf32_rna, "ZUif", "", AND(SM_80,PTX70)) @@ -553,6 +590,11 @@ TARGET_BUILTIN(__nvvm_bar_warp_sync, "vUi", "n", PTX60) TARGET_BUILTIN(__nvvm_barrier_sync, "vUi", "n", PTX60) TARGET_BUILTIN(__nvvm_barrier_sync_cnt, "vUiUi", "n", PTX60) +TARGET_BUILTIN(__nvvm_barrier_cluster_arrive, "v", "n", AND(SM_90,PTX78)) +TARGET_BUILTIN(__nvvm_barrier_cluster_arrive_relaxed, "v", "n", AND(SM_90,PTX80)) +TARGET_BUILTIN(__nvvm_barrier_cluster_wait, "v", "n", AND(SM_90,PTX78)) +TARGET_BUILTIN(__nvvm_fence_sc_cluster, "v", "n", AND(SM_90,PTX78)) + // Shuffle BUILTIN(__nvvm_shfl_down_i32, "iiii", "") @@ -782,8 +824,50 @@ TARGET_BUILTIN(__nvvm_atom_sys_cas_gen_ll, "LLiLLiD*LLiLLi", "n", SM_60) BUILTIN(__nvvm_compiler_error, "vcC*4", "n") BUILTIN(__nvvm_compiler_warn, "vcC*4", "n") -// __ldg. This is not implemented as a builtin by nvcc. +BUILTIN(__nvvm_ldu_c, "ccC*", "") +BUILTIN(__nvvm_ldu_sc, "ScScC*", "") +BUILTIN(__nvvm_ldu_s, "ssC*", "") +BUILTIN(__nvvm_ldu_i, "iiC*", "") +BUILTIN(__nvvm_ldu_l, "LiLiC*", "") +BUILTIN(__nvvm_ldu_ll, "LLiLLiC*", "") + +BUILTIN(__nvvm_ldu_uc, "UcUcC*", "") +BUILTIN(__nvvm_ldu_us, "UsUsC*", "") +BUILTIN(__nvvm_ldu_ui, "UiUiC*", "") +BUILTIN(__nvvm_ldu_ul, "ULiULiC*", "") +BUILTIN(__nvvm_ldu_ull, "ULLiULLiC*", "") + +BUILTIN(__nvvm_ldu_h, "hhC*", "") +BUILTIN(__nvvm_ldu_f, "ffC*", "") +BUILTIN(__nvvm_ldu_d, "ddC*", "") + +BUILTIN(__nvvm_ldu_c2, "E2cE2cC*", "") +BUILTIN(__nvvm_ldu_sc2, "E2ScE2ScC*", "") +BUILTIN(__nvvm_ldu_c4, "E4cE4cC*", "") +BUILTIN(__nvvm_ldu_sc4, "E4ScE4ScC*", "") +BUILTIN(__nvvm_ldu_s2, "E2sE2sC*", "") +BUILTIN(__nvvm_ldu_s4, "E4sE4sC*", "") +BUILTIN(__nvvm_ldu_i2, "E2iE2iC*", "") +BUILTIN(__nvvm_ldu_i4, "E4iE4iC*", "") +BUILTIN(__nvvm_ldu_l2, "E2LiE2LiC*", "") +BUILTIN(__nvvm_ldu_ll2, "E2LLiE2LLiC*", "") + +BUILTIN(__nvvm_ldu_uc2, "E2UcE2UcC*", "") +BUILTIN(__nvvm_ldu_uc4, "E4UcE4UcC*", "") +BUILTIN(__nvvm_ldu_us2, "E2UsE2UsC*", "") +BUILTIN(__nvvm_ldu_us4, "E4UsE4UsC*", "") +BUILTIN(__nvvm_ldu_ui2, "E2UiE2UiC*", "") +BUILTIN(__nvvm_ldu_ui4, "E4UiE4UiC*", "") +BUILTIN(__nvvm_ldu_ul2, "E2ULiE2ULiC*", "") +BUILTIN(__nvvm_ldu_ull2, "E2ULLiE2ULLiC*", "") + +BUILTIN(__nvvm_ldu_h2, "E2hE2hC*", "") +BUILTIN(__nvvm_ldu_f2, "E2fE2fC*", "") +BUILTIN(__nvvm_ldu_f4, "E4fE4fC*", "") +BUILTIN(__nvvm_ldu_d2, "E2dE2dC*", "") + BUILTIN(__nvvm_ldg_c, "ccC*", "") +BUILTIN(__nvvm_ldg_sc, "ScScC*", "") BUILTIN(__nvvm_ldg_s, "ssC*", "") BUILTIN(__nvvm_ldg_i, "iiC*", "") BUILTIN(__nvvm_ldg_l, "LiLiC*", "") @@ -795,15 +879,19 @@ BUILTIN(__nvvm_ldg_ui, "UiUiC*", "") BUILTIN(__nvvm_ldg_ul, "ULiULiC*", "") BUILTIN(__nvvm_ldg_ull, "ULLiULLiC*", "") +BUILTIN(__nvvm_ldg_h, "hhC*", "") BUILTIN(__nvvm_ldg_f, "ffC*", "") BUILTIN(__nvvm_ldg_d, "ddC*", "") BUILTIN(__nvvm_ldg_c2, "E2cE2cC*", "") +BUILTIN(__nvvm_ldg_sc2, "E2ScE2ScC*", "") BUILTIN(__nvvm_ldg_c4, "E4cE4cC*", "") +BUILTIN(__nvvm_ldg_sc4, "E4ScE4ScC*", "") BUILTIN(__nvvm_ldg_s2, "E2sE2sC*", "") BUILTIN(__nvvm_ldg_s4, "E4sE4sC*", "") BUILTIN(__nvvm_ldg_i2, "E2iE2iC*", "") BUILTIN(__nvvm_ldg_i4, "E4iE4iC*", "") +BUILTIN(__nvvm_ldg_l2, "E2LiE2LiC*", "") BUILTIN(__nvvm_ldg_ll2, "E2LLiE2LLiC*", "") BUILTIN(__nvvm_ldg_uc2, "E2UcE2UcC*", "") @@ -812,8 +900,10 @@ BUILTIN(__nvvm_ldg_us2, "E2UsE2UsC*", "") BUILTIN(__nvvm_ldg_us4, "E4UsE4UsC*", "") BUILTIN(__nvvm_ldg_ui2, "E2UiE2UiC*", "") BUILTIN(__nvvm_ldg_ui4, "E4UiE4UiC*", "") +BUILTIN(__nvvm_ldg_ul2, "E2ULiE2ULiC*", "") BUILTIN(__nvvm_ldg_ull2, "E2ULLiE2ULLiC*", "") +BUILTIN(__nvvm_ldg_h2, "E2hE2hC*", "") BUILTIN(__nvvm_ldg_f2, "E2fE2fC*", "") BUILTIN(__nvvm_ldg_f4, "E4fE4fC*", "") BUILTIN(__nvvm_ldg_d2, "E2dE2dC*", "") @@ -823,6 +913,7 @@ BUILTIN(__nvvm_isspacep_const, "bvC*", "nc") BUILTIN(__nvvm_isspacep_global, "bvC*", "nc") BUILTIN(__nvvm_isspacep_local, "bvC*", "nc") BUILTIN(__nvvm_isspacep_shared, "bvC*", "nc") +TARGET_BUILTIN(__nvvm_isspacep_shared_cluster,"bvC*", "nc", AND(SM_90,PTX78)) // Builtins to support WMMA instructions on sm_70 TARGET_BUILTIN(__hmma_m16n16k16_ld_a, "vi*iC*UiIi", "", AND(SM_70,PTX60)) @@ -930,10 +1021,10 @@ TARGET_BUILTIN(__nvvm_cp_async_mbarrier_arrive_shared, "vWi*3", "", AND(SM_80,PT TARGET_BUILTIN(__nvvm_cp_async_mbarrier_arrive_noinc, "vWi*", "", AND(SM_80,PTX70)) TARGET_BUILTIN(__nvvm_cp_async_mbarrier_arrive_noinc_shared, "vWi*3", "", AND(SM_80,PTX70)) -TARGET_BUILTIN(__nvvm_cp_async_ca_shared_global_4, "vv*3vC*1", "", AND(SM_80,PTX70)) -TARGET_BUILTIN(__nvvm_cp_async_ca_shared_global_8, "vv*3vC*1", "", AND(SM_80,PTX70)) -TARGET_BUILTIN(__nvvm_cp_async_ca_shared_global_16, "vv*3vC*1", "", AND(SM_80,PTX70)) -TARGET_BUILTIN(__nvvm_cp_async_cg_shared_global_16, "vv*3vC*1", "", AND(SM_80,PTX70)) +TARGET_BUILTIN(__nvvm_cp_async_ca_shared_global_4, "vv*3vC*1.", "", AND(SM_80,PTX70)) +TARGET_BUILTIN(__nvvm_cp_async_ca_shared_global_8, "vv*3vC*1.", "", AND(SM_80,PTX70)) +TARGET_BUILTIN(__nvvm_cp_async_ca_shared_global_16, "vv*3vC*1.", "", AND(SM_80,PTX70)) +TARGET_BUILTIN(__nvvm_cp_async_cg_shared_global_16, "vv*3vC*1.", "", AND(SM_80,PTX70)) TARGET_BUILTIN(__nvvm_cp_async_commit_group, "v", "", AND(SM_80,PTX70)) TARGET_BUILTIN(__nvvm_cp_async_wait_group, "vIi", "", AND(SM_80,PTX70)) @@ -941,10 +1032,15 @@ TARGET_BUILTIN(__nvvm_cp_async_wait_all, "v", "", AND(SM_80,PTX70)) // bf16, bf16x2 abs, neg -TARGET_BUILTIN(__nvvm_abs_bf16, "UsUs", "", AND(SM_80,PTX70)) -TARGET_BUILTIN(__nvvm_abs_bf16x2, "ZUiZUi", "", AND(SM_80,PTX70)) -TARGET_BUILTIN(__nvvm_neg_bf16, "UsUs", "", AND(SM_80,PTX70)) -TARGET_BUILTIN(__nvvm_neg_bf16x2, "ZUiZUi", "", AND(SM_80,PTX70)) +TARGET_BUILTIN(__nvvm_abs_bf16, "yy", "", AND(SM_80,PTX70)) +TARGET_BUILTIN(__nvvm_abs_bf16x2, "V2yV2y", "", AND(SM_80,PTX70)) +TARGET_BUILTIN(__nvvm_neg_bf16, "yy", "", AND(SM_80,PTX70)) +TARGET_BUILTIN(__nvvm_neg_bf16x2, "V2yV2y", "", AND(SM_80,PTX70)) + +TARGET_BUILTIN(__nvvm_mapa, "v*v*i", "", AND(SM_90, PTX78)) +TARGET_BUILTIN(__nvvm_mapa_shared_cluster, "v*3v*3i", "", AND(SM_90, PTX78)) +TARGET_BUILTIN(__nvvm_getctarank, "iv*", "", AND(SM_90, PTX78)) +TARGET_BUILTIN(__nvvm_getctarank_shared_cluster, "iv*3", "", AND(SM_90,PTX78)) #undef BUILTIN #undef TARGET_BUILTIN @@ -974,3 +1070,5 @@ TARGET_BUILTIN(__nvvm_neg_bf16x2, "ZUiZUi", "", AND(SM_80,PTX70)) #pragma pop_macro("PTX76") #pragma pop_macro("PTX77") #pragma pop_macro("PTX78") +#pragma pop_macro("PTX80") +#pragma pop_macro("PTX81") diff --git a/contrib/llvm-project/clang/include/clang/Basic/BuiltinsPPC.def b/contrib/llvm-project/clang/include/clang/Basic/BuiltinsPPC.def index 7b7625cf11c..1e52d351780 100644 --- a/contrib/llvm-project/clang/include/clang/Basic/BuiltinsPPC.def +++ b/contrib/llvm-project/clang/include/clang/Basic/BuiltinsPPC.def @@ -19,15 +19,33 @@ // The format of this database matches clang/Basic/Builtins.def except for the // MMA builtins that are using their own format documented below. -#if defined(BUILTIN) && !defined(CUSTOM_BUILTIN) -# define CUSTOM_BUILTIN(ID, INTR, TYPES, ACCUMULATE) \ - BUILTIN(__builtin_##ID, "i.", "t") -#elif defined(CUSTOM_BUILTIN) && !defined(BUILTIN) -# define BUILTIN(ID, TYPES, ATTRS) +#ifndef BUILTIN +#define BUILTIN(ID, TYPE, ATTRS) #endif -#define UNALIASED_CUSTOM_BUILTIN(ID, TYPES, ACCUMULATE) \ - CUSTOM_BUILTIN(ID, ID, TYPES, ACCUMULATE) +#if defined(BUILTIN) && !defined(TARGET_BUILTIN) +#define TARGET_BUILTIN(ID, TYPE, ATTRS, FEATURE) BUILTIN(ID, TYPE, ATTRS) +#endif + +#ifndef CUSTOM_BUILTIN +#define CUSTOM_BUILTIN(ID, INTR, TYPES, ACCUMULATE, FEATURE) \ + TARGET_BUILTIN(__builtin_##ID, "i.", "t", FEATURE) +#endif + +#define UNALIASED_CUSTOM_BUILTIN(ID, TYPES, ACCUMULATE, FEATURE) \ + CUSTOM_BUILTIN(ID, ID, TYPES, ACCUMULATE, FEATURE) + +// GCC predefined macros to rename builtins, undef them to keep original names. +#if defined(__GNUC__) && !defined(__clang__) +#undef __builtin_vsx_xvnmaddadp +#undef __builtin_vsx_xvnmaddasp +#undef __builtin_vsx_xvmsubasp +#undef __builtin_vsx_xvmsubadp +#undef __builtin_vsx_xvmaddadp +#undef __builtin_vsx_xvnmsubasp +#undef __builtin_vsx_xvnmsubadp +#undef __builtin_vsx_xvmaddasp +#endif // XL Compatibility built-ins BUILTIN(__builtin_ppc_popcntb, "ULiULi", "") @@ -46,7 +64,7 @@ BUILTIN(__builtin_ppc_dcbst, "vvC*", "") BUILTIN(__builtin_ppc_dcbt, "vv*", "") BUILTIN(__builtin_ppc_dcbtst, "vv*", "") BUILTIN(__builtin_ppc_dcbz, "vv*", "") -BUILTIN(__builtin_ppc_icbt, "vv*", "") +TARGET_BUILTIN(__builtin_ppc_icbt, "vv*", "", "isa-v207-instructions") BUILTIN(__builtin_ppc_fric, "dd", "") BUILTIN(__builtin_ppc_frim, "dd", "") BUILTIN(__builtin_ppc_frims, "ff", "") @@ -74,12 +92,12 @@ BUILTIN(__builtin_ppc_fetch_and_swap, "UiUiD*Ui", "") BUILTIN(__builtin_ppc_fetch_and_swaplp, "ULiULiD*ULi", "") BUILTIN(__builtin_ppc_ldarx, "LiLiD*", "") BUILTIN(__builtin_ppc_lwarx, "iiD*", "") -BUILTIN(__builtin_ppc_lharx, "ssD*", "") -BUILTIN(__builtin_ppc_lbarx, "ccD*", "") +TARGET_BUILTIN(__builtin_ppc_lharx, "ssD*", "", "isa-v207-instructions") +TARGET_BUILTIN(__builtin_ppc_lbarx, "ccD*", "", "isa-v207-instructions") BUILTIN(__builtin_ppc_stdcx, "iLiD*Li", "") BUILTIN(__builtin_ppc_stwcx, "iiD*i", "") -BUILTIN(__builtin_ppc_sthcx, "isD*s", "") -BUILTIN(__builtin_ppc_stbcx, "icD*i", "") +TARGET_BUILTIN(__builtin_ppc_sthcx, "isD*s", "", "isa-v207-instructions") +TARGET_BUILTIN(__builtin_ppc_stbcx, "icD*i", "", "isa-v207-instructions") BUILTIN(__builtin_ppc_tdw, "vLLiLLiIUi", "") BUILTIN(__builtin_ppc_tw, "viiIUi", "") BUILTIN(__builtin_ppc_trap, "vi", "") @@ -96,26 +114,27 @@ BUILTIN(__builtin_ppc_swdiv_nochk, "ddd", "") BUILTIN(__builtin_ppc_swdivs_nochk, "fff", "") BUILTIN(__builtin_ppc_alignx, "vIivC*", "nc") BUILTIN(__builtin_ppc_rdlam, "UWiUWiUWiUWIi", "nc") -BUILTIN(__builtin_ppc_compare_exp_uo, "idd", "") -BUILTIN(__builtin_ppc_compare_exp_lt, "idd", "") -BUILTIN(__builtin_ppc_compare_exp_gt, "idd", "") -BUILTIN(__builtin_ppc_compare_exp_eq, "idd", "") -BUILTIN(__builtin_ppc_test_data_class, "idIi", "t") +TARGET_BUILTIN(__builtin_ppc_compare_exp_uo, "idd", "", "isa-v30-instructions,vsx") +TARGET_BUILTIN(__builtin_ppc_compare_exp_lt, "idd", "", "isa-v30-instructions,vsx") +TARGET_BUILTIN(__builtin_ppc_compare_exp_gt, "idd", "", "isa-v30-instructions,vsx") +TARGET_BUILTIN(__builtin_ppc_compare_exp_eq, "idd", "", "isa-v30-instructions,vsx") +TARGET_BUILTIN(__builtin_ppc_test_data_class, "idIi", "t", "isa-v30-instructions,vsx") BUILTIN(__builtin_ppc_swdiv, "ddd", "") BUILTIN(__builtin_ppc_swdivs, "fff", "") // Compare -BUILTIN(__builtin_ppc_cmpeqb, "LLiLLiLLi", "") -BUILTIN(__builtin_ppc_cmprb, "iCIiii", "") -BUILTIN(__builtin_ppc_setb, "LLiLLiLLi", "") +TARGET_BUILTIN(__builtin_ppc_cmpeqb, "LLiLLiLLi", "", "isa-v30-instructions") +TARGET_BUILTIN(__builtin_ppc_cmprb, "iCIiii", "", "isa-v30-instructions") +TARGET_BUILTIN(__builtin_ppc_setb, "LLiLLiLLi", "", "isa-v30-instructions") BUILTIN(__builtin_ppc_cmpb, "LLiLLiLLi", "") // Multiply BUILTIN(__builtin_ppc_mulhd, "LLiLiLi", "") BUILTIN(__builtin_ppc_mulhdu, "ULLiULiULi", "") BUILTIN(__builtin_ppc_mulhw, "iii", "") BUILTIN(__builtin_ppc_mulhwu, "UiUiUi", "") -BUILTIN(__builtin_ppc_maddhd, "LLiLLiLLiLLi", "") -BUILTIN(__builtin_ppc_maddhdu, "ULLiULLiULLiULLi", "") -BUILTIN(__builtin_ppc_maddld, "LLiLLiLLiLLi", "") +TARGET_BUILTIN(__builtin_ppc_maddhd, "LLiLLiLLiLLi", "", "isa-v30-instructions") +TARGET_BUILTIN(__builtin_ppc_maddhdu, "ULLiULLiULLiULLi", "", + "isa-v30-instructions") +TARGET_BUILTIN(__builtin_ppc_maddld, "LLiLLiLLiLLi", "", "isa-v30-instructions") // Rotate BUILTIN(__builtin_ppc_rlwnm, "UiUiUiIUi", "") BUILTIN(__builtin_ppc_rlwimi, "UiUiUiIUiIUi", "") @@ -123,18 +142,18 @@ BUILTIN(__builtin_ppc_rldimi, "ULLiULLiULLiIUiIULLi", "") // load BUILTIN(__builtin_ppc_load2r, "UsUs*", "") BUILTIN(__builtin_ppc_load4r, "UiUi*", "") -BUILTIN(__builtin_ppc_load8r, "ULLiULLi*", "") +TARGET_BUILTIN(__builtin_ppc_load8r, "ULLiULLi*", "", "isa-v206-instructions") // store BUILTIN(__builtin_ppc_store2r, "vUiUs*", "") BUILTIN(__builtin_ppc_store4r, "vUiUi*", "") -BUILTIN(__builtin_ppc_store8r, "vULLiULLi*", "") -BUILTIN(__builtin_ppc_extract_exp, "Uid", "") -BUILTIN(__builtin_ppc_extract_sig, "ULLid", "") +TARGET_BUILTIN(__builtin_ppc_store8r, "vULLiULLi*", "", "isa-v206-instructions") +TARGET_BUILTIN(__builtin_ppc_extract_exp, "Uid", "", "power9-vector") +TARGET_BUILTIN(__builtin_ppc_extract_sig, "ULLid", "", "power9-vector") BUILTIN(__builtin_ppc_mtfsb0, "vUIi", "") BUILTIN(__builtin_ppc_mtfsb1, "vUIi", "") BUILTIN(__builtin_ppc_mtfsf, "vUIiUi", "") BUILTIN(__builtin_ppc_mtfsfi, "vUIiUIi", "") -BUILTIN(__builtin_ppc_insert_exp, "ddULLi", "") +TARGET_BUILTIN(__builtin_ppc_insert_exp, "ddULLi", "", "power9-vector") BUILTIN(__builtin_ppc_fmsub, "dddd", "") BUILTIN(__builtin_ppc_fmsubs, "ffff", "") BUILTIN(__builtin_ppc_fnmadd, "dddd", "") @@ -145,13 +164,13 @@ BUILTIN(__builtin_ppc_fre, "dd", "") BUILTIN(__builtin_ppc_fres, "ff", "") BUILTIN(__builtin_ppc_dcbtstt, "vv*", "") BUILTIN(__builtin_ppc_dcbtt, "vv*", "") -BUILTIN(__builtin_ppc_mftbu, "Ui","") +BUILTIN(__builtin_ppc_mftbu, "Ui", "") BUILTIN(__builtin_ppc_mfmsr, "Ui", "") BUILTIN(__builtin_ppc_mfspr, "ULiIi", "") BUILTIN(__builtin_ppc_mtmsr, "vUi", "") BUILTIN(__builtin_ppc_mtspr, "vIiULi", "") BUILTIN(__builtin_ppc_stfiw, "viC*d", "") -BUILTIN(__builtin_ppc_addex, "LLiLLiLLiCIi", "") +TARGET_BUILTIN(__builtin_ppc_addex, "LLiLLiLLiCIi", "", "isa-v30-instructions") // select BUILTIN(__builtin_ppc_maxfe, "LdLdLdLd.", "t") BUILTIN(__builtin_ppc_maxfl, "dddd.", "t") @@ -166,595 +185,696 @@ BUILTIN(__builtin_ppc_fnabss, "ff", "") BUILTIN(__builtin_ppc_get_timebase, "ULLi", "n") // This is just a placeholder, the types and attributes are wrong. -BUILTIN(__builtin_altivec_vaddcuw, "V4UiV4UiV4Ui", "") +TARGET_BUILTIN(__builtin_altivec_vaddcuw, "V4UiV4UiV4Ui", "", "altivec") -BUILTIN(__builtin_altivec_vaddsbs, "V16ScV16ScV16Sc", "") -BUILTIN(__builtin_altivec_vaddubs, "V16UcV16UcV16Uc", "") -BUILTIN(__builtin_altivec_vaddshs, "V8SsV8SsV8Ss", "") -BUILTIN(__builtin_altivec_vadduhs, "V8UsV8UsV8Us", "") -BUILTIN(__builtin_altivec_vaddsws, "V4SiV4SiV4Si", "") -BUILTIN(__builtin_altivec_vadduws, "V4UiV4UiV4Ui", "") -BUILTIN(__builtin_altivec_vaddeuqm, "V1ULLLiV1ULLLiV1ULLLiV1ULLLi","") -BUILTIN(__builtin_altivec_vaddcuq, "V1ULLLiV1ULLLiV1ULLLi","") -BUILTIN(__builtin_altivec_vaddecuq, "V1ULLLiV1ULLLiV1ULLLiV1ULLLi","") -BUILTIN(__builtin_altivec_vadduqm, "V1ULLLiV16UcV16Uc","") -BUILTIN(__builtin_altivec_vaddeuqm_c, "V16UcV16UcV16UcV16Uc","") -BUILTIN(__builtin_altivec_vaddcuq_c, "V16UcV16UcV16Uc","") -BUILTIN(__builtin_altivec_vaddecuq_c, "V16UcV16UcV16UcV16Uc","") +TARGET_BUILTIN(__builtin_altivec_vaddsbs, "V16ScV16ScV16Sc", "", "altivec") +TARGET_BUILTIN(__builtin_altivec_vaddubs, "V16UcV16UcV16Uc", "", "altivec") +TARGET_BUILTIN(__builtin_altivec_vaddshs, "V8SsV8SsV8Ss", "", "altivec") +TARGET_BUILTIN(__builtin_altivec_vadduhs, "V8UsV8UsV8Us", "", "altivec") +TARGET_BUILTIN(__builtin_altivec_vaddsws, "V4SiV4SiV4Si", "", "altivec") +TARGET_BUILTIN(__builtin_altivec_vadduws, "V4UiV4UiV4Ui", "", "altivec") +TARGET_BUILTIN(__builtin_altivec_vaddeuqm, "V1ULLLiV1ULLLiV1ULLLiV1ULLLi", "", + "power8-vector") +TARGET_BUILTIN(__builtin_altivec_vaddcuq, "V1ULLLiV1ULLLiV1ULLLi", "", + "power8-vector") +TARGET_BUILTIN(__builtin_altivec_vaddecuq, "V1ULLLiV1ULLLiV1ULLLiV1ULLLi", "", + "power8-vector") +TARGET_BUILTIN(__builtin_altivec_vadduqm, "V1ULLLiV16UcV16Uc", "", + "power8-vector") +TARGET_BUILTIN(__builtin_altivec_vaddeuqm_c, "V16UcV16UcV16UcV16Uc", "", + "power8-vector") +TARGET_BUILTIN(__builtin_altivec_vaddcuq_c, "V16UcV16UcV16Uc", "", + "power8-vector") +TARGET_BUILTIN(__builtin_altivec_vaddecuq_c, "V16UcV16UcV16UcV16Uc", "", + "power8-vector") -BUILTIN(__builtin_altivec_vsubsbs, "V16ScV16ScV16Sc", "") -BUILTIN(__builtin_altivec_vsububs, "V16UcV16UcV16Uc", "") -BUILTIN(__builtin_altivec_vsubshs, "V8SsV8SsV8Ss", "") -BUILTIN(__builtin_altivec_vsubuhs, "V8UsV8UsV8Us", "") -BUILTIN(__builtin_altivec_vsubsws, "V4SiV4SiV4Si", "") -BUILTIN(__builtin_altivec_vsubuws, "V4UiV4UiV4Ui", "") -BUILTIN(__builtin_altivec_vsubeuqm, "V1ULLLiV1ULLLiV1ULLLiV1ULLLi","") -BUILTIN(__builtin_altivec_vsubcuq, "V1ULLLiV1ULLLiV1ULLLi","") -BUILTIN(__builtin_altivec_vsubecuq, "V1ULLLiV1ULLLiV1ULLLiV1ULLLi","") -BUILTIN(__builtin_altivec_vsubuqm, "V1ULLLiV16UcV16Uc","") -BUILTIN(__builtin_altivec_vsubeuqm_c, "V16UcV16UcV16UcV16Uc","") -BUILTIN(__builtin_altivec_vsubcuq_c, "V16UcV16UcV16Uc","") -BUILTIN(__builtin_altivec_vsubecuq_c, "V16UcV16UcV16UcV16Uc","") +TARGET_BUILTIN(__builtin_altivec_vsubsbs, "V16ScV16ScV16Sc", "", "altivec") +TARGET_BUILTIN(__builtin_altivec_vsububs, "V16UcV16UcV16Uc", "", "altivec") +TARGET_BUILTIN(__builtin_altivec_vsubshs, "V8SsV8SsV8Ss", "", "altivec") +TARGET_BUILTIN(__builtin_altivec_vsubuhs, "V8UsV8UsV8Us", "", "altivec") +TARGET_BUILTIN(__builtin_altivec_vsubsws, "V4SiV4SiV4Si", "", "altivec") +TARGET_BUILTIN(__builtin_altivec_vsubuws, "V4UiV4UiV4Ui", "", "altivec") +TARGET_BUILTIN(__builtin_altivec_vsubeuqm, "V1ULLLiV1ULLLiV1ULLLiV1ULLLi", "", + "power8-vector") +TARGET_BUILTIN(__builtin_altivec_vsubcuq, "V1ULLLiV1ULLLiV1ULLLi", "", + "power8-vector") +TARGET_BUILTIN(__builtin_altivec_vsubecuq, "V1ULLLiV1ULLLiV1ULLLiV1ULLLi", "", + "power8-vector") +TARGET_BUILTIN(__builtin_altivec_vsubuqm, "V1ULLLiV16UcV16Uc", "", + "power8-vector") +TARGET_BUILTIN(__builtin_altivec_vsubeuqm_c, "V16UcV16UcV16UcV16Uc", "", + "power8-vector") +TARGET_BUILTIN(__builtin_altivec_vsubcuq_c, "V16UcV16UcV16Uc", "", + "power8-vector") +TARGET_BUILTIN(__builtin_altivec_vsubecuq_c, "V16UcV16UcV16UcV16Uc", "", + "power8-vector") -BUILTIN(__builtin_altivec_vavgsb, "V16ScV16ScV16Sc", "") -BUILTIN(__builtin_altivec_vavgub, "V16UcV16UcV16Uc", "") -BUILTIN(__builtin_altivec_vavgsh, "V8SsV8SsV8Ss", "") -BUILTIN(__builtin_altivec_vavguh, "V8UsV8UsV8Us", "") -BUILTIN(__builtin_altivec_vavgsw, "V4SiV4SiV4Si", "") -BUILTIN(__builtin_altivec_vavguw, "V4UiV4UiV4Ui", "") +TARGET_BUILTIN(__builtin_altivec_vavgsb, "V16ScV16ScV16Sc", "", "altivec") +TARGET_BUILTIN(__builtin_altivec_vavgub, "V16UcV16UcV16Uc", "", "altivec") +TARGET_BUILTIN(__builtin_altivec_vavgsh, "V8SsV8SsV8Ss", "", "altivec") +TARGET_BUILTIN(__builtin_altivec_vavguh, "V8UsV8UsV8Us", "", "altivec") +TARGET_BUILTIN(__builtin_altivec_vavgsw, "V4SiV4SiV4Si", "", "altivec") +TARGET_BUILTIN(__builtin_altivec_vavguw, "V4UiV4UiV4Ui", "", "altivec") -BUILTIN(__builtin_altivec_vrfip, "V4fV4f", "") +TARGET_BUILTIN(__builtin_altivec_vrfip, "V4fV4f", "", "altivec") -BUILTIN(__builtin_altivec_vcfsx, "V4fV4SiIi", "") -BUILTIN(__builtin_altivec_vcfux, "V4fV4UiIi", "") -BUILTIN(__builtin_altivec_vctsxs, "V4SiV4fIi", "") -BUILTIN(__builtin_altivec_vctuxs, "V4UiV4fIi", "") +TARGET_BUILTIN(__builtin_altivec_vcfsx, "V4fV4SiIi", "", "altivec") +TARGET_BUILTIN(__builtin_altivec_vcfux, "V4fV4UiIi", "", "altivec") +TARGET_BUILTIN(__builtin_altivec_vctsxs, "V4SiV4fIi", "", "altivec") +TARGET_BUILTIN(__builtin_altivec_vctuxs, "V4UiV4fIi", "", "altivec") -BUILTIN(__builtin_altivec_dss, "vUIi", "") -BUILTIN(__builtin_altivec_dssall, "v", "") -BUILTIN(__builtin_altivec_dst, "vvC*iUIi", "") -BUILTIN(__builtin_altivec_dstt, "vvC*iUIi", "") -BUILTIN(__builtin_altivec_dstst, "vvC*iUIi", "") -BUILTIN(__builtin_altivec_dststt, "vvC*iUIi", "") +TARGET_BUILTIN(__builtin_altivec_dss, "vUIi", "", "altivec") +TARGET_BUILTIN(__builtin_altivec_dssall, "v", "", "altivec") +TARGET_BUILTIN(__builtin_altivec_dst, "vvC*iUIi", "", "altivec") +TARGET_BUILTIN(__builtin_altivec_dstt, "vvC*iUIi", "", "altivec") +TARGET_BUILTIN(__builtin_altivec_dstst, "vvC*iUIi", "", "altivec") +TARGET_BUILTIN(__builtin_altivec_dststt, "vvC*iUIi", "", "altivec") -BUILTIN(__builtin_altivec_vexptefp, "V4fV4f", "") +TARGET_BUILTIN(__builtin_altivec_vexptefp, "V4fV4f", "", "altivec") -BUILTIN(__builtin_altivec_vrfim, "V4fV4f", "") +TARGET_BUILTIN(__builtin_altivec_vrfim, "V4fV4f", "", "altivec") -BUILTIN(__builtin_altivec_lvx, "V4iLivC*", "") -BUILTIN(__builtin_altivec_lvxl, "V4iLivC*", "") -BUILTIN(__builtin_altivec_lvebx, "V16cLivC*", "") -BUILTIN(__builtin_altivec_lvehx, "V8sLivC*", "") -BUILTIN(__builtin_altivec_lvewx, "V4iLivC*", "") +TARGET_BUILTIN(__builtin_altivec_lvx, "V4iLivC*", "", "altivec") +TARGET_BUILTIN(__builtin_altivec_lvxl, "V4iLivC*", "", "altivec") +TARGET_BUILTIN(__builtin_altivec_lvebx, "V16cLivC*", "", "altivec") +TARGET_BUILTIN(__builtin_altivec_lvehx, "V8sLivC*", "", "altivec") +TARGET_BUILTIN(__builtin_altivec_lvewx, "V4iLivC*", "", "altivec") -BUILTIN(__builtin_altivec_vlogefp, "V4fV4f", "") +TARGET_BUILTIN(__builtin_altivec_vlogefp, "V4fV4f", "", "altivec") -BUILTIN(__builtin_altivec_lvsl, "V16cUcvC*", "") -BUILTIN(__builtin_altivec_lvsr, "V16cUcvC*", "") +TARGET_BUILTIN(__builtin_altivec_lvsl, "V16cUcvC*", "", "altivec") +TARGET_BUILTIN(__builtin_altivec_lvsr, "V16cUcvC*", "", "altivec") -BUILTIN(__builtin_altivec_vmaddfp, "V4fV4fV4fV4f", "") -BUILTIN(__builtin_altivec_vmhaddshs, "V8sV8sV8sV8s", "") -BUILTIN(__builtin_altivec_vmhraddshs, "V8sV8sV8sV8s", "") +TARGET_BUILTIN(__builtin_altivec_vmaddfp, "V4fV4fV4fV4f", "", "altivec") +TARGET_BUILTIN(__builtin_altivec_vmhaddshs, "V8sV8sV8sV8s", "", "altivec") +TARGET_BUILTIN(__builtin_altivec_vmhraddshs, "V8sV8sV8sV8s", "", "altivec") -BUILTIN(__builtin_altivec_vmsumubm, "V4UiV16UcV16UcV4Ui", "") -BUILTIN(__builtin_altivec_vmsummbm, "V4SiV16ScV16UcV4Si", "") -BUILTIN(__builtin_altivec_vmsumuhm, "V4UiV8UsV8UsV4Ui", "") -BUILTIN(__builtin_altivec_vmsumshm, "V4SiV8SsV8SsV4Si", "") -BUILTIN(__builtin_altivec_vmsumuhs, "V4UiV8UsV8UsV4Ui", "") -BUILTIN(__builtin_altivec_vmsumshs, "V4SiV8SsV8SsV4Si", "") +TARGET_BUILTIN(__builtin_altivec_vmsumubm, "V4UiV16UcV16UcV4Ui", "", "altivec") +TARGET_BUILTIN(__builtin_altivec_vmsummbm, "V4SiV16ScV16UcV4Si", "", "altivec") +TARGET_BUILTIN(__builtin_altivec_vmsumuhm, "V4UiV8UsV8UsV4Ui", "", "altivec") +TARGET_BUILTIN(__builtin_altivec_vmsumshm, "V4SiV8SsV8SsV4Si", "", "altivec") +TARGET_BUILTIN(__builtin_altivec_vmsumuhs, "V4UiV8UsV8UsV4Ui", "", "altivec") +TARGET_BUILTIN(__builtin_altivec_vmsumshs, "V4SiV8SsV8SsV4Si", "", "altivec") -BUILTIN(__builtin_altivec_vmuleub, "V8UsV16UcV16Uc", "") -BUILTIN(__builtin_altivec_vmulesb, "V8SsV16ScV16Sc", "") -BUILTIN(__builtin_altivec_vmuleuh, "V4UiV8UsV8Us", "") -BUILTIN(__builtin_altivec_vmulesh, "V4SiV8SsV8Ss", "") -BUILTIN(__builtin_altivec_vmuleuw, "V2ULLiV4UiV4Ui", "") -BUILTIN(__builtin_altivec_vmulesw, "V2SLLiV4SiV4Si", "") -BUILTIN(__builtin_altivec_vmuloub, "V8UsV16UcV16Uc", "") -BUILTIN(__builtin_altivec_vmulosb, "V8SsV16ScV16Sc", "") -BUILTIN(__builtin_altivec_vmulouh, "V4UiV8UsV8Us", "") -BUILTIN(__builtin_altivec_vmulosh, "V4SiV8SsV8Ss", "") -BUILTIN(__builtin_altivec_vmulouw, "V2ULLiV4UiV4Ui", "") -BUILTIN(__builtin_altivec_vmulosw, "V2SLLiV4SiV4Si", "") -BUILTIN(__builtin_altivec_vmuleud, "V1ULLLiV2ULLiV2ULLi", "") -BUILTIN(__builtin_altivec_vmulesd, "V1SLLLiV2SLLiV2SLLi", "") -BUILTIN(__builtin_altivec_vmuloud, "V1ULLLiV2ULLiV2ULLi", "") -BUILTIN(__builtin_altivec_vmulosd, "V1SLLLiV2SLLiV2SLLi", "") -BUILTIN(__builtin_altivec_vmsumcud, "V1ULLLiV2ULLiV2ULLiV1ULLLi", "") +TARGET_BUILTIN(__builtin_altivec_vmuleub, "V8UsV16UcV16Uc", "", "altivec") +TARGET_BUILTIN(__builtin_altivec_vmulesb, "V8SsV16ScV16Sc", "", "altivec") +TARGET_BUILTIN(__builtin_altivec_vmuleuh, "V4UiV8UsV8Us", "", "altivec") +TARGET_BUILTIN(__builtin_altivec_vmulesh, "V4SiV8SsV8Ss", "", "altivec") +TARGET_BUILTIN(__builtin_altivec_vmuleuw, "V2ULLiV4UiV4Ui", "", "power8-vector") +TARGET_BUILTIN(__builtin_altivec_vmulesw, "V2SLLiV4SiV4Si", "", "power8-vector") +TARGET_BUILTIN(__builtin_altivec_vmuloub, "V8UsV16UcV16Uc", "", "altivec") +TARGET_BUILTIN(__builtin_altivec_vmulosb, "V8SsV16ScV16Sc", "", "altivec") +TARGET_BUILTIN(__builtin_altivec_vmulouh, "V4UiV8UsV8Us", "", "altivec") +TARGET_BUILTIN(__builtin_altivec_vmulosh, "V4SiV8SsV8Ss", "", "altivec") +TARGET_BUILTIN(__builtin_altivec_vmulouw, "V2ULLiV4UiV4Ui", "", "power8-vector") +TARGET_BUILTIN(__builtin_altivec_vmulosw, "V2SLLiV4SiV4Si", "", "power8-vector") +TARGET_BUILTIN(__builtin_altivec_vmuleud, "V1ULLLiV2ULLiV2ULLi", "", + "power10-vector") +TARGET_BUILTIN(__builtin_altivec_vmulesd, "V1SLLLiV2SLLiV2SLLi", "", + "power10-vector") +TARGET_BUILTIN(__builtin_altivec_vmuloud, "V1ULLLiV2ULLiV2ULLi", "", + "power10-vector") +TARGET_BUILTIN(__builtin_altivec_vmulosd, "V1SLLLiV2SLLiV2SLLi", "", + "power10-vector") +TARGET_BUILTIN(__builtin_altivec_vmsumcud, "V1ULLLiV2ULLiV2ULLiV1ULLLi", "", + "power10-vector") -BUILTIN(__builtin_altivec_vnmsubfp, "V4fV4fV4fV4f", "") +TARGET_BUILTIN(__builtin_altivec_vnmsubfp, "V4fV4fV4fV4f", "", "altivec") -BUILTIN(__builtin_altivec_vpkpx, "V8sV4UiV4Ui", "") -BUILTIN(__builtin_altivec_vpkuhus, "V16UcV8UsV8Us", "") -BUILTIN(__builtin_altivec_vpkshss, "V16ScV8SsV8Ss", "") -BUILTIN(__builtin_altivec_vpkuwus, "V8UsV4UiV4Ui", "") -BUILTIN(__builtin_altivec_vpkswss, "V8SsV4SiV4Si", "") -BUILTIN(__builtin_altivec_vpkshus, "V16UcV8SsV8Ss", "") -BUILTIN(__builtin_altivec_vpkswus, "V8UsV4SiV4Si", "") -BUILTIN(__builtin_altivec_vpksdss, "V4SiV2SLLiV2SLLi", "") -BUILTIN(__builtin_altivec_vpksdus, "V4UiV2SLLiV2SLLi", "") -BUILTIN(__builtin_altivec_vpkudus, "V4UiV2ULLiV2ULLi", "") -BUILTIN(__builtin_altivec_vpkudum, "V4UiV2ULLiV2ULLi", "") +TARGET_BUILTIN(__builtin_altivec_vpkpx, "V8sV4UiV4Ui", "", "altivec") +TARGET_BUILTIN(__builtin_altivec_vpkuhus, "V16UcV8UsV8Us", "", "altivec") +TARGET_BUILTIN(__builtin_altivec_vpkshss, "V16ScV8SsV8Ss", "", "altivec") +TARGET_BUILTIN(__builtin_altivec_vpkuwus, "V8UsV4UiV4Ui", "", "altivec") +TARGET_BUILTIN(__builtin_altivec_vpkswss, "V8SsV4SiV4Si", "", "altivec") +TARGET_BUILTIN(__builtin_altivec_vpkshus, "V16UcV8SsV8Ss", "", "altivec") +TARGET_BUILTIN(__builtin_altivec_vpkswus, "V8UsV4SiV4Si", "", "altivec") +TARGET_BUILTIN(__builtin_altivec_vpksdss, "V4SiV2SLLiV2SLLi", "", + "power8-vector") +TARGET_BUILTIN(__builtin_altivec_vpksdus, "V4UiV2SLLiV2SLLi", "", + "power8-vector") +TARGET_BUILTIN(__builtin_altivec_vpkudus, "V4UiV2ULLiV2ULLi", "", + "power8-vector") +TARGET_BUILTIN(__builtin_altivec_vpkudum, "V4UiV2ULLiV2ULLi", "", + "power8-vector") -BUILTIN(__builtin_altivec_vperm_4si, "V4iV4iV4iV16Uc", "") +TARGET_BUILTIN(__builtin_altivec_vperm_4si, "V4iV4iV4iV16Uc", "", "altivec") -BUILTIN(__builtin_altivec_stvx, "vV4iLiv*", "") -BUILTIN(__builtin_altivec_stvxl, "vV4iLiv*", "") -BUILTIN(__builtin_altivec_stvebx, "vV16cLiv*", "") -BUILTIN(__builtin_altivec_stvehx, "vV8sLiv*", "") -BUILTIN(__builtin_altivec_stvewx, "vV4iLiv*", "") +TARGET_BUILTIN(__builtin_altivec_stvx, "vV4iLiv*", "", "altivec") +TARGET_BUILTIN(__builtin_altivec_stvxl, "vV4iLiv*", "", "altivec") +TARGET_BUILTIN(__builtin_altivec_stvebx, "vV16cLiv*", "", "altivec") +TARGET_BUILTIN(__builtin_altivec_stvehx, "vV8sLiv*", "", "altivec") +TARGET_BUILTIN(__builtin_altivec_stvewx, "vV4iLiv*", "", "altivec") -BUILTIN(__builtin_altivec_vcmpbfp, "V4iV4fV4f", "") +TARGET_BUILTIN(__builtin_altivec_vcmpbfp, "V4iV4fV4f", "", "altivec") -BUILTIN(__builtin_altivec_vcmpgefp, "V4iV4fV4f", "") +TARGET_BUILTIN(__builtin_altivec_vcmpgefp, "V4iV4fV4f", "", "altivec") -BUILTIN(__builtin_altivec_vcmpequb, "V16cV16cV16c", "") -BUILTIN(__builtin_altivec_vcmpequh, "V8sV8sV8s", "") -BUILTIN(__builtin_altivec_vcmpequw, "V4iV4iV4i", "") -BUILTIN(__builtin_altivec_vcmpequd, "V2LLiV2LLiV2LLi", "") -BUILTIN(__builtin_altivec_vcmpeqfp, "V4iV4fV4f", "") +TARGET_BUILTIN(__builtin_altivec_vcmpequb, "V16cV16cV16c", "", "altivec") +TARGET_BUILTIN(__builtin_altivec_vcmpequh, "V8sV8sV8s", "", "altivec") +TARGET_BUILTIN(__builtin_altivec_vcmpequw, "V4iV4iV4i", "", "altivec") +TARGET_BUILTIN(__builtin_altivec_vcmpequd, "V2LLiV2LLiV2LLi", "", + "power8-vector") +TARGET_BUILTIN(__builtin_altivec_vcmpeqfp, "V4iV4fV4f", "", "altivec") -BUILTIN(__builtin_altivec_vcmpneb, "V16cV16cV16c", "") -BUILTIN(__builtin_altivec_vcmpneh, "V8sV8sV8s", "") -BUILTIN(__builtin_altivec_vcmpnew, "V4iV4iV4i", "") +TARGET_BUILTIN(__builtin_altivec_vcmpneb, "V16cV16cV16c", "", "power9-vector") +TARGET_BUILTIN(__builtin_altivec_vcmpneh, "V8sV8sV8s", "", "power9-vector") +TARGET_BUILTIN(__builtin_altivec_vcmpnew, "V4iV4iV4i", "", "power9-vector") -BUILTIN(__builtin_altivec_vcmpnezb, "V16cV16cV16c", "") -BUILTIN(__builtin_altivec_vcmpnezh, "V8sV8sV8s", "") -BUILTIN(__builtin_altivec_vcmpnezw, "V4iV4iV4i", "") +TARGET_BUILTIN(__builtin_altivec_vcmpnezb, "V16cV16cV16c", "", "power9-vector") +TARGET_BUILTIN(__builtin_altivec_vcmpnezh, "V8sV8sV8s", "", "power9-vector") +TARGET_BUILTIN(__builtin_altivec_vcmpnezw, "V4iV4iV4i", "", "power9-vector") -BUILTIN(__builtin_altivec_vcmpgtsb, "V16cV16ScV16Sc", "") -BUILTIN(__builtin_altivec_vcmpgtub, "V16cV16UcV16Uc", "") -BUILTIN(__builtin_altivec_vcmpgtsh, "V8sV8SsV8Ss", "") -BUILTIN(__builtin_altivec_vcmpgtuh, "V8sV8UsV8Us", "") -BUILTIN(__builtin_altivec_vcmpgtsw, "V4iV4SiV4Si", "") -BUILTIN(__builtin_altivec_vcmpgtuw, "V4iV4UiV4Ui", "") -BUILTIN(__builtin_altivec_vcmpgtsd, "V2LLiV2LLiV2LLi", "") -BUILTIN(__builtin_altivec_vcmpgtud, "V2LLiV2ULLiV2ULLi", "") -BUILTIN(__builtin_altivec_vcmpgtfp, "V4iV4fV4f", "") +TARGET_BUILTIN(__builtin_altivec_vcmpgtsb, "V16cV16ScV16Sc", "", "altivec") +TARGET_BUILTIN(__builtin_altivec_vcmpgtub, "V16cV16UcV16Uc", "", "altivec") +TARGET_BUILTIN(__builtin_altivec_vcmpgtsh, "V8sV8SsV8Ss", "", "altivec") +TARGET_BUILTIN(__builtin_altivec_vcmpgtuh, "V8sV8UsV8Us", "", "altivec") +TARGET_BUILTIN(__builtin_altivec_vcmpgtsw, "V4iV4SiV4Si", "", "altivec") +TARGET_BUILTIN(__builtin_altivec_vcmpgtuw, "V4iV4UiV4Ui", "", "altivec") +TARGET_BUILTIN(__builtin_altivec_vcmpgtsd, "V2LLiV2LLiV2LLi", "", + "power8-vector") +TARGET_BUILTIN(__builtin_altivec_vcmpgtud, "V2LLiV2ULLiV2ULLi", "", + "power8-vector") +TARGET_BUILTIN(__builtin_altivec_vcmpgtfp, "V4iV4fV4f", "", "altivec") // P10 Vector compare builtins. -BUILTIN(__builtin_altivec_vcmpequq, "V1LLLiV1ULLLiV1ULLLi", "") -BUILTIN(__builtin_altivec_vcmpgtsq, "V1LLLiV1SLLLiV1SLLLi", "") -BUILTIN(__builtin_altivec_vcmpgtuq, "V1LLLiV1ULLLiV1ULLLi", "") -BUILTIN(__builtin_altivec_vcmpequq_p, "iiV1ULLLiV1LLLi", "") -BUILTIN(__builtin_altivec_vcmpgtsq_p, "iiV1SLLLiV1SLLLi", "") -BUILTIN(__builtin_altivec_vcmpgtuq_p, "iiV1ULLLiV1ULLLi", "") +TARGET_BUILTIN(__builtin_altivec_vcmpequq, "V1LLLiV1ULLLiV1ULLLi", "", + "power10-vector") +TARGET_BUILTIN(__builtin_altivec_vcmpgtsq, "V1LLLiV1SLLLiV1SLLLi", "", + "power10-vector") +TARGET_BUILTIN(__builtin_altivec_vcmpgtuq, "V1LLLiV1ULLLiV1ULLLi", "", + "power10-vector") +TARGET_BUILTIN(__builtin_altivec_vcmpequq_p, "iiV1ULLLiV1LLLi", "", "altivec") +TARGET_BUILTIN(__builtin_altivec_vcmpgtsq_p, "iiV1SLLLiV1SLLLi", "", + "power10-vector") +TARGET_BUILTIN(__builtin_altivec_vcmpgtuq_p, "iiV1ULLLiV1ULLLi", "", + "power10-vector") -BUILTIN(__builtin_altivec_vmaxsb, "V16ScV16ScV16Sc", "") -BUILTIN(__builtin_altivec_vmaxub, "V16UcV16UcV16Uc", "") -BUILTIN(__builtin_altivec_vmaxsh, "V8SsV8SsV8Ss", "") -BUILTIN(__builtin_altivec_vmaxuh, "V8UsV8UsV8Us", "") -BUILTIN(__builtin_altivec_vmaxsw, "V4SiV4SiV4Si", "") -BUILTIN(__builtin_altivec_vmaxuw, "V4UiV4UiV4Ui", "") -BUILTIN(__builtin_altivec_vmaxsd, "V2LLiV2LLiV2LLi", "") -BUILTIN(__builtin_altivec_vmaxud, "V2ULLiV2ULLiV2ULLi", "") -BUILTIN(__builtin_altivec_vmaxfp, "V4fV4fV4f", "") +TARGET_BUILTIN(__builtin_altivec_vmaxsb, "V16ScV16ScV16Sc", "", "altivec") +TARGET_BUILTIN(__builtin_altivec_vmaxub, "V16UcV16UcV16Uc", "", "altivec") +TARGET_BUILTIN(__builtin_altivec_vmaxsh, "V8SsV8SsV8Ss", "", "altivec") +TARGET_BUILTIN(__builtin_altivec_vmaxuh, "V8UsV8UsV8Us", "", "altivec") +TARGET_BUILTIN(__builtin_altivec_vmaxsw, "V4SiV4SiV4Si", "", "altivec") +TARGET_BUILTIN(__builtin_altivec_vmaxuw, "V4UiV4UiV4Ui", "", "altivec") +TARGET_BUILTIN(__builtin_altivec_vmaxsd, "V2LLiV2LLiV2LLi", "", "power8-vector") +TARGET_BUILTIN(__builtin_altivec_vmaxud, "V2ULLiV2ULLiV2ULLi", "", + "power8-vector") +TARGET_BUILTIN(__builtin_altivec_vmaxfp, "V4fV4fV4f", "", "altivec") -BUILTIN(__builtin_altivec_mfvscr, "V8Us", "") +TARGET_BUILTIN(__builtin_altivec_mfvscr, "V8Us", "", "altivec") -BUILTIN(__builtin_altivec_vminsb, "V16ScV16ScV16Sc", "") -BUILTIN(__builtin_altivec_vminub, "V16UcV16UcV16Uc", "") -BUILTIN(__builtin_altivec_vminsh, "V8SsV8SsV8Ss", "") -BUILTIN(__builtin_altivec_vminuh, "V8UsV8UsV8Us", "") -BUILTIN(__builtin_altivec_vminsw, "V4SiV4SiV4Si", "") -BUILTIN(__builtin_altivec_vminuw, "V4UiV4UiV4Ui", "") -BUILTIN(__builtin_altivec_vminsd, "V2LLiV2LLiV2LLi", "") -BUILTIN(__builtin_altivec_vminud, "V2ULLiV2ULLiV2ULLi", "") -BUILTIN(__builtin_altivec_vminfp, "V4fV4fV4f", "") +TARGET_BUILTIN(__builtin_altivec_vminsb, "V16ScV16ScV16Sc", "", "altivec") +TARGET_BUILTIN(__builtin_altivec_vminub, "V16UcV16UcV16Uc", "", "altivec") +TARGET_BUILTIN(__builtin_altivec_vminsh, "V8SsV8SsV8Ss", "", "altivec") +TARGET_BUILTIN(__builtin_altivec_vminuh, "V8UsV8UsV8Us", "", "altivec") +TARGET_BUILTIN(__builtin_altivec_vminsw, "V4SiV4SiV4Si", "", "altivec") +TARGET_BUILTIN(__builtin_altivec_vminuw, "V4UiV4UiV4Ui", "", "altivec") +TARGET_BUILTIN(__builtin_altivec_vminsd, "V2LLiV2LLiV2LLi", "", "power8-vector") +TARGET_BUILTIN(__builtin_altivec_vminud, "V2ULLiV2ULLiV2ULLi", "", + "power8-vector") +TARGET_BUILTIN(__builtin_altivec_vminfp, "V4fV4fV4f", "", "altivec") -BUILTIN(__builtin_altivec_mtvscr, "vV4i", "") +TARGET_BUILTIN(__builtin_altivec_mtvscr, "vV4i", "", "altivec") -BUILTIN(__builtin_altivec_vrefp, "V4fV4f", "") +TARGET_BUILTIN(__builtin_altivec_vrefp, "V4fV4f", "", "altivec") -BUILTIN(__builtin_altivec_vrlb, "V16cV16cV16Uc", "") -BUILTIN(__builtin_altivec_vrlh, "V8sV8sV8Us", "") -BUILTIN(__builtin_altivec_vrlw, "V4iV4iV4Ui", "") -BUILTIN(__builtin_altivec_vrld, "V2LLiV2LLiV2ULLi", "") +TARGET_BUILTIN(__builtin_altivec_vrlb, "V16cV16cV16Uc", "", "altivec") +TARGET_BUILTIN(__builtin_altivec_vrlh, "V8sV8sV8Us", "", "altivec") +TARGET_BUILTIN(__builtin_altivec_vrlw, "V4iV4iV4Ui", "", "altivec") +TARGET_BUILTIN(__builtin_altivec_vrld, "V2LLiV2LLiV2ULLi", "", "power8-vector") -BUILTIN(__builtin_altivec_vsel_4si, "V4iV4iV4iV4Ui", "") +TARGET_BUILTIN(__builtin_altivec_vsel_4si, "V4iV4iV4iV4Ui", "", "altivec") -BUILTIN(__builtin_altivec_vsl, "V4iV4iV4i", "") -BUILTIN(__builtin_altivec_vslo, "V4iV4iV4i", "") +TARGET_BUILTIN(__builtin_altivec_vsl, "V4iV4iV4i", "", "altivec") +TARGET_BUILTIN(__builtin_altivec_vslo, "V4iV4iV4i", "", "altivec") -BUILTIN(__builtin_altivec_vsrab, "V16cV16cV16Uc", "") -BUILTIN(__builtin_altivec_vsrah, "V8sV8sV8Us", "") -BUILTIN(__builtin_altivec_vsraw, "V4iV4iV4Ui", "") +TARGET_BUILTIN(__builtin_altivec_vsrab, "V16cV16cV16Uc", "", "altivec") +TARGET_BUILTIN(__builtin_altivec_vsrah, "V8sV8sV8Us", "", "altivec") +TARGET_BUILTIN(__builtin_altivec_vsraw, "V4iV4iV4Ui", "", "altivec") -BUILTIN(__builtin_altivec_vsr, "V4iV4iV4i", "") -BUILTIN(__builtin_altivec_vsro, "V4iV4iV4i", "") +TARGET_BUILTIN(__builtin_altivec_vsr, "V4iV4iV4i", "", "altivec") +TARGET_BUILTIN(__builtin_altivec_vsro, "V4iV4iV4i", "", "altivec") -BUILTIN(__builtin_altivec_vrfin, "V4fV4f", "") +TARGET_BUILTIN(__builtin_altivec_vrfin, "V4fV4f", "", "altivec") -BUILTIN(__builtin_altivec_vrsqrtefp, "V4fV4f", "") +TARGET_BUILTIN(__builtin_altivec_vrsqrtefp, "V4fV4f", "", "altivec") -BUILTIN(__builtin_altivec_vsubcuw, "V4UiV4UiV4Ui", "") +TARGET_BUILTIN(__builtin_altivec_vsubcuw, "V4UiV4UiV4Ui", "", "altivec") -BUILTIN(__builtin_altivec_vsum4sbs, "V4SiV16ScV4Si", "") -BUILTIN(__builtin_altivec_vsum4ubs, "V4UiV16UcV4Ui", "") -BUILTIN(__builtin_altivec_vsum4shs, "V4SiV8SsV4Si", "") +TARGET_BUILTIN(__builtin_altivec_vsum4sbs, "V4SiV16ScV4Si", "", "altivec") +TARGET_BUILTIN(__builtin_altivec_vsum4ubs, "V4UiV16UcV4Ui", "", "altivec") +TARGET_BUILTIN(__builtin_altivec_vsum4shs, "V4SiV8SsV4Si", "", "altivec") -BUILTIN(__builtin_altivec_vsum2sws, "V4SiV4SiV4Si", "") +TARGET_BUILTIN(__builtin_altivec_vsum2sws, "V4SiV4SiV4Si", "", "altivec") -BUILTIN(__builtin_altivec_vsumsws, "V4SiV4SiV4Si", "") +TARGET_BUILTIN(__builtin_altivec_vsumsws, "V4SiV4SiV4Si", "", "altivec") -BUILTIN(__builtin_altivec_vrfiz, "V4fV4f", "") +TARGET_BUILTIN(__builtin_altivec_vrfiz, "V4fV4f", "", "altivec") -BUILTIN(__builtin_altivec_vupkhsb, "V8sV16c", "") -BUILTIN(__builtin_altivec_vupkhpx, "V4UiV8s", "") -BUILTIN(__builtin_altivec_vupkhsh, "V4iV8s", "") -BUILTIN(__builtin_altivec_vupkhsw, "V2LLiV4i", "") +TARGET_BUILTIN(__builtin_altivec_vupkhsb, "V8sV16c", "", "altivec") +TARGET_BUILTIN(__builtin_altivec_vupkhpx, "V4UiV8s", "", "altivec") +TARGET_BUILTIN(__builtin_altivec_vupkhsh, "V4iV8s", "", "altivec") +TARGET_BUILTIN(__builtin_altivec_vupkhsw, "V2LLiV4i", "", "power8-vector") -BUILTIN(__builtin_altivec_vupklsb, "V8sV16c", "") -BUILTIN(__builtin_altivec_vupklpx, "V4UiV8s", "") -BUILTIN(__builtin_altivec_vupklsh, "V4iV8s", "") -BUILTIN(__builtin_altivec_vupklsw, "V2LLiV4i", "") +TARGET_BUILTIN(__builtin_altivec_vupklsb, "V8sV16c", "", "altivec") +TARGET_BUILTIN(__builtin_altivec_vupklpx, "V4UiV8s", "", "altivec") +TARGET_BUILTIN(__builtin_altivec_vupklsh, "V4iV8s", "", "altivec") +TARGET_BUILTIN(__builtin_altivec_vupklsw, "V2LLiV4i", "", "power8-vector") -BUILTIN(__builtin_altivec_vcmpbfp_p, "iiV4fV4f", "") +TARGET_BUILTIN(__builtin_altivec_vcmpbfp_p, "iiV4fV4f", "", "altivec") -BUILTIN(__builtin_altivec_vcmpgefp_p, "iiV4fV4f", "") +TARGET_BUILTIN(__builtin_altivec_vcmpgefp_p, "iiV4fV4f", "", "altivec") -BUILTIN(__builtin_altivec_vcmpequb_p, "iiV16cV16c", "") -BUILTIN(__builtin_altivec_vcmpequh_p, "iiV8sV8s", "") -BUILTIN(__builtin_altivec_vcmpequw_p, "iiV4iV4i", "") -BUILTIN(__builtin_altivec_vcmpequd_p, "iiV2LLiV2LLi", "") -BUILTIN(__builtin_altivec_vcmpeqfp_p, "iiV4fV4f", "") +TARGET_BUILTIN(__builtin_altivec_vcmpequb_p, "iiV16cV16c", "", "altivec") +TARGET_BUILTIN(__builtin_altivec_vcmpequh_p, "iiV8sV8s", "", "altivec") +TARGET_BUILTIN(__builtin_altivec_vcmpequw_p, "iiV4iV4i", "", "altivec") +TARGET_BUILTIN(__builtin_altivec_vcmpequd_p, "iiV2LLiV2LLi", "", "vsx") +TARGET_BUILTIN(__builtin_altivec_vcmpeqfp_p, "iiV4fV4f", "", "altivec") -BUILTIN(__builtin_altivec_vcmpneb_p, "iiV16cV16c", "") -BUILTIN(__builtin_altivec_vcmpneh_p, "iiV8sV8s", "") -BUILTIN(__builtin_altivec_vcmpnew_p, "iiV4iV4i", "") -BUILTIN(__builtin_altivec_vcmpned_p, "iiV2LLiV2LLi", "") +TARGET_BUILTIN(__builtin_altivec_vcmpneb_p, "iiV16cV16c", "", "power9-vector") +TARGET_BUILTIN(__builtin_altivec_vcmpneh_p, "iiV8sV8s", "", "power9-vector") +TARGET_BUILTIN(__builtin_altivec_vcmpnew_p, "iiV4iV4i", "", "power9-vector") +TARGET_BUILTIN(__builtin_altivec_vcmpned_p, "iiV2LLiV2LLi", "", "vsx") -BUILTIN(__builtin_altivec_vcmpgtsb_p, "iiV16ScV16Sc", "") -BUILTIN(__builtin_altivec_vcmpgtub_p, "iiV16UcV16Uc", "") -BUILTIN(__builtin_altivec_vcmpgtsh_p, "iiV8SsV8Ss", "") -BUILTIN(__builtin_altivec_vcmpgtuh_p, "iiV8UsV8Us", "") -BUILTIN(__builtin_altivec_vcmpgtsw_p, "iiV4SiV4Si", "") -BUILTIN(__builtin_altivec_vcmpgtuw_p, "iiV4UiV4Ui", "") -BUILTIN(__builtin_altivec_vcmpgtsd_p, "iiV2LLiV2LLi", "") -BUILTIN(__builtin_altivec_vcmpgtud_p, "iiV2ULLiV2ULLi", "") -BUILTIN(__builtin_altivec_vcmpgtfp_p, "iiV4fV4f", "") +TARGET_BUILTIN(__builtin_altivec_vcmpgtsb_p, "iiV16ScV16Sc", "", "altivec") +TARGET_BUILTIN(__builtin_altivec_vcmpgtub_p, "iiV16UcV16Uc", "", "altivec") +TARGET_BUILTIN(__builtin_altivec_vcmpgtsh_p, "iiV8SsV8Ss", "", "altivec") +TARGET_BUILTIN(__builtin_altivec_vcmpgtuh_p, "iiV8UsV8Us", "", "altivec") +TARGET_BUILTIN(__builtin_altivec_vcmpgtsw_p, "iiV4SiV4Si", "", "altivec") +TARGET_BUILTIN(__builtin_altivec_vcmpgtuw_p, "iiV4UiV4Ui", "", "altivec") +TARGET_BUILTIN(__builtin_altivec_vcmpgtsd_p, "iiV2LLiV2LLi", "", "vsx") +TARGET_BUILTIN(__builtin_altivec_vcmpgtud_p, "iiV2ULLiV2ULLi", "", "vsx") +TARGET_BUILTIN(__builtin_altivec_vcmpgtfp_p, "iiV4fV4f", "", "altivec") -BUILTIN(__builtin_altivec_vgbbd, "V16UcV16Uc", "") -BUILTIN(__builtin_altivec_vbpermq, "V2ULLiV16UcV16Uc", "") -BUILTIN(__builtin_altivec_vbpermd, "V2ULLiV2ULLiV16Uc", "") +TARGET_BUILTIN(__builtin_altivec_vgbbd, "V16UcV16Uc", "", "power8-vector") +TARGET_BUILTIN(__builtin_altivec_vbpermq, "V2ULLiV16UcV16Uc", "", + "power8-vector") +TARGET_BUILTIN(__builtin_altivec_vbpermd, "V2ULLiV2ULLiV16Uc", "", + "power9-vector") // P8 Crypto built-ins. -BUILTIN(__builtin_altivec_crypto_vsbox, "V16UcV16Uc", "") -BUILTIN(__builtin_altivec_crypto_vpermxor, "V16UcV16UcV16UcV16Uc", "") -BUILTIN(__builtin_altivec_crypto_vpermxor_be, "V16UcV16UcV16UcV16Uc", "") -BUILTIN(__builtin_altivec_crypto_vshasigmaw, "V4UiV4UiIiIi", "") -BUILTIN(__builtin_altivec_crypto_vshasigmad, "V2ULLiV2ULLiIiIi", "") -BUILTIN(__builtin_altivec_crypto_vcipher, "V16UcV16UcV16Uc", "") -BUILTIN(__builtin_altivec_crypto_vcipherlast, "V16UcV16UcV16Uc", "") -BUILTIN(__builtin_altivec_crypto_vncipher, "V16UcV16UcV16Uc", "") -BUILTIN(__builtin_altivec_crypto_vncipherlast, "V16UcV16UcV16Uc", "") -BUILTIN(__builtin_altivec_crypto_vpmsumb, "V16UcV16UcV16Uc", "") -BUILTIN(__builtin_altivec_crypto_vpmsumh, "V8UsV8UsV8Us", "") -BUILTIN(__builtin_altivec_crypto_vpmsumw, "V4UiV4UiV4Ui", "") -BUILTIN(__builtin_altivec_crypto_vpmsumd, "V2ULLiV2ULLiV2ULLi", "") +TARGET_BUILTIN(__builtin_altivec_crypto_vsbox, "V16UcV16Uc", "", + "power8-vector") +TARGET_BUILTIN(__builtin_altivec_crypto_vpermxor, "V16UcV16UcV16UcV16Uc", "", + "power8-vector") +TARGET_BUILTIN(__builtin_altivec_crypto_vpermxor_be, "V16UcV16UcV16UcV16Uc", "", + "power8-vector") +TARGET_BUILTIN(__builtin_altivec_crypto_vshasigmaw, "V4UiV4UiIiIi", "", + "power8-vector") +TARGET_BUILTIN(__builtin_altivec_crypto_vshasigmad, "V2ULLiV2ULLiIiIi", "", + "power8-vector") +TARGET_BUILTIN(__builtin_altivec_crypto_vcipher, "V16UcV16UcV16Uc", "", + "power8-vector") +TARGET_BUILTIN(__builtin_altivec_crypto_vcipherlast, "V16UcV16UcV16Uc", "", + "power8-vector") +TARGET_BUILTIN(__builtin_altivec_crypto_vncipher, "V16UcV16UcV16Uc", "", + "power8-vector") +TARGET_BUILTIN(__builtin_altivec_crypto_vncipherlast, "V16UcV16UcV16Uc", "", + "power8-vector") +TARGET_BUILTIN(__builtin_altivec_crypto_vpmsumb, "V16UcV16UcV16Uc", "", + "power8-vector") +TARGET_BUILTIN(__builtin_altivec_crypto_vpmsumh, "V8UsV8UsV8Us", "", + "power8-vector") +TARGET_BUILTIN(__builtin_altivec_crypto_vpmsumw, "V4UiV4UiV4Ui", "", + "power8-vector") +TARGET_BUILTIN(__builtin_altivec_crypto_vpmsumd, "V2ULLiV2ULLiV2ULLi", "", + "power8-vector") -BUILTIN(__builtin_altivec_vclzb, "V16UcV16Uc", "") -BUILTIN(__builtin_altivec_vclzh, "V8UsV8Us", "") -BUILTIN(__builtin_altivec_vclzw, "V4UiV4Ui", "") -BUILTIN(__builtin_altivec_vclzd, "V2ULLiV2ULLi", "") -BUILTIN(__builtin_altivec_vctzb, "V16UcV16Uc", "") -BUILTIN(__builtin_altivec_vctzh, "V8UsV8Us", "") -BUILTIN(__builtin_altivec_vctzw, "V4UiV4Ui", "") -BUILTIN(__builtin_altivec_vctzd, "V2ULLiV2ULLi", "") +TARGET_BUILTIN(__builtin_altivec_vclzb, "V16UcV16Uc", "", "power8-vector") +TARGET_BUILTIN(__builtin_altivec_vclzh, "V8UsV8Us", "", "power8-vector") +TARGET_BUILTIN(__builtin_altivec_vclzw, "V4UiV4Ui", "", "power8-vector") +TARGET_BUILTIN(__builtin_altivec_vclzd, "V2ULLiV2ULLi", "", "power8-vector") +TARGET_BUILTIN(__builtin_altivec_vctzb, "V16UcV16Uc", "", "power9-vector") +TARGET_BUILTIN(__builtin_altivec_vctzh, "V8UsV8Us", "", "power9-vector") +TARGET_BUILTIN(__builtin_altivec_vctzw, "V4UiV4Ui", "", "power9-vector") +TARGET_BUILTIN(__builtin_altivec_vctzd, "V2ULLiV2ULLi", "", "power9-vector") // P8 BCD builtins. -BUILTIN(__builtin_ppc_bcdadd, "V16UcV16UcV16UcIi", "") -BUILTIN(__builtin_ppc_bcdsub, "V16UcV16UcV16UcIi", "") -BUILTIN(__builtin_ppc_bcdadd_p, "iiV16UcV16Uc", "") -BUILTIN(__builtin_ppc_bcdsub_p, "iiV16UcV16Uc", "") +TARGET_BUILTIN(__builtin_ppc_bcdadd, "V16UcV16UcV16UcIi", "", + "isa-v207-instructions") +TARGET_BUILTIN(__builtin_ppc_bcdsub, "V16UcV16UcV16UcIi", "", + "isa-v207-instructions") +TARGET_BUILTIN(__builtin_ppc_bcdadd_p, "iiV16UcV16Uc", "", + "isa-v207-instructions") +TARGET_BUILTIN(__builtin_ppc_bcdsub_p, "iiV16UcV16Uc", "", + "isa-v207-instructions") -BUILTIN(__builtin_altivec_vclzlsbb, "SiV16Uc", "") -BUILTIN(__builtin_altivec_vctzlsbb, "SiV16Uc", "") -BUILTIN(__builtin_altivec_vprtybw, "V4UiV4Ui", "") -BUILTIN(__builtin_altivec_vprtybd, "V2ULLiV2ULLi", "") -BUILTIN(__builtin_altivec_vprtybq, "V1ULLLiV1ULLLi", "") +TARGET_BUILTIN(__builtin_altivec_vclzlsbb, "SiV16Uc", "", "power9-vector") +TARGET_BUILTIN(__builtin_altivec_vctzlsbb, "SiV16Uc", "", "power9-vector") +TARGET_BUILTIN(__builtin_altivec_vprtybw, "V4UiV4Ui", "", "power9-vector") +TARGET_BUILTIN(__builtin_altivec_vprtybd, "V2ULLiV2ULLi", "", "power9-vector") +TARGET_BUILTIN(__builtin_altivec_vprtybq, "V1ULLLiV1ULLLi", "", "power9-vector") // Vector population count built-ins -BUILTIN(__builtin_altivec_vpopcntb, "V16UcV16Uc", "") -BUILTIN(__builtin_altivec_vpopcnth, "V8UsV8Us", "") -BUILTIN(__builtin_altivec_vpopcntw, "V4UiV4Ui", "") -BUILTIN(__builtin_altivec_vpopcntd, "V2ULLiV2ULLi", "") +TARGET_BUILTIN(__builtin_altivec_vpopcntb, "V16UcV16Uc", "", "power8-vector") +TARGET_BUILTIN(__builtin_altivec_vpopcnth, "V8UsV8Us", "", "power8-vector") +TARGET_BUILTIN(__builtin_altivec_vpopcntw, "V4UiV4Ui", "", "power8-vector") +TARGET_BUILTIN(__builtin_altivec_vpopcntd, "V2ULLiV2ULLi", "", "power8-vector") // Absolute difference built-ins -BUILTIN(__builtin_altivec_vabsdub, "V16UcV16UcV16Uc", "") -BUILTIN(__builtin_altivec_vabsduh, "V8UsV8UsV8Us", "") -BUILTIN(__builtin_altivec_vabsduw, "V4UiV4UiV4Ui", "") +TARGET_BUILTIN(__builtin_altivec_vabsdub, "V16UcV16UcV16Uc", "", + "power9-vector") +TARGET_BUILTIN(__builtin_altivec_vabsduh, "V8UsV8UsV8Us", "", "power9-vector") +TARGET_BUILTIN(__builtin_altivec_vabsduw, "V4UiV4UiV4Ui", "", "power9-vector") // P9 Shift built-ins. -BUILTIN(__builtin_altivec_vslv, "V16UcV16UcV16Uc", "") -BUILTIN(__builtin_altivec_vsrv, "V16UcV16UcV16Uc", "") +TARGET_BUILTIN(__builtin_altivec_vslv, "V16UcV16UcV16Uc", "", "power9-vector") +TARGET_BUILTIN(__builtin_altivec_vsrv, "V16UcV16UcV16Uc", "", "power9-vector") // P9 Vector rotate built-ins -BUILTIN(__builtin_altivec_vrlwmi, "V4UiV4UiV4UiV4Ui", "") -BUILTIN(__builtin_altivec_vrldmi, "V2ULLiV2ULLiV2ULLiV2ULLi", "") -BUILTIN(__builtin_altivec_vrlwnm, "V4UiV4UiV4Ui", "") -BUILTIN(__builtin_altivec_vrldnm, "V2ULLiV2ULLiV2ULLi", "") +TARGET_BUILTIN(__builtin_altivec_vrlwmi, "V4UiV4UiV4UiV4Ui", "", + "power9-vector") +TARGET_BUILTIN(__builtin_altivec_vrldmi, "V2ULLiV2ULLiV2ULLiV2ULLi", "", + "power9-vector") +TARGET_BUILTIN(__builtin_altivec_vrlwnm, "V4UiV4UiV4Ui", "", "power9-vector") +TARGET_BUILTIN(__builtin_altivec_vrldnm, "V2ULLiV2ULLiV2ULLi", "", + "power9-vector") // P9 Vector extend sign builtins. -BUILTIN(__builtin_altivec_vextsb2w, "V4SiV16Sc", "") -BUILTIN(__builtin_altivec_vextsb2d, "V2SLLiV16Sc", "") -BUILTIN(__builtin_altivec_vextsh2w, "V4SiV8Ss", "") -BUILTIN(__builtin_altivec_vextsh2d, "V2SLLiV8Ss", "") -BUILTIN(__builtin_altivec_vextsw2d, "V2SLLiV4Si", "") +TARGET_BUILTIN(__builtin_altivec_vextsb2w, "V4SiV16Sc", "", "power9-vector") +TARGET_BUILTIN(__builtin_altivec_vextsb2d, "V2SLLiV16Sc", "", "power9-vector") +TARGET_BUILTIN(__builtin_altivec_vextsh2w, "V4SiV8Ss", "", "power9-vector") +TARGET_BUILTIN(__builtin_altivec_vextsh2d, "V2SLLiV8Ss", "", "power9-vector") +TARGET_BUILTIN(__builtin_altivec_vextsw2d, "V2SLLiV4Si", "", "power9-vector") // P10 Vector extend sign builtins. -BUILTIN(__builtin_altivec_vextsd2q, "V1SLLLiV2SLLi", "") +TARGET_BUILTIN(__builtin_altivec_vextsd2q, "V1SLLLiV2SLLi", "", + "power10-vector") // P10 Vector Extract with Mask built-ins. -BUILTIN(__builtin_altivec_vextractbm, "UiV16Uc", "") -BUILTIN(__builtin_altivec_vextracthm, "UiV8Us", "") -BUILTIN(__builtin_altivec_vextractwm, "UiV4Ui", "") -BUILTIN(__builtin_altivec_vextractdm, "UiV2ULLi", "") -BUILTIN(__builtin_altivec_vextractqm, "UiV1ULLLi", "") +TARGET_BUILTIN(__builtin_altivec_vextractbm, "UiV16Uc", "", "power10-vector") +TARGET_BUILTIN(__builtin_altivec_vextracthm, "UiV8Us", "", "power10-vector") +TARGET_BUILTIN(__builtin_altivec_vextractwm, "UiV4Ui", "", "power10-vector") +TARGET_BUILTIN(__builtin_altivec_vextractdm, "UiV2ULLi", "", "power10-vector") +TARGET_BUILTIN(__builtin_altivec_vextractqm, "UiV1ULLLi", "", "power10-vector") // P10 Vector Divide Extended built-ins. -BUILTIN(__builtin_altivec_vdivesw, "V4SiV4SiV4Si", "") -BUILTIN(__builtin_altivec_vdiveuw, "V4UiV4UiV4Ui", "") -BUILTIN(__builtin_altivec_vdivesd, "V2LLiV2LLiV2LLi", "") -BUILTIN(__builtin_altivec_vdiveud, "V2ULLiV2ULLiV2ULLi", "") -BUILTIN(__builtin_altivec_vdivesq, "V1SLLLiV1SLLLiV1SLLLi", "") -BUILTIN(__builtin_altivec_vdiveuq, "V1ULLLiV1ULLLiV1ULLLi", "") +TARGET_BUILTIN(__builtin_altivec_vdivesw, "V4SiV4SiV4Si", "", "power10-vector") +TARGET_BUILTIN(__builtin_altivec_vdiveuw, "V4UiV4UiV4Ui", "", "power10-vector") +TARGET_BUILTIN(__builtin_altivec_vdivesd, "V2LLiV2LLiV2LLi", "", + "power10-vector") +TARGET_BUILTIN(__builtin_altivec_vdiveud, "V2ULLiV2ULLiV2ULLi", "", + "power10-vector") +TARGET_BUILTIN(__builtin_altivec_vdivesq, "V1SLLLiV1SLLLiV1SLLLi", "", + "power10-vector") +TARGET_BUILTIN(__builtin_altivec_vdiveuq, "V1ULLLiV1ULLLiV1ULLLi", "", + "power10-vector") // P10 Vector Multiply High built-ins. -BUILTIN(__builtin_altivec_vmulhsw, "V4SiV4SiV4Si", "") -BUILTIN(__builtin_altivec_vmulhuw, "V4UiV4UiV4Ui", "") -BUILTIN(__builtin_altivec_vmulhsd, "V2LLiV2LLiV2LLi", "") -BUILTIN(__builtin_altivec_vmulhud, "V2ULLiV2ULLiV2ULLi", "") +TARGET_BUILTIN(__builtin_altivec_vmulhsw, "V4SiV4SiV4Si", "", "power10-vector") +TARGET_BUILTIN(__builtin_altivec_vmulhuw, "V4UiV4UiV4Ui", "", "power10-vector") +TARGET_BUILTIN(__builtin_altivec_vmulhsd, "V2LLiV2LLiV2LLi", "", + "power10-vector") +TARGET_BUILTIN(__builtin_altivec_vmulhud, "V2ULLiV2ULLiV2ULLi", "", + "power10-vector") // P10 Vector Expand with Mask built-ins. -BUILTIN(__builtin_altivec_vexpandbm, "V16UcV16Uc", "") -BUILTIN(__builtin_altivec_vexpandhm, "V8UsV8Us", "") -BUILTIN(__builtin_altivec_vexpandwm, "V4UiV4Ui", "") -BUILTIN(__builtin_altivec_vexpanddm, "V2ULLiV2ULLi", "") -BUILTIN(__builtin_altivec_vexpandqm, "V1ULLLiV1ULLLi", "") +TARGET_BUILTIN(__builtin_altivec_vexpandbm, "V16UcV16Uc", "", "power10-vector") +TARGET_BUILTIN(__builtin_altivec_vexpandhm, "V8UsV8Us", "", "power10-vector") +TARGET_BUILTIN(__builtin_altivec_vexpandwm, "V4UiV4Ui", "", "power10-vector") +TARGET_BUILTIN(__builtin_altivec_vexpanddm, "V2ULLiV2ULLi", "", + "power10-vector") +TARGET_BUILTIN(__builtin_altivec_vexpandqm, "V1ULLLiV1ULLLi", "", + "power10-vector") // P10 Vector Count with Mask built-ins. -BUILTIN(__builtin_altivec_vcntmbb, "ULLiV16UcUi", "") -BUILTIN(__builtin_altivec_vcntmbh, "ULLiV8UsUi", "") -BUILTIN(__builtin_altivec_vcntmbw, "ULLiV4UiUi", "") -BUILTIN(__builtin_altivec_vcntmbd, "ULLiV2ULLiUi", "") +TARGET_BUILTIN(__builtin_altivec_vcntmbb, "ULLiV16UcUi", "", "power10-vector") +TARGET_BUILTIN(__builtin_altivec_vcntmbh, "ULLiV8UsUi", "", "power10-vector") +TARGET_BUILTIN(__builtin_altivec_vcntmbw, "ULLiV4UiUi", "", "power10-vector") +TARGET_BUILTIN(__builtin_altivec_vcntmbd, "ULLiV2ULLiUi", "", "power10-vector") // P10 Move to VSR with Mask built-ins. -BUILTIN(__builtin_altivec_mtvsrbm, "V16UcULLi", "") -BUILTIN(__builtin_altivec_mtvsrhm, "V8UsULLi", "") -BUILTIN(__builtin_altivec_mtvsrwm, "V4UiULLi", "") -BUILTIN(__builtin_altivec_mtvsrdm, "V2ULLiULLi", "") -BUILTIN(__builtin_altivec_mtvsrqm, "V1ULLLiULLi", "") +TARGET_BUILTIN(__builtin_altivec_mtvsrbm, "V16UcULLi", "", "power10-vector") +TARGET_BUILTIN(__builtin_altivec_mtvsrhm, "V8UsULLi", "", "power10-vector") +TARGET_BUILTIN(__builtin_altivec_mtvsrwm, "V4UiULLi", "", "power10-vector") +TARGET_BUILTIN(__builtin_altivec_mtvsrdm, "V2ULLiULLi", "", "power10-vector") +TARGET_BUILTIN(__builtin_altivec_mtvsrqm, "V1ULLLiULLi", "", "power10-vector") // P10 Vector Parallel Bits built-ins. -BUILTIN(__builtin_altivec_vpdepd, "V2ULLiV2ULLiV2ULLi", "") -BUILTIN(__builtin_altivec_vpextd, "V2ULLiV2ULLiV2ULLi", "") +TARGET_BUILTIN(__builtin_altivec_vpdepd, "V2ULLiV2ULLiV2ULLi", "", + "power10-vector") +TARGET_BUILTIN(__builtin_altivec_vpextd, "V2ULLiV2ULLiV2ULLi", "", + "power10-vector") // P10 Vector String Isolate Built-ins. -BUILTIN(__builtin_altivec_vstribr, "V16UcV16Uc", "") -BUILTIN(__builtin_altivec_vstribl, "V16UcV16Uc", "") -BUILTIN(__builtin_altivec_vstrihr, "V8sV8s", "") -BUILTIN(__builtin_altivec_vstrihl, "V8sV8s", "") -BUILTIN(__builtin_altivec_vstribr_p, "iiV16Uc", "") -BUILTIN(__builtin_altivec_vstribl_p, "iiV16Uc", "") -BUILTIN(__builtin_altivec_vstrihr_p, "iiV8s", "") -BUILTIN(__builtin_altivec_vstrihl_p, "iiV8s", "") +TARGET_BUILTIN(__builtin_altivec_vstribr, "V16UcV16Uc", "", "power10-vector") +TARGET_BUILTIN(__builtin_altivec_vstribl, "V16UcV16Uc", "", "power10-vector") +TARGET_BUILTIN(__builtin_altivec_vstrihr, "V8sV8s", "", "power10-vector") +TARGET_BUILTIN(__builtin_altivec_vstrihl, "V8sV8s", "", "power10-vector") +TARGET_BUILTIN(__builtin_altivec_vstribr_p, "iiV16Uc", "", "power10-vector") +TARGET_BUILTIN(__builtin_altivec_vstribl_p, "iiV16Uc", "", "power10-vector") +TARGET_BUILTIN(__builtin_altivec_vstrihr_p, "iiV8s", "", "power10-vector") +TARGET_BUILTIN(__builtin_altivec_vstrihl_p, "iiV8s", "", "power10-vector") // P10 Vector Centrifuge built-in. -BUILTIN(__builtin_altivec_vcfuged, "V2ULLiV2ULLiV2ULLi", "") +TARGET_BUILTIN(__builtin_altivec_vcfuged, "V2ULLiV2ULLiV2ULLi", "", + "power10-vector") // P10 Vector Gather Every N-th Bit built-in. -BUILTIN(__builtin_altivec_vgnb, "ULLiV1ULLLiIi", "") +TARGET_BUILTIN(__builtin_altivec_vgnb, "ULLiV1ULLLiIi", "", "power10-vector") // P10 Vector Clear Bytes built-ins. -BUILTIN(__builtin_altivec_vclrlb, "V16UcV16UcUi", "") -BUILTIN(__builtin_altivec_vclrrb, "V16UcV16UcUi", "") +TARGET_BUILTIN(__builtin_altivec_vclrlb, "V16UcV16UcUi", "", "power10-vector") +TARGET_BUILTIN(__builtin_altivec_vclrrb, "V16UcV16UcUi", "", "power10-vector") // P10 Vector Count Leading / Trailing Zeroes under bit Mask built-ins. -BUILTIN(__builtin_altivec_vclzdm, "V2ULLiV2ULLiV2ULLi", "") -BUILTIN(__builtin_altivec_vctzdm, "V2ULLiV2ULLiV2ULLi", "") +TARGET_BUILTIN(__builtin_altivec_vclzdm, "V2ULLiV2ULLiV2ULLi", "", + "power10-vector") +TARGET_BUILTIN(__builtin_altivec_vctzdm, "V2ULLiV2ULLiV2ULLi", "", + "power10-vector") // P10 Vector Shift built-ins. -BUILTIN(__builtin_altivec_vsldbi, "V16UcV16UcV16UcIi", "") -BUILTIN(__builtin_altivec_vsrdbi, "V16UcV16UcV16UcIi", "") +TARGET_BUILTIN(__builtin_altivec_vsldbi, "V16UcV16UcV16UcIi", "", + "power10-vector") +TARGET_BUILTIN(__builtin_altivec_vsrdbi, "V16UcV16UcV16UcIi", "", + "power10-vector") // P10 Vector Insert built-ins. -BUILTIN(__builtin_altivec_vinsblx, "V16UcV16UcUiUi", "") -BUILTIN(__builtin_altivec_vinsbrx, "V16UcV16UcUiUi", "") -BUILTIN(__builtin_altivec_vinshlx, "V8UsV8UsUiUi", "") -BUILTIN(__builtin_altivec_vinshrx, "V8UsV8UsUiUi", "") -BUILTIN(__builtin_altivec_vinswlx, "V4UiV4UiUiUi", "") -BUILTIN(__builtin_altivec_vinswrx, "V4UiV4UiUiUi", "") -BUILTIN(__builtin_altivec_vinsdlx, "V2ULLiV2ULLiULLiULLi", "") -BUILTIN(__builtin_altivec_vinsdrx, "V2ULLiV2ULLiULLiULLi", "") -BUILTIN(__builtin_altivec_vinsbvlx, "V16UcV16UcUiV16Uc", "") -BUILTIN(__builtin_altivec_vinsbvrx, "V16UcV16UcUiV16Uc", "") -BUILTIN(__builtin_altivec_vinshvlx, "V8UsV8UsUiV8Us", "") -BUILTIN(__builtin_altivec_vinshvrx, "V8UsV8UsUiV8Us", "") -BUILTIN(__builtin_altivec_vinswvlx, "V4UiV4UiUiV4Ui", "") -BUILTIN(__builtin_altivec_vinswvrx, "V4UiV4UiUiV4Ui", "") -BUILTIN(__builtin_altivec_vinsw, "V16UcV16UcUiIi", "") -BUILTIN(__builtin_altivec_vinsd, "V16UcV16UcULLiIi", "") -BUILTIN(__builtin_altivec_vinsw_elt, "V16UcV16UcUiiC", "") -BUILTIN(__builtin_altivec_vinsd_elt, "V16UcV16UcULLiiC", "") +TARGET_BUILTIN(__builtin_altivec_vinsblx, "V16UcV16UcUiUi", "", + "power10-vector") +TARGET_BUILTIN(__builtin_altivec_vinsbrx, "V16UcV16UcUiUi", "", + "power10-vector") +TARGET_BUILTIN(__builtin_altivec_vinshlx, "V8UsV8UsUiUi", "", "power10-vector") +TARGET_BUILTIN(__builtin_altivec_vinshrx, "V8UsV8UsUiUi", "", "power10-vector") +TARGET_BUILTIN(__builtin_altivec_vinswlx, "V4UiV4UiUiUi", "", "power10-vector") +TARGET_BUILTIN(__builtin_altivec_vinswrx, "V4UiV4UiUiUi", "", "power10-vector") +TARGET_BUILTIN(__builtin_altivec_vinsdlx, "V2ULLiV2ULLiULLiULLi", "", + "power10-vector") +TARGET_BUILTIN(__builtin_altivec_vinsdrx, "V2ULLiV2ULLiULLiULLi", "", + "power10-vector") +TARGET_BUILTIN(__builtin_altivec_vinsbvlx, "V16UcV16UcUiV16Uc", "", + "power10-vector") +TARGET_BUILTIN(__builtin_altivec_vinsbvrx, "V16UcV16UcUiV16Uc", "", + "power10-vector") +TARGET_BUILTIN(__builtin_altivec_vinshvlx, "V8UsV8UsUiV8Us", "", + "power10-vector") +TARGET_BUILTIN(__builtin_altivec_vinshvrx, "V8UsV8UsUiV8Us", "", + "power10-vector") +TARGET_BUILTIN(__builtin_altivec_vinswvlx, "V4UiV4UiUiV4Ui", "", + "power10-vector") +TARGET_BUILTIN(__builtin_altivec_vinswvrx, "V4UiV4UiUiV4Ui", "", + "power10-vector") +TARGET_BUILTIN(__builtin_altivec_vinsw, "V16UcV16UcUiIi", "", "power10-vector") +TARGET_BUILTIN(__builtin_altivec_vinsd, "V16UcV16UcULLiIi", "", + "power10-vector") +TARGET_BUILTIN(__builtin_altivec_vinsw_elt, "V16UcV16UcUiiC", "", + "power10-vector") +TARGET_BUILTIN(__builtin_altivec_vinsd_elt, "V16UcV16UcULLiiC", "", + "power10-vector") // P10 Vector Extract built-ins. -BUILTIN(__builtin_altivec_vextdubvlx, "V2ULLiV16UcV16UcUi", "") -BUILTIN(__builtin_altivec_vextdubvrx, "V2ULLiV16UcV16UcUi", "") -BUILTIN(__builtin_altivec_vextduhvlx, "V2ULLiV8UsV8UsUi", "") -BUILTIN(__builtin_altivec_vextduhvrx, "V2ULLiV8UsV8UsUi", "") -BUILTIN(__builtin_altivec_vextduwvlx, "V2ULLiV4UiV4UiUi", "") -BUILTIN(__builtin_altivec_vextduwvrx, "V2ULLiV4UiV4UiUi", "") -BUILTIN(__builtin_altivec_vextddvlx, "V2ULLiV2ULLiV2ULLiUi", "") -BUILTIN(__builtin_altivec_vextddvrx, "V2ULLiV2ULLiV2ULLiUi", "") +TARGET_BUILTIN(__builtin_altivec_vextdubvlx, "V2ULLiV16UcV16UcUi", "", + "power10-vector") +TARGET_BUILTIN(__builtin_altivec_vextdubvrx, "V2ULLiV16UcV16UcUi", "", + "power10-vector") +TARGET_BUILTIN(__builtin_altivec_vextduhvlx, "V2ULLiV8UsV8UsUi", "", + "power10-vector") +TARGET_BUILTIN(__builtin_altivec_vextduhvrx, "V2ULLiV8UsV8UsUi", "", + "power10-vector") +TARGET_BUILTIN(__builtin_altivec_vextduwvlx, "V2ULLiV4UiV4UiUi", "", + "power10-vector") +TARGET_BUILTIN(__builtin_altivec_vextduwvrx, "V2ULLiV4UiV4UiUi", "", + "power10-vector") +TARGET_BUILTIN(__builtin_altivec_vextddvlx, "V2ULLiV2ULLiV2ULLiUi", "", + "power10-vector") +TARGET_BUILTIN(__builtin_altivec_vextddvrx, "V2ULLiV2ULLiV2ULLiUi", "", + "power10-vector") // P10 Vector rotate built-ins. -BUILTIN(__builtin_altivec_vrlqmi, "V1ULLLiV1ULLLiV1ULLLiV1ULLLi", "") -BUILTIN(__builtin_altivec_vrlqnm, "V1ULLLiV1ULLLiV1ULLLi", "") +TARGET_BUILTIN(__builtin_altivec_vrlqmi, "V1ULLLiV1ULLLiV1ULLLiV1ULLLi", "", + "power10-vector") +TARGET_BUILTIN(__builtin_altivec_vrlqnm, "V1ULLLiV1ULLLiV1ULLLi", "", + "power10-vector") // VSX built-ins. -BUILTIN(__builtin_vsx_lxvd2x, "V2dLivC*", "") -BUILTIN(__builtin_vsx_lxvw4x, "V4iLivC*", "") -BUILTIN(__builtin_vsx_lxvd2x_be, "V2dSLLivC*", "") -BUILTIN(__builtin_vsx_lxvw4x_be, "V4iSLLivC*", "") +TARGET_BUILTIN(__builtin_vsx_lxvd2x, "V2dLivC*", "", "vsx") +TARGET_BUILTIN(__builtin_vsx_lxvw4x, "V4iLivC*", "", "vsx") +TARGET_BUILTIN(__builtin_vsx_lxvd2x_be, "V2dSLLivC*", "", "vsx") +TARGET_BUILTIN(__builtin_vsx_lxvw4x_be, "V4iSLLivC*", "", "vsx") -BUILTIN(__builtin_vsx_stxvd2x, "vV2dLiv*", "") -BUILTIN(__builtin_vsx_stxvw4x, "vV4iLiv*", "") -BUILTIN(__builtin_vsx_stxvd2x_be, "vV2dSLLivC*", "") -BUILTIN(__builtin_vsx_stxvw4x_be, "vV4iSLLivC*", "") +TARGET_BUILTIN(__builtin_vsx_stxvd2x, "vV2dLiv*", "", "vsx") +TARGET_BUILTIN(__builtin_vsx_stxvw4x, "vV4iLiv*", "", "vsx") +TARGET_BUILTIN(__builtin_vsx_stxvd2x_be, "vV2dSLLivC*", "", "vsx") +TARGET_BUILTIN(__builtin_vsx_stxvw4x_be, "vV4iSLLivC*", "", "vsx") -BUILTIN(__builtin_vsx_lxvl, "V4ivC*ULLi", "") -BUILTIN(__builtin_vsx_lxvll, "V4ivC*ULLi", "") -BUILTIN(__builtin_vsx_stxvl, "vV4iv*ULLi", "") -BUILTIN(__builtin_vsx_stxvll, "vV4iv*ULLi", "") -BUILTIN(__builtin_vsx_ldrmb, "V16UcCc*Ii", "") -BUILTIN(__builtin_vsx_strmb, "vCc*IiV16Uc", "") +TARGET_BUILTIN(__builtin_vsx_lxvl, "V4ivC*ULLi", "", "power9-vector") +TARGET_BUILTIN(__builtin_vsx_lxvll, "V4ivC*ULLi", "", "power9-vector") +TARGET_BUILTIN(__builtin_vsx_stxvl, "vV4iv*ULLi", "", "power9-vector") +TARGET_BUILTIN(__builtin_vsx_stxvll, "vV4iv*ULLi", "", "power9-vector") +TARGET_BUILTIN(__builtin_vsx_ldrmb, "V16UcCc*Ii", "", "isa-v207-instructions") +TARGET_BUILTIN(__builtin_vsx_strmb, "vCc*IiV16Uc", "", "isa-v207-instructions") -BUILTIN(__builtin_vsx_xvmaxdp, "V2dV2dV2d", "") -BUILTIN(__builtin_vsx_xvmaxsp, "V4fV4fV4f", "") -BUILTIN(__builtin_vsx_xsmaxdp, "ddd", "") +TARGET_BUILTIN(__builtin_vsx_xvmaxdp, "V2dV2dV2d", "", "vsx") +TARGET_BUILTIN(__builtin_vsx_xvmaxsp, "V4fV4fV4f", "", "vsx") +TARGET_BUILTIN(__builtin_vsx_xsmaxdp, "ddd", "", "vsx") -BUILTIN(__builtin_vsx_xvmindp, "V2dV2dV2d", "") -BUILTIN(__builtin_vsx_xvminsp, "V4fV4fV4f", "") -BUILTIN(__builtin_vsx_xsmindp, "ddd", "") +TARGET_BUILTIN(__builtin_vsx_xvmindp, "V2dV2dV2d", "", "vsx") +TARGET_BUILTIN(__builtin_vsx_xvminsp, "V4fV4fV4f", "", "vsx") +TARGET_BUILTIN(__builtin_vsx_xsmindp, "ddd", "", "vsx") -BUILTIN(__builtin_vsx_xvdivdp, "V2dV2dV2d", "") -BUILTIN(__builtin_vsx_xvdivsp, "V4fV4fV4f", "") +TARGET_BUILTIN(__builtin_vsx_xvdivdp, "V2dV2dV2d", "", "vsx") +TARGET_BUILTIN(__builtin_vsx_xvdivsp, "V4fV4fV4f", "", "vsx") -BUILTIN(__builtin_vsx_xvrdpip, "V2dV2d", "") -BUILTIN(__builtin_vsx_xvrspip, "V4fV4f", "") +TARGET_BUILTIN(__builtin_vsx_xvrdpip, "V2dV2d", "", "vsx") +TARGET_BUILTIN(__builtin_vsx_xvrspip, "V4fV4f", "", "vsx") -BUILTIN(__builtin_vsx_xvcmpeqdp, "V2ULLiV2dV2d", "") -BUILTIN(__builtin_vsx_xvcmpeqsp, "V4UiV4fV4f", "") +TARGET_BUILTIN(__builtin_vsx_xvcmpeqdp, "V2ULLiV2dV2d", "", "vsx") +TARGET_BUILTIN(__builtin_vsx_xvcmpeqsp, "V4UiV4fV4f", "", "vsx") -BUILTIN(__builtin_vsx_xvcmpeqdp_p, "iiV2dV2d", "") -BUILTIN(__builtin_vsx_xvcmpeqsp_p, "iiV4fV4f", "") +TARGET_BUILTIN(__builtin_vsx_xvcmpeqdp_p, "iiV2dV2d", "", "vsx") +TARGET_BUILTIN(__builtin_vsx_xvcmpeqsp_p, "iiV4fV4f", "", "vsx") -BUILTIN(__builtin_vsx_xvcmpgedp, "V2ULLiV2dV2d", "") -BUILTIN(__builtin_vsx_xvcmpgesp, "V4UiV4fV4f", "") +TARGET_BUILTIN(__builtin_vsx_xvcmpgedp, "V2ULLiV2dV2d", "", "vsx") +TARGET_BUILTIN(__builtin_vsx_xvcmpgesp, "V4UiV4fV4f", "", "vsx") -BUILTIN(__builtin_vsx_xvcmpgedp_p, "iiV2dV2d", "") -BUILTIN(__builtin_vsx_xvcmpgesp_p, "iiV4fV4f", "") +TARGET_BUILTIN(__builtin_vsx_xvcmpgedp_p, "iiV2dV2d", "", "vsx") +TARGET_BUILTIN(__builtin_vsx_xvcmpgesp_p, "iiV4fV4f", "", "vsx") -BUILTIN(__builtin_vsx_xvcmpgtdp, "V2ULLiV2dV2d", "") -BUILTIN(__builtin_vsx_xvcmpgtsp, "V4UiV4fV4f", "") +TARGET_BUILTIN(__builtin_vsx_xvcmpgtdp, "V2ULLiV2dV2d", "", "vsx") +TARGET_BUILTIN(__builtin_vsx_xvcmpgtsp, "V4UiV4fV4f", "", "vsx") -BUILTIN(__builtin_vsx_xvcmpgtdp_p, "iiV2dV2d", "") -BUILTIN(__builtin_vsx_xvcmpgtsp_p, "iiV4fV4f", "") +TARGET_BUILTIN(__builtin_vsx_xvcmpgtdp_p, "iiV2dV2d", "", "vsx") +TARGET_BUILTIN(__builtin_vsx_xvcmpgtsp_p, "iiV4fV4f", "", "vsx") -BUILTIN(__builtin_vsx_xvrdpim, "V2dV2d", "") -BUILTIN(__builtin_vsx_xvrspim, "V4fV4f", "") +TARGET_BUILTIN(__builtin_vsx_xvrdpim, "V2dV2d", "", "vsx") +TARGET_BUILTIN(__builtin_vsx_xvrspim, "V4fV4f", "", "vsx") -BUILTIN(__builtin_vsx_xvrdpi, "V2dV2d", "") -BUILTIN(__builtin_vsx_xvrspi, "V4fV4f", "") +TARGET_BUILTIN(__builtin_vsx_xvrdpi, "V2dV2d", "", "vsx") +TARGET_BUILTIN(__builtin_vsx_xvrspi, "V4fV4f", "", "vsx") -BUILTIN(__builtin_vsx_xvrdpic, "V2dV2d", "") -BUILTIN(__builtin_vsx_xvrspic, "V4fV4f", "") +TARGET_BUILTIN(__builtin_vsx_xvrdpic, "V2dV2d", "", "vsx") +TARGET_BUILTIN(__builtin_vsx_xvrspic, "V4fV4f", "", "vsx") -BUILTIN(__builtin_vsx_xvrdpiz, "V2dV2d", "") -BUILTIN(__builtin_vsx_xvrspiz, "V4fV4f", "") +TARGET_BUILTIN(__builtin_vsx_xvrdpiz, "V2dV2d", "", "vsx") +TARGET_BUILTIN(__builtin_vsx_xvrspiz, "V4fV4f", "", "vsx") -BUILTIN(__builtin_vsx_xvmaddadp, "V2dV2dV2dV2d", "") -BUILTIN(__builtin_vsx_xvmaddasp, "V4fV4fV4fV4f", "") +TARGET_BUILTIN(__builtin_vsx_xvmaddadp, "V2dV2dV2dV2d", "", "vsx") +TARGET_BUILTIN(__builtin_vsx_xvmaddasp, "V4fV4fV4fV4f", "", "vsx") -BUILTIN(__builtin_vsx_xvmsubadp, "V2dV2dV2dV2d", "") -BUILTIN(__builtin_vsx_xvmsubasp, "V4fV4fV4fV4f", "") +TARGET_BUILTIN(__builtin_vsx_xvmsubadp, "V2dV2dV2dV2d", "", "vsx") +TARGET_BUILTIN(__builtin_vsx_xvmsubasp, "V4fV4fV4fV4f", "", "vsx") -BUILTIN(__builtin_vsx_xvmuldp, "V2dV2dV2d", "") -BUILTIN(__builtin_vsx_xvmulsp, "V4fV4fV4f", "") +TARGET_BUILTIN(__builtin_vsx_xvmuldp, "V2dV2dV2d", "", "vsx") +TARGET_BUILTIN(__builtin_vsx_xvmulsp, "V4fV4fV4f", "", "vsx") -BUILTIN(__builtin_vsx_xvnmaddadp, "V2dV2dV2dV2d", "") -BUILTIN(__builtin_vsx_xvnmaddasp, "V4fV4fV4fV4f", "") +TARGET_BUILTIN(__builtin_vsx_xvnmaddadp, "V2dV2dV2dV2d", "", "vsx") +TARGET_BUILTIN(__builtin_vsx_xvnmaddasp, "V4fV4fV4fV4f", "", "vsx") -BUILTIN(__builtin_vsx_xvnmsubadp, "V2dV2dV2dV2d", "") -BUILTIN(__builtin_vsx_xvnmsubasp, "V4fV4fV4fV4f", "") +TARGET_BUILTIN(__builtin_vsx_xvnmsubadp, "V2dV2dV2dV2d", "", "vsx") +TARGET_BUILTIN(__builtin_vsx_xvnmsubasp, "V4fV4fV4fV4f", "", "vsx") -BUILTIN(__builtin_vsx_xvredp, "V2dV2d", "") -BUILTIN(__builtin_vsx_xvresp, "V4fV4f", "") +TARGET_BUILTIN(__builtin_vsx_xvredp, "V2dV2d", "", "vsx") +TARGET_BUILTIN(__builtin_vsx_xvresp, "V4fV4f", "", "vsx") -BUILTIN(__builtin_vsx_xvrsqrtedp, "V2dV2d", "") -BUILTIN(__builtin_vsx_xvrsqrtesp, "V4fV4f", "") +TARGET_BUILTIN(__builtin_vsx_xvrsqrtedp, "V2dV2d", "", "vsx") +TARGET_BUILTIN(__builtin_vsx_xvrsqrtesp, "V4fV4f", "", "vsx") -BUILTIN(__builtin_vsx_xvsqrtdp, "V2dV2d", "") -BUILTIN(__builtin_vsx_xvsqrtsp, "V4fV4f", "") +TARGET_BUILTIN(__builtin_vsx_xvsqrtdp, "V2dV2d", "", "vsx") +TARGET_BUILTIN(__builtin_vsx_xvsqrtsp, "V4fV4f", "", "vsx") -BUILTIN(__builtin_vsx_xxleqv, "V4UiV4UiV4Ui", "") +TARGET_BUILTIN(__builtin_vsx_xxleqv, "V4UiV4UiV4Ui", "", "power8-vector") -BUILTIN(__builtin_vsx_xvcpsgndp, "V2dV2dV2d", "") -BUILTIN(__builtin_vsx_xvcpsgnsp, "V4fV4fV4f", "") +TARGET_BUILTIN(__builtin_vsx_xvcpsgndp, "V2dV2dV2d", "", "vsx") +TARGET_BUILTIN(__builtin_vsx_xvcpsgnsp, "V4fV4fV4f", "", "vsx") -BUILTIN(__builtin_vsx_xvabssp, "V4fV4f", "") -BUILTIN(__builtin_vsx_xvabsdp, "V2dV2d", "") +TARGET_BUILTIN(__builtin_vsx_xvabssp, "V4fV4f", "", "vsx") +TARGET_BUILTIN(__builtin_vsx_xvabsdp, "V2dV2d", "", "vsx") -BUILTIN(__builtin_vsx_xxgenpcvbm, "V16UcV16Uci", "") -BUILTIN(__builtin_vsx_xxgenpcvhm, "V8UsV8Usi", "") -BUILTIN(__builtin_vsx_xxgenpcvwm, "V4UiV4Uii", "") -BUILTIN(__builtin_vsx_xxgenpcvdm, "V2ULLiV2ULLii", "") +TARGET_BUILTIN(__builtin_vsx_xxgenpcvbm, "V16UcV16Uci", "", "power10-vector") +TARGET_BUILTIN(__builtin_vsx_xxgenpcvhm, "V8UsV8Usi", "", "power10-vector") +TARGET_BUILTIN(__builtin_vsx_xxgenpcvwm, "V4UiV4Uii", "", "power10-vector") +TARGET_BUILTIN(__builtin_vsx_xxgenpcvdm, "V2ULLiV2ULLii", "", "power10-vector") // vector Insert/Extract exponent/significand builtins -BUILTIN(__builtin_vsx_xviexpdp, "V2dV2ULLiV2ULLi", "") -BUILTIN(__builtin_vsx_xviexpsp, "V4fV4UiV4Ui", "") -BUILTIN(__builtin_vsx_xvxexpdp, "V2ULLiV2d", "") -BUILTIN(__builtin_vsx_xvxexpsp, "V4UiV4f", "") -BUILTIN(__builtin_vsx_xvxsigdp, "V2ULLiV2d", "") -BUILTIN(__builtin_vsx_xvxsigsp, "V4UiV4f", "") +TARGET_BUILTIN(__builtin_vsx_xviexpdp, "V2dV2ULLiV2ULLi", "", "power9-vector") +TARGET_BUILTIN(__builtin_vsx_xviexpsp, "V4fV4UiV4Ui", "", "power9-vector") +TARGET_BUILTIN(__builtin_vsx_xvxexpdp, "V2ULLiV2d", "", "power9-vector") +TARGET_BUILTIN(__builtin_vsx_xvxexpsp, "V4UiV4f", "", "power9-vector") +TARGET_BUILTIN(__builtin_vsx_xvxsigdp, "V2ULLiV2d", "", "power9-vector") +TARGET_BUILTIN(__builtin_vsx_xvxsigsp, "V4UiV4f", "", "power9-vector") // Conversion builtins -BUILTIN(__builtin_vsx_xvcvdpsxws, "V4SiV2d", "") -BUILTIN(__builtin_vsx_xvcvdpuxws, "V4UiV2d", "") -BUILTIN(__builtin_vsx_xvcvspsxds, "V2SLLiV4f", "") -BUILTIN(__builtin_vsx_xvcvspuxds, "V2ULLiV4f", "") -BUILTIN(__builtin_vsx_xvcvsxwdp, "V2dV4Si", "") -BUILTIN(__builtin_vsx_xvcvuxwdp, "V2dV4Ui", "") -BUILTIN(__builtin_vsx_xvcvspdp, "V2dV4f", "") -BUILTIN(__builtin_vsx_xvcvsxdsp, "V4fV2SLLi", "") -BUILTIN(__builtin_vsx_xvcvuxdsp, "V4fV2ULLi", "") -BUILTIN(__builtin_vsx_xvcvdpsp, "V4fV2d", "") +TARGET_BUILTIN(__builtin_vsx_xvcvdpsxws, "V4SiV2d", "", "vsx") +TARGET_BUILTIN(__builtin_vsx_xvcvdpuxws, "V4UiV2d", "", "vsx") +TARGET_BUILTIN(__builtin_vsx_xvcvspsxds, "V2SLLiV4f", "", "vsx") +TARGET_BUILTIN(__builtin_vsx_xvcvspuxds, "V2ULLiV4f", "", "vsx") +TARGET_BUILTIN(__builtin_vsx_xvcvsxwdp, "V2dV4Si", "", "vsx") +TARGET_BUILTIN(__builtin_vsx_xvcvuxwdp, "V2dV4Ui", "", "vsx") +TARGET_BUILTIN(__builtin_vsx_xvcvspdp, "V2dV4f", "", "vsx") +TARGET_BUILTIN(__builtin_vsx_xvcvsxdsp, "V4fV2SLLi", "", "vsx") +TARGET_BUILTIN(__builtin_vsx_xvcvuxdsp, "V4fV2ULLi", "", "vsx") +TARGET_BUILTIN(__builtin_vsx_xvcvdpsp, "V4fV2d", "", "vsx") -BUILTIN(__builtin_vsx_xvcvsphp, "V4fV4f", "") -BUILTIN(__builtin_vsx_xvcvhpsp, "V4fV8Us", "") +TARGET_BUILTIN(__builtin_vsx_xvcvsphp, "V4fV4f", "", "power9-vector") +TARGET_BUILTIN(__builtin_vsx_xvcvhpsp, "V4fV8Us", "", "power9-vector") -BUILTIN(__builtin_vsx_xvcvspbf16, "V16UcV16Uc", "") -BUILTIN(__builtin_vsx_xvcvbf16spn, "V16UcV16Uc", "") +TARGET_BUILTIN(__builtin_vsx_xvcvspbf16, "V16UcV16Uc", "", "power10-vector") +TARGET_BUILTIN(__builtin_vsx_xvcvbf16spn, "V16UcV16Uc", "", "power10-vector") // Vector Test Data Class builtins -BUILTIN(__builtin_vsx_xvtstdcdp, "V2ULLiV2dIi", "") -BUILTIN(__builtin_vsx_xvtstdcsp, "V4UiV4fIi", "") +TARGET_BUILTIN(__builtin_vsx_xvtstdcdp, "V2ULLiV2dIi", "", "power9-vector") +TARGET_BUILTIN(__builtin_vsx_xvtstdcsp, "V4UiV4fIi", "", "power9-vector") -BUILTIN(__builtin_vsx_insertword, "V16UcV4UiV16UcIi", "") -BUILTIN(__builtin_vsx_extractuword, "V2ULLiV16UcIi", "") +TARGET_BUILTIN(__builtin_vsx_insertword, "V16UcV4UiV16UcIi", "", "vsx") +TARGET_BUILTIN(__builtin_vsx_extractuword, "V2ULLiV16UcIi", "", "vsx") -BUILTIN(__builtin_vsx_xxpermdi, "v.", "t") -BUILTIN(__builtin_vsx_xxsldwi, "v.", "t") +TARGET_BUILTIN(__builtin_vsx_xxpermdi, "v.", "t", "vsx") +TARGET_BUILTIN(__builtin_vsx_xxsldwi, "v.", "t", "vsx") -BUILTIN(__builtin_vsx_xxeval, "V2ULLiV2ULLiV2ULLiV2ULLiIi", "") +TARGET_BUILTIN(__builtin_vsx_xxeval, "V2ULLiV2ULLiV2ULLiV2ULLiIi", "", + "power10-vector") -BUILTIN(__builtin_vsx_xvtlsbb, "iV16UcUi", "") +TARGET_BUILTIN(__builtin_vsx_xvtlsbb, "iV16UcUi", "", "power10-vector") -BUILTIN(__builtin_vsx_xvtdivdp, "iV2dV2d", "") -BUILTIN(__builtin_vsx_xvtdivsp, "iV4fV4f", "") -BUILTIN(__builtin_vsx_xvtsqrtdp, "iV2d", "") -BUILTIN(__builtin_vsx_xvtsqrtsp, "iV4f", "") +TARGET_BUILTIN(__builtin_vsx_xvtdivdp, "iV2dV2d", "", "vsx") +TARGET_BUILTIN(__builtin_vsx_xvtdivsp, "iV4fV4f", "", "vsx") +TARGET_BUILTIN(__builtin_vsx_xvtsqrtdp, "iV2d", "", "vsx") +TARGET_BUILTIN(__builtin_vsx_xvtsqrtsp, "iV4f", "", "vsx") // P10 Vector Permute Extended built-in. -BUILTIN(__builtin_vsx_xxpermx, "V16UcV16UcV16UcV16UcIi", "") +TARGET_BUILTIN(__builtin_vsx_xxpermx, "V16UcV16UcV16UcV16UcIi", "", + "power10-vector") // P10 Vector Blend built-ins. -BUILTIN(__builtin_vsx_xxblendvb, "V16UcV16UcV16UcV16Uc", "") -BUILTIN(__builtin_vsx_xxblendvh, "V8UsV8UsV8UsV8Us", "") -BUILTIN(__builtin_vsx_xxblendvw, "V4UiV4UiV4UiV4Ui", "") -BUILTIN(__builtin_vsx_xxblendvd, "V2ULLiV2ULLiV2ULLiV2ULLi", "") +TARGET_BUILTIN(__builtin_vsx_xxblendvb, "V16UcV16UcV16UcV16Uc", "", + "power10-vector") +TARGET_BUILTIN(__builtin_vsx_xxblendvh, "V8UsV8UsV8UsV8Us", "", + "power10-vector") +TARGET_BUILTIN(__builtin_vsx_xxblendvw, "V4UiV4UiV4UiV4Ui", "", + "power10-vector") +TARGET_BUILTIN(__builtin_vsx_xxblendvd, "V2ULLiV2ULLiV2ULLiV2ULLi", "", + "power10-vector") // Float 128 built-ins -BUILTIN(__builtin_sqrtf128_round_to_odd, "LLdLLd", "") -BUILTIN(__builtin_addf128_round_to_odd, "LLdLLdLLd", "") -BUILTIN(__builtin_subf128_round_to_odd, "LLdLLdLLd", "") -BUILTIN(__builtin_mulf128_round_to_odd, "LLdLLdLLd", "") -BUILTIN(__builtin_divf128_round_to_odd, "LLdLLdLLd", "") -BUILTIN(__builtin_fmaf128_round_to_odd, "LLdLLdLLdLLd", "") -BUILTIN(__builtin_truncf128_round_to_odd, "dLLd", "") -BUILTIN(__builtin_vsx_scalar_extract_expq, "ULLiLLd", "") -BUILTIN(__builtin_vsx_scalar_insert_exp_qp, "LLdLLdULLi", "") +TARGET_BUILTIN(__builtin_sqrtf128_round_to_odd, "LLdLLd", "", "float128") +TARGET_BUILTIN(__builtin_addf128_round_to_odd, "LLdLLdLLd", "", "float128") +TARGET_BUILTIN(__builtin_subf128_round_to_odd, "LLdLLdLLd", "", "float128") +TARGET_BUILTIN(__builtin_mulf128_round_to_odd, "LLdLLdLLd", "", "float128") +TARGET_BUILTIN(__builtin_divf128_round_to_odd, "LLdLLdLLd", "", "float128") +TARGET_BUILTIN(__builtin_fmaf128_round_to_odd, "LLdLLdLLdLLd", "", "float128") +TARGET_BUILTIN(__builtin_truncf128_round_to_odd, "dLLd", "", "float128") +TARGET_BUILTIN(__builtin_vsx_scalar_extract_expq, "ULLiLLd", "", "float128") +TARGET_BUILTIN(__builtin_vsx_scalar_insert_exp_qp, "LLdLLdULLi", "", "float128") // Fastmath by default builtins BUILTIN(__builtin_ppc_rsqrtf, "V4fV4f", "") @@ -763,60 +883,60 @@ BUILTIN(__builtin_ppc_recipdivf, "V4fV4fV4f", "") BUILTIN(__builtin_ppc_recipdivd, "V2dV2dV2d", "") // HTM builtins -BUILTIN(__builtin_tbegin, "UiUIi", "") -BUILTIN(__builtin_tend, "UiUIi", "") +TARGET_BUILTIN(__builtin_tbegin, "UiUIi", "", "htm") +TARGET_BUILTIN(__builtin_tend, "UiUIi", "", "htm") -BUILTIN(__builtin_tabort, "UiUi", "") -BUILTIN(__builtin_tabortdc, "UiUiUiUi", "") -BUILTIN(__builtin_tabortdci, "UiUiUii", "") -BUILTIN(__builtin_tabortwc, "UiUiUiUi", "") -BUILTIN(__builtin_tabortwci, "UiUiUii", "") +TARGET_BUILTIN(__builtin_tabort, "UiUi", "", "htm") +TARGET_BUILTIN(__builtin_tabortdc, "UiUiUiUi", "", "htm") +TARGET_BUILTIN(__builtin_tabortdci, "UiUiUii", "", "htm") +TARGET_BUILTIN(__builtin_tabortwc, "UiUiUiUi", "", "htm") +TARGET_BUILTIN(__builtin_tabortwci, "UiUiUii", "", "htm") -BUILTIN(__builtin_tcheck, "Ui", "") -BUILTIN(__builtin_treclaim, "UiUi", "") -BUILTIN(__builtin_trechkpt, "Ui", "") -BUILTIN(__builtin_tsr, "UiUi", "") +TARGET_BUILTIN(__builtin_tcheck, "Ui", "", "htm") +TARGET_BUILTIN(__builtin_treclaim, "UiUi", "", "htm") +TARGET_BUILTIN(__builtin_trechkpt, "Ui", "", "htm") +TARGET_BUILTIN(__builtin_tsr, "UiUi", "", "htm") -BUILTIN(__builtin_tendall, "Ui", "") -BUILTIN(__builtin_tresume, "Ui", "") -BUILTIN(__builtin_tsuspend, "Ui", "") +TARGET_BUILTIN(__builtin_tendall, "Ui", "", "htm") +TARGET_BUILTIN(__builtin_tresume, "Ui", "", "htm") +TARGET_BUILTIN(__builtin_tsuspend, "Ui", "", "htm") -BUILTIN(__builtin_get_texasr, "LUi", "c") -BUILTIN(__builtin_get_texasru, "LUi", "c") -BUILTIN(__builtin_get_tfhar, "LUi", "c") -BUILTIN(__builtin_get_tfiar, "LUi", "c") +TARGET_BUILTIN(__builtin_get_texasr, "LUi", "c", "htm") +TARGET_BUILTIN(__builtin_get_texasru, "LUi", "c", "htm") +TARGET_BUILTIN(__builtin_get_tfhar, "LUi", "c", "htm") +TARGET_BUILTIN(__builtin_get_tfiar, "LUi", "c", "htm") -BUILTIN(__builtin_set_texasr, "vLUi", "c") -BUILTIN(__builtin_set_texasru, "vLUi", "c") -BUILTIN(__builtin_set_tfhar, "vLUi", "c") -BUILTIN(__builtin_set_tfiar, "vLUi", "c") +TARGET_BUILTIN(__builtin_set_texasr, "vLUi", "c", "htm") +TARGET_BUILTIN(__builtin_set_texasru, "vLUi", "c", "htm") +TARGET_BUILTIN(__builtin_set_tfhar, "vLUi", "c", "htm") +TARGET_BUILTIN(__builtin_set_tfiar, "vLUi", "c", "htm") -BUILTIN(__builtin_ttest, "LUi", "") +TARGET_BUILTIN(__builtin_ttest, "LUi", "", "htm") // Scalar built-ins -BUILTIN(__builtin_divwe, "SiSiSi", "") -BUILTIN(__builtin_divweu, "UiUiUi", "") -BUILTIN(__builtin_divde, "SLLiSLLiSLLi", "") -BUILTIN(__builtin_divdeu, "ULLiULLiULLi", "") -BUILTIN(__builtin_bpermd, "SLLiSLLiSLLi", "") -BUILTIN(__builtin_pdepd, "ULLiULLiULLi", "") -BUILTIN(__builtin_pextd, "ULLiULLiULLi", "") -BUILTIN(__builtin_cfuged, "ULLiULLiULLi", "") -BUILTIN(__builtin_cntlzdm, "ULLiULLiULLi", "") -BUILTIN(__builtin_cnttzdm, "ULLiULLiULLi", "") +TARGET_BUILTIN(__builtin_divwe, "SiSiSi", "", "extdiv") +TARGET_BUILTIN(__builtin_divweu, "UiUiUi", "", "extdiv") +TARGET_BUILTIN(__builtin_divde, "SLLiSLLiSLLi", "", "extdiv") +TARGET_BUILTIN(__builtin_divdeu, "ULLiULLiULLi", "", "extdiv") +TARGET_BUILTIN(__builtin_bpermd, "SLLiSLLiSLLi", "", "bpermd") +TARGET_BUILTIN(__builtin_pdepd, "ULLiULLiULLi", "", "isa-v31-instructions") +TARGET_BUILTIN(__builtin_pextd, "ULLiULLiULLi", "", "isa-v31-instructions") +TARGET_BUILTIN(__builtin_cfuged, "ULLiULLiULLi", "", "isa-v31-instructions") +TARGET_BUILTIN(__builtin_cntlzdm, "ULLiULLiULLi", "", "isa-v31-instructions") +TARGET_BUILTIN(__builtin_cnttzdm, "ULLiULLiULLi", "", "isa-v31-instructions") // Double-double (un)pack BUILTIN(__builtin_unpack_longdouble, "dLdIi", "") BUILTIN(__builtin_pack_longdouble, "Lddd", "") // Generate random number -BUILTIN(__builtin_darn, "LLi", "") -BUILTIN(__builtin_darn_raw, "LLi", "") -BUILTIN(__builtin_darn_32, "i", "") +TARGET_BUILTIN(__builtin_darn, "LLi", "", "isa-v30-instructions") +TARGET_BUILTIN(__builtin_darn_raw, "LLi", "", "isa-v30-instructions") +TARGET_BUILTIN(__builtin_darn_32, "i", "", "isa-v30-instructions") // Vector int128 (un)pack -BUILTIN(__builtin_unpack_vector_int128, "ULLiV1LLLii", "") -BUILTIN(__builtin_pack_vector_int128, "V1LLLiULLiULLi", "") +TARGET_BUILTIN(__builtin_unpack_vector_int128, "ULLiV1LLLii", "", "vsx") +TARGET_BUILTIN(__builtin_pack_vector_int128, "V1LLLiULLiULLi", "", "vsx") // Set the floating point rounding mode BUILTIN(__builtin_setrnd, "di", "") @@ -850,86 +970,159 @@ BUILTIN(__builtin_dcbf, "vvC*", "") // its given accumulator. // Provided builtins with _mma_ prefix for compatibility. -CUSTOM_BUILTIN(mma_lxvp, vsx_lxvp, "W256SLiW256C*", false) -CUSTOM_BUILTIN(mma_stxvp, vsx_stxvp, "vW256SLiW256*", false) -CUSTOM_BUILTIN(mma_assemble_pair, vsx_assemble_pair, "vW256*VV", false) -CUSTOM_BUILTIN(mma_disassemble_pair, vsx_disassemble_pair, "vv*W256*", false) -CUSTOM_BUILTIN(vsx_build_pair, vsx_assemble_pair, "vW256*VV", false) -CUSTOM_BUILTIN(mma_build_acc, mma_assemble_acc, "vW512*VVVV", false) +CUSTOM_BUILTIN(mma_lxvp, vsx_lxvp, "W256SLiW256C*", false, + "paired-vector-memops") +CUSTOM_BUILTIN(mma_stxvp, vsx_stxvp, "vW256SLiW256*", false, + "paired-vector-memops") +CUSTOM_BUILTIN(mma_assemble_pair, vsx_assemble_pair, "vW256*VV", false, + "paired-vector-memops") +CUSTOM_BUILTIN(mma_disassemble_pair, vsx_disassemble_pair, "vv*W256*", false, + "paired-vector-memops") +CUSTOM_BUILTIN(vsx_build_pair, vsx_assemble_pair, "vW256*VV", false, + "paired-vector-memops") +CUSTOM_BUILTIN(mma_build_acc, mma_assemble_acc, "vW512*VVVV", false, "mma") // UNALIASED_CUSTOM_BUILTIN macro is used for built-ins that have // the same name as that of the intrinsic they generate, i.e. the // ID and INTR are the same. // This avoids repeating the ID and INTR in the macro expression. -UNALIASED_CUSTOM_BUILTIN(vsx_lxvp, "W256SLiW256C*", false) -UNALIASED_CUSTOM_BUILTIN(vsx_stxvp, "vW256SLiW256*", false) -UNALIASED_CUSTOM_BUILTIN(vsx_assemble_pair, "vW256*VV", false) -UNALIASED_CUSTOM_BUILTIN(vsx_disassemble_pair, "vv*W256*", false) +UNALIASED_CUSTOM_BUILTIN(vsx_lxvp, "W256SLiW256C*", false, + "paired-vector-memops") +UNALIASED_CUSTOM_BUILTIN(vsx_stxvp, "vW256SLiW256*", false, + "paired-vector-memops") +UNALIASED_CUSTOM_BUILTIN(vsx_assemble_pair, "vW256*VV", false, + "paired-vector-memops") +UNALIASED_CUSTOM_BUILTIN(vsx_disassemble_pair, "vv*W256*", false, + "paired-vector-memops") -UNALIASED_CUSTOM_BUILTIN(mma_assemble_acc, "vW512*VVVV", false) -UNALIASED_CUSTOM_BUILTIN(mma_disassemble_acc, "vv*W512*", false) -UNALIASED_CUSTOM_BUILTIN(mma_xxmtacc, "vW512*", true) -UNALIASED_CUSTOM_BUILTIN(mma_xxmfacc, "vW512*", true) -UNALIASED_CUSTOM_BUILTIN(mma_xxsetaccz, "vW512*", false) -UNALIASED_CUSTOM_BUILTIN(mma_xvi4ger8, "vW512*VV", false) -UNALIASED_CUSTOM_BUILTIN(mma_xvi8ger4, "vW512*VV", false) -UNALIASED_CUSTOM_BUILTIN(mma_xvi16ger2, "vW512*VV", false) -UNALIASED_CUSTOM_BUILTIN(mma_xvi16ger2s, "vW512*VV", false) -UNALIASED_CUSTOM_BUILTIN(mma_xvf16ger2, "vW512*VV", false) -UNALIASED_CUSTOM_BUILTIN(mma_xvf32ger, "vW512*VV", false) -UNALIASED_CUSTOM_BUILTIN(mma_xvf64ger, "vW512*W256V", false) -UNALIASED_CUSTOM_BUILTIN(mma_pmxvi4ger8, "vW512*VVi15i15i255", false) -UNALIASED_CUSTOM_BUILTIN(mma_pmxvi8ger4, "vW512*VVi15i15i15", false) -UNALIASED_CUSTOM_BUILTIN(mma_pmxvi16ger2, "vW512*VVi15i15i3", false) -UNALIASED_CUSTOM_BUILTIN(mma_pmxvi16ger2s, "vW512*VVi15i15i3", false) -UNALIASED_CUSTOM_BUILTIN(mma_pmxvf16ger2, "vW512*VVi15i15i3", false) -UNALIASED_CUSTOM_BUILTIN(mma_pmxvf32ger, "vW512*VVi15i15", false) -UNALIASED_CUSTOM_BUILTIN(mma_pmxvf64ger, "vW512*W256Vi15i3", false) -UNALIASED_CUSTOM_BUILTIN(mma_xvi4ger8pp, "vW512*VV", true) -UNALIASED_CUSTOM_BUILTIN(mma_xvi8ger4pp, "vW512*VV", true) -UNALIASED_CUSTOM_BUILTIN(mma_xvi8ger4spp, "vW512*VV", true) -UNALIASED_CUSTOM_BUILTIN(mma_xvi16ger2pp, "vW512*VV", true) -UNALIASED_CUSTOM_BUILTIN(mma_xvi16ger2spp, "vW512*VV", true) -UNALIASED_CUSTOM_BUILTIN(mma_pmxvi4ger8pp, "vW512*VVi15i15i255", true) -UNALIASED_CUSTOM_BUILTIN(mma_pmxvi8ger4pp, "vW512*VVi15i15i15", true) -UNALIASED_CUSTOM_BUILTIN(mma_pmxvi8ger4spp, "vW512*VVi15i15i15", true) -UNALIASED_CUSTOM_BUILTIN(mma_pmxvi16ger2pp, "vW512*VVi15i15i3", true) -UNALIASED_CUSTOM_BUILTIN(mma_pmxvi16ger2spp, "vW512*VVi15i15i3", true) -UNALIASED_CUSTOM_BUILTIN(mma_xvf16ger2pp, "vW512*VV", true) -UNALIASED_CUSTOM_BUILTIN(mma_xvf16ger2pn, "vW512*VV", true) -UNALIASED_CUSTOM_BUILTIN(mma_xvf16ger2np, "vW512*VV", true) -UNALIASED_CUSTOM_BUILTIN(mma_xvf16ger2nn, "vW512*VV", true) -UNALIASED_CUSTOM_BUILTIN(mma_pmxvf16ger2pp, "vW512*VVi15i15i3", true) -UNALIASED_CUSTOM_BUILTIN(mma_pmxvf16ger2pn, "vW512*VVi15i15i3", true) -UNALIASED_CUSTOM_BUILTIN(mma_pmxvf16ger2np, "vW512*VVi15i15i3", true) -UNALIASED_CUSTOM_BUILTIN(mma_pmxvf16ger2nn, "vW512*VVi15i15i3", true) -UNALIASED_CUSTOM_BUILTIN(mma_xvf32gerpp, "vW512*VV", true) -UNALIASED_CUSTOM_BUILTIN(mma_xvf32gerpn, "vW512*VV", true) -UNALIASED_CUSTOM_BUILTIN(mma_xvf32gernp, "vW512*VV", true) -UNALIASED_CUSTOM_BUILTIN(mma_xvf32gernn, "vW512*VV", true) -UNALIASED_CUSTOM_BUILTIN(mma_pmxvf32gerpp, "vW512*VVi15i15", true) -UNALIASED_CUSTOM_BUILTIN(mma_pmxvf32gerpn, "vW512*VVi15i15", true) -UNALIASED_CUSTOM_BUILTIN(mma_pmxvf32gernp, "vW512*VVi15i15", true) -UNALIASED_CUSTOM_BUILTIN(mma_pmxvf32gernn, "vW512*VVi15i15", true) -UNALIASED_CUSTOM_BUILTIN(mma_xvf64gerpp, "vW512*W256V", true) -UNALIASED_CUSTOM_BUILTIN(mma_xvf64gerpn, "vW512*W256V", true) -UNALIASED_CUSTOM_BUILTIN(mma_xvf64gernp, "vW512*W256V", true) -UNALIASED_CUSTOM_BUILTIN(mma_xvf64gernn, "vW512*W256V", true) -UNALIASED_CUSTOM_BUILTIN(mma_pmxvf64gerpp, "vW512*W256Vi15i3", true) -UNALIASED_CUSTOM_BUILTIN(mma_pmxvf64gerpn, "vW512*W256Vi15i3", true) -UNALIASED_CUSTOM_BUILTIN(mma_pmxvf64gernp, "vW512*W256Vi15i3", true) -UNALIASED_CUSTOM_BUILTIN(mma_pmxvf64gernn, "vW512*W256Vi15i3", true) -UNALIASED_CUSTOM_BUILTIN(mma_xvbf16ger2, "vW512*VV", false) -UNALIASED_CUSTOM_BUILTIN(mma_pmxvbf16ger2, "vW512*VVi15i15i3", false) -UNALIASED_CUSTOM_BUILTIN(mma_xvbf16ger2pp, "vW512*VV", true) -UNALIASED_CUSTOM_BUILTIN(mma_xvbf16ger2pn, "vW512*VV", true) -UNALIASED_CUSTOM_BUILTIN(mma_xvbf16ger2np, "vW512*VV", true) -UNALIASED_CUSTOM_BUILTIN(mma_xvbf16ger2nn, "vW512*VV", true) -UNALIASED_CUSTOM_BUILTIN(mma_pmxvbf16ger2pp, "vW512*VVi15i15i3", true) -UNALIASED_CUSTOM_BUILTIN(mma_pmxvbf16ger2pn, "vW512*VVi15i15i3", true) -UNALIASED_CUSTOM_BUILTIN(mma_pmxvbf16ger2np, "vW512*VVi15i15i3", true) -UNALIASED_CUSTOM_BUILTIN(mma_pmxvbf16ger2nn, "vW512*VVi15i15i3", true) +// TODO: Require only mma after backend supports these without paired memops +UNALIASED_CUSTOM_BUILTIN(mma_assemble_acc, "vW512*VVVV", false, + "mma,paired-vector-memops") +UNALIASED_CUSTOM_BUILTIN(mma_disassemble_acc, "vv*W512*", false, + "mma,paired-vector-memops") +UNALIASED_CUSTOM_BUILTIN(mma_xxmtacc, "vW512*", true, + "mma,paired-vector-memops") +UNALIASED_CUSTOM_BUILTIN(mma_xxmfacc, "vW512*", true, + "mma,paired-vector-memops") +UNALIASED_CUSTOM_BUILTIN(mma_xxsetaccz, "vW512*", false, + "mma,paired-vector-memops") +UNALIASED_CUSTOM_BUILTIN(mma_xvi4ger8, "vW512*VV", false, + "mma,paired-vector-memops") +UNALIASED_CUSTOM_BUILTIN(mma_xvi8ger4, "vW512*VV", false, + "mma,paired-vector-memops") +UNALIASED_CUSTOM_BUILTIN(mma_xvi16ger2, "vW512*VV", false, + "mma,paired-vector-memops") +UNALIASED_CUSTOM_BUILTIN(mma_xvi16ger2s, "vW512*VV", false, + "mma,paired-vector-memops") +UNALIASED_CUSTOM_BUILTIN(mma_xvf16ger2, "vW512*VV", false, + "mma,paired-vector-memops") +UNALIASED_CUSTOM_BUILTIN(mma_xvf32ger, "vW512*VV", false, + "mma,paired-vector-memops") +UNALIASED_CUSTOM_BUILTIN(mma_xvf64ger, "vW512*W256V", false, + "mma,paired-vector-memops") +UNALIASED_CUSTOM_BUILTIN(mma_pmxvi4ger8, "vW512*VVi15i15i255", false, + "mma,paired-vector-memops") +UNALIASED_CUSTOM_BUILTIN(mma_pmxvi8ger4, "vW512*VVi15i15i15", false, + "mma,paired-vector-memops") +UNALIASED_CUSTOM_BUILTIN(mma_pmxvi16ger2, "vW512*VVi15i15i3", false, + "mma,paired-vector-memops") +UNALIASED_CUSTOM_BUILTIN(mma_pmxvi16ger2s, "vW512*VVi15i15i3", false, + "mma,paired-vector-memops") +UNALIASED_CUSTOM_BUILTIN(mma_pmxvf16ger2, "vW512*VVi15i15i3", false, + "mma,paired-vector-memops") +UNALIASED_CUSTOM_BUILTIN(mma_pmxvf32ger, "vW512*VVi15i15", false, + "mma,paired-vector-memops") +UNALIASED_CUSTOM_BUILTIN(mma_pmxvf64ger, "vW512*W256Vi15i3", false, + "mma,paired-vector-memops") +UNALIASED_CUSTOM_BUILTIN(mma_xvi4ger8pp, "vW512*VV", true, + "mma,paired-vector-memops") +UNALIASED_CUSTOM_BUILTIN(mma_xvi8ger4pp, "vW512*VV", true, + "mma,paired-vector-memops") +UNALIASED_CUSTOM_BUILTIN(mma_xvi8ger4spp, "vW512*VV", true, + "mma,paired-vector-memops") +UNALIASED_CUSTOM_BUILTIN(mma_xvi16ger2pp, "vW512*VV", true, + "mma,paired-vector-memops") +UNALIASED_CUSTOM_BUILTIN(mma_xvi16ger2spp, "vW512*VV", true, + "mma,paired-vector-memops") +UNALIASED_CUSTOM_BUILTIN(mma_pmxvi4ger8pp, "vW512*VVi15i15i255", true, + "mma,paired-vector-memops") +UNALIASED_CUSTOM_BUILTIN(mma_pmxvi8ger4pp, "vW512*VVi15i15i15", true, + "mma,paired-vector-memops") +UNALIASED_CUSTOM_BUILTIN(mma_pmxvi8ger4spp, "vW512*VVi15i15i15", true, + "mma,paired-vector-memops") +UNALIASED_CUSTOM_BUILTIN(mma_pmxvi16ger2pp, "vW512*VVi15i15i3", true, + "mma,paired-vector-memops") +UNALIASED_CUSTOM_BUILTIN(mma_pmxvi16ger2spp, "vW512*VVi15i15i3", true, + "mma,paired-vector-memops") +UNALIASED_CUSTOM_BUILTIN(mma_xvf16ger2pp, "vW512*VV", true, + "mma,paired-vector-memops") +UNALIASED_CUSTOM_BUILTIN(mma_xvf16ger2pn, "vW512*VV", true, + "mma,paired-vector-memops") +UNALIASED_CUSTOM_BUILTIN(mma_xvf16ger2np, "vW512*VV", true, + "mma,paired-vector-memops") +UNALIASED_CUSTOM_BUILTIN(mma_xvf16ger2nn, "vW512*VV", true, + "mma,paired-vector-memops") +UNALIASED_CUSTOM_BUILTIN(mma_pmxvf16ger2pp, "vW512*VVi15i15i3", true, + "mma,paired-vector-memops") +UNALIASED_CUSTOM_BUILTIN(mma_pmxvf16ger2pn, "vW512*VVi15i15i3", true, + "mma,paired-vector-memops") +UNALIASED_CUSTOM_BUILTIN(mma_pmxvf16ger2np, "vW512*VVi15i15i3", true, + "mma,paired-vector-memops") +UNALIASED_CUSTOM_BUILTIN(mma_pmxvf16ger2nn, "vW512*VVi15i15i3", true, + "mma,paired-vector-memops") +UNALIASED_CUSTOM_BUILTIN(mma_xvf32gerpp, "vW512*VV", true, + "mma,paired-vector-memops") +UNALIASED_CUSTOM_BUILTIN(mma_xvf32gerpn, "vW512*VV", true, + "mma,paired-vector-memops") +UNALIASED_CUSTOM_BUILTIN(mma_xvf32gernp, "vW512*VV", true, + "mma,paired-vector-memops") +UNALIASED_CUSTOM_BUILTIN(mma_xvf32gernn, "vW512*VV", true, + "mma,paired-vector-memops") +UNALIASED_CUSTOM_BUILTIN(mma_pmxvf32gerpp, "vW512*VVi15i15", true, + "mma,paired-vector-memops") +UNALIASED_CUSTOM_BUILTIN(mma_pmxvf32gerpn, "vW512*VVi15i15", true, + "mma,paired-vector-memops") +UNALIASED_CUSTOM_BUILTIN(mma_pmxvf32gernp, "vW512*VVi15i15", true, + "mma,paired-vector-memops") +UNALIASED_CUSTOM_BUILTIN(mma_pmxvf32gernn, "vW512*VVi15i15", true, + "mma,paired-vector-memops") +UNALIASED_CUSTOM_BUILTIN(mma_xvf64gerpp, "vW512*W256V", true, + "mma,paired-vector-memops") +UNALIASED_CUSTOM_BUILTIN(mma_xvf64gerpn, "vW512*W256V", true, + "mma,paired-vector-memops") +UNALIASED_CUSTOM_BUILTIN(mma_xvf64gernp, "vW512*W256V", true, + "mma,paired-vector-memops") +UNALIASED_CUSTOM_BUILTIN(mma_xvf64gernn, "vW512*W256V", true, + "mma,paired-vector-memops") +UNALIASED_CUSTOM_BUILTIN(mma_pmxvf64gerpp, "vW512*W256Vi15i3", true, + "mma,paired-vector-memops") +UNALIASED_CUSTOM_BUILTIN(mma_pmxvf64gerpn, "vW512*W256Vi15i3", true, + "mma,paired-vector-memops") +UNALIASED_CUSTOM_BUILTIN(mma_pmxvf64gernp, "vW512*W256Vi15i3", true, + "mma,paired-vector-memops") +UNALIASED_CUSTOM_BUILTIN(mma_pmxvf64gernn, "vW512*W256Vi15i3", true, + "mma,paired-vector-memops") +UNALIASED_CUSTOM_BUILTIN(mma_xvbf16ger2, "vW512*VV", false, + "mma,paired-vector-memops") +UNALIASED_CUSTOM_BUILTIN(mma_pmxvbf16ger2, "vW512*VVi15i15i3", false, + "mma,paired-vector-memops") +UNALIASED_CUSTOM_BUILTIN(mma_xvbf16ger2pp, "vW512*VV", true, + "mma,paired-vector-memops") +UNALIASED_CUSTOM_BUILTIN(mma_xvbf16ger2pn, "vW512*VV", true, + "mma,paired-vector-memops") +UNALIASED_CUSTOM_BUILTIN(mma_xvbf16ger2np, "vW512*VV", true, + "mma,paired-vector-memops") +UNALIASED_CUSTOM_BUILTIN(mma_xvbf16ger2nn, "vW512*VV", true, + "mma,paired-vector-memops") +UNALIASED_CUSTOM_BUILTIN(mma_pmxvbf16ger2pp, "vW512*VVi15i15i3", true, + "mma,paired-vector-memops") +UNALIASED_CUSTOM_BUILTIN(mma_pmxvbf16ger2pn, "vW512*VVi15i15i3", true, + "mma,paired-vector-memops") +UNALIASED_CUSTOM_BUILTIN(mma_pmxvbf16ger2np, "vW512*VVi15i15i3", true, + "mma,paired-vector-memops") +UNALIASED_CUSTOM_BUILTIN(mma_pmxvbf16ger2nn, "vW512*VVi15i15i3", true, + "mma,paired-vector-memops") // FIXME: Obviously incomplete. diff --git a/contrib/llvm-project/clang/include/clang/Basic/BuiltinsRISCV.def b/contrib/llvm-project/clang/include/clang/Basic/BuiltinsRISCV.def index c26e3b80737..50e912c2c1c 100644 --- a/contrib/llvm-project/clang/include/clang/Basic/BuiltinsRISCV.def +++ b/contrib/llvm-project/clang/include/clang/Basic/BuiltinsRISCV.def @@ -16,68 +16,78 @@ #endif // Zbb extension -TARGET_BUILTIN(__builtin_riscv_orc_b_32, "ZiZi", "nc", "zbb") -TARGET_BUILTIN(__builtin_riscv_orc_b_64, "WiWi", "nc", "zbb,64bit") -TARGET_BUILTIN(__builtin_riscv_clz_32, "ZiZi", "nc", "zbb") -TARGET_BUILTIN(__builtin_riscv_clz_64, "WiWi", "nc", "zbb,64bit") -TARGET_BUILTIN(__builtin_riscv_ctz_32, "ZiZi", "nc", "zbb") -TARGET_BUILTIN(__builtin_riscv_ctz_64, "WiWi", "nc", "zbb,64bit") +TARGET_BUILTIN(__builtin_riscv_orc_b_32, "UiUi", "nc", "zbb") +TARGET_BUILTIN(__builtin_riscv_orc_b_64, "UWiUWi", "nc", "zbb,64bit") +TARGET_BUILTIN(__builtin_riscv_clz_32, "UiUi", "nc", "zbb|xtheadbb") +TARGET_BUILTIN(__builtin_riscv_clz_64, "UiUWi", "nc", "zbb|xtheadbb,64bit") +TARGET_BUILTIN(__builtin_riscv_ctz_32, "UiUi", "nc", "zbb") +TARGET_BUILTIN(__builtin_riscv_ctz_64, "UiUWi", "nc", "zbb,64bit") // Zbc or Zbkc extension -TARGET_BUILTIN(__builtin_riscv_clmul, "LiLiLi", "nc", "zbc|zbkc") -TARGET_BUILTIN(__builtin_riscv_clmulh, "LiLiLi", "nc", "zbc|zbkc") -TARGET_BUILTIN(__builtin_riscv_clmulr, "LiLiLi", "nc", "zbc") +TARGET_BUILTIN(__builtin_riscv_clmul_32, "UiUiUi", "nc", "zbc|zbkc") +TARGET_BUILTIN(__builtin_riscv_clmul_64, "UWiUWiUWi", "nc", "zbc|zbkc,64bit") +TARGET_BUILTIN(__builtin_riscv_clmulh_32, "UiUiUi", "nc", "zbc|zbkc,32bit") +TARGET_BUILTIN(__builtin_riscv_clmulh_64, "UWiUWiUWi", "nc", "zbc|zbkc,64bit") +TARGET_BUILTIN(__builtin_riscv_clmulr_32, "UiUiUi", "nc", "zbc,32bit") +TARGET_BUILTIN(__builtin_riscv_clmulr_64, "UWiUWiUWi", "nc", "zbc,64bit") // Zbkx -TARGET_BUILTIN(__builtin_riscv_xperm4, "LiLiLi", "nc", "zbkx") -TARGET_BUILTIN(__builtin_riscv_xperm8, "LiLiLi", "nc", "zbkx") +TARGET_BUILTIN(__builtin_riscv_xperm4_32, "UiUiUi", "nc", "zbkx,32bit") +TARGET_BUILTIN(__builtin_riscv_xperm4_64, "UWiUWiUWi", "nc", "zbkx,64bit") +TARGET_BUILTIN(__builtin_riscv_xperm8_32, "UiUiUi", "nc", "zbkx,32bit") +TARGET_BUILTIN(__builtin_riscv_xperm8_64, "UWiUWiUWi", "nc", "zbkx,64bit") // Zbkb extension -TARGET_BUILTIN(__builtin_riscv_brev8, "LiLi", "nc", "zbkb") -TARGET_BUILTIN(__builtin_riscv_zip_32, "ZiZi", "nc", "zbkb,32bit") -TARGET_BUILTIN(__builtin_riscv_unzip_32, "ZiZi", "nc", "zbkb,32bit") +TARGET_BUILTIN(__builtin_riscv_brev8_32, "UiUi", "nc", "zbkb") +TARGET_BUILTIN(__builtin_riscv_brev8_64, "UWiUWi", "nc", "zbkb,64bit") +TARGET_BUILTIN(__builtin_riscv_zip_32, "UiUi", "nc", "zbkb,32bit") +TARGET_BUILTIN(__builtin_riscv_unzip_32, "UiUi", "nc", "zbkb,32bit") // Zknd extension -TARGET_BUILTIN(__builtin_riscv_aes32dsi_32, "ZiZiZiIUc", "nc", "zknd,32bit") -TARGET_BUILTIN(__builtin_riscv_aes32dsmi_32, "ZiZiZiIUc", "nc", "zknd,32bit") -TARGET_BUILTIN(__builtin_riscv_aes64ds_64, "WiWiWi", "nc", "zknd,64bit") -TARGET_BUILTIN(__builtin_riscv_aes64dsm_64, "WiWiWi", "nc", "zknd,64bit") -TARGET_BUILTIN(__builtin_riscv_aes64im_64, "WiWi", "nc", "zknd,64bit") +TARGET_BUILTIN(__builtin_riscv_aes32dsi, "UiUiUiIUi", "nc", "zknd,32bit") +TARGET_BUILTIN(__builtin_riscv_aes32dsmi, "UiUiUiIUi", "nc", "zknd,32bit") +TARGET_BUILTIN(__builtin_riscv_aes64ds, "UWiUWiUWi", "nc", "zknd,64bit") +TARGET_BUILTIN(__builtin_riscv_aes64dsm, "UWiUWiUWi", "nc", "zknd,64bit") +TARGET_BUILTIN(__builtin_riscv_aes64im, "UWiUWi", "nc", "zknd,64bit") -// Zknd & zkne -TARGET_BUILTIN(__builtin_riscv_aes64ks1i_64, "WiWiIUi", "nc", "zknd|zkne,64bit") -TARGET_BUILTIN(__builtin_riscv_aes64ks2_64, "WiWiWi", "nc", "zknd|zkne,64bit") +// Zknd & Zkne +TARGET_BUILTIN(__builtin_riscv_aes64ks1i, "UWiUWiIUi", "nc", "zknd|zkne,64bit") +TARGET_BUILTIN(__builtin_riscv_aes64ks2, "UWiUWiUWi", "nc", "zknd|zkne,64bit") // Zkne extension -TARGET_BUILTIN(__builtin_riscv_aes32esi_32, "ZiZiZiIUc", "nc", "zkne,32bit") -TARGET_BUILTIN(__builtin_riscv_aes32esmi_32, "ZiZiZiIUc", "nc", "zkne,32bit") -TARGET_BUILTIN(__builtin_riscv_aes64es_64, "WiWiWi", "nc", "zkne,64bit") -TARGET_BUILTIN(__builtin_riscv_aes64esm_64, "WiWiWi", "nc", "zkne,64bit") +TARGET_BUILTIN(__builtin_riscv_aes32esi, "UiUiUiIUi", "nc", "zkne,32bit") +TARGET_BUILTIN(__builtin_riscv_aes32esmi, "UiUiUiIUi", "nc", "zkne,32bit") +TARGET_BUILTIN(__builtin_riscv_aes64es, "UWiUWiUWi", "nc", "zkne,64bit") +TARGET_BUILTIN(__builtin_riscv_aes64esm, "UWiUWiUWi", "nc", "zkne,64bit") // Zknh extension -TARGET_BUILTIN(__builtin_riscv_sha256sig0, "LiLi", "nc", "zknh") -TARGET_BUILTIN(__builtin_riscv_sha256sig1, "LiLi", "nc", "zknh") -TARGET_BUILTIN(__builtin_riscv_sha256sum0, "LiLi", "nc", "zknh") -TARGET_BUILTIN(__builtin_riscv_sha256sum1, "LiLi", "nc", "zknh") +TARGET_BUILTIN(__builtin_riscv_sha256sig0, "UiUi", "nc", "zknh") +TARGET_BUILTIN(__builtin_riscv_sha256sig1, "UiUi", "nc", "zknh") +TARGET_BUILTIN(__builtin_riscv_sha256sum0, "UiUi", "nc", "zknh") +TARGET_BUILTIN(__builtin_riscv_sha256sum1, "UiUi", "nc", "zknh") -TARGET_BUILTIN(__builtin_riscv_sha512sig0h_32, "ZiZiZi", "nc", "zknh,32bit") -TARGET_BUILTIN(__builtin_riscv_sha512sig0l_32, "ZiZiZi", "nc", "zknh,32bit") -TARGET_BUILTIN(__builtin_riscv_sha512sig1h_32, "ZiZiZi", "nc", "zknh,32bit") -TARGET_BUILTIN(__builtin_riscv_sha512sig1l_32, "ZiZiZi", "nc", "zknh,32bit") -TARGET_BUILTIN(__builtin_riscv_sha512sum0r_32, "ZiZiZi", "nc", "zknh,32bit") -TARGET_BUILTIN(__builtin_riscv_sha512sum1r_32, "ZiZiZi", "nc", "zknh,32bit") -TARGET_BUILTIN(__builtin_riscv_sha512sig0_64, "WiWi", "nc", "zknh,64bit") -TARGET_BUILTIN(__builtin_riscv_sha512sig1_64, "WiWi", "nc", "zknh,64bit") -TARGET_BUILTIN(__builtin_riscv_sha512sum0_64, "WiWi", "nc", "zknh,64bit") -TARGET_BUILTIN(__builtin_riscv_sha512sum1_64, "WiWi", "nc", "zknh,64bit") +TARGET_BUILTIN(__builtin_riscv_sha512sig0h, "UiUiUi", "nc", "zknh,32bit") +TARGET_BUILTIN(__builtin_riscv_sha512sig0l, "UiUiUi", "nc", "zknh,32bit") +TARGET_BUILTIN(__builtin_riscv_sha512sig1h, "UiUiUi", "nc", "zknh,32bit") +TARGET_BUILTIN(__builtin_riscv_sha512sig1l, "UiUiUi", "nc", "zknh,32bit") +TARGET_BUILTIN(__builtin_riscv_sha512sum0r, "UiUiUi", "nc", "zknh,32bit") +TARGET_BUILTIN(__builtin_riscv_sha512sum1r, "UiUiUi", "nc", "zknh,32bit") +TARGET_BUILTIN(__builtin_riscv_sha512sig0, "UWiUWi", "nc", "zknh,64bit") +TARGET_BUILTIN(__builtin_riscv_sha512sig1, "UWiUWi", "nc", "zknh,64bit") +TARGET_BUILTIN(__builtin_riscv_sha512sum0, "UWiUWi", "nc", "zknh,64bit") +TARGET_BUILTIN(__builtin_riscv_sha512sum1, "UWiUWi", "nc", "zknh,64bit") // Zksed extension -TARGET_BUILTIN(__builtin_riscv_sm4ed, "LiLiLiIUc", "nc", "zksed") -TARGET_BUILTIN(__builtin_riscv_sm4ks, "LiLiLiIUc", "nc", "zksed") +TARGET_BUILTIN(__builtin_riscv_sm4ed, "UiUiUiIUi", "nc", "zksed") +TARGET_BUILTIN(__builtin_riscv_sm4ks, "UiUiUiIUi", "nc", "zksed") // Zksh extension -TARGET_BUILTIN(__builtin_riscv_sm3p0, "LiLi", "nc", "zksh") -TARGET_BUILTIN(__builtin_riscv_sm3p1, "LiLi", "nc", "zksh") +TARGET_BUILTIN(__builtin_riscv_sm3p0, "UiUi", "nc", "zksh") +TARGET_BUILTIN(__builtin_riscv_sm3p1, "UiUi", "nc", "zksh") + +// Zihintntl extension +TARGET_BUILTIN(__builtin_riscv_ntl_load, "v.", "t", "experimental-zihintntl") +TARGET_BUILTIN(__builtin_riscv_ntl_store, "v.", "t", "experimental-zihintntl") #undef BUILTIN #undef TARGET_BUILTIN diff --git a/contrib/llvm-project/clang/include/clang/Basic/BuiltinsRISCVVector.def b/contrib/llvm-project/clang/include/clang/Basic/BuiltinsRISCVVector.def index 008cb939a30..6dfa87a1a1d 100644 --- a/contrib/llvm-project/clang/include/clang/Basic/BuiltinsRISCVVector.def +++ b/contrib/llvm-project/clang/include/clang/Basic/BuiltinsRISCVVector.def @@ -16,6 +16,7 @@ #endif #include "clang/Basic/riscv_vector_builtins.inc" +#include "clang/Basic/riscv_sifive_vector_builtins.inc" #undef BUILTIN #undef TARGET_BUILTIN diff --git a/contrib/llvm-project/clang/include/clang/Basic/BuiltinsSME.def b/contrib/llvm-project/clang/include/clang/Basic/BuiltinsSME.def new file mode 100644 index 00000000000..180ee20295c --- /dev/null +++ b/contrib/llvm-project/clang/include/clang/Basic/BuiltinsSME.def @@ -0,0 +1,21 @@ +//===--- BuiltinsSME.def - SME Builtin function database --------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +// +// This file defines the SME-specific builtin function database. Users of +// this file must define the BUILTIN macro to make use of this information. +// +//===----------------------------------------------------------------------===// + +// The format of this database matches clang/Basic/Builtins.def. + +#define GET_SME_BUILTINS +#include "clang/Basic/arm_sme_builtins.inc" +#undef GET_SME_BUILTINS + +#undef BUILTIN +#undef TARGET_BUILTIN diff --git a/contrib/llvm-project/clang/include/clang/Basic/BuiltinsWebAssembly.def b/contrib/llvm-project/clang/include/clang/Basic/BuiltinsWebAssembly.def index 9064ded12fd..7e950914ad9 100644 --- a/contrib/llvm-project/clang/include/clang/Basic/BuiltinsWebAssembly.def +++ b/contrib/llvm-project/clang/include/clang/Basic/BuiltinsWebAssembly.def @@ -161,7 +161,7 @@ TARGET_BUILTIN(__builtin_wasm_narrow_u_i16x8_i32x4, "V8UsV4iV4i", "nc", "simd128 TARGET_BUILTIN(__builtin_wasm_trunc_sat_s_zero_f64x2_i32x4, "V4iV2d", "nc", "simd128") TARGET_BUILTIN(__builtin_wasm_trunc_sat_u_zero_f64x2_i32x4, "V4UiV2d", "nc", "simd128") -// Relaxed SIMD builtins (experimental) +// Relaxed SIMD builtins TARGET_BUILTIN(__builtin_wasm_relaxed_madd_f32x4, "V4fV4fV4fV4f", "nc", "relaxed-simd") TARGET_BUILTIN(__builtin_wasm_relaxed_nmadd_f32x4, "V4fV4fV4fV4f", "nc", "relaxed-simd") TARGET_BUILTIN(__builtin_wasm_relaxed_madd_f64x2, "V2dV2dV2dV2d", "nc", "relaxed-simd") @@ -190,5 +190,24 @@ TARGET_BUILTIN(__builtin_wasm_relaxed_dot_i8x16_i7x16_s_i16x8, "V8sV16ScV16Sc", TARGET_BUILTIN(__builtin_wasm_relaxed_dot_i8x16_i7x16_add_s_i32x4, "V4iV16ScV16ScV4i", "nc", "relaxed-simd") TARGET_BUILTIN(__builtin_wasm_relaxed_dot_bf16x8_add_f32_f32x4, "V4fV8UsV8UsV4f", "nc", "relaxed-simd") +// Reference Types builtins +// Some builtins are custom type-checked - see 't' as part of the third argument, +// in which case the argument spec (second argument) is unused. + +TARGET_BUILTIN(__builtin_wasm_ref_null_extern, "i", "nct", "reference-types") + +// A funcref represented as a function pointer with the funcref attribute +// attached to the type, therefore SemaChecking will check for the right +// return type. +TARGET_BUILTIN(__builtin_wasm_ref_null_func, "i", "nct", "reference-types") + +// Table builtins +TARGET_BUILTIN(__builtin_wasm_table_set, "viii", "t", "reference-types") +TARGET_BUILTIN(__builtin_wasm_table_get, "iii", "t", "reference-types") +TARGET_BUILTIN(__builtin_wasm_table_size, "zi", "nt", "reference-types") +TARGET_BUILTIN(__builtin_wasm_table_grow, "iiii", "nt", "reference-types") +TARGET_BUILTIN(__builtin_wasm_table_fill, "viiii", "t", "reference-types") +TARGET_BUILTIN(__builtin_wasm_table_copy, "viiiii", "t", "reference-types") + #undef BUILTIN #undef TARGET_BUILTIN diff --git a/contrib/llvm-project/clang/include/clang/Basic/BuiltinsX86.def b/contrib/llvm-project/clang/include/clang/Basic/BuiltinsX86.def index 122896b417c..10ac3b3c34e 100644 --- a/contrib/llvm-project/clang/include/clang/Basic/BuiltinsX86.def +++ b/contrib/llvm-project/clang/include/clang/Basic/BuiltinsX86.def @@ -2116,6 +2116,20 @@ TARGET_HEADER_BUILTIN(__readgsword, "UsUNi", "nh", INTRIN_H, ALL_MS_LANGUAGES, TARGET_HEADER_BUILTIN(__readgsdword, "UNiUNi", "nh", INTRIN_H, ALL_MS_LANGUAGES, "") TARGET_HEADER_BUILTIN(__readgsqword, "ULLiUNi", "nh", INTRIN_H, ALL_MS_LANGUAGES, "") +// AVX-VNNI-INT16 +TARGET_BUILTIN(__builtin_ia32_vpdpwsud128, "V4iV4iV4iV4i", "nV:128:", "avxvnniint16") +TARGET_BUILTIN(__builtin_ia32_vpdpwsud256, "V8iV8iV8iV8i", "nV:256:", "avxvnniint16") +TARGET_BUILTIN(__builtin_ia32_vpdpwsuds128, "V4iV4iV4iV4i", "nV:128:", "avxvnniint16") +TARGET_BUILTIN(__builtin_ia32_vpdpwsuds256, "V8iV8iV8iV8i", "nV:256:", "avxvnniint16") +TARGET_BUILTIN(__builtin_ia32_vpdpwusd128, "V4iV4iV4iV4i", "nV:128:", "avxvnniint16") +TARGET_BUILTIN(__builtin_ia32_vpdpwusd256, "V8iV8iV8iV8i", "nV:256:", "avxvnniint16") +TARGET_BUILTIN(__builtin_ia32_vpdpwusds128, "V4iV4iV4iV4i", "nV:128:", "avxvnniint16") +TARGET_BUILTIN(__builtin_ia32_vpdpwusds256, "V8iV8iV8iV8i", "nV:256:", "avxvnniint16") +TARGET_BUILTIN(__builtin_ia32_vpdpwuud128, "V4iV4iV4iV4i", "nV:128:", "avxvnniint16") +TARGET_BUILTIN(__builtin_ia32_vpdpwuud256, "V8iV8iV8iV8i", "nV:256:", "avxvnniint16") +TARGET_BUILTIN(__builtin_ia32_vpdpwuuds128, "V4iV4iV4iV4i", "nV:128:", "avxvnniint16") +TARGET_BUILTIN(__builtin_ia32_vpdpwuuds256, "V8iV8iV8iV8i", "nV:256:", "avxvnniint16") + // AVX-NE-CONVERT TARGET_BUILTIN(__builtin_ia32_vbcstnebf162ps128, "V4fyC*", "nV:128:", "avxneconvert") TARGET_BUILTIN(__builtin_ia32_vbcstnebf162ps256, "V8fyC*", "nV:256:", "avxneconvert") @@ -2132,6 +2146,11 @@ TARGET_BUILTIN(__builtin_ia32_vcvtneoph2ps256, "V8fV16xC*", "nV:256:", "avxnecon TARGET_BUILTIN(__builtin_ia32_vcvtneps2bf16128, "V8yV4f", "nV:128:", "avx512bf16,avx512vl|avxneconvert") TARGET_BUILTIN(__builtin_ia32_vcvtneps2bf16256, "V8yV8f", "nV:256:", "avx512bf16,avx512vl|avxneconvert") +// SHA512 +TARGET_BUILTIN(__builtin_ia32_vsha512msg1, "V4ULLiV4ULLiV2ULLi", "nV:256:", "sha512") +TARGET_BUILTIN(__builtin_ia32_vsha512msg2, "V4ULLiV4ULLiV4ULLi", "nV:256:", "sha512") +TARGET_BUILTIN(__builtin_ia32_vsha512rnds2, "V4ULLiV4ULLiV4ULLiV2ULLi", "nV:256:", "sha512") + TARGET_HEADER_BUILTIN(_InterlockedAnd64, "WiWiD*Wi", "nh", INTRIN_H, ALL_MS_LANGUAGES, "") TARGET_HEADER_BUILTIN(_InterlockedDecrement64, "WiWiD*", "nh", INTRIN_H, ALL_MS_LANGUAGES, "") TARGET_HEADER_BUILTIN(_InterlockedExchange64, "WiWiD*Wi", "nh", INTRIN_H, ALL_MS_LANGUAGES, "") @@ -2141,6 +2160,17 @@ TARGET_HEADER_BUILTIN(_InterlockedIncrement64, "WiWiD*", "nh", INTRIN_H, ALL TARGET_HEADER_BUILTIN(_InterlockedOr64, "WiWiD*Wi", "nh", INTRIN_H, ALL_MS_LANGUAGES, "") TARGET_HEADER_BUILTIN(_InterlockedXor64, "WiWiD*Wi", "nh", INTRIN_H, ALL_MS_LANGUAGES, "") +// SM3 +TARGET_BUILTIN(__builtin_ia32_vsm3msg1, "V4UiV4UiV4UiV4Ui", "nV:128:", "sm3") +TARGET_BUILTIN(__builtin_ia32_vsm3msg2, "V4UiV4UiV4UiV4Ui", "nV:128:", "sm3") +TARGET_BUILTIN(__builtin_ia32_vsm3rnds2, "V4UiV4UiV4UiV4UiIUi", "nV:128:", "sm3") + +// SM4 +TARGET_BUILTIN(__builtin_ia32_vsm4key4128, "V4UiV4UiV4Ui", "nV:128:", "sm4") +TARGET_BUILTIN(__builtin_ia32_vsm4key4256, "V8UiV8UiV8Ui", "nV:256:", "sm4") +TARGET_BUILTIN(__builtin_ia32_vsm4rnds4128, "V4UiV4UiV4Ui", "nV:128:", "sm4") +TARGET_BUILTIN(__builtin_ia32_vsm4rnds4256, "V8UiV8UiV8Ui", "nV:256:", "sm4") + #undef BUILTIN #undef TARGET_BUILTIN #undef TARGET_HEADER_BUILTIN diff --git a/contrib/llvm-project/clang/include/clang/Basic/BuiltinsX86_64.def b/contrib/llvm-project/clang/include/clang/Basic/BuiltinsX86_64.def index 4b9e7d29d65..e5c1fe8b319 100644 --- a/contrib/llvm-project/clang/include/clang/Basic/BuiltinsX86_64.def +++ b/contrib/llvm-project/clang/include/clang/Basic/BuiltinsX86_64.def @@ -117,6 +117,8 @@ TARGET_BUILTIN(__builtin_ia32_tilestored64_internal, "vUsUsv*zV256i", "n", "amx- TARGET_BUILTIN(__builtin_ia32_tilezero_internal, "V256iUsUs", "n", "amx-tile") TARGET_BUILTIN(__builtin_ia32_tdpbf16ps_internal, "V256iUsUsUsV256iV256iV256i", "n", "amx-bf16") TARGET_BUILTIN(__builtin_ia32_tdpfp16ps_internal, "V256iUsUsUsV256iV256iV256i", "n", "amx-fp16") +TARGET_BUILTIN(__builtin_ia32_tcmmimfp16ps_internal, "V256iUsUsUsV256iV256iV256i", "n", "amx-complex") +TARGET_BUILTIN(__builtin_ia32_tcmmrlfp16ps_internal, "V256iUsUsUsV256iV256iV256i", "n", "amx-complex") // AMX TARGET_BUILTIN(__builtin_ia32_tile_loadconfig, "vvC*", "n", "amx-tile") TARGET_BUILTIN(__builtin_ia32_tile_storeconfig, "vvC*", "n", "amx-tile") @@ -134,6 +136,9 @@ TARGET_BUILTIN(__builtin_ia32_tdpbuud, "vIUcIUcIUc", "n", "amx-int8") TARGET_BUILTIN(__builtin_ia32_tdpbf16ps, "vIUcIUcIUc", "n", "amx-bf16") TARGET_BUILTIN(__builtin_ia32_ptwrite64, "vUOi", "n", "ptwrite") +TARGET_BUILTIN(__builtin_ia32_tcmmimfp16ps, "vIUcIUcIUc", "n", "amx-complex") +TARGET_BUILTIN(__builtin_ia32_tcmmrlfp16ps, "vIUcIUcIUc", "n", "amx-complex") + TARGET_BUILTIN(__builtin_ia32_prefetchi, "vvC*Ui", "nc", "prefetchi") TARGET_BUILTIN(__builtin_ia32_cmpccxadd32, "Siv*SiSiIi", "n", "cmpccxadd") TARGET_BUILTIN(__builtin_ia32_cmpccxadd64, "SLLiv*SLLiSLLiIi", "n", "cmpccxadd") diff --git a/contrib/llvm-project/clang/include/clang/Basic/CodeGenOptions.def b/contrib/llvm-project/clang/include/clang/Basic/CodeGenOptions.def index 436226c6f17..11aec88c533 100644 --- a/contrib/llvm-project/clang/include/clang/Basic/CodeGenOptions.def +++ b/contrib/llvm-project/clang/include/clang/Basic/CodeGenOptions.def @@ -36,6 +36,7 @@ CODEGENOPT(Dwarf64 , 1, 0) ///< -gdwarf64. CODEGENOPT(Dwarf32 , 1, 1) ///< -gdwarf32. CODEGENOPT(PreserveAsmComments, 1, 1) ///< -dA, -fno-preserve-as-comments. CODEGENOPT(AssumeSaneOperatorNew , 1, 1) ///< implicit __attribute__((malloc)) operator new +CODEGENOPT(AssumeUniqueVTables , 1, 1) ///< Assume a class has only one vtable. CODEGENOPT(Autolink , 1, 1) ///< -fno-autolink CODEGENOPT(ObjCAutoRefCountExceptions , 1, 0) ///< Whether ARC should be EH-safe. CODEGENOPT(Backchain , 1, 0) ///< -mbackchain @@ -52,6 +53,7 @@ CODEGENOPT(UniqueBasicBlockSectionNames, 1, 1) ///< Set for -funique-basic-block ///< Produce unique section names with ///< basic block sections. CODEGENOPT(EnableAIXExtendedAltivecABI, 1, 0) ///< Set for -mabi=vec-extabi. Enables the extended Altivec ABI on AIX. +CODEGENOPT(XCOFFReadOnlyPointers, 1, 0) ///< Set for -mxcoff-roptr. ENUM_CODEGENOPT(FramePointer, FramePointerKind, 2, FramePointerKind::None) /// frame-pointer: all,non-leaf,none CODEGENOPT(ClearASTBeforeBackend , 1, 0) ///< Free the AST before running backend code generation. Only works with -disable-free. @@ -84,8 +86,6 @@ CODEGENOPT(EmitDeclMetadata , 1, 0) ///< Emit special metadata indicating what ///< Only useful when running CodeGen as a ///< subroutine. CODEGENOPT(EmitVersionIdentMetadata , 1, 1) ///< Emit compiler version metadata. -CODEGENOPT(EmitGcovArcs , 1, 0) ///< Emit coverage data files, aka. GCDA. -CODEGENOPT(EmitGcovNotes , 1, 0) ///< Emit coverage "notes" files, aka GCNO. CODEGENOPT(EmitOpenCLArgMetadata , 1, 0) ///< Emit OpenCL kernel arg metadata. CODEGENOPT(EmulatedTLS , 1, 0) ///< Set by default or -f[no-]emulated-tls. /// Embed Bitcode mode (off/all/bitcode/marker). @@ -115,6 +115,9 @@ CODEGENOPT(StackSizeSection , 1, 0) ///< Set when -fstack-size-section is enabl CODEGENOPT(ForceDwarfFrameSection , 1, 0) ///< Set when -fforce-dwarf-frame is ///< enabled. +///< Set when -femit-compact-unwind-non-canonical is enabled. +CODEGENOPT(EmitCompactUnwindNonCanonical, 1, 0) + ///< Set when -femit-dwarf-unwind is passed. ENUM_CODEGENOPT(EmitDwarfUnwind, llvm::EmitDwarfUnwindType, 2, llvm::EmitDwarfUnwindType::Default) @@ -128,8 +131,8 @@ CODEGENOPT(XRayAlwaysEmitTypedEvents , 1, 0) ///< Set when -fxray-ignore-loops is enabled. CODEGENOPT(XRayIgnoreLoops , 1, 0) -///< Set with -fno-xray-function-index to omit the index section. -CODEGENOPT(XRayOmitFunctionIndex , 1, 0) +///< Emit the XRay function index section. +CODEGENOPT(XRayFunctionIndex , 1, 1) ///< Set the minimum number of instructions in a function to determine selective @@ -162,10 +165,12 @@ CODEGENOPT(PrepareForThinLTO , 1, 0) ///< Set when -flto=thin is enabled on the ///< compile step. CODEGENOPT(LTOUnit, 1, 0) ///< Emit IR to support LTO unit features (CFI, whole ///< program vtable opt). +CODEGENOPT(FatLTO, 1, 0) ///< Set when -ffat-lto-objects is enabled. CODEGENOPT(EnableSplitLTOUnit, 1, 0) ///< Enable LTO unit splitting to support /// CFI and traditional whole program /// devirtualization that require whole /// program IR support. +CODEGENOPT(UnifiedLTO, 1, 0) ///< Use the unified LTO pipeline. CODEGENOPT(IncrementalLinkerCompatible, 1, 0) ///< Emit an object file which can ///< be used with an incremental ///< linker. @@ -257,6 +262,8 @@ CODEGENOPT(SanitizeMinimalRuntime, 1, 0) ///< Use "_minimal" sanitizer runtime f ///< diagnostics. CODEGENOPT(SanitizeCfiICallGeneralizePointers, 1, 0) ///< Generalize pointer types in ///< CFI icall function signatures +CODEGENOPT(SanitizeCfiICallNormalizeIntegers, 1, 0) ///< Normalize integer types in + ///< CFI icall function signatures CODEGENOPT(SanitizeCfiCanonicalJumpTables, 1, 0) ///< Make jump table symbols canonical ///< instead of creating a local jump table. CODEGENOPT(SanitizeCoverageType, 2, 0) ///< Type of sanitizer coverage @@ -318,6 +325,8 @@ CODEGENOPT(UseRegisterSizedBitfieldAccess , 1, 0) CODEGENOPT(VerifyModule , 1, 1) ///< Control whether the module should be run ///< through the LLVM Verifier. +CODEGENOPT(VerifyEach , 1, 1) ///< Control whether the LLVM verifier + ///< should run after every pass. CODEGENOPT(StackRealignment , 1, 0) ///< Control whether to force stack ///< realignment. @@ -333,8 +342,8 @@ VALUE_CODEGENOPT(WarnStackSize , 32, UINT_MAX) ///< Set via -fwarn-stack-siz CODEGENOPT(NoStackArgProbe, 1, 0) ///< Set when -mno-stack-arg-probe is used CODEGENOPT(DebugStrictDwarf, 1, 1) ///< Whether or not to use strict DWARF info. -CODEGENOPT(EnableAssignmentTracking, 1,0) ///< Enable the Assignment Tracking - ///< debug info feature. +/// Control the Assignment Tracking debug info feature. +ENUM_CODEGENOPT(AssignmentTrackingMode, AssignmentTrackingOpts, 2, AssignmentTrackingOpts::Disabled) CODEGENOPT(DebugColumnInfo, 1, 0) ///< Whether or not to use column information ///< in debug info. @@ -356,7 +365,7 @@ CODEGENOPT(DebugFwdTemplateParams, 1, 0) ///< Whether to emit complete ///< template parameter descriptions in ///< forward declarations (versus just ///< including them in the name). -ENUM_CODEGENOPT(DebugSimpleTemplateNames, codegenoptions::DebugTemplateNamesKind, 2, codegenoptions::DebugTemplateNamesKind::Full) ///< Whether to emit template parameters +ENUM_CODEGENOPT(DebugSimpleTemplateNames, llvm::codegenoptions::DebugTemplateNamesKind, 2, llvm::codegenoptions::DebugTemplateNamesKind::Full) ///< Whether to emit template parameters ///< in the textual names of template ///< specializations. ///< Implies DebugFwdTemplateNames to @@ -386,7 +395,7 @@ VALUE_CODEGENOPT(SmallDataLimit, 32, 0) VALUE_CODEGENOPT(SSPBufferSize, 32, 0) /// The kind of generated debug info. -ENUM_CODEGENOPT(DebugInfo, codegenoptions::DebugInfoKind, 4, codegenoptions::NoDebugInfo) +ENUM_CODEGENOPT(DebugInfo, llvm::codegenoptions::DebugInfoKind, 4, llvm::codegenoptions::NoDebugInfo) /// Whether to generate macro debug info. CODEGENOPT(MacroDebugInfo, 1, 0) @@ -470,6 +479,10 @@ CODEGENOPT(Addrsig, 1, 0) /// Whether to emit unused static constants. CODEGENOPT(KeepStaticConsts, 1, 0) +/// Whether to emit all variables that have a persistent storage duration, +/// including global, static and thread local variables. +CODEGENOPT(KeepPersistentStorageVariables, 1, 0) + /// Whether to follow the AAPCS enforcing at least one read before storing to a volatile bitfield CODEGENOPT(ForceAAPCSBitfieldLoad, 1, 0) @@ -497,9 +510,6 @@ CODEGENOPT(SkipRaxSetup, 1, 0) ENUM_CODEGENOPT(ZeroCallUsedRegs, llvm::ZeroCallUsedRegs::ZeroCallUsedRegsKind, 5, llvm::ZeroCallUsedRegs::ZeroCallUsedRegsKind::Skip) -/// Whether to use opaque pointers. -CODEGENOPT(OpaquePointers, 1, 0) - /// Modify C++ ABI to returning `this` pointer from constructors and /// non-deleting destructors. (No effect on Microsoft ABI.) CODEGENOPT(CtorDtorReturnThis, 1, 0) diff --git a/contrib/llvm-project/clang/include/clang/Basic/CodeGenOptions.h b/contrib/llvm-project/clang/include/clang/Basic/CodeGenOptions.h index 4175fe3072a..14fc94fe27f 100644 --- a/contrib/llvm-project/clang/include/clang/Basic/CodeGenOptions.h +++ b/contrib/llvm-project/clang/include/clang/Basic/CodeGenOptions.h @@ -13,10 +13,10 @@ #ifndef LLVM_CLANG_BASIC_CODEGENOPTIONS_H #define LLVM_CLANG_BASIC_CODEGENOPTIONS_H -#include "clang/Basic/DebugInfoOptions.h" #include "clang/Basic/Sanitizers.h" #include "clang/Basic/XRayInstr.h" #include "llvm/ADT/FloatingPointMode.h" +#include "llvm/Frontend/Debug/Options.h" #include "llvm/Support/CodeGen.h" #include "llvm/Support/Regex.h" #include "llvm/Target/TargetOptions.h" @@ -55,13 +55,14 @@ public: }; enum VectorLibrary { - NoLibrary, // Don't use any vector library. - Accelerate, // Use the Accelerate framework. - LIBMVEC, // GLIBC vector math library. - MASSV, // IBM MASS vector library. - SVML, // Intel short vector math library. - SLEEF, // SLEEF SIMD Library for Evaluating Elementary Functions. - Darwin_libsystem_m // Use Darwin's libsytem_m vector functions. + NoLibrary, // Don't use any vector library. + Accelerate, // Use the Accelerate framework. + LIBMVEC, // GLIBC vector math library. + MASSV, // IBM MASS vector library. + SVML, // Intel short vector math library. + SLEEF, // SLEEF SIMD Library for Evaluating Elementary Functions. + Darwin_libsystem_m, // Use Darwin's libsytem_m vector functions. + ArmPL // Arm Performance Libraries. }; enum ObjCDispatchMethodKind { @@ -163,6 +164,12 @@ public: Never, // No loop is assumed to be finite. }; + enum AssignmentTrackingOpts { + Disabled, + Enabled, + Forced, + }; + /// The code model to use (-mcmodel). std::string CodeModel; @@ -200,8 +207,11 @@ public: /// if non-empty. std::string RecordCommandLine; - std::map DebugPrefixMap; - std::map CoveragePrefixMap; + llvm::SmallVector, 0> DebugPrefixMap; + + /// Prefix replacement map for source-based code coverage to remap source + /// file paths in coverage mapping. + llvm::SmallVector, 0> CoveragePrefixMap; /// The ABI to use for passing floating point arguments. std::string FloatABI; @@ -273,6 +283,9 @@ public: /// Name of the profile file to use as output for with -fmemory-profile. std::string MemoryProfileOutput; + /// Name of the profile file to use as input for -fmemory-profile-use. + std::string MemoryProfileUsePath; + /// Name of the profile file to use as input for -fprofile-instr-use std::string ProfileInstrumentUsePath; @@ -326,12 +339,12 @@ public: /// Optimization remark with an optional regular expression pattern. struct OptRemark { - RemarkKind Kind; + RemarkKind Kind = RK_Missing; std::string Pattern; std::shared_ptr Regex; /// By default, optimization remark is missing. - OptRemark() : Kind(RK_Missing), Regex(nullptr) {} + OptRemark() = default; /// Returns true iff the optimization remark holds a valid regular /// expression. @@ -362,9 +375,6 @@ public: /// transformation. OptRemark OptimizationRemarkAnalysis; - /// Set of files defining the rules for the symbol rewriting. - std::vector RewriteMapFiles; - /// Set of sanitizer checks that are non-fatal (i.e. execution should be /// continued when possible). SanitizerSet SanitizeRecover; @@ -417,6 +427,11 @@ public: /// coverage pass should actually not be instrumented. std::vector SanitizeCoverageIgnorelistFiles; + /// Path to ignorelist file specifying which objects + /// (files, functions) listed for instrumentation by sanitizer + /// binary metadata pass should not be instrumented. + std::vector SanitizeMetadataIgnorelistFiles; + /// Name of the stack usage file (i.e., .su file) if user passes /// -fstack-usage. If empty, it can be implied that -fstack-usage is not /// passed on the command line. @@ -494,12 +509,12 @@ public: /// Check if type and variable info should be emitted. bool hasReducedDebugInfo() const { - return getDebugInfo() >= codegenoptions::DebugInfoConstructor; + return getDebugInfo() >= llvm::codegenoptions::DebugInfoConstructor; } /// Check if maybe unused type info should be emitted. bool hasMaybeUnusedDebugInfo() const { - return getDebugInfo() >= codegenoptions::UnusedTypeInfo; + return getDebugInfo() >= llvm::codegenoptions::UnusedTypeInfo; } // Check if any one of SanitizeCoverage* is enabled. diff --git a/contrib/llvm-project/clang/include/clang/Basic/Cuda.h b/contrib/llvm-project/clang/include/clang/Basic/Cuda.h index 8ff28944f23..7f65d711bb3 100644 --- a/contrib/llvm-project/clang/include/clang/Basic/Cuda.h +++ b/contrib/llvm-project/clang/include/clang/Basic/Cuda.h @@ -37,9 +37,11 @@ enum class CudaVersion { CUDA_116, CUDA_117, CUDA_118, - FULLY_SUPPORTED = CUDA_115, + CUDA_120, + CUDA_121, + FULLY_SUPPORTED = CUDA_118, PARTIALLY_SUPPORTED = - CUDA_118, // Partially supported. Proceed with a warning. + CUDA_121, // Partially supported. Proceed with a warning. NEW = 10000, // Too new. Issue a warning, but allow using it. }; const char *CudaVersionToString(CudaVersion V); @@ -92,6 +94,8 @@ enum class CudaArch { GFX90a, GFX90c, GFX940, + GFX941, + GFX942, GFX1010, GFX1011, GFX1012, @@ -107,6 +111,8 @@ enum class CudaArch { GFX1101, GFX1102, GFX1103, + GFX1150, + GFX1151, Generic, // A processor model named 'generic' if the target backend defines a // public one. LAST, diff --git a/contrib/llvm-project/clang/include/clang/Basic/DarwinSDKInfo.h b/contrib/llvm-project/clang/include/clang/Basic/DarwinSDKInfo.h index 62e23682872..dedfbd934a7 100644 --- a/contrib/llvm-project/clang/include/clang/Basic/DarwinSDKInfo.h +++ b/contrib/llvm-project/clang/include/clang/Basic/DarwinSDKInfo.h @@ -11,10 +11,10 @@ #include "clang/Basic/LLVM.h" #include "llvm/ADT/DenseMap.h" -#include "llvm/ADT/Triple.h" #include "llvm/Support/Error.h" #include "llvm/Support/VersionTuple.h" #include "llvm/Support/VirtualFileSystem.h" +#include "llvm/TargetParser/Triple.h" #include namespace llvm { diff --git a/contrib/llvm-project/clang/include/clang/Basic/Diagnostic.h b/contrib/llvm-project/clang/include/clang/Basic/Diagnostic.h index b9ba459d135..5606a22fe9d 100644 --- a/contrib/llvm-project/clang/include/clang/Basic/Diagnostic.h +++ b/contrib/llvm-project/clang/include/clang/Basic/Diagnostic.h @@ -1565,7 +1565,7 @@ inline DiagnosticBuilder DiagnosticsEngine::Report(unsigned DiagID) { /// currently in-flight diagnostic. class Diagnostic { const DiagnosticsEngine *DiagObj; - StringRef StoredDiagMessage; + std::optional StoredDiagMessage; public: explicit Diagnostic(const DiagnosticsEngine *DO) : DiagObj(DO) {} diff --git a/contrib/llvm-project/clang/include/clang/Basic/Diagnostic.td b/contrib/llvm-project/clang/include/clang/Basic/Diagnostic.td index 21de05b707a..8d66e265fba 100644 --- a/contrib/llvm-project/clang/include/clang/Basic/Diagnostic.td +++ b/contrib/llvm-project/clang/include/clang/Basic/Diagnostic.td @@ -55,11 +55,11 @@ class DiagCategory { } // Diagnostic Groups. -class DiagGroup subgroups = []> { +class DiagGroup subgroups = [], code docs = [{}]> { string GroupName = Name; list SubGroups = subgroups; string CategoryName = ""; - code Documentation = [{}]; + code Documentation = docs; } class InGroup { DiagGroup Group = G; } //class IsGroup { DiagGroup Group = DiagGroup; } @@ -157,7 +157,6 @@ class DefaultRemark { Severity DefaultSeverity = SEV_Remark; } // Definitions for Diagnostics. include "DiagnosticASTKinds.td" -include "DiagnosticAnalysisKinds.td" include "DiagnosticCommentKinds.td" include "DiagnosticCommonKinds.td" include "DiagnosticCrossTUKinds.td" diff --git a/contrib/llvm-project/clang/include/clang/Basic/DiagnosticASTKinds.td b/contrib/llvm-project/clang/include/clang/Basic/DiagnosticASTKinds.td index 4e2e0bd3079..566cdc34060 100644 --- a/contrib/llvm-project/clang/include/clang/Basic/DiagnosticASTKinds.td +++ b/contrib/llvm-project/clang/include/clang/Basic/DiagnosticASTKinds.td @@ -15,6 +15,10 @@ def note_constexpr_invalid_cast : Note< " performs the conversions of a reinterpret_cast}1|cast from %1}0" " is not allowed in a constant expression" "%select{| in C++ standards before C++20||}0">; +def note_constexpr_invalid_void_star_cast : Note< + "cast from %0 is not allowed in a constant expression " + "%select{in C++ standards before C++2c|because the pointed object " + "type %2 is not similar to the target type %3}1">; def note_constexpr_invalid_downcast : Note< "cannot cast object of dynamic type %0 to type %1">; def note_constexpr_overflow : Note< @@ -65,7 +69,7 @@ def note_consteval_address_accessible : Note< "%select{pointer|reference}0 to a consteval declaration " "is not a constant expression">; def note_constexpr_uninitialized : Note< - "%select{|sub}0object of type %1 is not initialized">; + "subobject %0 is not initialized">; def note_constexpr_static_local : Note< "control flows through the definition of a %select{static|thread_local}0 variable">; def note_constexpr_subobject_declared_here : Note< @@ -127,6 +131,8 @@ def note_constexpr_null_subobject : Note< "access array element of|perform pointer arithmetic on|" "access real component of|" "access imaginary component of}0 null pointer">; +def note_constexpr_null_callee : Note< + "'%0' evaluates to a null function pointer">; def note_constexpr_function_param_value_unknown : Note< "function parameter %0 with unknown value cannot be used in a constant " "expression">; @@ -775,7 +781,7 @@ def err_module_odr_violation_field : Error< "%select{non-|}5bitfield %4|" "bitfield %4 with one width expression|" "%select{non-|}5mutable field %4|" - "field %4 with %select{no|an}5 initalizer|" + "field %4 with %select{no|an}5 initializer|" "field %4 with an initializer" "}3">; def note_module_odr_violation_field : Note< diff --git a/contrib/llvm-project/clang/include/clang/Basic/DiagnosticCommonKinds.td b/contrib/llvm-project/clang/include/clang/Basic/DiagnosticCommonKinds.td index c59adcc72a6..ee994e765e0 100644 --- a/contrib/llvm-project/clang/include/clang/Basic/DiagnosticCommonKinds.td +++ b/contrib/llvm-project/clang/include/clang/Basic/DiagnosticCommonKinds.td @@ -55,7 +55,7 @@ def err_expected_colon_after_setter_name : Error< def err_expected_string_literal : Error<"expected string literal " "%select{in %1|for diagnostic message in static_assert|" "for optional message in 'availability' attribute|" - "for %select{language|source container}1 name in " + "for %select{language name|source container name|USR}1 in " "'external_source_symbol' attribute}0">; def err_invalid_string_udl : Error< "string literal with user-defined suffix cannot be used here">; @@ -63,6 +63,10 @@ def err_invalid_character_udl : Error< "character literal with user-defined suffix cannot be used here">; def err_invalid_numeric_udl : Error< "numeric literal with user-defined suffix cannot be used here">; +def warn_pragma_debug_missing_argument : Warning< + "missing argument to debug command '%0'">, InGroup; +def warn_pragma_debug_unexpected_argument : Warning< + "unexpected argument to debug command">, InGroup; } @@ -117,7 +121,7 @@ def note_pragma_entered_here : Note<"#pragma entered here">; def note_decl_hiding_tag_type : Note< "%1 %0 is hidden by a non-type declaration of %0 here">; def err_attribute_not_type_attr : Error< - "%0 attribute cannot be applied to types">; + "%0%select{ attribute|}1 cannot be applied to types">; def err_enum_template : Error<"enumeration cannot be a template">; def warn_cxx20_compat_consteval : Warning< @@ -126,6 +130,12 @@ def warn_cxx20_compat_consteval : Warning< def warn_missing_type_specifier : Warning< "type specifier missing, defaults to 'int'">, InGroup, DefaultIgnore; + +def ext_c_empty_initializer : Extension< + "use of an empty initializer is a C2x extension">, InGroup; +def warn_c2x_compat_empty_initializer : Warning< + "use of an empty initializer is incompatible with C standards before C2x">, + InGroup, DefaultIgnore; } let CategoryName = "Nullability Issue" in { @@ -165,6 +175,8 @@ def warn_unknown_attribute_ignored : Warning< "unknown attribute %0 ignored">, InGroup; def warn_attribute_ignored : Warning<"%0 attribute ignored">, InGroup; +def err_keyword_not_supported_on_target : Error< + "%0 is not supported on this target">; def err_use_of_tag_name_without_tag : Error< "must use '%1' tag to refer to type %0%select{| in this scope}2">; @@ -200,14 +212,14 @@ def ext_cxx11_longlong : Extension< def warn_cxx98_compat_longlong : Warning< "'long long' is incompatible with C++98">, InGroup, DefaultIgnore; -def ext_cxx2b_size_t_suffix : ExtWarn< - "'size_t' suffix for literals is a C++2b extension">, - InGroup; +def ext_cxx23_size_t_suffix : ExtWarn< + "'size_t' suffix for literals is a C++23 extension">, + InGroup; def warn_cxx20_compat_size_t_suffix : Warning< "'size_t' suffix for literals is incompatible with C++ standards before " - "C++2b">, InGroup, DefaultIgnore; -def err_cxx2b_size_t_suffix: Error< - "'size_t' suffix for literals is a C++2b feature">; + "C++23">, InGroup, DefaultIgnore; +def err_cxx23_size_t_suffix: Error< + "'size_t' suffix for literals is a C++23 feature">; def err_size_t_literal_too_large: Error< "%select{signed |}0'size_t' literal is out of range of possible " "%select{signed |}0'size_t' values">; @@ -293,12 +305,13 @@ def warn_slh_does_not_support_asm_goto : Warning< // Sema && Serialization def warn_dup_category_def : Warning< - "duplicate definition of category %1 on interface %0">; + "duplicate definition of category %1 on interface %0">, + InGroup>; // Targets def err_target_unknown_triple : Error< - "unknown target triple '%0', please use -triple or -arch">; + "unknown target triple '%0'">; def err_target_unknown_cpu : Error<"unknown target CPU '%0'">; def note_valid_options : Note<"valid target CPU values are: %0">; def err_target_unsupported_cpu_for_micromips : Error< @@ -329,6 +342,9 @@ def err_opt_not_valid_on_target : Error< "option '%0' cannot be specified on this target">; def err_invalid_feature_combination : Error< "invalid feature combination: %0">; +def warn_target_unrecognized_env : Warning< + "mismatch between architecture and environment in target triple '%0'; did you mean '%1'?">, + InGroup; // Source manager def err_cannot_open_file : Error<"cannot open file '%0': %1">, DefaultFatal; diff --git a/contrib/llvm-project/clang/include/clang/Basic/DiagnosticDocs.td b/contrib/llvm-project/clang/include/clang/Basic/DiagnosticDocs.td index bf88d5d0456..e9862422b49 100644 --- a/contrib/llvm-project/clang/include/clang/Basic/DiagnosticDocs.td +++ b/contrib/llvm-project/clang/include/clang/Basic/DiagnosticDocs.td @@ -81,3 +81,9 @@ Diagnostic flags }]; } +defvar GCCWriteStringsDocs = [{ +**Note:** enabling this warning in C will change the semantic behavior of the +program by treating all string literals as having type ``const char *`` +instead of ``char *``. This can cause unexpected behaviors with type-sensitive +constructs like ``_Generic``. +}]; diff --git a/contrib/llvm-project/clang/include/clang/Basic/DiagnosticDriverKinds.td b/contrib/llvm-project/clang/include/clang/Basic/DiagnosticDriverKinds.td index f3d43b2e066..1b69324d073 100644 --- a/contrib/llvm-project/clang/include/clang/Basic/DiagnosticDriverKinds.td +++ b/contrib/llvm-project/clang/include/clang/Basic/DiagnosticDriverKinds.td @@ -29,6 +29,8 @@ def err_drv_invalid_arch_name : Error< "invalid arch name '%0'">; def err_drv_invalid_riscv_arch_name : Error< "invalid arch name '%0', %1">; +def err_drv_invalid_riscv_cpu_name_for_target : Error< + "cpu '%0' does not support rv%select{32|64}1">; def warn_drv_invalid_arch_name_with_suggestion : Warning< "ignoring invalid /arch: argument '%0'; for %select{64|32}1-bit expected one of %2">, InGroup; @@ -80,6 +82,9 @@ def err_drv_hipspv_no_hip_path : Error< def err_drv_undetermined_gpu_arch : Error< "cannot determine %0 architecture: %1; consider passing it via " "'%2'">; +def warn_drv_multi_gpu_arch : Warning< + "multiple %0 architectures are detected: %1; only the first one is used for " + "'%2'">, InGroup; def err_drv_cuda_version_unsupported : Error< "GPU arch %0 is supported by CUDA versions between %1 and %2 (inclusive), " "but installation at %3 is %4; use '--cuda-path' to specify a different CUDA " @@ -113,6 +118,12 @@ def warn_drv_unsupported_option_for_target : Warning< def warn_drv_unsupported_option_for_flang : Warning< "the argument '%0' is not supported for option '%1'. Mapping to '%1%2'">, InGroup; +def warn_drv_unsupported_diag_option_for_flang : Warning< + "The warning option '-%0' is not supported">, + InGroup; +def warn_drv_unsupported_option_for_processor : Warning< + "ignoring '%0' option as it is not currently supported for processor '%1'">, + InGroup; def err_drv_invalid_thread_model_for_target : Error< "invalid thread model '%0' in '%1' for this target">; @@ -127,7 +138,7 @@ def err_drv_invalid_unwindlib_name : Error< def err_drv_incompatible_unwindlib : Error< "--rtlib=libgcc requires --unwindlib=libgcc">; def err_drv_incompatible_options : Error< - "The combination of '%0' and '%1' is incompatible">; + "the combination of '%0' and '%1' is incompatible">; def err_drv_invalid_stdlib_name : Error< "invalid library name in argument '%0'">; def err_drv_invalid_output_with_multiple_archs : Error< @@ -215,8 +226,10 @@ def err_drv_malformed_sanitizer_coverage_allowlist : Error< "malformed sanitizer coverage allowlist: '%0'">; def err_drv_malformed_sanitizer_coverage_ignorelist : Error< "malformed sanitizer coverage ignorelist: '%0'">; -def err_drv_unsupported_static_ubsan_darwin : Error< - "static UndefinedBehaviorSanitizer runtime is not supported on darwin">; +def err_drv_malformed_sanitizer_metadata_ignorelist : Error< + "malformed sanitizer metadata ignorelist: '%0'">; +def err_drv_unsupported_static_sanitizer_darwin : Error< + "static %0 runtime is not supported on darwin">; def err_drv_duplicate_config : Error< "no more than one option '--config' is allowed">; def err_drv_cannot_open_config_file : Error< @@ -248,6 +261,7 @@ def warn_drv_unknown_argument_clang_cl : Warning< def warn_drv_unknown_argument_clang_cl_with_suggestion : Warning< "unknown argument ignored in clang-cl '%0'; did you mean '%1'?">, InGroup; +def err_drv_unknown_target_triple : Error<"unknown target triple '%0'">; def warn_drv_ycyu_different_arg_clang_cl : Warning< "support for '/Yc' and '/Yu' with different filenames not implemented yet; flags ignored">, @@ -405,7 +419,10 @@ def warn_drv_assuming_mfloat_abi_is : Warning< "unknown platform, assuming -mfloat-abi=%0">; def warn_drv_unsupported_float_abi_by_lib : Warning< "float ABI '%0' is not supported by current library">, - InGroup>; + InGroup; +def warn_drv_no_floating_point_registers: Warning< + "'%0': selected processor lacks floating point registers">, + InGroup; def warn_ignoring_ftabstop_value : Warning< "ignoring invalid -ftabstop value '%0', using default value %1">; def warn_drv_overriding_flag_option : Warning< @@ -558,17 +575,13 @@ def err_drv_unsupported_fpatchable_function_entry_argument : Error< "the second argument of '-fpatchable-function-entry' must be smaller than the first argument">; def warn_drv_unable_to_find_directory_expected : Warning< - "unable to find %0 directory, expected to be in '%1'">, + "unable to find %0 directory, expected to be in '%1' found via %2">, InGroup, DefaultIgnore; def warn_drv_ps_force_pic : Warning< "option '%0' was ignored by the %1 toolchain, using '-fPIC'">, InGroup; -def warn_drv_ps_sdk_dir : Warning< - "environment variable '%0' is set, but points to invalid or nonexistent directory '%1'">, - InGroup; - def err_drv_defsym_invalid_format : Error<"defsym must be of the form: sym=value: %0">; def err_drv_defsym_invalid_symval : Error<"value is not an integer: %0">; def warn_drv_msvc_not_found : Warning< @@ -608,6 +621,9 @@ def warn_drv_darwin_sdk_invalid_settings : Warning< "SDK settings were ignored as 'SDKSettings.json' could not be parsed">, InGroup>; +def err_drv_darwin_sdk_missing_arclite : Error< + "SDK does not contain 'libarclite' at the path '%0'; try increasing the minimum deployment target">; + def err_drv_trivial_auto_var_init_stop_after_missing_dependency : Error< "'-ftrivial-auto-var-init-stop-after=*' is used without " "'-ftrivial-auto-var-init=zero' or '-ftrivial-auto-var-init=pattern'">; @@ -632,21 +648,14 @@ def warn_drv_libstdcxx_not_found : Warning< "command line to use the libc++ standard library instead">, InGroup>; -def warn_deperecated_fcoroutines_ts_flag : Warning< - "the '-fcoroutines-ts' flag is deprecated and it will be removed in Clang 17; " - "use '-std=c++20' or higher to use standard C++ coroutines instead">, - InGroup; -def warn_deprecated_fmodules_ts_flag : Warning< - "the '-fmodules-ts' flag is deprecated and it will be removed in Clang 17; " - "use '-std=c++20' or higher to use standard C++ modules instead">, - InGroup>; - def err_drv_cannot_mix_options : Error<"cannot specify '%1' along with '%0'">; def err_drv_invalid_object_mode : Error< "OBJECT_MODE setting %0 is not recognized and is not a valid setting">; def err_aix_unsupported_tls_model : Error<"TLS model '%0' is not yet supported on AIX">; +def err_roptr_requires_data_sections: Error<"-mxcoff-roptr is supported only with -fdata-sections">; +def err_roptr_cannot_build_shared: Error<"-mxcoff-roptr is not supported with -shared">; def err_invalid_cxx_abi : Error<"invalid C++ ABI name '%0'">; def err_unsupported_cxx_abi : Error<"C++ ABI '%0' is not supported on target triple '%1'">; @@ -697,6 +706,9 @@ def err_drv_dxc_missing_target_profile : Error< "target profile option (-T) is missing">; def err_drv_hlsl_unsupported_target : Error< "HLSL code generation is unsupported for target '%0'">; +def warn_drv_dxc_missing_dxv : Warning<"dxv not found. " + "Resulting DXIL will not be validated or signed for use in release environments.">, + InGroup; def err_drv_invalid_range_dxil_validator_version : Error< "invalid validator version : %0\n" @@ -715,6 +727,18 @@ def warn_drv_sarif_format_unstable : Warning< def err_drv_riscv_unsupported_with_linker_relaxation : Error< "%0 is unsupported with RISC-V linker relaxation (-mrelax)">; +def warn_drv_loongarch_conflicting_implied_val : Warning< + "ignoring '%0' as it conflicts with that implied by '%1' (%2)">, + InGroup; def err_drv_loongarch_invalid_mfpu_EQ : Error< "invalid argument '%0' to -mfpu=; must be one of: 64, 32, none, 0 (alias for none)">; + +def err_drv_expand_response_file : Error< + "failed to expand response file: %0">; + +def warn_drv_missing_multilib : Warning< + "no multilib found matching flags: %0">, + InGroup>; +def note_drv_available_multilibs : Note< + "available multilibs are:%0">; } diff --git a/contrib/llvm-project/clang/include/clang/Basic/DiagnosticError.h b/contrib/llvm-project/clang/include/clang/Basic/DiagnosticError.h index 3660bd1b3b3..744f7fe19db 100644 --- a/contrib/llvm-project/clang/include/clang/Basic/DiagnosticError.h +++ b/contrib/llvm-project/clang/include/clang/Basic/DiagnosticError.h @@ -35,8 +35,8 @@ public: } /// Extracts and returns the diagnostic payload from the given \c Error if - /// the error is a \c DiagnosticError. Returns none if the given error is not - /// a \c DiagnosticError. + /// the error is a \c DiagnosticError. Returns std::nullopt if the given error + /// is not a \c DiagnosticError. static std::optional take(llvm::Error &Err) { std::optional Result; Err = llvm::handleErrors(std::move(Err), [&](DiagnosticError &E) { diff --git a/contrib/llvm-project/clang/include/clang/Basic/DiagnosticFrontendKinds.td b/contrib/llvm-project/clang/include/clang/Basic/DiagnosticFrontendKinds.td index d0f672ae5a1..9ed9a88fa3d 100644 --- a/contrib/llvm-project/clang/include/clang/Basic/DiagnosticFrontendKinds.td +++ b/contrib/llvm-project/clang/include/clang/Basic/DiagnosticFrontendKinds.td @@ -11,7 +11,7 @@ class BackendInfo : CatBackend, ShowInSystemHeader; let Component = "Frontend" in { def err_fe_error_opening : Error<"error opening '%0': %1">; -def err_fe_error_reading : Error<"error reading '%0'">; +def err_fe_error_reading : Error<"error reading '%0': %1">; def err_fe_error_reading_stdin : Error<"error reading stdin: %0">; def err_fe_error_backend : Error<"error in backend: %0">, DefaultFatal; @@ -55,6 +55,9 @@ def warn_fe_backend_unsupported_fp_exceptions : Warning< def warn_fe_backend_invalid_feature_flag : Warning< "feature flag '%0' must start with either '+' to enable the feature or '-'" " to disable it; flag ignored">, InGroup; +def warn_fe_backend_readonly_feature_flag : Warning< + "feature flag '%0' is ignored since the feature is read only">, + InGroup; def err_incompatible_fp_eval_method_options : Error< "option 'ffp-eval-method' cannot be used with option " @@ -209,7 +212,7 @@ def note_incompatible_analyzer_plugin_api : Note< def err_module_build_requires_fmodules : Error< "module compilation requires '-fmodules'">; def err_module_interface_requires_cpp_modules : Error< - "module interface compilation requires '-std=c++20' or '-fmodules-ts'">; + "module interface compilation requires '-std=c++20'">; def warn_module_config_mismatch : Warning< "module file %0 cannot be loaded due to a configuration mismatch with the current " "compilation">, InGroup>, DefaultError; @@ -241,8 +244,10 @@ def warn_module_config_macro_undef : Warning< def note_module_def_undef_here : Note< "macro was %select{defined|#undef'd}0 here">; def remark_module_build : Remark<"building module '%0' as '%1'">, + ShowInSystemHeader, InGroup; def remark_module_build_done : Remark<"finished building module '%0'">, + ShowInSystemHeader, InGroup; def remark_module_lock : Remark<"locking '%0' to build module '%1'">, InGroup; @@ -278,6 +283,10 @@ def err_avx_calling_convention : Error; def err_alias_to_undefined : Error< "%select{alias|ifunc}0 must point to a defined " "%select{variable or |}1function">; +def note_alias_requires_mangled_name : Note< + "the %select{function or variable|function}0 specified in an %select{alias|ifunc}1 must refer to its mangled name">; +def note_alias_mangled_name_alternative: Note< + "function by that name is mangled as \"%0\"">; def warn_alias_to_weak_alias : Warning< "%select{alias|ifunc}2 will always resolve to %0 even if weak definition of " "%1 is overridden">, @@ -305,6 +314,10 @@ def warn_atomic_op_oversized : Warning< "; the access size (%0 bytes) exceeds the max lock-free size (%1 bytes)">, InGroup; +def warn_sync_op_misaligned : Warning< + "__sync builtin operation MUST have natural alignment (consider using __atomic).">, + InGroup; + def warn_alias_with_section : Warning< "%select{alias|ifunc}1 will not be in section '%0' but in the same section " "as the %select{aliasee|resolver}2">, diff --git a/contrib/llvm-project/clang/include/clang/Basic/DiagnosticGroups.td b/contrib/llvm-project/clang/include/clang/Basic/DiagnosticGroups.td index 6c997c37cc5..7b4d415bf06 100644 --- a/contrib/llvm-project/clang/include/clang/Basic/DiagnosticGroups.td +++ b/contrib/llvm-project/clang/include/clang/Basic/DiagnosticGroups.td @@ -60,14 +60,12 @@ def CompoundTokenSplit : DiagGroup<"compound-token-split", CompoundTokenSplitBySpace]>; def CoroutineMissingUnhandledException : DiagGroup<"coroutine-missing-unhandled-exception">; -def DeprecatedExperimentalCoroutine : - DiagGroup<"deprecated-experimental-coroutine">; def DeprecatedCoroutine : - DiagGroup<"deprecated-coroutine", [DeprecatedExperimentalCoroutine]>; + DiagGroup<"deprecated-coroutine">; def AlwaysInlineCoroutine : DiagGroup<"always-inline-coroutine">; def CoroNonAlignedAllocationFunction : - DiagGroup<"coro-non-aligned-allocation-funciton">; + DiagGroup<"coro-non-aligned-allocation-function">; def Coroutine : DiagGroup<"coroutine", [CoroutineMissingUnhandledException, DeprecatedCoroutine, AlwaysInlineCoroutine, CoroNonAlignedAllocationFunction]>; def ObjCBoolConstantConversion : DiagGroup<"objc-bool-constant-conversion">; @@ -185,9 +183,11 @@ def DeprecatedCopyWithUserProvidedCopy : DiagGroup<"deprecated-copy-with-user-pr def DeprecatedCopyWithUserProvidedDtor : DiagGroup<"deprecated-copy-with-user-provided-dtor">; def DeprecatedCopy : DiagGroup<"deprecated-copy", [DeprecatedCopyWithUserProvidedCopy]>; def DeprecatedCopyWithDtor : DiagGroup<"deprecated-copy-with-dtor", [DeprecatedCopyWithUserProvidedDtor]>; +def DeprecatedLiteralOperator : DiagGroup<"deprecated-literal-operator">; // For compatibility with GCC. def : DiagGroup<"deprecated-copy-dtor", [DeprecatedCopyWithDtor]>; def DeprecatedDeclarations : DiagGroup<"deprecated-declarations">; +def DeprecatedRedundantConstexprStaticDef : DiagGroup<"deprecated-redundant-constexpr-static-def">; def UnavailableDeclarations : DiagGroup<"unavailable-declarations">; def UnguardedAvailabilityNew : DiagGroup<"unguarded-availability-new">; def UnguardedAvailability : DiagGroup<"unguarded-availability", @@ -221,12 +221,15 @@ def Deprecated : DiagGroup<"deprecated", [DeprecatedAnonEnumEnumConversion, DeprecatedEnumFloatConversion, DeprecatedBuiltins, DeprecatedIncrementBool, + DeprecatedLiteralOperator, DeprecatedPragma, DeprecatedRegister, DeprecatedThisCapture, DeprecatedType, DeprecatedVolatile, - DeprecatedWritableStr]>, + DeprecatedWritableStr, + DeprecatedRedundantConstexprStaticDef, + ]>, DiagCategory<"Deprecations">; def CXX20Designator : DiagGroup<"c++20-designator">; @@ -258,7 +261,6 @@ def EmptyBody : DiagGroup<"empty-body">; def Exceptions : DiagGroup<"exceptions">; def DeclarationAfterStatement : DiagGroup<"declaration-after-statement">; -def GNUEmptyInitializer : DiagGroup<"gnu-empty-initializer">; def GNUEmptyStruct : DiagGroup<"gnu-empty-struct">; def ExtraTokens : DiagGroup<"extra-tokens">; def CXX98CompatExtraSemi : DiagGroup<"c++98-compat-extra-semi">; @@ -307,9 +309,14 @@ def CXXPre20CompatPedantic : DiagGroup<"pre-c++20-compat-pedantic", [CXXPre20Compat]>; def : DiagGroup<"c++98-c++11-c++14-c++17-compat-pedantic", [CXXPre20CompatPedantic]>; -def CXXPre2bCompat : DiagGroup<"pre-c++2b-compat">; -def CXXPre2bCompatPedantic : - DiagGroup<"pre-c++2b-compat-pedantic", [CXXPre2bCompat]>; +def CXXPre23Compat : DiagGroup<"pre-c++23-compat">; +def CXXPre23CompatPedantic : + DiagGroup<"pre-c++23-compat-pedantic", [CXXPre23Compat]>; +def CXXPre26Compat : DiagGroup<"pre-c++26-compat">; +def CXXPre26CompatPedantic : + DiagGroup<"pre-c++26-compat-pedantic", [CXXPre26Compat]>; +def : DiagGroup<"pre-c++2c-compat", [CXXPre26Compat]>; +def : DiagGroup<"pre-c++2c-compat-pedantic", [CXXPre26CompatPedantic]>; def CXX98CompatBindToTemporaryCopy : DiagGroup<"c++98-compat-bind-to-temporary-copy">; @@ -324,7 +331,7 @@ def CXX98Compat : DiagGroup<"c++98-compat", CXXPre14Compat, CXXPre17Compat, CXXPre20Compat, - CXXPre2bCompat]>; + CXXPre23Compat]>; // Warnings for C++11 features which are Extensions in C++98 mode. def CXX98CompatPedantic : DiagGroup<"c++98-compat-pedantic", [CXX98Compat, @@ -333,7 +340,7 @@ def CXX98CompatPedantic : DiagGroup<"c++98-compat-pedantic", CXXPre14CompatPedantic, CXXPre17CompatPedantic, CXXPre20CompatPedantic, - CXXPre2bCompatPedantic]>; + CXXPre23CompatPedantic]>; def CXX11Narrowing : DiagGroup<"c++11-narrowing">; @@ -363,39 +370,39 @@ def CXX11Compat : DiagGroup<"c++11-compat", CXXPre14Compat, CXXPre17Compat, CXXPre20Compat, - CXXPre2bCompat]>; + CXXPre23Compat]>; def : DiagGroup<"c++0x-compat", [CXX11Compat]>; def CXX11CompatPedantic : DiagGroup<"c++11-compat-pedantic", [CXX11Compat, CXXPre14CompatPedantic, CXXPre17CompatPedantic, CXXPre20CompatPedantic, - CXXPre2bCompatPedantic]>; + CXXPre23CompatPedantic]>; def CXX14Compat : DiagGroup<"c++14-compat", [CXXPre17Compat, CXXPre20Compat, - CXXPre2bCompat]>; + CXXPre23Compat]>; def CXX14CompatPedantic : DiagGroup<"c++14-compat-pedantic", [CXX14Compat, CXXPre17CompatPedantic, CXXPre20CompatPedantic, - CXXPre2bCompatPedantic]>; + CXXPre23CompatPedantic]>; def CXX17Compat : DiagGroup<"c++17-compat", [DeprecatedRegister, DeprecatedIncrementBool, CXX17CompatMangling, CXXPre20Compat, - CXXPre2bCompat]>; + CXXPre23Compat]>; def CXX17CompatPedantic : DiagGroup<"c++17-compat-pedantic", [CXX17Compat, CXXPre20CompatPedantic, - CXXPre2bCompatPedantic]>; + CXXPre23CompatPedantic]>; def : DiagGroup<"c++1z-compat", [CXX17Compat]>; -def CXX20Compat : DiagGroup<"c++20-compat", [CXXPre2bCompat]>; +def CXX20Compat : DiagGroup<"c++20-compat", [CXXPre23Compat]>; def CXX20CompatPedantic : DiagGroup<"c++20-compat-pedantic", [CXX20Compat, - CXXPre2bCompatPedantic]>; + CXXPre23CompatPedantic]>; def : DiagGroup<"c++2a-compat", [CXX20Compat]>; def : DiagGroup<"c++2a-compat-pedantic", [CXX20CompatPedantic]>; @@ -803,6 +810,7 @@ def AtomicAlignment : DiagGroup<"atomic-alignment">; def CustomAtomic : DiagGroup<"custom-atomic-properties">; def AtomicProperties : DiagGroup<"atomic-properties", [ImplicitAtomic, CustomAtomic]>; +def SyncAlignment : DiagGroup<"sync-alignment">; def ARCUnsafeRetainedAssign : DiagGroup<"arc-unsafe-retained-assign">; def ARCRetainCycles : DiagGroup<"arc-retain-cycles">; def ARCNonPodMemAccess : DiagGroup<"arc-non-pod-memaccess">; @@ -849,15 +857,17 @@ def WritableStrings : DiagGroup<"writable-strings", [DeprecatedWritableStr]>; // // FIXME: Should this affect C++11 (where this is an error, // not just deprecated) or not? -def GCCWriteStrings : DiagGroup<"write-strings" , [WritableStrings]>; +def GCCWriteStrings : DiagGroup<"write-strings" , [WritableStrings], + GCCWriteStringsDocs>; def CharSubscript : DiagGroup<"char-subscripts">; def LargeByValueCopy : DiagGroup<"large-by-value-copy">; def DuplicateArgDecl : DiagGroup<"duplicate-method-arg">; def SignedEnumBitfield : DiagGroup<"signed-enum-bitfield">; +def ReservedModuleIdentifier : DiagGroup<"reserved-module-identifier">; def ReservedIdentifier : DiagGroup<"reserved-identifier", - [ReservedIdAsMacro]>; + [ReservedIdAsMacro, ReservedModuleIdentifier, UserDefinedLiterals]>; // Unreachable code warning groups. // @@ -1055,7 +1065,7 @@ def Consumed : DiagGroup<"consumed">; // warning should be active _only_ when -Wall is passed in, mark it as // DefaultIgnore in addition to putting it here. def All : DiagGroup<"all", [Most, Parentheses, Switch, SwitchBool, - MisleadingIndentation]>; + MisleadingIndentation, PackedNonPod]>; // Warnings that should be in clang-cl /w4. def : DiagGroup<"CL4", [All, Extra]>; @@ -1108,14 +1118,20 @@ def CXX17 : DiagGroup<"c++17-extensions", [CXX17Attrs]>; // earlier C++ versions. def CXX20 : DiagGroup<"c++20-extensions", [CXX20Designator, CXX20Attrs]>; -// A warning group for warnings about using C++2b features as extensions in +// A warning group for warnings about using C++23 features as extensions in // earlier C++ versions. -def CXX2b : DiagGroup<"c++2b-extensions">; +def CXX23 : DiagGroup<"c++23-extensions">; + +// A warning group for warnings about using C++26 features as extensions in +// earlier C++ versions. +def CXX26 : DiagGroup<"c++26-extensions">; def : DiagGroup<"c++0x-extensions", [CXX11]>; def : DiagGroup<"c++1y-extensions", [CXX14]>; def : DiagGroup<"c++1z-extensions", [CXX17]>; def : DiagGroup<"c++2a-extensions", [CXX20]>; +def : DiagGroup<"c++2b-extensions", [CXX23]>; +def : DiagGroup<"c++2c-extensions", [CXX26]>; def DelegatingCtorCycles : DiagGroup<"delegating-ctor-cycles">; @@ -1135,7 +1151,7 @@ def GNU : DiagGroup<"gnu", [GNUAlignofExpression, GNUAnonymousStruct, GNUBinaryLiteral, GNUCaseRange, GNUComplexInteger, GNUCompoundLiteralInitializer, GNUConditionalOmittedOperand, GNUDesignator, - GNUEmptyInitializer, GNUEmptyStruct, + GNUEmptyStruct, VLAExtension, GNUFlexibleArrayInitializer, GNUFlexibleArrayUnionMember, GNUFoldingConstant, GNUImaginaryConstant, GNUIncludeNext, @@ -1190,6 +1206,7 @@ def MicrosoftCommentPaste : DiagGroup<"microsoft-comment-paste">; def MicrosoftEndOfFile : DiagGroup<"microsoft-end-of-file">; def MicrosoftInaccessibleBase : DiagGroup<"microsoft-inaccessible-base">; def MicrosoftStaticAssert : DiagGroup<"microsoft-static-assert">; +def MicrosoftInitFromPredefined : DiagGroup<"microsoft-init-from-predefined">; // Aliases. def : DiagGroup<"msvc-include", [MicrosoftInclude]>; @@ -1207,7 +1224,7 @@ def Microsoft : DiagGroup<"microsoft", MicrosoftFlexibleArray, MicrosoftExtraQualification, MicrosoftCast, MicrosoftConstInit, MicrosoftVoidPseudoDtor, MicrosoftAnonTag, MicrosoftCommentPaste, MicrosoftEndOfFile, MicrosoftStaticAssert, - MicrosoftInconsistentDllImport]>; + MicrosoftInitFromPredefined, MicrosoftInconsistentDllImport]>; def ClangClPch : DiagGroup<"clang-cl-pch">; @@ -1278,7 +1295,7 @@ invocation. The diagnostic information can be saved to a file in a machine readable format, like YAML by adding the `-foptimization-record-file=` command-line flag. -Results can be filtered by function name by passing +Results can be filtered by function name by passing `-mllvm -filter-print-funcs=foo`, where `foo` is the target function's name. .. code-block: console @@ -1321,6 +1338,12 @@ def CudaUnknownVersion: DiagGroup<"unknown-cuda-version">; // ignored by CUDA. def HIPOnly : DiagGroup<"hip-only">; +// Warning about mixed HIP and OpenMP compilation / target offloading. +def HIPOpenMPOffloading: DiagGroup<"hip-omp-target-directives">; + +// Warning about multiple GPUs are detected. +def MultiGPU: DiagGroup<"multi-gpu">; + // Warnings which cause linking of the runtime libraries like // libc and the CRT to be skipped. def AVRRtlibLinkingQuirks : DiagGroup<"avr-rtlib-linking-quirks">; @@ -1334,6 +1357,8 @@ def OptionIgnored : DiagGroup<"option-ignored">; def UnknownArgument : DiagGroup<"unknown-argument">; +def UnsupportedABI : DiagGroup<"unsupported-abi">; + // A warning group for warnings about code that clang accepts when // compiling OpenCL C/C++ but which is not compatible with the SPIR(-V) spec. def SpirCompat : DiagGroup<"spir-compat">; @@ -1412,6 +1437,9 @@ def BranchProtection : DiagGroup<"branch-protection">; // Warnings for HLSL Clang extensions def HLSLExtension : DiagGroup<"hlsl-extensions">; +// Warnings for DXIL validation +def DXILValidation : DiagGroup<"dxil-validation">; + // Warnings and notes related to const_var_decl_type attribute checks def ReadOnlyPlacementChecks : DiagGroup<"read-only-types">; diff --git a/contrib/llvm-project/clang/include/clang/Basic/DiagnosticIDs.h b/contrib/llvm-project/clang/include/clang/Basic/DiagnosticIDs.h index 6dd78bf93ea..bf4995175ef 100644 --- a/contrib/llvm-project/clang/include/clang/Basic/DiagnosticIDs.h +++ b/contrib/llvm-project/clang/include/clang/Basic/DiagnosticIDs.h @@ -36,7 +36,7 @@ namespace clang { DIAG_SIZE_SERIALIZATION = 120, DIAG_SIZE_LEX = 400, DIAG_SIZE_PARSE = 700, - DIAG_SIZE_AST = 250, + DIAG_SIZE_AST = 300, DIAG_SIZE_COMMENT = 100, DIAG_SIZE_CROSSTU = 100, DIAG_SIZE_SEMA = 4500, @@ -159,6 +159,10 @@ public: Result.Severity = Bits & 0x7; return Result; } + + bool operator==(DiagnosticMapping Other) const { + return serialize() == Other.serialize(); + } }; /// Used for handling and querying diagnostic IDs. @@ -208,6 +212,9 @@ public: /// default. static bool isDefaultMappingAsError(unsigned DiagID); + /// Get the default mapping for this diagnostic. + static DiagnosticMapping getDefaultMapping(unsigned DiagID); + /// Determine whether the given built-in diagnostic ID is a Note. static bool isBuiltinNote(unsigned DiagID); diff --git a/contrib/llvm-project/clang/include/clang/Basic/DiagnosticLexKinds.td b/contrib/llvm-project/clang/include/clang/Basic/DiagnosticLexKinds.td index 3b1b466e760..0eb270aeea0 100644 --- a/contrib/llvm-project/clang/include/clang/Basic/DiagnosticLexKinds.td +++ b/contrib/llvm-project/clang/include/clang/Basic/DiagnosticLexKinds.td @@ -138,13 +138,13 @@ def ext_mathematical_notation : ExtWarn< def ext_delimited_escape_sequence : Extension< "%select{delimited|named}0 escape sequences are a " - "%select{Clang|C++2b}1 extension">, + "%select{Clang|C++23}1 extension">, InGroup>; -def warn_cxx2b_delimited_escape_sequence : Warning< +def warn_cxx23_delimited_escape_sequence : Warning< "%select{delimited|named}0 escape sequences are " - "incompatible with C++ standards before C++2b">, - InGroup, DefaultIgnore; + "incompatible with C++ standards before C++23">, + InGroup, DefaultIgnore; def err_delimited_escape_empty : Error< "delimited escape sequence cannot be empty">; @@ -197,6 +197,14 @@ def warn_cxx98_compat_literal_ucn_escape_basic_scs : Warning< def warn_cxx98_compat_literal_ucn_control_character : Warning< "universal character name referring to a control character " "is incompatible with C++98">, InGroup, DefaultIgnore; +def warn_c2x_compat_literal_ucn_escape_basic_scs : Warning< + "specifying character '%0' with a universal character name is " + "incompatible with C standards before C2x">, + InGroup, DefaultIgnore; +def warn_c2x_compat_literal_ucn_control_character : Warning< + "universal character name referring to a control character " + "is incompatible with C standards before C2x">, + InGroup, DefaultIgnore; def warn_ucn_not_valid_in_c89 : Warning< "universal character names are only valid in C99 or C++; " "treating as '\\' followed by identifier">, InGroup; @@ -276,6 +284,13 @@ def ext_ms_reserved_user_defined_literal : ExtWarn< "identifier">, InGroup; def err_unsupported_string_concat : Error< "unsupported non-standard concatenation of string literals">; + +def err_unevaluated_string_prefix : Error< + "an unevaluated string literal cannot have an encoding prefix">; +def err_unevaluated_string_udl : Error< + "an unevaluated string literal cannot be a user-defined literal">; +def err_unevaluated_string_invalid_escape_sequence : Error< + "invalid escape sequence '%0' in an unevaluated string literal">; def err_string_concat_mixed_suffix : Error< "differing user-defined suffixes ('%0' and '%1') in string literal " "concatenation">; @@ -396,10 +411,10 @@ def ext_pp_include_next_directive : Extension< "#include_next is a language extension">, InGroup; def ext_pp_warning_directive : Extension< - "#warning is a %select{C2x|C++2b}0 extension">; -def warn_cxx2b_compat_warning_directive : Warning< - "#warning is incompatible with C++ standards before C++2b">, - InGroup, DefaultIgnore; + "#warning is a %select{C2x|C++23}0 extension">; +def warn_cxx23_compat_warning_directive : Warning< + "#warning is incompatible with C++ standards before C++23">, + InGroup, DefaultIgnore; def warn_c2x_compat_warning_directive : Warning< "#warning is incompatible with C standards before C2x">, InGroup, DefaultIgnore; @@ -655,10 +670,6 @@ def warn_pragma_debug_missing_command : Warning< "missing debug command">, InGroup; def warn_pragma_debug_unexpected_command : Warning< "unexpected debug command '%0'">, InGroup; -def warn_pragma_debug_missing_argument : Warning< - "missing argument to debug command '%0'">, InGroup; -def warn_pragma_debug_unexpected_argument : Warning< - "unexpected argument to debug command">, InGroup; def warn_pragma_debug_unknown_module : Warning< "unknown module '%0'">, InGroup; // #pragma module @@ -743,14 +754,14 @@ def ext_c2x_pp_directive : ExtWarn< "use of a '#%select{|elifdef|elifndef}0' directive " "is a C2x extension">, InGroup; -def warn_cxx2b_compat_pp_directive : Warning< +def warn_cxx23_compat_pp_directive : Warning< "use of a '#%select{|elifdef|elifndef}0' directive " - "is incompatible with C++ standards before C++2b">, - InGroup, DefaultIgnore; -def ext_cxx2b_pp_directive : ExtWarn< + "is incompatible with C++ standards before C++23">, + InGroup, DefaultIgnore; +def ext_cxx23_pp_directive : ExtWarn< "use of a '#%select{|elifdef|elifndef}0' directive " - "is a C++2b extension">, - InGroup; + "is a C++23 extension">, + InGroup; def err_pp_visibility_non_macro : Error<"no macro named %0">; @@ -888,6 +899,8 @@ def warn_use_of_private_header_outside_module : Warning< InGroup>, DefaultError; def err_undeclared_use_of_module : Error< "module %0 does not depend on a module exporting '%1'">; +def err_undeclared_use_of_module_indirect : Error< + "module %0 does not directly depend on a module exporting '%1', which is part of indirectly-used module %2">; def warn_non_modular_include_in_framework_module : Warning< "include of non-modular header inside framework module '%0': '%1'">, InGroup, DefaultIgnore; @@ -943,4 +956,15 @@ def err_dep_source_scanner_unexpected_tokens_at_import : Error< } +def err_pp_double_begin_pragma_unsafe_buffer_usage : +Error<"already inside '#pragma unsafe_buffer_usage'">; + +def err_pp_unmatched_end_begin_pragma_unsafe_buffer_usage : +Error<"not currently inside '#pragma unsafe_buffer_usage'">; + +def err_pp_unclosed_pragma_unsafe_buffer_usage : +Error<"'#pragma unsafe_buffer_usage' was not ended">; + +def err_pp_pragma_unsafe_buffer_usage_syntax : +Error<"Expected 'begin' or 'end'">; } diff --git a/contrib/llvm-project/clang/include/clang/Basic/DiagnosticOptions.def b/contrib/llvm-project/clang/include/clang/Basic/DiagnosticOptions.def index 7be81f6b6a9..6d0c1b14acc 100644 --- a/contrib/llvm-project/clang/include/clang/Basic/DiagnosticOptions.def +++ b/contrib/llvm-project/clang/include/clang/Basic/DiagnosticOptions.def @@ -90,11 +90,15 @@ VALUE_DIAGOPT(ConstexprBacktraceLimit, 32, DefaultConstexprBacktraceLimit) VALUE_DIAGOPT(SpellCheckingLimit, 32, DefaultSpellCheckingLimit) /// Limit number of lines shown in a snippet. VALUE_DIAGOPT(SnippetLineLimit, 32, DefaultSnippetLineLimit) +/// Show line number column on the left of snippets. +VALUE_DIAGOPT(ShowLineNumbers, 1, DefaultShowLineNumbers) VALUE_DIAGOPT(TabStop, 32, DefaultTabStop) /// The distance between tab stops. /// Column limit for formatting message diagnostics, or 0 if unused. VALUE_DIAGOPT(MessageLength, 32, 0) +DIAGOPT(ShowSafeBufferUsageSuggestions, 1, 0) + #undef DIAGOPT #undef ENUM_DIAGOPT #undef VALUE_DIAGOPT diff --git a/contrib/llvm-project/clang/include/clang/Basic/DiagnosticOptions.h b/contrib/llvm-project/clang/include/clang/Basic/DiagnosticOptions.h index 4b0d45a3ff7..7e218b9c71e 100644 --- a/contrib/llvm-project/clang/include/clang/Basic/DiagnosticOptions.h +++ b/contrib/llvm-project/clang/include/clang/Basic/DiagnosticOptions.h @@ -84,7 +84,8 @@ public: DefaultTemplateBacktraceLimit = 10, DefaultConstexprBacktraceLimit = 10, DefaultSpellCheckingLimit = 50, - DefaultSnippetLineLimit = 1, + DefaultSnippetLineLimit = 16, + DefaultShowLineNumbers = 1, }; // Define simple diagnostic options (with no accessors). diff --git a/contrib/llvm-project/clang/include/clang/Basic/DiagnosticParseKinds.td b/contrib/llvm-project/clang/include/clang/Basic/DiagnosticParseKinds.td index e99beb3a763..8d729c31641 100644 --- a/contrib/llvm-project/clang/include/clang/Basic/DiagnosticParseKinds.td +++ b/contrib/llvm-project/clang/include/clang/Basic/DiagnosticParseKinds.td @@ -157,11 +157,17 @@ def err_duplicate_default_assoc : Error< "duplicate default generic association">; def note_previous_default_assoc : Note< "previous default generic association is here">; +def ext_generic_with_type_arg : Extension< + "passing a type argument as the first operand to '_Generic' is a Clang " + "extension">, InGroup>; def ext_c99_feature : Extension< "'%0' is a C99 extension">, InGroup; def ext_c11_feature : Extension< "'%0' is a C11 extension">, InGroup; +def warn_c2x_compat_keyword : Warning< + "'%0' is incompatible with C standards before C2x">, + InGroup, DefaultIgnore; def err_c11_noreturn_misplaced : Error< "'_Noreturn' keyword must precede function declarator">; @@ -179,8 +185,6 @@ def ext_gnu_statement_expr_macro : Extension< InGroup; def ext_gnu_conditional_expr : Extension< "use of GNU ?: conditional expression extension, omitting middle operand">, InGroup; -def ext_gnu_empty_initializer : Extension< - "use of GNU empty initializer extension">, InGroup; def ext_gnu_array_range : Extension<"use of GNU array range extension">, InGroup; def ext_gnu_missing_equal_designator : ExtWarn< @@ -299,14 +303,14 @@ def ext_c_label_end_of_compound_statement : ExtWarn< "label at end of compound statement is a C2x extension">, InGroup; def ext_cxx_label_end_of_compound_statement : ExtWarn< - "label at end of compound statement is a C++2b extension">, - InGroup; + "label at end of compound statement is a C++23 extension">, + InGroup; def warn_c2x_compat_label_end_of_compound_statement : Warning< "label at end of compound statement is incompatible with C standards before C2x">, InGroup, DefaultIgnore; def warn_cxx20_compat_label_end_of_compound_statement : Warning< - "label at end of compound statement is incompatible with C++ standards before C++2b">, - InGroup, DefaultIgnore; + "label at end of compound statement is incompatible with C++ standards before C++23">, + InGroup, DefaultIgnore; def err_address_of_label_outside_fn : Error< "use of address-of-label extension outside of a function body">; def err_asm_operand_wide_string_literal : Error< @@ -371,9 +375,6 @@ def warn_cxx11_compat_decltype_auto_type_specifier : Warning< def ext_auto_type : Extension< "'__auto_type' is a GNU extension">, InGroup; -def warn_c2x_compat_typeof_type_specifier : Warning< - "'%select{typeof|typeof_unqual}0' is incompatible with C standards before " - "C2x">, InGroup, DefaultIgnore; def ext_for_range : ExtWarn< "range-based for loop is a C++11 extension">, InGroup; def warn_cxx98_compat_for_range : Warning< @@ -552,7 +553,7 @@ def err_invalid_operator_on_type : Error< def err_expected_unqualified_id : Error< "expected %select{identifier|unqualified-id}0">; def err_while_loop_outside_of_a_function : Error< - "while loop outside of a function">; + "while loop outside of a function">; def err_brackets_go_after_unqualified_id : Error< "brackets are not allowed here; to declare an array, " "place the brackets after the %select{identifier|name}0">; @@ -568,11 +569,11 @@ def err_expected_init_in_condition_lparen : Error< def err_extraneous_rparen_in_condition : Error< "extraneous ')' after condition, expected a statement">; def ext_alias_in_init_statement : ExtWarn< - "alias declaration in this context is a C++2b extension">, - InGroup; + "alias declaration in this context is a C++23 extension">, + InGroup; def warn_cxx20_alias_in_init_statement : Warning< - "alias declaration in this context is incompatible with C++ standards before C++2b">, - DefaultIgnore, InGroup; + "alias declaration in this context is incompatible with C++ standards before C++23">, + DefaultIgnore, InGroup; def warn_dangling_else : Warning< "add explicit braces to avoid dangling else">, InGroup; @@ -654,11 +655,11 @@ def warn_cxx14_compat_constexpr_if : Warning< "constexpr if is incompatible with C++ standards before C++17">, DefaultIgnore, InGroup; def ext_consteval_if : ExtWarn< - "consteval if is a C++2b extension">, - InGroup; + "consteval if is a C++23 extension">, + InGroup; def warn_cxx20_compat_consteval_if : Warning< - "consteval if is incompatible with C++ standards before C++2b">, - InGroup, DefaultIgnore; + "consteval if is incompatible with C++ standards before C++23">, + InGroup, DefaultIgnore; def ext_init_statement : ExtWarn< "'%select{if|switch}0' initialization statements are a C++17 extension">, @@ -704,9 +705,6 @@ def warn_cxx98_compat_nullptr : Warning< "'nullptr' is incompatible with C++98">, InGroup, DefaultIgnore; def ext_c_nullptr : Extension< "'nullptr' is a C2x extension">, InGroup; -def warn_c17_compat_nullptr : Warning< - "'nullptr' is incompatible with C standards before C2x">, - InGroup, DefaultIgnore; def warn_wrong_clang_attr_namespace : Warning< "'__clang__' is a predefined macro name, not an attribute scope specifier; " @@ -721,8 +719,17 @@ def warn_cxx14_compat_ns_enum_attribute : Warning< def warn_cxx98_compat_alignas : Warning<"'alignas' is incompatible with C++98">, InGroup, DefaultIgnore; def warn_cxx98_compat_attribute : Warning< - "C++11 attribute syntax is incompatible with C++98">, + "[[]] attributes are incompatible with C++ standards before C++11">, InGroup, DefaultIgnore; +def warn_ext_cxx11_attributes : Extension< + "[[]] attributes are a C++11 extension">, + InGroup; +def warn_pre_c2x_compat_attributes : Warning< + "[[]] attributes are incompatible with C standards before C2x">, + DefaultIgnore, InGroup; +def warn_ext_c2x_attributes : Extension< + "[[]] attributes are a C2x extension">, + InGroup; def err_cxx11_attribute_forbids_arguments : Error< "attribute %0 cannot have an argument list">; def err_attribute_requires_arguments : Error< @@ -738,10 +745,12 @@ def ext_using_attribute_ns : ExtWarn< def err_using_attribute_ns_conflict : Error< "attribute with scope specifier cannot follow default scope specifier">; def err_attributes_not_allowed : Error<"an attribute list cannot appear here">; +def err_keyword_not_allowed : Error<"%0 cannot appear here">; def ext_cxx11_attr_placement : ExtWarn< - "ISO C++ does not allow an attribute list to appear here">, + "ISO C++ does not allow %select{an attribute list|%0}1 to appear here">, InGroup>; def err_attributes_misplaced : Error<"misplaced attributes; expected attributes here">; +def err_keyword_misplaced : Error<"misplaced %0; expected %0 here">; def err_l_square_l_square_not_attribute : Error< "C++11 only allows consecutive left square brackets when " "introducing an attribute">; @@ -1019,14 +1028,15 @@ def err_lambda_capture_multiple_ellipses : Error< def err_capture_default_first : Error< "capture default must be first">; def ext_decl_attrs_on_lambda : ExtWarn< - "an attribute specifier sequence in this position is a C++2b extension">, - InGroup; + "%select{an attribute specifier sequence|%0}1 in this position " + "is a C++23 extension">, InGroup; def ext_lambda_missing_parens : ExtWarn< - "lambda without a parameter clause is a C++2b extension">, - InGroup; + "lambda without a parameter clause is a C++23 extension">, + InGroup; def warn_cxx20_compat_decl_attrs_on_lambda : Warning< - "an attribute specifier sequence in this position is incompatible with C++ " - "standards before C++2b">, InGroup, DefaultIgnore; + "%select{an attribute specifier sequence|%1}0 in this position " + "is incompatible with C++ standards before C++23">, + InGroup, DefaultIgnore; // C++17 lambda expressions def err_expected_star_this_capture : Error< @@ -1049,12 +1059,12 @@ def warn_cxx17_compat_lambda_template_parameter_list: Warning< def err_lambda_template_parameter_list_empty : Error< "lambda template parameter list cannot be empty">; -// C++2b static lambdas +// C++23 static lambdas def err_static_lambda: ExtWarn< - "static lambdas are a C++2b extension">, InGroup; + "static lambdas are a C++23 extension">, InGroup; def warn_cxx20_compat_static_lambda : Warning< - "static lambdas are incompatible with C++ standards before C++2b">, - InGroup, DefaultIgnore; + "static lambdas are incompatible with C++ standards before C++23">, + InGroup, DefaultIgnore; def err_static_mutable_lambda : Error< "lambda cannot be both mutable and static">; def err_static_lambda_captures : Error< @@ -1104,7 +1114,7 @@ def err_availability_query_repeated_star : Error< // External source symbol attribute def err_external_source_symbol_expected_keyword : Error< - "expected 'language', 'defined_in', or 'generated_declaration'">; + "expected 'language', 'defined_in', 'generated_declaration', or 'USR'">; def err_external_source_symbol_duplicate_clause : Error< "duplicate %0 clause in an 'external_source_symbol' attribute">; @@ -1303,6 +1313,10 @@ def note_pragma_attribute_namespace_on_attribute : Note< def warn_no_support_for_eval_method_source_on_m32 : Warning< "Setting the floating point evaluation method to `source` on a target" " without SSE is not supported.">, InGroup; +// - #pragma __debug +def warn_pragma_debug_dependent_argument : Warning< + "%select{value|type}0-dependent expression passed as an argument to debug " + "command">, InGroup; // OpenCL EXTENSION pragma (OpenCL 1.1 [9.1]) def warn_pragma_expected_colon : Warning< @@ -1358,6 +1372,7 @@ def err_omp_expected_punc_after_iterator : Error< "expected ',' or ')' after iterator specifier">; def err_omp_decl_in_declare_simd_variant : Error< "function declaration is expected after 'declare %select{simd|variant}0' directive">; +def err_omp_sink_and_source_iteration_not_allowd: Error<" '%0 %select{sink:|source:}1' must be with '%select{omp_cur_iteration - 1|omp_cur_iteration}1'">; def err_omp_unknown_map_type : Error< "incorrect map type, expected one of 'to', 'from', 'tofrom', 'alloc', 'release', or 'delete'">; def err_omp_unknown_map_type_modifier : Error< @@ -1369,6 +1384,9 @@ def err_omp_map_type_modifier_missing : Error< "missing map type modifier">; def err_omp_declare_simd_inbranch_notinbranch : Error< "unexpected '%0' clause, '%1' is specified already">; +def err_omp_expected_clause_argument + : Error<"expected '%0' clause with an argument on '#pragma omp %1' " + "construct">; def err_expected_end_declare_target_or_variant : Error< "expected '#pragma omp end declare %select{target|variant}0'">; def err_expected_begin_declare_variant @@ -1520,6 +1538,8 @@ def err_omp_requires_out_inout_depend_type : Error< def warn_omp_more_one_omp_all_memory : Warning< "reserved locator 'omp_all_memory' cannot be specified more than once">, InGroup; +def warn_omp_depend_in_ordered_deprecated : Warning<"'depend' clause for" + " 'ordered' is deprecated; use 'doacross' instead">, InGroup; // Pragma loop support. def err_pragma_loop_missing_argument : Error< @@ -1571,9 +1591,6 @@ def warn_ext_int_deprecated : Warning< def ext_bit_int : Extension< "'_BitInt' in %select{C17 and earlier|C++}0 is a Clang extension">, InGroup>; -def warn_c17_compat_bit_int : Warning< - "'_BitInt' is incompatible with C standards before C2x">, - InGroup, DefaultIgnore; } // end of Parse Issue category. let CategoryName = "Modules Issue" in { @@ -1583,8 +1600,12 @@ def err_module_expected_ident : Error< "expected a module name after '%select{module|import}0'">; def err_attribute_not_module_attr : Error< "%0 attribute cannot be applied to a module">; +def err_keyword_not_module_attr : Error< + "%0 cannot be applied to a module">; def err_attribute_not_import_attr : Error< "%0 attribute cannot be applied to a module import">; +def err_keyword_not_import_attr : Error< + "%0 cannot be applied to a module import">; def err_module_expected_semi : Error< "expected ';' after module name">; def err_global_module_introducer_not_at_start : Error< diff --git a/contrib/llvm-project/clang/include/clang/Basic/DiagnosticSemaKinds.td b/contrib/llvm-project/clang/include/clang/Basic/DiagnosticSemaKinds.td index e4651678603..0c0530f8a11 100644 --- a/contrib/llvm-project/clang/include/clang/Basic/DiagnosticSemaKinds.td +++ b/contrib/llvm-project/clang/include/clang/Basic/DiagnosticSemaKinds.td @@ -83,8 +83,8 @@ def err_typecheck_converted_constant_expression_indirect : Error< "bind reference to a temporary">; def err_expr_not_cce : Error< "%select{case value|enumerator value|non-type template argument|" - "array size|explicit specifier argument|noexcept specifier argument}0 " - "is not a constant expression">; + "array size|explicit specifier argument|noexcept specifier argument|" + "call to 'size()'|call to 'data()'}0 is not a constant expression">; def ext_cce_narrowing : ExtWarn< "%select{case value|enumerator value|non-type template argument|" "array size|explicit specifier argument|noexcept specifier argument}0 " @@ -112,6 +112,9 @@ def err_expr_not_string_literal : Error<"expression is not a string literal">; def ext_predef_outside_function : Warning< "predefined identifier is only valid inside function">, InGroup>; +def ext_init_from_predefined : ExtWarn< + "initializing an array from a '%0' predefined identifier is a Microsoft extension">, + InGroup; def warn_float_overflow : Warning< "magnitude of floating-point constant too large for type %0; maximum is %1">, InGroup; @@ -186,6 +189,8 @@ def warn_initializer_overrides : Warning< "this subobject">, InGroup; def ext_initializer_overrides : ExtWarn, InGroup, SFINAEFailure; +def ext_initializer_union_overrides : ExtWarn, + InGroup, DefaultError, SFINAEFailure; def err_initializer_overrides_destructed : Error< "initializer would partially override prior initialization of object of " "type %1 with non-trivial destruction">; @@ -401,6 +406,11 @@ def warn_reserved_extern_symbol: Warning< "it starts with '_' followed by a capital letter|" "it contains '__'}1">, InGroup, DefaultIgnore; +def warn_deprecated_literal_operator_id: Warning< + "identifier %0 preceded by whitespace in a literal operator declaration " + "is deprecated">, InGroup, DefaultIgnore; +def warn_reserved_module_name : Warning< + "%0 is a reserved name for a module">, InGroup; def warn_parameter_size: Warning< "%0 is a large (%1 bytes) pass-by-value argument; " @@ -426,9 +436,6 @@ def err_ellipsis_first_param : Error< "ISO C requires a named parameter before '...'">; def err_declarator_need_ident : Error<"declarator requires an identifier">; def err_language_linkage_spec_unknown : Error<"unknown linkage language">; -def err_language_linkage_spec_not_ascii : Error< - "string literal in language linkage specifier cannot have an " - "encoding-prefix">; def ext_use_out_of_scope_declaration : ExtWarn< "use of out-of-scope declaration of %0%select{| whose type is not " "compatible with that of an implicit declaration}1">, @@ -443,7 +450,7 @@ def warn_qual_return_type : Warning< def warn_deprecated_redundant_constexpr_static_def : Warning< "out-of-line definition of constexpr static data member is redundant " "in C++17 and is deprecated">, - InGroup, DefaultIgnore; + InGroup, DefaultIgnore; def warn_decl_shadow : Warning<"declaration shadows a %select{" @@ -1538,6 +1545,24 @@ def err_static_assert_requirement_failed : Error< "static assertion failed due to requirement '%0'%select{: %2|}1">; def note_expr_evaluates_to : Note< "expression evaluates to '%0 %1 %2'">; +def err_static_assert_invalid_message : Error< + "the message in a static assertion must be a string literal or an " + "object with 'data()' and 'size()' member functions">; +def err_static_assert_missing_member_function : Error< + "the message object in this static assertion is missing %select{" + "a 'size()' member function|" + "a 'data()' member function|" + "'data()' and 'size()' member functions}0">; +def err_static_assert_invalid_mem_fn_ret_ty : Error< + "the message in a static assertion must have a '%select{size|data}0()' member " + "function returning an object convertible to '%select{std::size_t|const char *}0'">; +def warn_static_assert_message_constexpr : Warning< + "the message in this static assertion is not a " + "constant expression">, + DefaultError, InGroup>; +def err_static_assert_message_constexpr : Error< + "the message in a static assertion must be produced by a " + "constant expression">; def warn_consteval_if_always_true : Warning< "consteval if is always true in an %select{unevaluated|immediate}0 context">, @@ -1554,6 +1579,8 @@ def warn_inline_namespace_reopened_noninline : Warning< InGroup; def err_inline_namespace_mismatch : Error< "non-inline namespace cannot be reopened as inline">; +def err_inline_namespace_std : Error< + "cannot declare the namespace 'std' to be inline">; def err_unexpected_friend : Error< "friends can only be classes or functions">; @@ -2189,6 +2216,8 @@ def err_reference_has_multiple_inits : Error< "reference cannot be initialized with multiple values">; def err_init_non_aggr_init_list : Error< "initialization of non-aggregate type %0 with an initializer list">; +def err_designated_init_for_non_aggregate : Error< + "initialization of non-aggregate type %0 with a designated initializer list">; def err_init_reference_member_uninitialized : Error< "reference member of type %0 uninitialized">; def note_uninit_reference_member : Note< @@ -2311,8 +2340,6 @@ def err_auto_variable_cannot_appear_in_own_initializer : Error< def err_binding_cannot_appear_in_own_initializer : Error< "binding %0 cannot appear in the initializer of its own " "decomposition declaration">; -def err_illegal_decl_array_of_auto : Error< - "'%0' declared as array of %1">; def err_new_array_of_auto : Error< "cannot allocate array of 'auto'">; def err_auto_not_allowed : Error< @@ -2368,7 +2395,7 @@ def err_auto_expr_init_paren_braces : Error< "%select{parenthesized|nested}0 initializer list">; def warn_cxx20_compat_auto_expr : Warning< "'auto' as a functional-style cast is incompatible with C++ standards " - "before C++2b">, InGroup, DefaultIgnore; + "before C++23">, InGroup, DefaultIgnore; def err_auto_missing_trailing_return : Error< "'auto' return without trailing return type; deduced return types are a " "C++14 extension">; @@ -2649,12 +2676,26 @@ def warn_cxx14_compat_constexpr_not_const : Warning< "in C++14; add 'const' to avoid a change in behavior">, InGroup>; def err_invalid_consteval_take_address : Error< - "cannot take address of consteval function %0 outside" + "cannot take address of %select{immediate|consteval}2 " + "%select{function|call operator of}1 %0 outside" " of an immediate invocation">; def err_invalid_consteval_call : Error< - "call to consteval function %q0 is not a constant expression">; + "call to %select{immediate|consteval}1 function " + "%q0 is not a constant expression">; + +def err_immediate_function_used_before_definition : Error< + "immediate function %0 used before it is defined">; + +def note_immediate_function_reason : Note< + "%0 is an immediate %select{function|constructor}5 because " + "%select{its body|the%select{| default}7 initializer of %8}6 " + "%select{evaluates the address of %select{an immediate|a consteval}2 " + "function %1|contains a call to %select{an immediate|a consteval}2 " + "%select{function|constructor}4 %1 and that call is not a constant " + "expression}3">; + def note_invalid_consteval_initializer : Note< - "in the default initalizer of %0">; + "in the default initializer of %0">; def note_invalid_consteval_initializer_here : Note< "initialized here %0">; def err_invalid_consteval_decl_kind : Error< @@ -2665,7 +2706,7 @@ def err_invalid_constexpr : Error< def err_invalid_constexpr_member : Error<"non-static data member cannot be " "constexpr%select{; did you intend to make it %select{const|static}0?|}1">; def err_constexpr_tag : Error< - "%select{class|struct|interface|union|enum}0 " + "%select{class|struct|interface|union|enum|enum class|enum struct}0 " "cannot be marked %sub{select_constexpr_spec_kind}1">; def err_constexpr_dtor : Error< "destructor cannot be declared %sub{select_constexpr_spec_kind}0">; @@ -2725,13 +2766,13 @@ def warn_cxx17_compat_constexpr_body_invalid_stmt : Warning< "use of this statement in a constexpr %select{function|constructor}0 " "is incompatible with C++ standards before C++20">, InGroup, DefaultIgnore; -def ext_constexpr_body_invalid_stmt_cxx2b : ExtWarn< +def ext_constexpr_body_invalid_stmt_cxx23 : ExtWarn< "use of this statement in a constexpr %select{function|constructor}0 " - "is a C++2b extension">, InGroup; + "is a C++23 extension">, InGroup; def warn_cxx20_compat_constexpr_body_invalid_stmt : Warning< "use of this statement in a constexpr %select{function|constructor}0 " - "is incompatible with C++ standards before C++2b">, - InGroup, DefaultIgnore; + "is incompatible with C++ standards before C++23">, + InGroup, DefaultIgnore; def ext_constexpr_type_definition : ExtWarn< "type definition in a constexpr %select{function|constructor}0 " "is a C++14 extension">, InGroup; @@ -2752,15 +2793,15 @@ def warn_cxx11_compat_constexpr_local_var : Warning< def ext_constexpr_static_var : ExtWarn< "definition of a %select{static|thread_local}1 variable " "in a constexpr %select{function|constructor}0 " - "is a C++2b extension">, InGroup; + "is a C++23 extension">, InGroup; def warn_cxx20_compat_constexpr_var : Warning< "definition of a %select{static variable|thread_local variable|variable " "of non-literal type}1 in a constexpr %select{function|constructor}0 " - "is incompatible with C++ standards before C++2b">, - InGroup, DefaultIgnore; + "is incompatible with C++ standards before C++23">, + InGroup, DefaultIgnore; def err_constexpr_local_var_non_literal_type : Error< "variable of non-literal type %1 cannot be defined in a constexpr " - "%select{function|constructor}0 before C++2b">; + "%select{function|constructor}0 before C++23">; def ext_constexpr_local_var_no_init : ExtWarn< "uninitialized variable in a constexpr %select{function|constructor}0 " "is a C++20 extension">, InGroup; @@ -2961,6 +3002,10 @@ def warn_attribute_ignored_no_calls_in_stmt: Warning< "statement">, InGroup; +def warn_attribute_ignored_non_function_pointer: Warning< + "%0 attribute is ignored because %1 is not a function pointer">, + InGroup; + def warn_function_attribute_ignored_in_stmt : Warning< "attribute is ignored on this statement as it only applies to functions; " "use '%0' on statements">, @@ -3015,7 +3060,7 @@ def err_musttail_no_variadic : Error< def err_nsobject_attribute : Error< "'NSObject' attribute is for pointer types only">; def err_attributes_are_not_compatible : Error< - "%0 and %1 attributes are not compatible">; + "%0 and %1%select{ attributes|}2 are not compatible">; def err_attribute_invalid_argument : Error< "%select{a reference type|an array type|a non-vector or " "non-vectorizable scalar type}0 is an invalid argument to attribute %1">; @@ -3054,6 +3099,14 @@ def err_attribute_arm_feature_sve_bits_unsupported : Error< "value of 128, 256, 512, 1024 or 2048.">; def err_sve_vector_in_non_sve_target : Error< "SVE vector type %0 cannot be used in a target without sve">; +def err_attribute_riscv_rvv_bits_unsupported : Error< + "%0 is only supported when '-mrvv-vector-bits=' is specified with a " + "value of \"zvl\" or a power 2 in the range [64,65536]">; +def err_attribute_bad_rvv_vector_size : Error< + "invalid RVV vector size '%0', expected size is '%1' based on LMUL of type " + "and '-mrvv-vector-bits'">; +def err_attribute_invalid_rvv_type : Error< + "%0 attribute applied to non-RVV type %1">; def err_attribute_requires_positive_integer : Error< "%0 attribute requires a %select{positive|non-negative}1 " "integral compile time constant expression">; @@ -3164,10 +3217,11 @@ def err_attribute_invalid_size : Error< "vector size not an integral multiple of component size">; def err_attribute_zero_size : Error<"zero %0 size">; def err_attribute_size_too_large : Error<"%0 size too large">; -def err_typecheck_sve_ambiguous : Error< - "cannot combine fixed-length and sizeless SVE vectors in expression, result is ambiguous (%0 and %1)">; -def err_typecheck_sve_gnu_ambiguous : Error< - "cannot combine GNU and SVE vectors in expression, result is ambiguous (%0 and %1)">; +def err_typecheck_sve_rvv_ambiguous : Error< + "cannot combine fixed-length and sizeless %select{SVE|RVV}0 vectors " + "in expression, result is ambiguous (%1 and %2)">; +def err_typecheck_sve_rvv_gnu_ambiguous : Error< + "cannot combine GNU and %select{SVE|RVV}0 vectors in expression, result is ambiguous (%1 and %2)">; def err_typecheck_vector_not_convertable_implict_truncation : Error< "cannot convert between %select{scalar|vector}0 type %1 and vector type" " %2 as implicit conversion would cause truncation">; @@ -3414,16 +3468,20 @@ def warn_attribute_has_no_effect_on_compile_time_if : Warning< def note_attribute_has_no_effect_on_compile_time_if_here : Note< "annotating the 'if %select{constexpr|consteval}0' statement here">; def err_decl_attribute_invalid_on_stmt : Error< - "%0 attribute cannot be applied to a statement">; + "%0%select{ attribute|}1 cannot be applied to a statement">; def err_attribute_invalid_on_decl : Error< - "%0 attribute cannot be applied to a declaration">; + "%0%select{ attribute|}1 cannot be applied to a declaration">; def warn_type_attribute_deprecated_on_decl : Warning< "applying attribute %0 to a declaration is deprecated; apply it to the type instead">, InGroup; def warn_declspec_attribute_ignored : Warning< "attribute %0 is ignored, place it after " - "\"%select{class|struct|interface|union|enum}1\" to apply attribute to " + "\"%select{class|struct|interface|union|enum|enum class|enum struct}1\" to apply attribute to " "type declaration">, InGroup; +def err_declspec_keyword_has_no_effect : Error< + "%0 cannot appear here, place it after " + "\"%select{class|struct|interface|union|enum}1\" to apply it to the " + "type declaration">; def warn_attribute_precede_definition : Warning< "attribute declaration must precede definition">, InGroup; @@ -3522,11 +3580,11 @@ def err_attribute_weakref_without_alias : Error< def err_alias_not_supported_on_darwin : Error < "aliases are not supported on darwin">; def warn_attribute_wrong_decl_type_str : Warning< - "%0 attribute only applies to %1">, InGroup; + "%0%select{ attribute|}1 only applies to %2">, InGroup; def err_attribute_wrong_decl_type_str : Error< warn_attribute_wrong_decl_type_str.Summary>; def warn_attribute_wrong_decl_type : Warning< - "%0 attribute only applies to %select{" + "%0%select{ attribute|}1 only applies to %select{" "functions" "|unions" "|variables and functions" @@ -3539,13 +3597,15 @@ def warn_attribute_wrong_decl_type : Warning< "|types and namespaces" "|variables, functions and classes" "|kernel functions" - "|non-K&R-style functions}1">, + "|non-K&R-style functions}2">, InGroup; def err_attribute_wrong_decl_type : Error; def warn_type_attribute_wrong_type : Warning< "'%0' only applies to %select{function|pointer|" "Objective-C object or block pointer}1 types; type here is %2">, InGroup; +def err_type_attribute_wrong_type : Error< + warn_type_attribute_wrong_type.Summary>; def warn_incomplete_encoded_type : Warning< "encoding of %0 type is incomplete because %1 component has unknown encoding">, InGroup>; @@ -3596,7 +3656,7 @@ def err_invalid_pcs : Error<"invalid PCS type">; def warn_attribute_not_on_decl : Warning< "%0 attribute ignored when parsing type">, InGroup; def err_base_specifier_attribute : Error< - "%0 attribute cannot be applied to a base specifier">; + "%0%select{ attribute|}1 cannot be applied to a base specifier">; def warn_declspec_allocator_nonpointer : Warning< "ignoring __declspec(allocator) because the function return type %0 is not " "a pointer or reference type">, InGroup; @@ -4661,9 +4721,6 @@ def note_ovl_candidate_bad_cvr : Note< "%select{const|restrict|const and restrict|volatile|const and volatile|" "volatile and restrict|const, volatile, and restrict}4 qualifier" "%select{||s||s|s|s}4">; -def note_ovl_candidate_bad_unaligned : Note< - "candidate %sub{select_ovl_candidate_kind}0,1,2 not viable: " - "%ordinal5 argument (%3) would lose __unaligned qualifier">; def note_ovl_candidate_bad_base_to_derived_conv : Note< "candidate %sub{select_ovl_candidate_kind}0,1,2 not viable: " "cannot %select{convert from|convert from|bind}3 " @@ -4678,6 +4735,8 @@ def note_ovl_candidate_bad_target : Note< def note_ovl_candidate_constraints_not_satisfied : Note< "candidate %sub{select_ovl_candidate_kind}0,1,2 not viable: constraints " "not satisfied">; +def note_ovl_surrogate_constraints_not_satisfied : Note< + "conversion candidate %0 not viable: constraints not satisfied">; def note_implicit_member_target_infer_collision : Note< "implicit %sub{select_special_member_kind}0 inferred target collision: call to both " "%select{__device__|__global__|__host__|__host__ __device__}1 and " @@ -5314,6 +5373,8 @@ def note_constraint_normalization_here : Note< def note_parameter_mapping_substitution_here : Note< "while substituting into concept arguments here; substitution failures not " "allowed in concept arguments">; +def note_lambda_substitution_here : Note< + "while substituting into a lambda expression here">; def note_instantiation_contexts_suppressed : Note< "(skipping %0 context%s0 in backtrace; use -ftemplate-backtrace-limit=0 to " "see all)">; @@ -5472,10 +5533,10 @@ def note_template_kw_refers_to_non_template : Note< def err_template_kw_refers_to_dependent_non_template : Error< "%0%select{| following the 'template' keyword}1 " "cannot refer to a dependent template">; -def err_template_kw_refers_to_class_template : Error< - "'%0%1' instantiated to a class template, not a function template">; -def note_referenced_class_template : Note< - "class template declared here">; +def err_template_kw_refers_to_type_template : Error< + "'%0%1' is expected to be a non-type template, but instantiated to a %select{class|type alias}2 template">; +def note_referenced_type_template : Note< + "%select{class|type alias}0 template declared here">; def err_template_kw_missing : Error< "missing 'template' keyword prior to dependent template name '%0%1'">; def ext_template_outside_of_template : ExtWarn< @@ -6161,6 +6222,8 @@ def note_enters_block_captures_non_trivial_c_struct : Note< "to destroy">; def note_enters_compound_literal_scope : Note< "jump enters lifetime of a compound literal that is non-trivial to destruct">; +def note_enters_statement_expression : Note< + "jump enters a statement expression">; def note_exits_cleanup : Note< "jump exits scope of variable with __attribute__((cleanup))">; @@ -6733,7 +6796,7 @@ def err_arithmetic_nonfragile_interface : Error< def warn_deprecated_comma_subscript : Warning< "top-level comma expression in array subscript is deprecated " - "in C++20 and unsupported in C++2b">, + "in C++20 and unsupported in C++23">, InGroup; def ext_subscript_non_lvalue : Extension< @@ -6927,7 +6990,7 @@ def warn_standalone_specifier : Warning<"'%0' ignored on this declaration">, def ext_standalone_specifier : ExtWarn<"'%0' is not permitted on a declaration " "of a type">, InGroup; def err_standalone_class_nested_name_specifier : Error< - "forward declaration of %select{class|struct|interface|union|enum}0 cannot " + "forward declaration of %select{class|struct|interface|union|enum|enum class|enum struct}0 cannot " "have a nested name specifier">; def err_typecheck_sclass_func : Error<"illegal storage class on function">; def err_static_block_func : Error< @@ -6963,9 +7026,8 @@ def err_typecheck_indirection_requires_pointer : Error< def ext_typecheck_indirection_through_void_pointer : ExtWarn< "ISO C does not allow indirection on operand of type %0">, InGroup; -def ext_typecheck_indirection_through_void_pointer_cpp - : ExtWarn<"ISO C++ does not allow indirection on operand of type %0">, - InGroup, DefaultError, SFINAEFailure; +def err_typecheck_indirection_through_void_pointer_cpp + : Error<"indirection not permitted on operand of type %0">; def warn_indirection_through_null : Warning< "indirection of non-volatile null pointer will be deleted, not trap">, InGroup; @@ -7386,6 +7448,8 @@ def err_attribute_arm_builtin_alias : Error< "'__clang_arm_builtin_alias' attribute can only be applied to an ARM builtin">; def err_attribute_arm_mve_polymorphism : Error< "'__clang_arm_mve_strict_polymorphism' attribute can only be applied to an MVE/NEON vector type">; +def err_attribute_webassembly_funcref : Error< + "'__funcref' attribute can only be applied to a function pointer type">; def warn_setter_getter_impl_required : Warning< "property %0 requires method %1 to be defined - " @@ -7636,7 +7700,7 @@ def warn_increment_bool : Warning< "incompatible with C++17">, InGroup; def ext_increment_bool : ExtWarn< "ISO C++17 does not allow incrementing expression of type bool">, - DefaultError, InGroup; + DefaultError, SFINAEFailure, InGroup; def err_increment_decrement_enum : Error< "cannot %select{decrement|increment}0 expression of enum type %1">; @@ -7907,7 +7971,7 @@ let CategoryName = "Lambda Issue" in { "is a C++20 extension">, InGroup; def warn_deprecated_this_capture : Warning< "implicit capture of 'this' with a capture default of '=' is deprecated">, - InGroup, DefaultIgnore; + InGroup; def note_deprecated_this_capture : Note< "add an explicit capture of 'this' to capture '*this' by reference">; @@ -8504,6 +8568,9 @@ def err_atomic_op_needs_atomic_int_ptr_or_fp : Error< def err_atomic_op_needs_atomic_int_or_ptr : Error< "address argument to atomic operation must be a pointer to %select{|atomic }0" "integer or pointer (%1 invalid)">; +def err_atomic_op_needs_atomic_int_or_fp : Error< + "address argument to atomic operation must be a pointer to %select{|atomic }0" + "integer or supported floating point type (%1 invalid)">; def err_atomic_op_needs_atomic_int : Error< "address argument to atomic operation must be a pointer to " "%select{|atomic }0integer (%1 invalid)">; @@ -8631,6 +8698,10 @@ def note_cuda_device_builtin_surftex_should_be_template_class : Note< def err_hip_invalid_args_builtin_mangled_name : Error< "invalid argument: symbol must be a device-side function or global variable">; +def warn_hip_omp_target_directives : Warning< + "HIP does not support OpenMP target directives; directive has been ignored">, + InGroup, DefaultError; + def warn_non_pod_vararg_with_format_string : Warning< "cannot pass %select{non-POD|non-trivial}0 object of type %1 to variadic " "%select{function|block|method|constructor}2; expected type from format " @@ -8724,8 +8795,6 @@ def err_cast_pointer_to_non_pointer_int : Error< def err_nullptr_cast : Error< "cannot cast an object of type %select{'nullptr_t' to %1|%1 to 'nullptr_t'}0" >; -def err_cast_to_bfloat16 : Error<"cannot type-cast to __bf16">; -def err_cast_from_bfloat16 : Error<"cannot type-cast from __bf16">; def err_typecheck_expect_scalar_operand : Error< "operand of type %0 where arithmetic or pointer type is required">; def err_typecheck_cond_incompatible_operands : Error< @@ -9131,9 +9200,9 @@ def err_operator_overload_needs_class_or_enum : Error< def err_operator_overload_variadic : Error<"overloaded %0 cannot be variadic">; def warn_cxx20_compat_operator_overload_static : Warning< "declaring overloaded %0 as 'static' is incompatible with C++ standards " - "before C++2b">, InGroup, DefaultIgnore; + "before C++23">, InGroup, DefaultIgnore; def ext_operator_overload_static : ExtWarn< - "declaring overloaded %0 as 'static' is a C++2b extension">, InGroup; + "declaring overloaded %0 as 'static' is a C++23 extension">, InGroup; def err_operator_overload_static : Error< "overloaded %0 cannot be a static member function">; def err_operator_overload_default_arg : Error< @@ -9141,9 +9210,9 @@ def err_operator_overload_default_arg : Error< def ext_subscript_overload : Warning< "overloaded %0 with %select{no|a defaulted|more than one}1 parameter is a " - "C++2b extension">, InGroup, DefaultIgnore; + "C++23 extension">, InGroup, DefaultIgnore; def error_subscript_overload : Error< - "overloaded %0 cannot have %select{no|a defaulted|more than one}1 parameter before C++2b">; + "overloaded %0 cannot have %select{no|a defaulted|more than one}1 parameter before C++23">; def err_operator_overload_must_be : Error< "overloaded %0 must be a %select{unary|binary|unary or binary}2 operator " @@ -9220,8 +9289,8 @@ def ext_string_literal_operator_template : ExtWarn< "string literal operator templates are a GNU extension">, InGroup; def warn_user_literal_reserved : Warning< - "user-defined literal suffixes not starting with '_' are reserved" - "%select{; no literal will invoke this operator|}0">, + "user-defined literal suffixes %select{|not starting with '_'|containing '__'}0 are reserved" + "%select{; no literal will invoke this operator|}1">, InGroup; // C++ conversion functions @@ -9409,12 +9478,21 @@ def note_defaulted_comparison_cannot_deduce_undeduced_auto : Note< "%select{|member|base class}0 %1 declared here">; def note_defaulted_comparison_cannot_deduce_callee : Note< "selected 'operator<=>' for %select{|member|base class}0 %1 declared here">; -def err_incorrect_defaulted_comparison_constexpr : Error< +def ext_defaulted_comparison_constexpr_mismatch : Extension< "defaulted definition of %select{%sub{select_defaulted_comparison_kind}1|" - "three-way comparison operator}0 " - "cannot be declared %select{constexpr|consteval}2 because " - "%select{it|the corresponding implicit 'operator=='}0 " - "invokes a non-constexpr comparison function">; + "three-way comparison operator}0 that is " + "declared %select{constexpr|consteval}2 but" + "%select{|for which the corresponding implicit 'operator==' }0 " + "invokes a non-constexpr comparison function is a C++23 extension">, + InGroup>; +def warn_cxx23_compat_defaulted_comparison_constexpr_mismatch : Warning< + "defaulted definition of %select{%sub{select_defaulted_comparison_kind}1|" + "three-way comparison operator}0 that is " + "declared %select{constexpr|consteval}2 but" + "%select{|for which the corresponding implicit 'operator==' }0 " + "invokes a non-constexpr comparison function is incompatible with C++ " + "standards before C++23">, + InGroup, DefaultIgnore; def note_defaulted_comparison_not_constexpr : Note< "non-constexpr comparison function would be used to compare " "%select{|member %1|base class %1}0">; @@ -9423,6 +9501,10 @@ def note_defaulted_comparison_not_constexpr_here : Note< def note_in_declaration_of_implicit_equality_comparison : Note< "while declaring the corresponding implicit 'operator==' " "for this defaulted 'operator<=>'">; +def err_volatile_comparison_operator : Error< + "defaulted comparison function must not be volatile">; +def err_ref_qualifier_comparison_operator : Error< + "ref-qualifier '&&' is not allowed on a defaulted comparison operator">; def ext_implicit_exception_spec_mismatch : ExtWarn< "function previously declared with an %select{explicit|implicit}0 exception " @@ -9606,7 +9688,7 @@ def note_lambda_capture_initializer : Note< "%select{implicitly |}2captured%select{| by reference}3" "%select{%select{ due to use|}2 here|" " via initialization of lambda capture %0}1">; -def note_init_with_default_member_initalizer : Note< +def note_init_with_default_member_initializer : Note< "initializing field %0 with default member initializer">; // Check for initializing a member variable with the address or a reference to @@ -10022,12 +10104,6 @@ def err_mips_builtin_requires_dspr2 : Error< "this builtin requires 'dsp r2' ASE, please use -mdspr2">; def err_mips_builtin_requires_msa : Error< "this builtin requires 'msa' ASE, please use -mmsa">; -def err_ppc_builtin_only_on_arch : Error< - "this builtin is only valid on POWER%0 or later CPUs">; -def err_ppc_builtin_requires_vsx : Error< - "this builtin requires VSX to be enabled">; -def err_ppc_builtin_requires_htm : Error< - "this builtin requires HTM to be enabled">; def err_ppc_builtin_requires_abi : Error< "this builtin requires ABI -mabi=%0">; def err_ppc_invalid_use_mma_type : Error< @@ -10464,6 +10540,9 @@ def err_omp_lastprivate_incomplete_type : Error< "a lastprivate variable with incomplete type %0">; def err_omp_reduction_incomplete_type : Error< "a reduction list item with incomplete type %0">; +def warn_omp_minus_in_reduction_deprecated : Warning< + "minus(-) operator for reductions is deprecated; use + or user defined reduction instead">, + InGroup; def err_omp_unexpected_clause_value : Error< "expected %0 in OpenMP clause '%1'">; def err_omp_unexpected_call_to_omp_runtime_api @@ -10628,9 +10707,12 @@ def err_omp_simd_region_cannot_use_stmt : Error< def warn_omp_loop_64_bit_var : Warning< "OpenMP loop iteration variable cannot have more than 64 bits size and will be narrowed">, InGroup; -def err_omp_unknown_reduction_identifier : Error< +def err_omp_unknown_reduction_identifier_prior_omp_6_0 : Error< "incorrect reduction identifier, expected one of '+', '-', '*', '&', '|', '^', " "'&&', '||', 'min' or 'max' or declare reduction for type %0">; +def err_omp_unknown_reduction_identifier_since_omp_6_0 : Error< + "incorrect reduction identifier, expected one of '+', '*', '&', '|', '^', " + "'&&', '||', 'min' or 'max' or declare reduction for type %0">; def err_omp_not_resolved_reduction_identifier : Error< "unable to resolve declare reduction construct for type %0">; def err_omp_reduction_ref_type_arg : Error< @@ -10814,7 +10896,7 @@ def note_omp_previous_named_if_clause : Note< def err_omp_ordered_directive_with_param : Error< "'ordered' directive %select{without any clauses|with 'threads' clause}0 cannot be closely nested inside ordered region with specified parameter">; def err_omp_ordered_directive_without_param : Error< - "'ordered' directive with 'depend' clause cannot be closely nested inside ordered region without specified parameter">; + "'ordered' directive with '%0' clause cannot be closely nested inside ordered region without specified parameter">; def note_omp_ordered_param : Note< "'ordered' clause%select{| with specified parameter}0">; def err_omp_expected_base_var_name : Error< @@ -10846,7 +10928,7 @@ def note_omp_critical_hint_here : Note< def note_omp_critical_no_hint : Note< "%select{|previous }0directive with no 'hint' clause specified">; def err_omp_depend_clause_thread_simd : Error< - "'depend' clauses cannot be mixed with '%0' clause">; + "'%0' clauses cannot be mixed with '%1' clause">; def err_omp_depend_sink_expected_loop_iteration : Error< "expected%select{| %1}0 loop iteration variable">; def err_omp_depend_sink_unexpected_expr : Error< @@ -10855,8 +10937,8 @@ def err_omp_depend_sink_expected_plus_minus : Error< "expected '+' or '-' operation">; def err_omp_taskwait_depend_mutexinoutset_not_allowed : Error< "'mutexinoutset' modifier not allowed in 'depend' clause on 'taskwait' directive">; -def err_omp_depend_sink_source_not_allowed : Error< - "'depend(%select{source|sink:vec}0)' clause%select{|s}0 cannot be mixed with 'depend(%select{sink:vec|source}0)' clause%select{s|}0">; +def err_omp_sink_and_source_not_allowed : Error< + "'%0(%select{source|sink:vec}1)' clause%select{|s}1 cannot be mixed with '%0(%select{sink:vec|source}1)' clause%select{s|}1">; def err_omp_depend_zero_length_array_section_not_allowed : Error< "zero-length array section is not allowed in 'depend' clause">; def err_omp_depend_sink_source_with_modifier : Error< @@ -11209,30 +11291,18 @@ def note_global_module_introducer_missing : Note< def err_export_within_anonymous_namespace : Error< "export declaration appears within anonymous namespace">; def note_anonymous_namespace : Note<"anonymous namespace begins here">; -def ext_export_no_name_block : ExtWarn< - "ISO C++20 does not permit %select{an empty|a static_assert}0 declaration " - "to appear in an export block">, InGroup; -def ext_export_no_names : ExtWarn< - "ISO C++20 does not permit a declaration that does not introduce any names " - "to be exported">, InGroup; -def introduces_no_names : Error< - "declaration does not introduce any names to be exported">; def note_export : Note<"export block begins here">; -def err_export_no_name : Error< - "%select{empty|static_assert|asm}0 declaration cannot be exported">; -def ext_export_using_directive : ExtWarn< - "ISO C++20 does not permit using directive to be exported">, - InGroup>; def err_export_within_export : Error< "export declaration appears within another export declaration">; +def err_export_anon_ns_internal : Error< + "anonymous namespaces cannot be exported">; def err_export_internal : Error< "declaration of %0 with internal linkage cannot be exported">; def err_export_using_internal : Error< "using declaration referring to %1 with %select{internal|module|unknown}0 " "linkage cannot be exported">; def err_export_not_in_module_interface : Error< - "export declaration can only be used within a module interface unit" - "%select{ after the module declaration|}0">; + "export declaration can only be used within a module purview">; def err_export_inline_not_defined : Error< "inline function not defined%select{| before the private module fragment}0">; def err_export_partition_impl : Error< @@ -11249,11 +11319,14 @@ def err_private_module_fragment_not_module_interface : Error< "private module fragment in module implementation unit">; def note_not_module_interface_add_export : Note< "add 'export' here if this is intended to be a module interface unit">; -def err_invalid_module_name : Error< - "%0 is %select{an invalid|a reserved}1 name for a module">; +def err_invalid_module_name : Error<"%0 is an invalid name for a module">; def err_extern_def_in_header_unit : Error< "non-inline external definitions are not permitted in C++ header units">; +def warn_experimental_header_unit : Warning< + "the implementation of header units is in an experimental phase">, + InGroup>; + def ext_equivalent_internal_linkage_decl_in_modules : ExtWarn< "ambiguous use of internal linkage declaration %0 defined in multiple modules">, InGroup>; @@ -11286,15 +11359,7 @@ def err_coroutine_invalid_func_context : Error< "|a consteval function}0">; def err_implied_coroutine_type_not_found : Error< "%0 type was not found; include before defining " - "a coroutine; include if your version " - "of libcxx is less than 14.0">; -def warn_deprecated_coroutine_namespace : Warning< - "support for 'std::experimental::%0' will be removed in Clang 17; " - "use 'std::%0' instead">, - InGroup; -def err_mixed_use_std_and_experimental_namespace_for_coroutine : Error< - "conflicting mixed use of std and std::experimental namespaces for " - "coroutine components">; + "a coroutine">; def err_implicit_coroutine_std_nothrow_type_not_found : Error< "std::nothrow was not found; include before defining a coroutine which " "uses get_return_object_on_allocation_failure()">; @@ -11378,6 +11443,8 @@ def err_coro_invalid_addr_of_label : Error< let CategoryName = "Documentation Issue" in { def warn_not_a_doxygen_trailing_member_comment : Warning< "not a Doxygen trailing comment">, InGroup, DefaultIgnore; +def warn_splice_in_doxygen_comment : Warning< + "line splicing in Doxygen comments are not supported">, InGroup, DefaultIgnore; } // end of documentation issue category let CategoryName = "Nullability Issue" in { @@ -11509,6 +11576,10 @@ def err_objc_type_args_wrong_arity : Error< "too %select{many|few}0 type arguments for class %1 (have %2, expected %3)">; } +def err_type_available_only_in_default_eval_method : Error< + "cannot use type '%0' within '#pragma clang fp eval_method'; type is set " + "according to the default eval method for the translation unit">; + def err_objc_type_arg_not_id_compatible : Error< "type argument %0 is neither an Objective-C object nor a block type">; @@ -11740,6 +11811,9 @@ def err_riscv_builtin_requires_extension : Error< "builtin requires%select{| at least one of the following extensions to be enabled}0: %1">; def err_riscv_builtin_invalid_lmul : Error< "LMUL argument must be in the range [0,3] or [5,7]">; +def err_riscv_type_requires_extension : Error< + "RISC-V type %0 requires the '%1' extension" +>; def err_std_source_location_impl_not_found : Error< "'std::source_location::__impl' was not found; it must be defined before '__builtin_source_location' is called">; @@ -11752,6 +11826,8 @@ def err_hlsl_attr_invalid_type : Error< "attribute %0 only applies to a field or parameter of type '%1'">; def err_hlsl_attr_invalid_ast_node : Error< "attribute %0 only applies to %1">; +def err_hlsl_entry_shader_attr_mismatch : Error< + "%0 attribute on entry function does not match the pipeline stage">; def err_hlsl_numthreads_argument_oor : Error<"argument '%select{X|Y|Z}0' to numthreads attribute cannot exceed %1">; def err_hlsl_numthreads_invalid : Error<"total number of threads cannot exceed %0">; def err_hlsl_missing_numthreads : Error<"missing numthreads attribute for %0 shader entry">; @@ -11788,10 +11864,56 @@ def warn_unsafe_buffer_variable : Warning< InGroup, DefaultIgnore; def warn_unsafe_buffer_operation : Warning< "%select{unsafe pointer operation|unsafe pointer arithmetic|" - "unsafe buffer access}0">, + "unsafe buffer access|function introduces unsafe buffer manipulation}0">, InGroup, DefaultIgnore; def note_unsafe_buffer_operation : Note< "used%select{| in pointer arithmetic| in buffer access}0 here">; +def note_unsafe_buffer_variable_fixit_group : Note< + "change type of %0 to '%select{std::span|std::array|std::span::iterator}1' to preserve bounds information%select{|, and change %2 to '%select{std::span|std::array|std::span::iterator}1' to propagate bounds information between them}3">; +def note_safe_buffer_usage_suggestions_disabled : Note< + "pass -fsafe-buffer-usage-suggestions to receive code hardening suggestions">; def err_loongarch_builtin_requires_la32 : Error< "this builtin requires target: loongarch32">; + +def err_builtin_pass_in_regs_non_class : Error< + "argument %0 is not an unqualified class type">; + + +// WebAssembly reference type and table diagnostics. +def err_wasm_reference_pr : Error< + "%select{pointer|reference}0 to WebAssembly reference type is not allowed">; +def err_wasm_ca_reference : Error< + "cannot %select{capture|take address of}0 WebAssembly reference">; +def err_wasm_funcref_not_wasm : Error< + "invalid use of '__funcref' keyword outside the WebAssembly triple">; +def err_wasm_table_pr : Error< + "cannot form a %select{pointer|reference}0 to a WebAssembly table">; +def err_typecheck_wasm_table_must_have_zero_length : Error< + "only zero-length WebAssembly tables are currently supported">; +def err_wasm_table_in_function : Error< + "WebAssembly table cannot be declared within a function">; +def err_wasm_table_as_function_parameter : Error< + "cannot use WebAssembly table as a function parameter">; +def err_wasm_table_invalid_uett_operand : Error< + "invalid application of '%0' to WebAssembly table">; +def err_wasm_cast_table : Error< + "cannot cast %select{to|from}0 a WebAssembly table">; +def err_wasm_table_conditional_expression : Error< + "cannot use a WebAssembly table within a branch of a conditional expression">; +def err_wasm_table_art : Error< + "cannot %select{assign|return|throw|subscript}0 a WebAssembly table">; +def err_wasm_reftype_tc : Error< + "cannot %select{throw|catch}0 a WebAssembly reference type">; +def err_wasm_reftype_exception_spec : Error< + "WebAssembly reference type not allowed in exception specification">; +def err_wasm_table_must_be_static : Error< + "WebAssembly table must be static">; +def err_wasm_reftype_multidimensional_array : Error< + "multi-dimensional arrays of WebAssembly references are not allowed">; +def err_wasm_builtin_arg_must_be_table_type : Error < + "%ordinal0 argument must be a WebAssembly table">; +def err_wasm_builtin_arg_must_match_table_element_type : Error < + "%ordinal0 argument must match the element type of the WebAssembly table in the %ordinal1 argument">; +def err_wasm_builtin_arg_must_be_integer_type : Error < + "%ordinal0 argument must be an integer">; } // end of sema component. diff --git a/contrib/llvm-project/clang/include/clang/Basic/DiagnosticSerializationKinds.td b/contrib/llvm-project/clang/include/clang/Basic/DiagnosticSerializationKinds.td index f515ea0d9f6..5197aa16c4a 100644 --- a/contrib/llvm-project/clang/include/clang/Basic/DiagnosticSerializationKinds.td +++ b/contrib/llvm-project/clang/include/clang/Basic/DiagnosticSerializationKinds.td @@ -75,6 +75,7 @@ def note_module_file_conflict : Note< def remark_module_import : Remark< "importing module '%0'%select{| into '%3'}2 from '%1'">, + ShowInSystemHeader, InGroup; def err_imported_module_not_found : Error< @@ -127,6 +128,16 @@ def warn_module_system_bit_conflict : Warning< "module file '%0' was validated as a system module and is now being imported " "as a non-system module; any difference in diagnostic options will be ignored">, InGroup; + +def warn_eagerly_load_for_standard_cplusplus_modules : Warning< + "the form '-fmodule-file=' is deprecated for standard C++ named modules;" + "consider to use '-fmodule-file==' instead">, + InGroup>; + +def warn_reading_std_cxx_module_by_implicit_paths : Warning< + "it is deprecated to read module '%0' implicitly; it is going to be removed in clang 18; " + "consider to specify the dependencies explicitly">, + InGroup>; } // let CategoryName let CategoryName = "AST Serialization Issue" in { diff --git a/contrib/llvm-project/clang/include/clang/Basic/DirectoryEntry.h b/contrib/llvm-project/clang/include/clang/Basic/DirectoryEntry.h index 6c8da121365..5d083e68fac 100644 --- a/contrib/llvm-project/clang/include/clang/Basic/DirectoryEntry.h +++ b/contrib/llvm-project/clang/include/clang/Basic/DirectoryEntry.h @@ -46,6 +46,7 @@ class DirectoryEntry { StringRef Name; // Name of the directory. public: + LLVM_DEPRECATED("Use DirectoryEntryRef::getName() instead.", "") StringRef getName() const { return Name; } }; @@ -71,7 +72,7 @@ public: bool isSameRef(DirectoryEntryRef RHS) const { return ME == RHS.ME; } DirectoryEntryRef() = delete; - DirectoryEntryRef(const MapEntry &ME) : ME(&ME) {} + explicit DirectoryEntryRef(const MapEntry &ME) : ME(&ME) {} /// Allow DirectoryEntryRef to degrade into 'const DirectoryEntry*' to /// facilitate incremental adoption. @@ -196,6 +197,21 @@ static_assert(std::is_trivially_copyable::value, } // namespace clang namespace llvm { + +template <> struct PointerLikeTypeTraits { + static inline void *getAsVoidPointer(clang::DirectoryEntryRef Dir) { + return const_cast(&Dir.getMapEntry()); + } + + static inline clang::DirectoryEntryRef getFromVoidPointer(void *Ptr) { + return clang::DirectoryEntryRef( + *reinterpret_cast(Ptr)); + } + + static constexpr int NumLowBitsAvailable = PointerLikeTypeTraits< + const clang::DirectoryEntryRef::MapEntry *>::NumLowBitsAvailable; +}; + /// Specialisation of DenseMapInfo for DirectoryEntryRef. template <> struct DenseMapInfo { static inline clang::DirectoryEntryRef getEmptyKey() { diff --git a/contrib/llvm-project/clang/include/clang/Basic/ExceptionSpecificationType.h b/contrib/llvm-project/clang/include/clang/Basic/ExceptionSpecificationType.h index 5616860555c..d3c9e9cd063 100644 --- a/contrib/llvm-project/clang/include/clang/Basic/ExceptionSpecificationType.h +++ b/contrib/llvm-project/clang/include/clang/Basic/ExceptionSpecificationType.h @@ -50,6 +50,11 @@ inline bool isUnresolvedExceptionSpec(ExceptionSpecificationType ESpecType) { return ESpecType == EST_Unevaluated || ESpecType == EST_Uninstantiated; } +inline bool isExplicitThrowExceptionSpec(ExceptionSpecificationType ESpecType) { + return ESpecType == EST_Dynamic || ESpecType == EST_MSAny || + ESpecType == EST_NoexceptFalse; +} + /// Possible results from evaluation of a noexcept expression. enum CanThrowResult { CT_Cannot, diff --git a/contrib/llvm-project/clang/include/clang/Basic/FPOptions.def b/contrib/llvm-project/clang/include/clang/Basic/FPOptions.def index 0c687e3c3fa..4517be6f178 100644 --- a/contrib/llvm-project/clang/include/clang/Basic/FPOptions.def +++ b/contrib/llvm-project/clang/include/clang/Basic/FPOptions.def @@ -26,4 +26,5 @@ OPTION(AllowReciprocal, bool, 1, NoSignedZero) OPTION(AllowApproxFunc, bool, 1, AllowReciprocal) OPTION(FPEvalMethod, LangOptions::FPEvalMethodKind, 2, AllowApproxFunc) OPTION(Float16ExcessPrecision, LangOptions::ExcessPrecisionKind, 2, FPEvalMethod) +OPTION(BFloat16ExcessPrecision, LangOptions::ExcessPrecisionKind, 2, FPEvalMethod) #undef OPTION diff --git a/contrib/llvm-project/clang/include/clang/Basic/Features.def b/contrib/llvm-project/clang/include/clang/Basic/Features.def index 0581c61dcba..e05ac462582 100644 --- a/contrib/llvm-project/clang/include/clang/Basic/Features.def +++ b/contrib/llvm-project/clang/include/clang/Basic/Features.def @@ -242,10 +242,15 @@ EXTENSION(c_alignas, true) EXTENSION(c_alignof, true) EXTENSION(c_atomic, true) EXTENSION(c_generic_selections, true) +EXTENSION(c_generic_selection_with_controlling_type, true) EXTENSION(c_static_assert, true) EXTENSION(c_thread_local, PP.getTargetInfo().isTLSSupported()) +// C2x features supported by other languages as extensions +EXTENSION(c_attributes, true) // C++11 features supported by other languages as extensions. EXTENSION(cxx_atomic, LangOpts.CPlusPlus) +EXTENSION(cxx_default_function_template_args, LangOpts.CPlusPlus) +EXTENSION(cxx_defaulted_functions, LangOpts.CPlusPlus) EXTENSION(cxx_deleted_functions, LangOpts.CPlusPlus) EXTENSION(cxx_explicit_conversions, LangOpts.CPlusPlus) EXTENSION(cxx_inline_namespaces, LangOpts.CPlusPlus) @@ -268,6 +273,7 @@ EXTENSION(pragma_clang_attribute_external_declaration, true) EXTENSION(statement_attributes_with_gnu_syntax, true) EXTENSION(gnu_asm, LangOpts.GNUAsm) EXTENSION(gnu_asm_goto_with_outputs, LangOpts.GNUAsm) +EXTENSION(gnu_asm_goto_with_outputs_full, LangOpts.GNUAsm) EXTENSION(matrix_types, LangOpts.MatrixTypes) EXTENSION(matrix_types_scalar_division, true) EXTENSION(cxx_attributes_on_using_declarations, LangOpts.CPlusPlus11) diff --git a/contrib/llvm-project/clang/include/clang/Basic/FileEntry.h b/contrib/llvm-project/clang/include/clang/Basic/FileEntry.h index 93e84cf233a..50110b8572e 100644 --- a/contrib/llvm-project/clang/include/clang/Basic/FileEntry.h +++ b/contrib/llvm-project/clang/include/clang/Basic/FileEntry.h @@ -70,7 +70,7 @@ public: const FileEntry &getFileEntry() const { return *getBaseMapEntry().second->V.get(); } - DirectoryEntryRef getDir() const { return *getBaseMapEntry().second->Dir; } + DirectoryEntryRef getDir() const { return ME->second->Dir; } inline off_t getSize() const; inline unsigned getUID() const; @@ -118,17 +118,14 @@ public: /// VFSs that use external names. In that case, the \c FileEntryRef /// returned by the \c FileManager will have the external name, and not the /// name that was used to lookup the file. - /// - /// The second type is really a `const MapEntry *`, but that confuses - /// gcc5.3. Once that's no longer supported, change this back. - llvm::PointerUnion V; + llvm::PointerUnion V; - /// Directory the file was found in. Set if and only if V is a FileEntry. - OptionalDirectoryEntryRef Dir; + /// Directory the file was found in. + DirectoryEntryRef Dir; MapValue() = delete; MapValue(FileEntry &FE, DirectoryEntryRef Dir) : V(&FE), Dir(Dir) {} - MapValue(MapEntry &ME) : V(&ME) {} + MapValue(MapEntry &ME, DirectoryEntryRef Dir) : V(&ME), Dir(Dir) {} }; /// Check if RHS referenced the file in exactly the same way. @@ -165,10 +162,10 @@ public: /// Retrieve the base MapEntry after redirects. const MapEntry &getBaseMapEntry() const { - const MapEntry *ME = this->ME; - while (const void *Next = ME->second->V.dyn_cast()) - ME = static_cast(Next); - return *ME; + const MapEntry *Base = ME; + while (const auto *Next = Base->second->V.dyn_cast()) + Base = Next; + return *Base; } private: @@ -237,6 +234,21 @@ static_assert(std::is_trivially_copyable::value, } // namespace clang namespace llvm { + +template <> struct PointerLikeTypeTraits { + static inline void *getAsVoidPointer(clang::FileEntryRef File) { + return const_cast(&File.getMapEntry()); + } + + static inline clang::FileEntryRef getFromVoidPointer(void *Ptr) { + return clang::FileEntryRef( + *reinterpret_cast(Ptr)); + } + + static constexpr int NumLowBitsAvailable = PointerLikeTypeTraits< + const clang::FileEntryRef::MapEntry *>::NumLowBitsAvailable; +}; + /// Specialisation of DenseMapInfo for FileEntryRef. template <> struct DenseMapInfo { static inline clang::FileEntryRef getEmptyKey() { diff --git a/contrib/llvm-project/clang/include/clang/Basic/FileManager.h b/contrib/llvm-project/clang/include/clang/Basic/FileManager.h index 84d569363a4..502b69c3b41 100644 --- a/contrib/llvm-project/clang/include/clang/Basic/FileManager.h +++ b/contrib/llvm-project/clang/include/clang/Basic/FileManager.h @@ -320,7 +320,7 @@ public: /// This is a very expensive operation, despite its results being cached, /// and should only be used when the physical layout of the file system is /// required, which is (almost) never. - StringRef getCanonicalName(const DirectoryEntry *Dir); + StringRef getCanonicalName(DirectoryEntryRef Dir); /// Retrieve the canonical name for a given file. /// diff --git a/contrib/llvm-project/clang/include/clang/Basic/IdentifierTable.h b/contrib/llvm-project/clang/include/clang/Basic/IdentifierTable.h index 1886b1d7ba6..f87f7671481 100644 --- a/contrib/llvm-project/clang/include/clang/Basic/IdentifierTable.h +++ b/contrib/llvm-project/clang/include/clang/Basic/IdentifierTable.h @@ -50,6 +50,12 @@ enum class ReservedIdentifierStatus { ContainsDoubleUnderscore, }; +enum class ReservedLiteralSuffixIdStatus { + NotReserved = 0, + NotStartsWithUnderscore, + ContainsDoubleUnderscore, +}; + /// Determine whether an identifier is reserved for use as a name at global /// scope. Such identifiers might be implementation-specific global functions /// or variables. @@ -76,6 +82,21 @@ enum { IdentifierInfoAlignment = 8 }; static constexpr int ObjCOrBuiltinIDBits = 16; +/// The "layout" of ObjCOrBuiltinID is: +/// - The first value (0) represents "not a special identifier". +/// - The next (NUM_OBJC_KEYWORDS - 1) values represent ObjCKeywordKinds (not +/// including objc_not_keyword). +/// - The next (NUM_INTERESTING_IDENTIFIERS - 1) values represent +/// InterestingIdentifierKinds (not including not_interesting). +/// - The rest of the values represent builtin IDs (not including NotBuiltin). +static constexpr int FirstObjCKeywordID = 1; +static constexpr int LastObjCKeywordID = + FirstObjCKeywordID + tok::NUM_OBJC_KEYWORDS - 2; +static constexpr int FirstInterestingIdentifierID = LastObjCKeywordID + 1; +static constexpr int LastInterestingIdentifierID = + FirstInterestingIdentifierID + tok::NUM_INTERESTING_IDENTIFIERS - 2; +static constexpr int FirstBuiltinID = LastInterestingIdentifierID + 1; + /// One of these records is kept for each identifier that /// is lexed. This contains information about whether the token was \#define'd, /// is a language keyword, or if it is a front-end token of some sort (e.g. a @@ -290,7 +311,9 @@ public: /// /// For example, 'class' will return tok::objc_class if ObjC is enabled. tok::ObjCKeywordKind getObjCKeywordID() const { - if (ObjCOrBuiltinID < tok::NUM_OBJC_KEYWORDS) + static_assert(FirstObjCKeywordID == 1, + "hard-coding this assumption to simplify code"); + if (ObjCOrBuiltinID <= LastObjCKeywordID) return tok::ObjCKeywordKind(ObjCOrBuiltinID); else return tok::objc_not_keyword; @@ -301,15 +324,30 @@ public: /// /// 0 is not-built-in. 1+ are specific builtin functions. unsigned getBuiltinID() const { - if (ObjCOrBuiltinID >= tok::NUM_OBJC_KEYWORDS) - return ObjCOrBuiltinID - tok::NUM_OBJC_KEYWORDS; + if (ObjCOrBuiltinID >= FirstBuiltinID) + return 1 + (ObjCOrBuiltinID - FirstBuiltinID); else return 0; } void setBuiltinID(unsigned ID) { - ObjCOrBuiltinID = ID + tok::NUM_OBJC_KEYWORDS; - assert(ObjCOrBuiltinID - unsigned(tok::NUM_OBJC_KEYWORDS) == ID - && "ID too large for field!"); + assert(ID != 0); + ObjCOrBuiltinID = FirstBuiltinID + (ID - 1); + assert(getBuiltinID() == ID && "ID too large for field!"); + } + void clearBuiltinID() { ObjCOrBuiltinID = 0; } + + tok::InterestingIdentifierKind getInterestingIdentifierID() const { + if (ObjCOrBuiltinID >= FirstInterestingIdentifierID && + ObjCOrBuiltinID <= LastInterestingIdentifierID) + return tok::InterestingIdentifierKind( + 1 + (ObjCOrBuiltinID - FirstInterestingIdentifierID)); + else + return tok::not_interesting; + } + void setInterestingIdentifierID(unsigned ID) { + assert(ID != tok::not_interesting); + ObjCOrBuiltinID = FirstInterestingIdentifierID + (ID - 1); + assert(getInterestingIdentifierID() == ID && "ID too large for field!"); } unsigned getObjCOrBuiltinID() const { return ObjCOrBuiltinID; } @@ -459,6 +497,10 @@ public: /// 7.1.3, C++ [lib.global.names]). ReservedIdentifierStatus isReserved(const LangOptions &LangOpts) const; + /// Determine whether \p this is a name reserved for future standardization or + /// the implementation (C++ [usrlit.suffix]). + ReservedLiteralSuffixIdStatus isReservedLiteralSuffixId() const; + /// If the identifier is an "uglified" reserved name, return a cleaned form. /// e.g. _Foo => Foo. Otherwise, just returns the name. StringRef deuglifiedName() const; diff --git a/contrib/llvm-project/clang/include/clang/Basic/LLVM.h b/contrib/llvm-project/clang/include/clang/Basic/LLVM.h index 7ffc4c40347..f4956cd16cb 100644 --- a/contrib/llvm-project/clang/include/clang/Basic/LLVM.h +++ b/contrib/llvm-project/clang/include/clang/Basic/LLVM.h @@ -19,9 +19,6 @@ // dependencies. // Casting.h has complex templates that cannot be easily forward declared. #include "llvm/Support/Casting.h" -// None.h includes an enumerator that is desired & cannot be forward declared -// without a definition of NoneType. -#include "llvm/ADT/None.h" // Add this header as a workaround to prevent `too few template arguments for // class template 'SmallVector'` building error with build compilers like XL. #include "llvm/ADT/SmallVector.h" @@ -37,7 +34,6 @@ namespace llvm { template class SmallString; template class SmallVector; template class SmallVectorImpl; - template using Optional = std::optional; template class Expected; template @@ -69,7 +65,6 @@ namespace clang { // ADT's. using llvm::ArrayRef; using llvm::MutableArrayRef; - using llvm::Optional; using llvm::OwningArrayRef; using llvm::SaveAndRestore; using llvm::SmallString; diff --git a/contrib/llvm-project/clang/include/clang/Basic/LangOptions.def b/contrib/llvm-project/clang/include/clang/Basic/LangOptions.def index d1cbe430643..f7ec0406f33 100644 --- a/contrib/llvm-project/clang/include/clang/Basic/LangOptions.def +++ b/contrib/llvm-project/clang/include/clang/Basic/LangOptions.def @@ -97,7 +97,8 @@ LANGOPT(CPlusPlus11 , 1, 0, "C++11") LANGOPT(CPlusPlus14 , 1, 0, "C++14") LANGOPT(CPlusPlus17 , 1, 0, "C++17") LANGOPT(CPlusPlus20 , 1, 0, "C++20") -LANGOPT(CPlusPlus2b , 1, 0, "C++2b") +LANGOPT(CPlusPlus23 , 1, 0, "C++23") +LANGOPT(CPlusPlus26 , 1, 0, "C++26") LANGOPT(ObjC , 1, 0, "Objective-C") BENIGN_LANGOPT(ObjCDefaultSynthProperties , 1, 0, "Objective-C auto-synthesized properties") @@ -171,7 +172,6 @@ BENIGN_LANGOPT(EmitAllDecls , 1, 0, "emitting all declarations") LANGOPT(MathErrno , 1, 1, "errno in math functions") BENIGN_LANGOPT(HeinousExtensions , 1, 0, "extensions that we really don't like and may be ripped out at any time") LANGOPT(Modules , 1, 0, "modules semantics") -COMPATIBLE_LANGOPT(ModulesTS , 1, 0, "C++ Modules TS syntax") COMPATIBLE_LANGOPT(CPlusPlusModules, 1, 0, "C++ modules syntax") BENIGN_ENUM_LANGOPT(CompilingModule, CompilingModuleKind, 3, CMK_None, "compiling a module interface") @@ -243,7 +243,7 @@ LANGOPT(OpenMP , 32, 0, "OpenMP support and version of OpenMP (31, 40 LANGOPT(OpenMPExtensions , 1, 1, "Enable all Clang extensions for OpenMP directives and clauses") LANGOPT(OpenMPSimd , 1, 0, "Use SIMD only OpenMP support.") LANGOPT(OpenMPUseTLS , 1, 0, "Use TLS for threadprivates or runtime calls") -LANGOPT(OpenMPIsDevice , 1, 0, "Generate code only for OpenMP target device") +LANGOPT(OpenMPIsTargetDevice , 1, 0, "Generate code only for OpenMP target device") LANGOPT(OpenMPCUDAMode , 1, 0, "Generate code for OpenMP pragmas in SIMT/SPMD mode") LANGOPT(OpenMPIRBuilder , 1, 0, "Use the experimental OpenMP-IR-Builder codegen path.") LANGOPT(OpenMPCUDANumSMs , 32, 0, "Number of SMs for CUDA devices.") @@ -317,7 +317,8 @@ COMPATIBLE_LANGOPT(ExpStrictFP, 1, false, "Enable experimental strict floating p BENIGN_LANGOPT(RoundingMath, 1, false, "Do not assume default floating-point rounding behavior") BENIGN_ENUM_LANGOPT(FPExceptionMode, FPExceptionModeKind, 2, FPE_Default, "FP Exception Behavior Mode type") BENIGN_ENUM_LANGOPT(FPEvalMethod, FPEvalMethodKind, 2, FEM_UnsetOnCommandLine, "FP type used for floating point arithmetic") -ENUM_LANGOPT(Float16ExcessPrecision, ExcessPrecisionKind, 2, FPP_Standard, "Intermediate truncation behavior for floating point arithmetic") +ENUM_LANGOPT(Float16ExcessPrecision, ExcessPrecisionKind, 2, FPP_Standard, "Intermediate truncation behavior for Float16 arithmetic") +ENUM_LANGOPT(BFloat16ExcessPrecision, ExcessPrecisionKind, 2, FPP_Standard, "Intermediate truncation behavior for BFloat16 arithmetic") LANGOPT(NoBitFieldTypeAlign , 1, 0, "bit-field type alignment") LANGOPT(HexagonQdsp6Compat , 1, 0, "hexagon-qdsp6 backward compatibility") LANGOPT(ObjCAutoRefCount , 1, 0, "Objective-C automated reference counting") @@ -465,6 +466,8 @@ LANGOPT(IncrementalExtensions, 1, 0, " True if we want to process statements" "avoid tearing the Lexer and etc. down). Controlled by " "-fincremental-extensions.") +BENIGN_LANGOPT(CheckNew, 1, 0, "Do not assume C++ operator new may not return NULL") + #undef LANGOPT #undef COMPATIBLE_LANGOPT #undef BENIGN_LANGOPT diff --git a/contrib/llvm-project/clang/include/clang/Basic/LangOptions.h b/contrib/llvm-project/clang/include/clang/Basic/LangOptions.h index 38261c4200e..3ef68ca8af6 100644 --- a/contrib/llvm-project/clang/include/clang/Basic/LangOptions.h +++ b/contrib/llvm-project/clang/include/clang/Basic/LangOptions.h @@ -23,7 +23,7 @@ #include "clang/Basic/Visibility.h" #include "llvm/ADT/FloatingPointMode.h" #include "llvm/ADT/StringRef.h" -#include "llvm/ADT/Triple.h" +#include "llvm/TargetParser/Triple.h" #include #include #include @@ -479,14 +479,18 @@ public: /// The seed used by the randomize structure layout feature. std::string RandstructSeed; - /// Indicates whether the __FILE__ macro should use the target's - /// platform-specific file separator or whether it should use the build - /// environment's platform-specific file separator. + /// Indicates whether to use target's platform-specific file separator when + /// __FILE__ macro is used and when concatenating filename with directory or + /// to use build environment environment's platform-specific file separator. /// /// The plaform-specific path separator is the backslash(\) for Windows and /// forward slash (/) elsewhere. bool UseTargetPathSeparator = false; + // Indicates whether we should keep all nullptr checks for pointers + // received as a result of a standard operator new (-fcheck-new) + bool CheckNew = false; + LangOptions(); /// Set language defaults for the given input language and diff --git a/contrib/llvm-project/clang/include/clang/Basic/LangStandard.h b/contrib/llvm-project/clang/include/clang/Basic/LangStandard.h index 4e78570ff73..fd949bcd685 100644 --- a/contrib/llvm-project/clang/include/clang/Basic/LangStandard.h +++ b/contrib/llvm-project/clang/include/clang/Basic/LangStandard.h @@ -55,12 +55,13 @@ enum LangFeatures { CPlusPlus14 = (1 << 7), CPlusPlus17 = (1 << 8), CPlusPlus20 = (1 << 9), - CPlusPlus2b = (1 << 10), - Digraphs = (1 << 11), - GNUMode = (1 << 12), - HexFloat = (1 << 13), - OpenCL = (1 << 14), - HLSL = (1 << 15) + CPlusPlus23 = (1 << 10), + CPlusPlus26 = (1 << 11), + Digraphs = (1 << 12), + GNUMode = (1 << 13), + HexFloat = (1 << 14), + OpenCL = (1 << 15), + HLSL = (1 << 16) }; /// LangStandard - Information about the properties of a particular language @@ -118,8 +119,11 @@ public: /// isCPlusPlus20 - Language is a C++20 variant (or later). bool isCPlusPlus20() const { return Flags & CPlusPlus20; } - /// isCPlusPlus2b - Language is a post-C++20 variant (or later). - bool isCPlusPlus2b() const { return Flags & CPlusPlus2b; } + /// isCPlusPlus23 - Language is a post-C++23 variant (or later). + bool isCPlusPlus23() const { return Flags & CPlusPlus23; } + + /// isCPlusPlus26 - Language is a post-C++26 variant (or later). + bool isCPlusPlus26() const { return Flags & CPlusPlus26; } /// hasDigraphs - Language supports digraphs. bool hasDigraphs() const { return Flags & Digraphs; } diff --git a/contrib/llvm-project/clang/include/clang/Basic/LangStandards.def b/contrib/llvm-project/clang/include/clang/Basic/LangStandards.def index c5d4da1cb2f..5c28bdd28ef 100644 --- a/contrib/llvm-project/clang/include/clang/Basic/LangStandards.def +++ b/contrib/llvm-project/clang/include/clang/Basic/LangStandards.def @@ -151,15 +151,29 @@ LANGSTANDARD(gnucxx20, "gnu++20", CPlusPlus20 | Digraphs | HexFloat | GNUMode) LANGSTANDARD_ALIAS_DEPR(gnucxx20, "gnu++2a") -LANGSTANDARD(cxx2b, "c++2b", - CXX, "Working draft for ISO C++ 2023 DIS", +LANGSTANDARD(cxx23, "c++23", + CXX, "ISO C++ 2023 DIS", LineComment | CPlusPlus | CPlusPlus11 | CPlusPlus14 | CPlusPlus17 | - CPlusPlus20 | CPlusPlus2b | Digraphs | HexFloat) + CPlusPlus20 | CPlusPlus23 | Digraphs | HexFloat) +LANGSTANDARD_ALIAS_DEPR(cxx23, "c++2b") -LANGSTANDARD(gnucxx2b, "gnu++2b", - CXX, "Working draft for ISO C++ 2023 DIS with GNU extensions", +LANGSTANDARD(gnucxx23, "gnu++23", + CXX, "ISO C++ 2023 DIS with GNU extensions", LineComment | CPlusPlus | CPlusPlus11 | CPlusPlus14 | CPlusPlus17 | - CPlusPlus20 | CPlusPlus2b | Digraphs | HexFloat | GNUMode) + CPlusPlus20 | CPlusPlus23 | Digraphs | HexFloat | GNUMode) +LANGSTANDARD_ALIAS_DEPR(gnucxx23, "gnu++2b") + +LANGSTANDARD(cxx26, "c++2c", + CXX, "Working draft for C++2c", + LineComment | CPlusPlus | CPlusPlus11 | CPlusPlus14 | CPlusPlus17 | + CPlusPlus20 | CPlusPlus23 | CPlusPlus26 | Digraphs | HexFloat) +LANGSTANDARD_ALIAS(cxx26, "c++26") + +LANGSTANDARD(gnucxx26, "gnu++2c", + CXX, "Working draft for C++2c with GNU extensions", + LineComment | CPlusPlus | CPlusPlus11 | CPlusPlus14 | CPlusPlus17 | + CPlusPlus20 | CPlusPlus23 | CPlusPlus26 | Digraphs | HexFloat | GNUMode) +LANGSTANDARD_ALIAS(gnucxx26, "gnu++26") // OpenCL LANGSTANDARD(opencl10, "cl1.0", @@ -200,14 +214,6 @@ LANGSTANDARD_ALIAS_DEPR(openclcpp10, "CLC++") LANGSTANDARD_ALIAS_DEPR(openclcpp10, "CLC++1.0") LANGSTANDARD_ALIAS_DEPR(openclcpp2021, "CLC++2021") -// CUDA -LANGSTANDARD(cuda, "cuda", CUDA, "NVIDIA CUDA(tm)", - LineComment | CPlusPlus | CPlusPlus11 | CPlusPlus14 | Digraphs) - -// HIP -LANGSTANDARD(hip, "hip", HIP, "HIP", - LineComment | CPlusPlus | CPlusPlus11 | CPlusPlus14 | Digraphs) - // HLSL LANGSTANDARD(hlsl, "hlsl", HLSL, "High Level Shader Language", diff --git a/contrib/llvm-project/clang/include/clang/Basic/Linkage.h b/contrib/llvm-project/clang/include/clang/Basic/Linkage.h index f4d442c084c..0b7b61954a0 100644 --- a/contrib/llvm-project/clang/include/clang/Basic/Linkage.h +++ b/contrib/llvm-project/clang/include/clang/Basic/Linkage.h @@ -43,11 +43,6 @@ enum Linkage : unsigned char { /// translation units because of types defined in a inline function. VisibleNoLinkage, - /// Internal linkage according to the Modules TS, but can be referred - /// to from other translation units indirectly through inline functions and - /// templates in the module interface. - ModuleInternalLinkage, - /// Module linkage, which indicates that the entity can be referred /// to from other translation units within the same module, and indirectly /// from arbitrary other translation units through inline functions and @@ -98,8 +93,6 @@ inline Linkage getFormalLinkage(Linkage L) { return ExternalLinkage; case VisibleNoLinkage: return NoLinkage; - case ModuleInternalLinkage: - return InternalLinkage; default: return L; } diff --git a/contrib/llvm-project/clang/include/clang/Basic/Module.h b/contrib/llvm-project/clang/include/clang/Basic/Module.h index c042cf15d19..a4ad8ad2f76 100644 --- a/contrib/llvm-project/clang/include/clang/Basic/Module.h +++ b/contrib/llvm-project/clang/include/clang/Basic/Module.h @@ -103,16 +103,22 @@ public: /// The location of the module definition. SourceLocation DefinitionLoc; + // FIXME: Consider if reducing the size of this enum (having Partition and + // Named modules only) then representing interface/implementation separately + // is more efficient. enum ModuleKind { /// This is a module that was defined by a module map and built out /// of header files. ModuleMapModule, + /// This is a C++ 20 header unit. + ModuleHeaderUnit, + /// This is a C++20 module interface unit. ModuleInterfaceUnit, - /// This is a C++ 20 header unit. - ModuleHeaderUnit, + /// This is a C++20 module implementation unit. + ModuleImplementationUnit, /// This is a C++ 20 module partition interface. ModulePartitionInterface, @@ -120,11 +126,17 @@ public: /// This is a C++ 20 module partition implementation. ModulePartitionImplementation, - /// This is a fragment of the global module within some C++ module. - GlobalModuleFragment, + /// This is the explicit Global Module Fragment of a modular TU. + /// As per C++ [module.global.frag]. + ExplicitGlobalModuleFragment, /// This is the private module fragment within some C++ module. PrivateModuleFragment, + + /// This is an implicit fragment of the global module which contains + /// only language linkage declarations (made in the purview of the + /// named module). + ImplicitGlobalModuleFragment, }; /// The kind of this module. @@ -137,15 +149,14 @@ public: /// The build directory of this module. This is the directory in /// which the module is notionally built, and relative to which its headers /// are found. - const DirectoryEntry *Directory = nullptr; + OptionalDirectoryEntryRefDegradesToDirectoryEntryPtr Directory; /// The presumed file name for the module map defining this module. /// Only non-empty when building from preprocessed source. std::string PresumedModuleMapFile; /// The umbrella header or directory. - llvm::PointerUnion - Umbrella; + llvm::PointerUnion Umbrella; /// The module signature. ASTFileSignature Signature; @@ -163,14 +174,29 @@ public: /// Does this Module scope describe part of the purview of a standard named /// C++ module? bool isModulePurview() const { - return Kind == ModuleInterfaceUnit || Kind == ModulePartitionInterface || - Kind == ModulePartitionImplementation || - Kind == PrivateModuleFragment; + switch (Kind) { + case ModuleInterfaceUnit: + case ModuleImplementationUnit: + case ModulePartitionInterface: + case ModulePartitionImplementation: + case PrivateModuleFragment: + return true; + default: + return false; + } } /// Does this Module scope describe a fragment of the global module within /// some C++ module. - bool isGlobalModule() const { return Kind == GlobalModuleFragment; } + bool isGlobalModule() const { + return isExplicitGlobalModule() || isImplicitGlobalModule(); + } + bool isExplicitGlobalModule() const { + return Kind == ExplicitGlobalModuleFragment; + } + bool isImplicitGlobalModule() const { + return Kind == ImplicitGlobalModuleFragment; + } bool isPrivateModule() const { return Kind == PrivateModuleFragment; } @@ -189,7 +215,7 @@ private: OptionalFileEntryRef ASTFile; /// The top-level headers associated with this module. - llvm::SmallSetVector TopHeaders; + llvm::SmallSetVector TopHeaders; /// top-level header filenames that aren't resolved to FileEntries yet. std::vector TopHeaderNames; @@ -215,9 +241,7 @@ public: struct Header { std::string NameAsWritten; std::string PathRelativeToRootModuleDirectory; - OptionalFileEntryRefDegradesToFileEntryPtr Entry; - - explicit operator bool() { return Entry.has_value(); } + FileEntryRef Entry; }; /// Information about a directory name as found in the module map @@ -225,9 +249,7 @@ public: struct DirectoryName { std::string NameAsWritten; std::string PathRelativeToRootModuleDirectory; - const DirectoryEntry *Entry; - - explicit operator bool() { return Entry; } + DirectoryEntryRef Entry; }; /// The headers that are part of this module. @@ -547,6 +569,11 @@ public: Kind == ModulePartitionImplementation; } + /// Is this a module implementation. + bool isModuleImplementation() const { + return Kind == ModuleImplementationUnit; + } + /// Is this module a header unit. bool isHeaderUnit() const { return Kind == ModuleHeaderUnit; } // Is this a C++20 module interface or a partition. @@ -619,27 +646,30 @@ public: getTopLevelModule()->ASTFile = File; } - /// Retrieve the directory for which this module serves as the - /// umbrella. - DirectoryName getUmbrellaDir() const; + /// Retrieve the umbrella directory as written. + std::optional getUmbrellaDirAsWritten() const { + if (Umbrella && Umbrella.is()) + return DirectoryName{UmbrellaAsWritten, + UmbrellaRelativeToRootModuleDirectory, + Umbrella.get()}; + return std::nullopt; + } - /// Retrieve the header that serves as the umbrella header for this - /// module. - Header getUmbrellaHeader() const { - if (auto *ME = Umbrella.dyn_cast()) + /// Retrieve the umbrella header as written. + std::optional
getUmbrellaHeaderAsWritten() const { + if (Umbrella && Umbrella.is()) return Header{UmbrellaAsWritten, UmbrellaRelativeToRootModuleDirectory, - FileEntryRef(*ME)}; - return Header{}; + Umbrella.get()}; + return std::nullopt; } - /// Determine whether this module has an umbrella directory that is - /// not based on an umbrella header. - bool hasUmbrellaDir() const { - return Umbrella && Umbrella.is(); - } + /// Get the effective umbrella directory for this module: either the one + /// explicitly written in the module map file, or the parent of the umbrella + /// header. + OptionalDirectoryEntryRef getEffectiveUmbrellaDir() const; /// Add a top-level header associated with this module. - void addTopHeader(const FileEntry *File); + void addTopHeader(FileEntryRef File); /// Add a top-level header filename associated with this module. void addTopHeaderFilename(StringRef Filename) { @@ -647,7 +677,7 @@ public: } /// The top-level headers associated with this module. - ArrayRef getTopHeaders(FileManager &FileMgr); + ArrayRef getTopHeaders(FileManager &FileMgr); /// Determine whether this module has declared its intention to /// directly use another module. @@ -709,16 +739,11 @@ public: using submodule_iterator = std::vector::iterator; using submodule_const_iterator = std::vector::const_iterator; - submodule_iterator submodule_begin() { return SubModules.begin(); } - submodule_const_iterator submodule_begin() const {return SubModules.begin();} - submodule_iterator submodule_end() { return SubModules.end(); } - submodule_const_iterator submodule_end() const { return SubModules.end(); } - llvm::iterator_range submodules() { - return llvm::make_range(submodule_begin(), submodule_end()); + return llvm::make_range(SubModules.begin(), SubModules.end()); } llvm::iterator_range submodules() const { - return llvm::make_range(submodule_begin(), submodule_end()); + return llvm::make_range(SubModules.begin(), SubModules.end()); } /// Appends this module's list of exported modules to \p Exported. @@ -794,6 +819,11 @@ public: ConflictCallback Cb = [](ArrayRef, Module *, StringRef) {}); + /// Make transitive imports visible for [module.import]/7. + void makeTransitiveImportsVisible( + Module *M, SourceLocation Loc, VisibleCallback Vis = [](Module *) {}, + ConflictCallback Cb = [](ArrayRef, Module *, StringRef) {}); + private: /// Import locations for each visible module. Indexed by the module's /// VisibilityID. diff --git a/contrib/llvm-project/clang/include/clang/Basic/ObjCRuntime.h b/contrib/llvm-project/clang/include/clang/Basic/ObjCRuntime.h index 30a5fde4075..0f714ed3ad6 100644 --- a/contrib/llvm-project/clang/include/clang/Basic/ObjCRuntime.h +++ b/contrib/llvm-project/clang/include/clang/Basic/ObjCRuntime.h @@ -16,10 +16,10 @@ #include "clang/Basic/LLVM.h" #include "llvm/ADT/StringRef.h" -#include "llvm/ADT/Triple.h" #include "llvm/Support/ErrorHandling.h" #include "llvm/Support/HashBuilder.h" #include "llvm/Support/VersionTuple.h" +#include "llvm/TargetParser/Triple.h" #include namespace clang { diff --git a/contrib/llvm-project/clang/include/clang/Basic/OpenCLExtensionTypes.def b/contrib/llvm-project/clang/include/clang/Basic/OpenCLExtensionTypes.def index 84ffbe936b7..17c72d69a02 100644 --- a/contrib/llvm-project/clang/include/clang/Basic/OpenCLExtensionTypes.def +++ b/contrib/llvm-project/clang/include/clang/Basic/OpenCLExtensionTypes.def @@ -28,10 +28,10 @@ INTEL_SUBGROUP_AVC_TYPE(mce_result_t, MceResult) INTEL_SUBGROUP_AVC_TYPE(ime_result_t, ImeResult) INTEL_SUBGROUP_AVC_TYPE(ref_result_t, RefResult) INTEL_SUBGROUP_AVC_TYPE(sic_result_t, SicResult) -INTEL_SUBGROUP_AVC_TYPE(ime_result_single_reference_streamout_t, ImeResultSingleRefStreamout) -INTEL_SUBGROUP_AVC_TYPE(ime_result_dual_reference_streamout_t, ImeResultDualRefStreamout) -INTEL_SUBGROUP_AVC_TYPE(ime_single_reference_streamin_t, ImeSingleRefStreamin) -INTEL_SUBGROUP_AVC_TYPE(ime_dual_reference_streamin_t, ImeDualRefStreamin) +INTEL_SUBGROUP_AVC_TYPE(ime_result_single_reference_streamout_t, ImeResultSingleReferenceStreamout) +INTEL_SUBGROUP_AVC_TYPE(ime_result_dual_reference_streamout_t, ImeResultDualReferenceStreamout) +INTEL_SUBGROUP_AVC_TYPE(ime_single_reference_streamin_t, ImeSingleReferenceStreamin) +INTEL_SUBGROUP_AVC_TYPE(ime_dual_reference_streamin_t, ImeDualReferenceStreamin) #undef INTEL_SUBGROUP_AVC_TYPE #endif // INTEL_SUBGROUP_AVC_TYPE diff --git a/contrib/llvm-project/clang/include/clang/Basic/OpenCLExtensions.def b/contrib/llvm-project/clang/include/clang/Basic/OpenCLExtensions.def index 70b4f15a95a..6f73b261375 100644 --- a/contrib/llvm-project/clang/include/clang/Basic/OpenCLExtensions.def +++ b/contrib/llvm-project/clang/include/clang/Basic/OpenCLExtensions.def @@ -31,7 +31,7 @@ // If extensions are to be enumerated without any information, // define OPENCLEXTNAME(ext) where ext is the name of the extension. // -// Difference between optional core feature and core feature is that the +// Difference between optional core feature and core feature is that the // later is unconditionally supported in specific OpenCL version. // // As per The OpenCL Extension Specification, Section 1.2, in this file, an diff --git a/contrib/llvm-project/clang/include/clang/Basic/OpenMPKinds.def b/contrib/llvm-project/clang/include/clang/Basic/OpenMPKinds.def index 64c488caa6a..c999b8b9c4f 100644 --- a/contrib/llvm-project/clang/include/clang/Basic/OpenMPKinds.def +++ b/contrib/llvm-project/clang/include/clang/Basic/OpenMPKinds.def @@ -80,6 +80,9 @@ #ifndef OPENMP_NUMTASKS_MODIFIER #define OPENMP_NUMTASKS_MODIFIER(Name) #endif +#ifndef OPENMP_DOACROSS_MODIFIER +#define OPENMP_DOACROSS_MODIFIER(Name) +#endif // Static attributes for 'schedule' clause. OPENMP_SCHEDULE_KIND(static) @@ -201,6 +204,12 @@ OPENMP_GRAINSIZE_MODIFIER(strict) // Modifiers for the 'num_tasks' clause. OPENMP_NUMTASKS_MODIFIER(strict) +// Modifiers for the 'doacross' clause. +OPENMP_DOACROSS_MODIFIER(source) +OPENMP_DOACROSS_MODIFIER(sink) +OPENMP_DOACROSS_MODIFIER(sink_omp_cur_iteration) +OPENMP_DOACROSS_MODIFIER(source_omp_cur_iteration) + #undef OPENMP_NUMTASKS_MODIFIER #undef OPENMP_GRAINSIZE_MODIFIER #undef OPENMP_BIND_KIND @@ -224,4 +233,5 @@ OPENMP_NUMTASKS_MODIFIER(strict) #undef OPENMP_DIST_SCHEDULE_KIND #undef OPENMP_DEFAULTMAP_KIND #undef OPENMP_DEFAULTMAP_MODIFIER +#undef OPENMP_DOACROSS_MODIFIER diff --git a/contrib/llvm-project/clang/include/clang/Basic/OpenMPKinds.h b/contrib/llvm-project/clang/include/clang/Basic/OpenMPKinds.h index 6491ee27782..f5fc7a8ce5b 100644 --- a/contrib/llvm-project/clang/include/clang/Basic/OpenMPKinds.h +++ b/contrib/llvm-project/clang/include/clang/Basic/OpenMPKinds.h @@ -215,6 +215,13 @@ enum OpenMPNumTasksClauseModifier { OMPC_NUMTASKS_unknown }; +/// OpenMP dependence types for 'doacross' clause. +enum OpenMPDoacrossClauseModifier { +#define OPENMP_DOACROSS_MODIFIER(Name) OMPC_DOACROSS_##Name, +#include "clang/Basic/OpenMPKinds.def" + OMPC_DOACROSS_unknown +}; + /// Contains 'interop' data for 'append_args' and 'init' clauses. class Expr; struct OMPInteropInfo final { diff --git a/contrib/llvm-project/clang/include/clang/Basic/ParsedAttrInfo.h b/contrib/llvm-project/clang/include/clang/Basic/ParsedAttrInfo.h new file mode 100644 index 00000000000..4444f12de9c --- /dev/null +++ b/contrib/llvm-project/clang/include/clang/Basic/ParsedAttrInfo.h @@ -0,0 +1,152 @@ +//===- ParsedAttrInfo.h - Info needed to parse an attribute -----*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +// +// This file defines the ParsedAttrInfo class, which dictates how to +// parse an attribute. This class is the one that plugins derive to +// define a new attribute. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CLANG_BASIC_PARSEDATTRINFO_H +#define LLVM_CLANG_BASIC_PARSEDATTRINFO_H + +#include "clang/Basic/AttrSubjectMatchRules.h" +#include "clang/Basic/AttributeCommonInfo.h" +#include "llvm/ADT/ArrayRef.h" +#include "llvm/Support/Registry.h" +#include +#include + +namespace clang { + +class Decl; +class LangOptions; +class ParsedAttr; +class Sema; +class Stmt; +class TargetInfo; + +struct ParsedAttrInfo { + /// Corresponds to the Kind enum. + unsigned AttrKind : 16; + /// The number of required arguments of this attribute. + unsigned NumArgs : 4; + /// The number of optional arguments of this attributes. + unsigned OptArgs : 4; + /// The number of non-fake arguments specified in the attribute definition. + unsigned NumArgMembers : 4; + /// True if the parsing does not match the semantic content. + unsigned HasCustomParsing : 1; + // True if this attribute accepts expression parameter pack expansions. + unsigned AcceptsExprPack : 1; + /// True if this attribute is only available for certain targets. + unsigned IsTargetSpecific : 1; + /// True if this attribute applies to types. + unsigned IsType : 1; + /// True if this attribute applies to statements. + unsigned IsStmt : 1; + /// True if this attribute has any spellings that are known to gcc. + unsigned IsKnownToGCC : 1; + /// True if this attribute is supported by #pragma clang attribute. + unsigned IsSupportedByPragmaAttribute : 1; + /// The syntaxes supported by this attribute and how they're spelled. + struct Spelling { + AttributeCommonInfo::Syntax Syntax; + const char *NormalizedFullName; + }; + ArrayRef Spellings; + // The names of the known arguments of this attribute. + ArrayRef ArgNames; + +protected: + constexpr ParsedAttrInfo(AttributeCommonInfo::Kind AttrKind = + AttributeCommonInfo::NoSemaHandlerAttribute) + : AttrKind(AttrKind), NumArgs(0), OptArgs(0), NumArgMembers(0), + HasCustomParsing(0), AcceptsExprPack(0), IsTargetSpecific(0), IsType(0), + IsStmt(0), IsKnownToGCC(0), IsSupportedByPragmaAttribute(0) {} + + constexpr ParsedAttrInfo(AttributeCommonInfo::Kind AttrKind, unsigned NumArgs, + unsigned OptArgs, unsigned NumArgMembers, + unsigned HasCustomParsing, unsigned AcceptsExprPack, + unsigned IsTargetSpecific, unsigned IsType, + unsigned IsStmt, unsigned IsKnownToGCC, + unsigned IsSupportedByPragmaAttribute, + ArrayRef Spellings, + ArrayRef ArgNames) + : AttrKind(AttrKind), NumArgs(NumArgs), OptArgs(OptArgs), + NumArgMembers(NumArgMembers), HasCustomParsing(HasCustomParsing), + AcceptsExprPack(AcceptsExprPack), IsTargetSpecific(IsTargetSpecific), + IsType(IsType), IsStmt(IsStmt), IsKnownToGCC(IsKnownToGCC), + IsSupportedByPragmaAttribute(IsSupportedByPragmaAttribute), + Spellings(Spellings), ArgNames(ArgNames) {} + +public: + virtual ~ParsedAttrInfo() = default; + + /// Check if this attribute has specified spelling. + bool hasSpelling(AttributeCommonInfo::Syntax Syntax, StringRef Name) const { + return llvm::any_of(Spellings, [&](const Spelling &S) { + return (S.Syntax == Syntax && S.NormalizedFullName == Name); + }); + } + + /// Check if this attribute appertains to D, and issue a diagnostic if not. + virtual bool diagAppertainsToDecl(Sema &S, const ParsedAttr &Attr, + const Decl *D) const { + return true; + } + /// Check if this attribute appertains to St, and issue a diagnostic if not. + virtual bool diagAppertainsToStmt(Sema &S, const ParsedAttr &Attr, + const Stmt *St) const { + return true; + } + /// Check if the given attribute is mutually exclusive with other attributes + /// already applied to the given declaration. + virtual bool diagMutualExclusion(Sema &S, const ParsedAttr &A, + const Decl *D) const { + return true; + } + /// Check if this attribute is allowed by the language we are compiling. + virtual bool acceptsLangOpts(const LangOptions &LO) const { return true; } + + /// Check if this attribute is allowed when compiling for the given target. + virtual bool existsInTarget(const TargetInfo &Target) const { return true; } + /// Convert the spelling index of Attr to a semantic spelling enum value. + virtual unsigned + spellingIndexToSemanticSpelling(const ParsedAttr &Attr) const { + return UINT_MAX; + } + /// Returns true if the specified parameter index for this attribute in + /// Attr.td is an ExprArgument or VariadicExprArgument, or a subclass thereof; + /// returns false otherwise. + virtual bool isParamExpr(size_t N) const { return false; } + /// Populate Rules with the match rules of this attribute. + virtual void getPragmaAttributeMatchRules( + llvm::SmallVectorImpl> &Rules, + const LangOptions &LangOpts) const {} + + enum AttrHandling { NotHandled, AttributeApplied, AttributeNotApplied }; + /// If this ParsedAttrInfo knows how to handle this ParsedAttr applied to this + /// Decl then do so and return either AttributeApplied if it was applied or + /// AttributeNotApplied if it wasn't. Otherwise return NotHandled. + virtual AttrHandling handleDeclAttribute(Sema &S, Decl *D, + const ParsedAttr &Attr) const { + return NotHandled; + } + + static const ParsedAttrInfo &get(const AttributeCommonInfo &A); + static ArrayRef getAllBuiltin(); +}; + +typedef llvm::Registry ParsedAttrInfoRegistry; + +const std::list> &getAttributePluginInstances(); + +} // namespace clang + +#endif // LLVM_CLANG_BASIC_PARSEDATTRINFO_H diff --git a/contrib/llvm-project/clang/include/clang/Basic/RISCVVTypes.def b/contrib/llvm-project/clang/include/clang/Basic/RISCVVTypes.def index 1d4024dfb20..575bca58b51 100644 --- a/contrib/llvm-project/clang/include/clang/Basic/RISCVVTypes.def +++ b/contrib/llvm-project/clang/include/clang/Basic/RISCVVTypes.def @@ -40,6 +40,10 @@ // //===----------------------------------------------------------------------===// +#ifndef RVV_TYPE +#define RVV_TYPE(Name, Id, SingletonId) +#endif + #ifndef RVV_VECTOR_TYPE #define RVV_VECTOR_TYPE(Name, Id, SingletonId, NumEls, ElBits, NF, IsSigned, IsFP)\ RVV_TYPE(Name, Id, SingletonId) @@ -140,6 +144,292 @@ RVV_PREDICATE_TYPE("__rvv_bool16_t", RvvBool16, RvvBool16Ty, 4) RVV_PREDICATE_TYPE("__rvv_bool32_t", RvvBool32, RvvBool32Ty, 2) RVV_PREDICATE_TYPE("__rvv_bool64_t", RvvBool64, RvvBool64Ty, 1) +//===- Tuple vector types -------------------------------------------------===// +//===- Int8 tuple types --------------------------------------------------===// +RVV_VECTOR_TYPE_INT("__rvv_int8mf8x2_t", RvvInt8mf8x2, RvvInt8mf8x2Ty, 1, 8, 2, true) +RVV_VECTOR_TYPE_INT("__rvv_int8mf8x3_t", RvvInt8mf8x3, RvvInt8mf8x3Ty, 1, 8, 3, true) +RVV_VECTOR_TYPE_INT("__rvv_int8mf8x4_t", RvvInt8mf8x4, RvvInt8mf8x4Ty, 1, 8, 4, true) +RVV_VECTOR_TYPE_INT("__rvv_int8mf8x5_t", RvvInt8mf8x5, RvvInt8mf8x5Ty, 1, 8, 5, true) +RVV_VECTOR_TYPE_INT("__rvv_int8mf8x6_t", RvvInt8mf8x6, RvvInt8mf8x6Ty, 1, 8, 6, true) +RVV_VECTOR_TYPE_INT("__rvv_int8mf8x7_t", RvvInt8mf8x7, RvvInt8mf8x7Ty, 1, 8, 7, true) +RVV_VECTOR_TYPE_INT("__rvv_int8mf8x8_t", RvvInt8mf8x8, RvvInt8mf8x8Ty, 1, 8, 8, true) + +RVV_VECTOR_TYPE_INT("__rvv_int8mf4x2_t", RvvInt8mf4x2, RvvInt8mf4x2Ty, 2, 8, 2, true) +RVV_VECTOR_TYPE_INT("__rvv_int8mf4x3_t", RvvInt8mf4x3, RvvInt8mf4x3Ty, 2, 8, 3, true) +RVV_VECTOR_TYPE_INT("__rvv_int8mf4x4_t", RvvInt8mf4x4, RvvInt8mf4x4Ty, 2, 8, 4, true) +RVV_VECTOR_TYPE_INT("__rvv_int8mf4x5_t", RvvInt8mf4x5, RvvInt8mf4x5Ty, 2, 8, 5, true) +RVV_VECTOR_TYPE_INT("__rvv_int8mf4x6_t", RvvInt8mf4x6, RvvInt8mf4x6Ty, 2, 8, 6, true) +RVV_VECTOR_TYPE_INT("__rvv_int8mf4x7_t", RvvInt8mf4x7, RvvInt8mf4x7Ty, 2, 8, 7, true) +RVV_VECTOR_TYPE_INT("__rvv_int8mf4x8_t", RvvInt8mf4x8, RvvInt8mf4x8Ty, 2, 8, 8, true) + +RVV_VECTOR_TYPE_INT("__rvv_int8mf2x2_t", RvvInt8mf2x2, RvvInt8mf2x2Ty, 4, 8, 2, true) +RVV_VECTOR_TYPE_INT("__rvv_int8mf2x3_t", RvvInt8mf2x3, RvvInt8mf2x3Ty, 4, 8, 3, true) +RVV_VECTOR_TYPE_INT("__rvv_int8mf2x4_t", RvvInt8mf2x4, RvvInt8mf2x4Ty, 4, 8, 4, true) +RVV_VECTOR_TYPE_INT("__rvv_int8mf2x5_t", RvvInt8mf2x5, RvvInt8mf2x5Ty, 4, 8, 5, true) +RVV_VECTOR_TYPE_INT("__rvv_int8mf2x6_t", RvvInt8mf2x6, RvvInt8mf2x6Ty, 4, 8, 6, true) +RVV_VECTOR_TYPE_INT("__rvv_int8mf2x7_t", RvvInt8mf2x7, RvvInt8mf2x7Ty, 4, 8, 7, true) +RVV_VECTOR_TYPE_INT("__rvv_int8mf2x8_t", RvvInt8mf2x8, RvvInt8mf2x8Ty, 4, 8, 8, true) + +RVV_VECTOR_TYPE_INT("__rvv_int8m1x2_t", RvvInt8m1x2, RvvInt8m1x2Ty, 8, 8, 2, true) +RVV_VECTOR_TYPE_INT("__rvv_int8m1x3_t", RvvInt8m1x3, RvvInt8m1x3Ty, 8, 8, 3, true) +RVV_VECTOR_TYPE_INT("__rvv_int8m1x4_t", RvvInt8m1x4, RvvInt8m1x4Ty, 8, 8, 4, true) +RVV_VECTOR_TYPE_INT("__rvv_int8m1x5_t", RvvInt8m1x5, RvvInt8m1x5Ty, 8, 8, 5, true) +RVV_VECTOR_TYPE_INT("__rvv_int8m1x6_t", RvvInt8m1x6, RvvInt8m1x6Ty, 8, 8, 6, true) +RVV_VECTOR_TYPE_INT("__rvv_int8m1x7_t", RvvInt8m1x7, RvvInt8m1x7Ty, 8, 8, 7, true) +RVV_VECTOR_TYPE_INT("__rvv_int8m1x8_t", RvvInt8m1x8, RvvInt8m1x8Ty, 8, 8, 8, true) + +RVV_VECTOR_TYPE_INT("__rvv_int8m2x2_t", RvvInt8m2x2, RvvInt8m2x2Ty, 16, 8, 2, true) +RVV_VECTOR_TYPE_INT("__rvv_int8m2x3_t", RvvInt8m2x3, RvvInt8m2x3Ty, 16, 8, 3, true) +RVV_VECTOR_TYPE_INT("__rvv_int8m2x4_t", RvvInt8m2x4, RvvInt8m2x4Ty, 16, 8, 4, true) + +RVV_VECTOR_TYPE_INT("__rvv_int8m4x2_t", RvvInt8m4x2, RvvInt8m4x2Ty, 32, 8, 2, true) + +//===- Uint8 tuple types -------------------------------------------------===// +RVV_VECTOR_TYPE_INT("__rvv_uint8mf8x2_t", RvvUint8mf8x2, RvvUint8mf8x2Ty, 1, 8, 2, false) +RVV_VECTOR_TYPE_INT("__rvv_uint8mf8x3_t", RvvUint8mf8x3, RvvUint8mf8x3Ty, 1, 8, 3, false) +RVV_VECTOR_TYPE_INT("__rvv_uint8mf8x4_t", RvvUint8mf8x4, RvvUint8mf8x4Ty, 1, 8, 4, false) +RVV_VECTOR_TYPE_INT("__rvv_uint8mf8x5_t", RvvUint8mf8x5, RvvUint8mf8x5Ty, 1, 8, 5, false) +RVV_VECTOR_TYPE_INT("__rvv_uint8mf8x6_t", RvvUint8mf8x6, RvvUint8mf8x6Ty, 1, 8, 6, false) +RVV_VECTOR_TYPE_INT("__rvv_uint8mf8x7_t", RvvUint8mf8x7, RvvUint8mf8x7Ty, 1, 8, 7, false) +RVV_VECTOR_TYPE_INT("__rvv_uint8mf8x8_t", RvvUint8mf8x8, RvvUint8mf8x8Ty, 1, 8, 8, false) + +RVV_VECTOR_TYPE_INT("__rvv_uint8mf4x2_t", RvvUint8mf4x2, RvvUint8mf4x2Ty, 2, 8, 2, false) +RVV_VECTOR_TYPE_INT("__rvv_uint8mf4x3_t", RvvUint8mf4x3, RvvUint8mf4x3Ty, 2, 8, 3, false) +RVV_VECTOR_TYPE_INT("__rvv_uint8mf4x4_t", RvvUint8mf4x4, RvvUint8mf4x4Ty, 2, 8, 4, false) +RVV_VECTOR_TYPE_INT("__rvv_uint8mf4x5_t", RvvUint8mf4x5, RvvUint8mf4x5Ty, 2, 8, 5, false) +RVV_VECTOR_TYPE_INT("__rvv_uint8mf4x6_t", RvvUint8mf4x6, RvvUint8mf4x6Ty, 2, 8, 6, false) +RVV_VECTOR_TYPE_INT("__rvv_uint8mf4x7_t", RvvUint8mf4x7, RvvUint8mf4x7Ty, 2, 8, 7, false) +RVV_VECTOR_TYPE_INT("__rvv_uint8mf4x8_t", RvvUint8mf4x8, RvvUint8mf4x8Ty, 2, 8, 8, false) + +RVV_VECTOR_TYPE_INT("__rvv_uint8mf2x2_t", RvvUint8mf2x2, RvvUint8mf2x2Ty, 4, 8, 2, false) +RVV_VECTOR_TYPE_INT("__rvv_uint8mf2x3_t", RvvUint8mf2x3, RvvUint8mf2x3Ty, 4, 8, 3, false) +RVV_VECTOR_TYPE_INT("__rvv_uint8mf2x4_t", RvvUint8mf2x4, RvvUint8mf2x4Ty, 4, 8, 4, false) +RVV_VECTOR_TYPE_INT("__rvv_uint8mf2x5_t", RvvUint8mf2x5, RvvUint8mf2x5Ty, 4, 8, 5, false) +RVV_VECTOR_TYPE_INT("__rvv_uint8mf2x6_t", RvvUint8mf2x6, RvvUint8mf2x6Ty, 4, 8, 6, false) +RVV_VECTOR_TYPE_INT("__rvv_uint8mf2x7_t", RvvUint8mf2x7, RvvUint8mf2x7Ty, 4, 8, 7, false) +RVV_VECTOR_TYPE_INT("__rvv_uint8mf2x8_t", RvvUint8mf2x8, RvvUint8mf2x8Ty, 4, 8, 8, false) + +RVV_VECTOR_TYPE_INT("__rvv_uint8m1x2_t", RvvUint8m1x2, RvvUint8m1x2Ty, 8, 8, 2, false) +RVV_VECTOR_TYPE_INT("__rvv_uint8m1x3_t", RvvUint8m1x3, RvvUint8m1x3Ty, 8, 8, 3, false) +RVV_VECTOR_TYPE_INT("__rvv_uint8m1x4_t", RvvUint8m1x4, RvvUint8m1x4Ty, 8, 8, 4, false) +RVV_VECTOR_TYPE_INT("__rvv_uint8m1x5_t", RvvUint8m1x5, RvvUint8m1x5Ty, 8, 8, 5, false) +RVV_VECTOR_TYPE_INT("__rvv_uint8m1x6_t", RvvUint8m1x6, RvvUint8m1x6Ty, 8, 8, 6, false) +RVV_VECTOR_TYPE_INT("__rvv_uint8m1x7_t", RvvUint8m1x7, RvvUint8m1x7Ty, 8, 8, 7, false) +RVV_VECTOR_TYPE_INT("__rvv_uint8m1x8_t", RvvUint8m1x8, RvvUint8m1x8Ty, 8, 8, 8, false) + +RVV_VECTOR_TYPE_INT("__rvv_uint8m2x2_t", RvvUint8m2x2, RvvUint8m2x2Ty, 16, 8, 2, false) +RVV_VECTOR_TYPE_INT("__rvv_uint8m2x3_t", RvvUint8m2x3, RvvUint8m2x3Ty, 16, 8, 3, false) +RVV_VECTOR_TYPE_INT("__rvv_uint8m2x4_t", RvvUint8m2x4, RvvUint8m2x4Ty, 16, 8, 4, false) + +RVV_VECTOR_TYPE_INT("__rvv_uint8m4x2_t", RvvUint8m4x2, RvvUint8m4x2Ty, 32, 8, 2, false) + +//===- Int16 tuple types --------------------------------------------------===// +RVV_VECTOR_TYPE_INT("__rvv_int16mf4x2_t", RvvInt16mf4x2, RvvInt16mf4x2Ty, 1, 16, 2, true) +RVV_VECTOR_TYPE_INT("__rvv_int16mf4x3_t", RvvInt16mf4x3, RvvInt16mf4x3Ty, 1, 16, 3, true) +RVV_VECTOR_TYPE_INT("__rvv_int16mf4x4_t", RvvInt16mf4x4, RvvInt16mf4x4Ty, 1, 16, 4, true) +RVV_VECTOR_TYPE_INT("__rvv_int16mf4x5_t", RvvInt16mf4x5, RvvInt16mf4x5Ty, 1, 16, 5, true) +RVV_VECTOR_TYPE_INT("__rvv_int16mf4x6_t", RvvInt16mf4x6, RvvInt16mf4x6Ty, 1, 16, 6, true) +RVV_VECTOR_TYPE_INT("__rvv_int16mf4x7_t", RvvInt16mf4x7, RvvInt16mf4x7Ty, 1, 16, 7, true) +RVV_VECTOR_TYPE_INT("__rvv_int16mf4x8_t", RvvInt16mf4x8, RvvInt16mf4x8Ty, 1, 16, 8, true) + +RVV_VECTOR_TYPE_INT("__rvv_int16mf2x2_t", RvvInt16mf2x2, RvvInt16mf2x2Ty, 2, 16, 2, true) +RVV_VECTOR_TYPE_INT("__rvv_int16mf2x3_t", RvvInt16mf2x3, RvvInt16mf2x3Ty, 2, 16, 3, true) +RVV_VECTOR_TYPE_INT("__rvv_int16mf2x4_t", RvvInt16mf2x4, RvvInt16mf2x4Ty, 2, 16, 4, true) +RVV_VECTOR_TYPE_INT("__rvv_int16mf2x5_t", RvvInt16mf2x5, RvvInt16mf2x5Ty, 2, 16, 5, true) +RVV_VECTOR_TYPE_INT("__rvv_int16mf2x6_t", RvvInt16mf2x6, RvvInt16mf2x6Ty, 2, 16, 6, true) +RVV_VECTOR_TYPE_INT("__rvv_int16mf2x7_t", RvvInt16mf2x7, RvvInt16mf2x7Ty, 2, 16, 7, true) +RVV_VECTOR_TYPE_INT("__rvv_int16mf2x8_t", RvvInt16mf2x8, RvvInt16mf2x8Ty, 2, 16, 8, true) + +RVV_VECTOR_TYPE_INT("__rvv_int16m1x2_t", RvvInt16m1x2, RvvInt16m1x2Ty, 4, 16, 2, true) +RVV_VECTOR_TYPE_INT("__rvv_int16m1x3_t", RvvInt16m1x3, RvvInt16m1x3Ty, 4, 16, 3, true) +RVV_VECTOR_TYPE_INT("__rvv_int16m1x4_t", RvvInt16m1x4, RvvInt16m1x4Ty, 4, 16, 4, true) +RVV_VECTOR_TYPE_INT("__rvv_int16m1x5_t", RvvInt16m1x5, RvvInt16m1x5Ty, 4, 16, 5, true) +RVV_VECTOR_TYPE_INT("__rvv_int16m1x6_t", RvvInt16m1x6, RvvInt16m1x6Ty, 4, 16, 6, true) +RVV_VECTOR_TYPE_INT("__rvv_int16m1x7_t", RvvInt16m1x7, RvvInt16m1x7Ty, 4, 16, 7, true) +RVV_VECTOR_TYPE_INT("__rvv_int16m1x8_t", RvvInt16m1x8, RvvInt16m1x8Ty, 4, 16, 8, true) + +RVV_VECTOR_TYPE_INT("__rvv_int16m2x2_t", RvvInt16m2x2, RvvInt16m2x2Ty, 8, 16, 2, true) +RVV_VECTOR_TYPE_INT("__rvv_int16m2x3_t", RvvInt16m2x3, RvvInt16m2x3Ty, 8, 16, 3, true) +RVV_VECTOR_TYPE_INT("__rvv_int16m2x4_t", RvvInt16m2x4, RvvInt16m2x4Ty, 8, 16, 4, true) + +RVV_VECTOR_TYPE_INT("__rvv_int16m4x2_t", RvvInt16m4x2, RvvInt16m4x2Ty, 16, 16, 2, true) + +//===- Uint16 tuple types -------------------------------------------------===// +RVV_VECTOR_TYPE_INT("__rvv_uint16mf4x2_t", RvvUint16mf4x2, RvvUint16mf4x2Ty, 1, 16, 2, false) +RVV_VECTOR_TYPE_INT("__rvv_uint16mf4x3_t", RvvUint16mf4x3, RvvUint16mf4x3Ty, 1, 16, 3, false) +RVV_VECTOR_TYPE_INT("__rvv_uint16mf4x4_t", RvvUint16mf4x4, RvvUint16mf4x4Ty, 1, 16, 4, false) +RVV_VECTOR_TYPE_INT("__rvv_uint16mf4x5_t", RvvUint16mf4x5, RvvUint16mf4x5Ty, 1, 16, 5, false) +RVV_VECTOR_TYPE_INT("__rvv_uint16mf4x6_t", RvvUint16mf4x6, RvvUint16mf4x6Ty, 1, 16, 6, false) +RVV_VECTOR_TYPE_INT("__rvv_uint16mf4x7_t", RvvUint16mf4x7, RvvUint16mf4x7Ty, 1, 16, 7, false) +RVV_VECTOR_TYPE_INT("__rvv_uint16mf4x8_t", RvvUint16mf4x8, RvvUint16mf4x8Ty, 1, 16, 8, false) + +RVV_VECTOR_TYPE_INT("__rvv_uint16mf2x2_t", RvvUint16mf2x2, RvvUint16mf2x2Ty, 2, 16, 2, false) +RVV_VECTOR_TYPE_INT("__rvv_uint16mf2x3_t", RvvUint16mf2x3, RvvUint16mf2x3Ty, 2, 16, 3, false) +RVV_VECTOR_TYPE_INT("__rvv_uint16mf2x4_t", RvvUint16mf2x4, RvvUint16mf2x4Ty, 2, 16, 4, false) +RVV_VECTOR_TYPE_INT("__rvv_uint16mf2x5_t", RvvUint16mf2x5, RvvUint16mf2x5Ty, 2, 16, 5, false) +RVV_VECTOR_TYPE_INT("__rvv_uint16mf2x6_t", RvvUint16mf2x6, RvvUint16mf2x6Ty, 2, 16, 6, false) +RVV_VECTOR_TYPE_INT("__rvv_uint16mf2x7_t", RvvUint16mf2x7, RvvUint16mf2x7Ty, 2, 16, 7, false) +RVV_VECTOR_TYPE_INT("__rvv_uint16mf2x8_t", RvvUint16mf2x8, RvvUint16mf2x8Ty, 2, 16, 8, false) + +RVV_VECTOR_TYPE_INT("__rvv_uint16m1x2_t", RvvUint16m1x2, RvvUint16m1x2Ty, 4, 16, 2, false) +RVV_VECTOR_TYPE_INT("__rvv_uint16m1x3_t", RvvUint16m1x3, RvvUint16m1x3Ty, 4, 16, 3, false) +RVV_VECTOR_TYPE_INT("__rvv_uint16m1x4_t", RvvUint16m1x4, RvvUint16m1x4Ty, 4, 16, 4, false) +RVV_VECTOR_TYPE_INT("__rvv_uint16m1x5_t", RvvUint16m1x5, RvvUint16m1x5Ty, 4, 16, 5, false) +RVV_VECTOR_TYPE_INT("__rvv_uint16m1x6_t", RvvUint16m1x6, RvvUint16m1x6Ty, 4, 16, 6, false) +RVV_VECTOR_TYPE_INT("__rvv_uint16m1x7_t", RvvUint16m1x7, RvvUint16m1x7Ty, 4, 16, 7, false) +RVV_VECTOR_TYPE_INT("__rvv_uint16m1x8_t", RvvUint16m1x8, RvvUint16m1x8Ty, 4, 16, 8, false) + +RVV_VECTOR_TYPE_INT("__rvv_uint16m2x2_t", RvvUint16m2x2, RvvUint16m2x2Ty, 8, 16, 2, false) +RVV_VECTOR_TYPE_INT("__rvv_uint16m2x3_t", RvvUint16m2x3, RvvUint16m2x3Ty, 8, 16, 3, false) +RVV_VECTOR_TYPE_INT("__rvv_uint16m2x4_t", RvvUint16m2x4, RvvUint16m2x4Ty, 8, 16, 4, false) + +RVV_VECTOR_TYPE_INT("__rvv_uint16m4x2_t", RvvUint16m4x2, RvvUint16m4x2Ty, 16, 16, 2, false) + +//===- Int32 tuple types --------------------------------------------------===// +RVV_VECTOR_TYPE_INT("__rvv_int32mf2x2_t", RvvInt32mf2x2, RvvInt32mf2x2Ty, 1, 32, 2, true) +RVV_VECTOR_TYPE_INT("__rvv_int32mf2x3_t", RvvInt32mf2x3, RvvInt32mf2x3Ty, 1, 32, 3, true) +RVV_VECTOR_TYPE_INT("__rvv_int32mf2x4_t", RvvInt32mf2x4, RvvInt32mf2x4Ty, 1, 32, 4, true) +RVV_VECTOR_TYPE_INT("__rvv_int32mf2x5_t", RvvInt32mf2x5, RvvInt32mf2x5Ty, 1, 32, 5, true) +RVV_VECTOR_TYPE_INT("__rvv_int32mf2x6_t", RvvInt32mf2x6, RvvInt32mf2x6Ty, 1, 32, 6, true) +RVV_VECTOR_TYPE_INT("__rvv_int32mf2x7_t", RvvInt32mf2x7, RvvInt32mf2x7Ty, 1, 32, 7, true) +RVV_VECTOR_TYPE_INT("__rvv_int32mf2x8_t", RvvInt32mf2x8, RvvInt32mf2x8Ty, 1, 32, 8, true) + +RVV_VECTOR_TYPE_INT("__rvv_int32m1x2_t", RvvInt32m1x2, RvvInt32m1x2Ty, 2, 32, 2, true) +RVV_VECTOR_TYPE_INT("__rvv_int32m1x3_t", RvvInt32m1x3, RvvInt32m1x3Ty, 2, 32, 3, true) +RVV_VECTOR_TYPE_INT("__rvv_int32m1x4_t", RvvInt32m1x4, RvvInt32m1x4Ty, 2, 32, 4, true) +RVV_VECTOR_TYPE_INT("__rvv_int32m1x5_t", RvvInt32m1x5, RvvInt32m1x5Ty, 2, 32, 5, true) +RVV_VECTOR_TYPE_INT("__rvv_int32m1x6_t", RvvInt32m1x6, RvvInt32m1x6Ty, 2, 32, 6, true) +RVV_VECTOR_TYPE_INT("__rvv_int32m1x7_t", RvvInt32m1x7, RvvInt32m1x7Ty, 2, 32, 7, true) +RVV_VECTOR_TYPE_INT("__rvv_int32m1x8_t", RvvInt32m1x8, RvvInt32m1x8Ty, 2, 32, 8, true) + +RVV_VECTOR_TYPE_INT("__rvv_int32m2x2_t", RvvInt32m2x2, RvvInt32m2x2Ty, 4, 32, 2, true) +RVV_VECTOR_TYPE_INT("__rvv_int32m2x3_t", RvvInt32m2x3, RvvInt32m2x3Ty, 4, 32, 3, true) +RVV_VECTOR_TYPE_INT("__rvv_int32m2x4_t", RvvInt32m2x4, RvvInt32m2x4Ty, 4, 32, 4, true) + +RVV_VECTOR_TYPE_INT("__rvv_int32m4x2_t", RvvInt32m4x2, RvvInt32m4x2Ty, 8, 32, 2, true) + +//===- Uint32 tuple types -------------------------------------------------===// +RVV_VECTOR_TYPE_INT("__rvv_uint32mf2x2_t", RvvUint32mf2x2, RvvUint32mf2x2Ty, 1, 32, 2, false) +RVV_VECTOR_TYPE_INT("__rvv_uint32mf2x3_t", RvvUint32mf2x3, RvvUint32mf2x3Ty, 1, 32, 3, false) +RVV_VECTOR_TYPE_INT("__rvv_uint32mf2x4_t", RvvUint32mf2x4, RvvUint32mf2x4Ty, 1, 32, 4, false) +RVV_VECTOR_TYPE_INT("__rvv_uint32mf2x5_t", RvvUint32mf2x5, RvvUint32mf2x5Ty, 1, 32, 5, false) +RVV_VECTOR_TYPE_INT("__rvv_uint32mf2x6_t", RvvUint32mf2x6, RvvUint32mf2x6Ty, 1, 32, 6, false) +RVV_VECTOR_TYPE_INT("__rvv_uint32mf2x7_t", RvvUint32mf2x7, RvvUint32mf2x7Ty, 1, 32, 7, false) +RVV_VECTOR_TYPE_INT("__rvv_uint32mf2x8_t", RvvUint32mf2x8, RvvUint32mf2x8Ty, 1, 32, 8, false) + +RVV_VECTOR_TYPE_INT("__rvv_uint32m1x2_t", RvvUint32m1x2, RvvUint32m1x2Ty, 2, 32, 2, false) +RVV_VECTOR_TYPE_INT("__rvv_uint32m1x3_t", RvvUint32m1x3, RvvUint32m1x3Ty, 2, 32, 3, false) +RVV_VECTOR_TYPE_INT("__rvv_uint32m1x4_t", RvvUint32m1x4, RvvUint32m1x4Ty, 2, 32, 4, false) +RVV_VECTOR_TYPE_INT("__rvv_uint32m1x5_t", RvvUint32m1x5, RvvUint32m1x5Ty, 2, 32, 5, false) +RVV_VECTOR_TYPE_INT("__rvv_uint32m1x6_t", RvvUint32m1x6, RvvUint32m1x6Ty, 2, 32, 6, false) +RVV_VECTOR_TYPE_INT("__rvv_uint32m1x7_t", RvvUint32m1x7, RvvUint32m1x7Ty, 2, 32, 7, false) +RVV_VECTOR_TYPE_INT("__rvv_uint32m1x8_t", RvvUint32m1x8, RvvUint32m1x8Ty, 2, 32, 8, false) + +RVV_VECTOR_TYPE_INT("__rvv_uint32m2x2_t", RvvUint32m2x2, RvvUint32m2x2Ty, 4, 32, 2, false) +RVV_VECTOR_TYPE_INT("__rvv_uint32m2x3_t", RvvUint32m2x3, RvvUint32m2x3Ty, 4, 32, 3, false) +RVV_VECTOR_TYPE_INT("__rvv_uint32m2x4_t", RvvUint32m2x4, RvvUint32m2x4Ty, 4, 32, 4, false) + +RVV_VECTOR_TYPE_INT("__rvv_uint32m4x2_t", RvvUint32m4x2, RvvUint32m4x2Ty, 8, 32, 2, false) + +//===- Int64 tuple types -------------------------------------------------===// +RVV_VECTOR_TYPE_INT("__rvv_int64m1x2_t", RvvInt64m1x2, RvvInt64m1x2Ty, 1, 64, 2, true) +RVV_VECTOR_TYPE_INT("__rvv_int64m1x3_t", RvvInt64m1x3, RvvInt64m1x3Ty, 1, 64, 3, true) +RVV_VECTOR_TYPE_INT("__rvv_int64m1x4_t", RvvInt64m1x4, RvvInt64m1x4Ty, 1, 64, 4, true) +RVV_VECTOR_TYPE_INT("__rvv_int64m1x5_t", RvvInt64m1x5, RvvInt64m1x5Ty, 1, 64, 5, true) +RVV_VECTOR_TYPE_INT("__rvv_int64m1x6_t", RvvInt64m1x6, RvvInt64m1x6Ty, 1, 64, 6, true) +RVV_VECTOR_TYPE_INT("__rvv_int64m1x7_t", RvvInt64m1x7, RvvInt64m1x7Ty, 1, 64, 7, true) +RVV_VECTOR_TYPE_INT("__rvv_int64m1x8_t", RvvInt64m1x8, RvvInt64m1x8Ty, 1, 64, 8, true) + +RVV_VECTOR_TYPE_INT("__rvv_int64m2x2_t", RvvInt64m2x2, RvvInt64m2x2Ty, 2, 64, 2, true) +RVV_VECTOR_TYPE_INT("__rvv_int64m2x3_t", RvvInt64m2x3, RvvInt64m2x3Ty, 2, 64, 3, true) +RVV_VECTOR_TYPE_INT("__rvv_int64m2x4_t", RvvInt64m2x4, RvvInt64m2x4Ty, 2, 64, 4, true) + +RVV_VECTOR_TYPE_INT("__rvv_int64m4x2_t", RvvInt64m4x2, RvvInt64m4x2Ty, 4, 64, 2, true) + +//===- Uint64 tuple types -------------------------------------------------===// +RVV_VECTOR_TYPE_INT("__rvv_uint64m1x2_t", RvvUint64m1x2, RvvUint64m1x2Ty, 1, 64, 2, false) +RVV_VECTOR_TYPE_INT("__rvv_uint64m1x3_t", RvvUint64m1x3, RvvUint64m1x3Ty, 1, 64, 3, false) +RVV_VECTOR_TYPE_INT("__rvv_uint64m1x4_t", RvvUint64m1x4, RvvUint64m1x4Ty, 1, 64, 4, false) +RVV_VECTOR_TYPE_INT("__rvv_uint64m1x5_t", RvvUint64m1x5, RvvUint64m1x5Ty, 1, 64, 5, false) +RVV_VECTOR_TYPE_INT("__rvv_uint64m1x6_t", RvvUint64m1x6, RvvUint64m1x6Ty, 1, 64, 6, false) +RVV_VECTOR_TYPE_INT("__rvv_uint64m1x7_t", RvvUint64m1x7, RvvUint64m1x7Ty, 1, 64, 7, false) +RVV_VECTOR_TYPE_INT("__rvv_uint64m1x8_t", RvvUint64m1x8, RvvUint64m1x8Ty, 1, 64, 8, false) + +RVV_VECTOR_TYPE_INT("__rvv_uint64m2x2_t", RvvUint64m2x2, RvvUint64m2x2Ty, 2, 64, 2, false) +RVV_VECTOR_TYPE_INT("__rvv_uint64m2x3_t", RvvUint64m2x3, RvvUint64m2x3Ty, 2, 64, 3, false) +RVV_VECTOR_TYPE_INT("__rvv_uint64m2x4_t", RvvUint64m2x4, RvvUint64m2x4Ty, 2, 64, 4, false) + +RVV_VECTOR_TYPE_INT("__rvv_uint64m4x2_t", RvvUint64m4x2, RvvUint64m4x2Ty, 4, 64, 2, false) + +//===- Float16 tuple types --------------------------------------------------===// +RVV_VECTOR_TYPE_FLOAT("__rvv_float16mf4x2_t", RvvFloat16mf4x2, RvvFloat16mf4x2Ty, 1, 16, 2) +RVV_VECTOR_TYPE_FLOAT("__rvv_float16mf4x3_t", RvvFloat16mf4x3, RvvFloat16mf4x3Ty, 1, 16, 3) +RVV_VECTOR_TYPE_FLOAT("__rvv_float16mf4x4_t", RvvFloat16mf4x4, RvvFloat16mf4x4Ty, 1, 16, 4) +RVV_VECTOR_TYPE_FLOAT("__rvv_float16mf4x5_t", RvvFloat16mf4x5, RvvFloat16mf4x5Ty, 1, 16, 5) +RVV_VECTOR_TYPE_FLOAT("__rvv_float16mf4x6_t", RvvFloat16mf4x6, RvvFloat16mf4x6Ty, 1, 16, 6) +RVV_VECTOR_TYPE_FLOAT("__rvv_float16mf4x7_t", RvvFloat16mf4x7, RvvFloat16mf4x7Ty, 1, 16, 7) +RVV_VECTOR_TYPE_FLOAT("__rvv_float16mf4x8_t", RvvFloat16mf4x8, RvvFloat16mf4x8Ty, 1, 16, 8) + +RVV_VECTOR_TYPE_FLOAT("__rvv_float16mf2x2_t", RvvFloat16mf2x2, RvvFloat16mf2x2Ty, 2, 16, 2) +RVV_VECTOR_TYPE_FLOAT("__rvv_float16mf2x3_t", RvvFloat16mf2x3, RvvFloat16mf2x3Ty, 2, 16, 3) +RVV_VECTOR_TYPE_FLOAT("__rvv_float16mf2x4_t", RvvFloat16mf2x4, RvvFloat16mf2x4Ty, 2, 16, 4) +RVV_VECTOR_TYPE_FLOAT("__rvv_float16mf2x5_t", RvvFloat16mf2x5, RvvFloat16mf2x5Ty, 2, 16, 5) +RVV_VECTOR_TYPE_FLOAT("__rvv_float16mf2x6_t", RvvFloat16mf2x6, RvvFloat16mf2x6Ty, 2, 16, 6) +RVV_VECTOR_TYPE_FLOAT("__rvv_float16mf2x7_t", RvvFloat16mf2x7, RvvFloat16mf2x7Ty, 2, 16, 7) +RVV_VECTOR_TYPE_FLOAT("__rvv_float16mf2x8_t", RvvFloat16mf2x8, RvvFloat16mf2x8Ty, 2, 16, 8) + +RVV_VECTOR_TYPE_FLOAT("__rvv_float16m1x2_t", RvvFloat16m1x2, RvvFloat16m1x2Ty, 4, 16, 2) +RVV_VECTOR_TYPE_FLOAT("__rvv_float16m1x3_t", RvvFloat16m1x3, RvvFloat16m1x3Ty, 4, 16, 3) +RVV_VECTOR_TYPE_FLOAT("__rvv_float16m1x4_t", RvvFloat16m1x4, RvvFloat16m1x4Ty, 4, 16, 4) +RVV_VECTOR_TYPE_FLOAT("__rvv_float16m1x5_t", RvvFloat16m1x5, RvvFloat16m1x5Ty, 4, 16, 5) +RVV_VECTOR_TYPE_FLOAT("__rvv_float16m1x6_t", RvvFloat16m1x6, RvvFloat16m1x6Ty, 4, 16, 6) +RVV_VECTOR_TYPE_FLOAT("__rvv_float16m1x7_t", RvvFloat16m1x7, RvvFloat16m1x7Ty, 4, 16, 7) +RVV_VECTOR_TYPE_FLOAT("__rvv_float16m1x8_t", RvvFloat16m1x8, RvvFloat16m1x8Ty, 4, 16, 8) + +RVV_VECTOR_TYPE_FLOAT("__rvv_float16m2x2_t", RvvFloat16m2x2, RvvFloat16m2x2Ty, 8, 16, 2) +RVV_VECTOR_TYPE_FLOAT("__rvv_float16m2x3_t", RvvFloat16m2x3, RvvFloat16m2x3Ty, 8, 16, 3) +RVV_VECTOR_TYPE_FLOAT("__rvv_float16m2x4_t", RvvFloat16m2x4, RvvFloat16m2x4Ty, 8, 16, 4) + +RVV_VECTOR_TYPE_FLOAT("__rvv_float16m4x2_t", RvvFloat16m4x2, RvvFloat16m4x2Ty, 16, 16, 2) + +//===- Float32 tuple types --------------------------------------------------===// +RVV_VECTOR_TYPE_FLOAT("__rvv_float32mf2x2_t", RvvFloat32mf2x2, RvvFloat32mf2x2Ty, 1, 32, 2) +RVV_VECTOR_TYPE_FLOAT("__rvv_float32mf2x3_t", RvvFloat32mf2x3, RvvFloat32mf2x3Ty, 1, 32, 3) +RVV_VECTOR_TYPE_FLOAT("__rvv_float32mf2x4_t", RvvFloat32mf2x4, RvvFloat32mf2x4Ty, 1, 32, 4) +RVV_VECTOR_TYPE_FLOAT("__rvv_float32mf2x5_t", RvvFloat32mf2x5, RvvFloat32mf2x5Ty, 1, 32, 5) +RVV_VECTOR_TYPE_FLOAT("__rvv_float32mf2x6_t", RvvFloat32mf2x6, RvvFloat32mf2x6Ty, 1, 32, 6) +RVV_VECTOR_TYPE_FLOAT("__rvv_float32mf2x7_t", RvvFloat32mf2x7, RvvFloat32mf2x7Ty, 1, 32, 7) +RVV_VECTOR_TYPE_FLOAT("__rvv_float32mf2x8_t", RvvFloat32mf2x8, RvvFloat32mf2x8Ty, 1, 32, 8) + +RVV_VECTOR_TYPE_FLOAT("__rvv_float32m1x2_t", RvvFloat32m1x2, RvvFloat32m1x2Ty, 2, 32, 2) +RVV_VECTOR_TYPE_FLOAT("__rvv_float32m1x3_t", RvvFloat32m1x3, RvvFloat32m1x3Ty, 2, 32, 3) +RVV_VECTOR_TYPE_FLOAT("__rvv_float32m1x4_t", RvvFloat32m1x4, RvvFloat32m1x4Ty, 2, 32, 4) +RVV_VECTOR_TYPE_FLOAT("__rvv_float32m1x5_t", RvvFloat32m1x5, RvvFloat32m1x5Ty, 2, 32, 5) +RVV_VECTOR_TYPE_FLOAT("__rvv_float32m1x6_t", RvvFloat32m1x6, RvvFloat32m1x6Ty, 2, 32, 6) +RVV_VECTOR_TYPE_FLOAT("__rvv_float32m1x7_t", RvvFloat32m1x7, RvvFloat32m1x7Ty, 2, 32, 7) +RVV_VECTOR_TYPE_FLOAT("__rvv_float32m1x8_t", RvvFloat32m1x8, RvvFloat32m1x8Ty, 2, 32, 8) + +RVV_VECTOR_TYPE_FLOAT("__rvv_float32m2x2_t", RvvFloat32m2x2, RvvFloat32m2x2Ty, 4, 32, 2) +RVV_VECTOR_TYPE_FLOAT("__rvv_float32m2x3_t", RvvFloat32m2x3, RvvFloat32m2x3Ty, 4, 32, 3) +RVV_VECTOR_TYPE_FLOAT("__rvv_float32m2x4_t", RvvFloat32m2x4, RvvFloat32m2x4Ty, 4, 32, 4) + +RVV_VECTOR_TYPE_FLOAT("__rvv_float32m4x2_t", RvvFloat32m4x2, RvvFloat32m4x2Ty, 8, 32, 2) + +//===- Float64 tuple types -------------------------------------------------===// +RVV_VECTOR_TYPE_FLOAT("__rvv_float64m1x2_t", RvvFloat64m1x2, RvvFloat64m1x2Ty, 1, 64, 2) +RVV_VECTOR_TYPE_FLOAT("__rvv_float64m1x3_t", RvvFloat64m1x3, RvvFloat64m1x3Ty, 1, 64, 3) +RVV_VECTOR_TYPE_FLOAT("__rvv_float64m1x4_t", RvvFloat64m1x4, RvvFloat64m1x4Ty, 1, 64, 4) +RVV_VECTOR_TYPE_FLOAT("__rvv_float64m1x5_t", RvvFloat64m1x5, RvvFloat64m1x5Ty, 1, 64, 5) +RVV_VECTOR_TYPE_FLOAT("__rvv_float64m1x6_t", RvvFloat64m1x6, RvvFloat64m1x6Ty, 1, 64, 6) +RVV_VECTOR_TYPE_FLOAT("__rvv_float64m1x7_t", RvvFloat64m1x7, RvvFloat64m1x7Ty, 1, 64, 7) +RVV_VECTOR_TYPE_FLOAT("__rvv_float64m1x8_t", RvvFloat64m1x8, RvvFloat64m1x8Ty, 1, 64, 8) + +RVV_VECTOR_TYPE_FLOAT("__rvv_float64m2x2_t", RvvFloat64m2x2, RvvFloat64m2x2Ty, 2, 64, 2) +RVV_VECTOR_TYPE_FLOAT("__rvv_float64m2x3_t", RvvFloat64m2x3, RvvFloat64m2x3Ty, 2, 64, 3) +RVV_VECTOR_TYPE_FLOAT("__rvv_float64m2x4_t", RvvFloat64m2x4, RvvFloat64m2x4Ty, 2, 64, 4) + +RVV_VECTOR_TYPE_FLOAT("__rvv_float64m4x2_t", RvvFloat64m4x2, RvvFloat64m4x2Ty, 4, 64, 2) + #undef RVV_VECTOR_TYPE_FLOAT #undef RVV_VECTOR_TYPE_INT #undef RVV_VECTOR_TYPE diff --git a/contrib/llvm-project/clang/include/clang/Basic/SourceManager.h b/contrib/llvm-project/clang/include/clang/Basic/SourceManager.h index a877308f041..48c6b661121 100644 --- a/contrib/llvm-project/clang/include/clang/Basic/SourceManager.h +++ b/contrib/llvm-project/clang/include/clang/Basic/SourceManager.h @@ -992,8 +992,7 @@ public: if (OverriddenFilesInfo) { if (OverriddenFilesInfo->OverriddenFilesWithBuffer.count(File)) return true; - if (OverriddenFilesInfo->OverriddenFiles.find(File) != - OverriddenFilesInfo->OverriddenFiles.end()) + if (OverriddenFilesInfo->OverriddenFiles.contains(File)) return true; } return false; @@ -1686,7 +1685,7 @@ public: fileinfo_iterator fileinfo_begin() const { return FileInfos.begin(); } fileinfo_iterator fileinfo_end() const { return FileInfos.end(); } bool hasFileInfo(const FileEntry *File) const { - return FileInfos.find(File) != FileInfos.end(); + return FileInfos.contains(File); } /// Print statistics to stderr. diff --git a/contrib/llvm-project/clang/include/clang/Basic/Specifiers.h b/contrib/llvm-project/clang/include/clang/Basic/Specifiers.h index a8c35fed999..06279a016a5 100644 --- a/contrib/llvm-project/clang/include/clang/Basic/Specifiers.h +++ b/contrib/llvm-project/clang/include/clang/Basic/Specifiers.h @@ -19,6 +19,9 @@ #include "llvm/Support/DataTypes.h" #include "llvm/Support/ErrorHandling.h" +namespace llvm { +class raw_ostream; +} // namespace llvm namespace clang { /// Define the meaning of possible values of the kind in ExplicitSpecifier. @@ -333,6 +336,8 @@ namespace clang { // parameters are assumed to only get null on error. NullableResult, }; + /// Prints human-readable debug representation. + llvm::raw_ostream &operator<<(llvm::raw_ostream&, NullabilityKind); /// Return true if \p L has a weaker nullability annotation than \p R. The /// ordering is: Unspecified < Nullable < NonNull. diff --git a/contrib/llvm-project/clang/include/clang/Basic/StmtNodes.td b/contrib/llvm-project/clang/include/clang/Basic/StmtNodes.td index eeec01dd8c8..4b31e06eb2c 100644 --- a/contrib/llvm-project/clang/include/clang/Basic/StmtNodes.td +++ b/contrib/llvm-project/clang/include/clang/Basic/StmtNodes.td @@ -50,7 +50,7 @@ def CXXCatchStmt : StmtNode; def CXXTryStmt : StmtNode; def CXXForRangeStmt : StmtNode; -// C++ Coroutines TS statements +// C++ Coroutines statements def CoroutineBodyStmt : StmtNode; def CoreturnStmt : StmtNode; @@ -162,7 +162,7 @@ def LambdaExpr : StmtNode; def CXXFoldExpr : StmtNode; def CXXParenListInitExpr: StmtNode; -// C++ Coroutines TS expressions +// C++ Coroutines expressions def CoroutineSuspendExpr : StmtNode; def CoawaitExpr : StmtNode; def DependentCoawaitExpr : StmtNode; diff --git a/contrib/llvm-project/clang/include/clang/Basic/TargetBuiltins.h b/contrib/llvm-project/clang/include/clang/Basic/TargetBuiltins.h index 2f94e839768..8f7881abf26 100644 --- a/contrib/llvm-project/clang/include/clang/Basic/TargetBuiltins.h +++ b/contrib/llvm-project/clang/include/clang/Basic/TargetBuiltins.h @@ -48,11 +48,22 @@ namespace clang { enum { LastNEONBuiltin = NEON::FirstTSBuiltin - 1, #define BUILTIN(ID, TYPE, ATTRS) BI##ID, +#define TARGET_BUILTIN(ID, TYPE, ATTRS, FEATURE) BI##ID, #include "clang/Basic/BuiltinsSVE.def" FirstTSBuiltin, }; } + namespace SME { + enum { + LastSVEBuiltin = SVE::FirstTSBuiltin - 1, +#define BUILTIN(ID, TYPE, ATTRS) BI##ID, +#define TARGET_BUILTIN(ID, TYPE, ATTRS, FEATURE) BI##ID, +#include "clang/Basic/BuiltinsSME.def" + FirstTSBuiltin, + }; + } + /// AArch64 builtins namespace AArch64 { enum { @@ -60,6 +71,8 @@ namespace clang { LastNEONBuiltin = NEON::FirstTSBuiltin - 1, FirstSVEBuiltin = NEON::FirstTSBuiltin, LastSVEBuiltin = SVE::FirstTSBuiltin - 1, + FirstSMEBuiltin = SVE::FirstTSBuiltin, + LastSMEBuiltin = SME::FirstTSBuiltin - 1, #define BUILTIN(ID, TYPE, ATTRS) BI##ID, #include "clang/Basic/BuiltinsAArch64.def" LastTSBuiltin @@ -243,10 +256,10 @@ namespace clang { }; SVETypeFlags(uint64_t F) : Flags(F) { - EltTypeShift = llvm::countTrailingZeros(EltTypeMask); - MemEltTypeShift = llvm::countTrailingZeros(MemEltTypeMask); - MergeTypeShift = llvm::countTrailingZeros(MergeTypeMask); - SplatOperandMaskShift = llvm::countTrailingZeros(SplatOperandMask); + EltTypeShift = llvm::countr_zero(EltTypeMask); + MemEltTypeShift = llvm::countr_zero(MemEltTypeMask); + MergeTypeShift = llvm::countr_zero(MergeTypeMask); + SplatOperandMaskShift = llvm::countr_zero(SplatOperandMask); } EltType getEltType() const { @@ -288,10 +301,14 @@ namespace clang { bool isInsertOp1SVALL() const { return Flags & IsInsertOp1SVALL; } bool isGatherPrefetch() const { return Flags & IsGatherPrefetch; } bool isReverseUSDOT() const { return Flags & ReverseUSDOT; } + bool isReverseMergeAnyBinOp() const { return Flags & ReverseMergeAnyBinOp; } + bool isReverseMergeAnyAccOp() const { return Flags & ReverseMergeAnyAccOp; } bool isUndef() const { return Flags & IsUndef; } bool isTupleCreate() const { return Flags & IsTupleCreate; } bool isTupleGet() const { return Flags & IsTupleGet; } bool isTupleSet() const { return Flags & IsTupleSet; } + bool isReadZA() const { return Flags & IsReadZA; } + bool isWriteZA() const { return Flags & IsWriteZA; } uint64_t getBits() const { return Flags; } bool isFlagSet(uint64_t Flag) const { return Flags & Flag; } diff --git a/contrib/llvm-project/clang/include/clang/Basic/TargetCXXABI.h b/contrib/llvm-project/clang/include/clang/Basic/TargetCXXABI.h index e727f85edad..c113a6a048a 100644 --- a/contrib/llvm-project/clang/include/clang/Basic/TargetCXXABI.h +++ b/contrib/llvm-project/clang/include/clang/Basic/TargetCXXABI.h @@ -19,8 +19,8 @@ #include "clang/Basic/LLVM.h" #include "llvm/ADT/StringMap.h" -#include "llvm/ADT/Triple.h" #include "llvm/Support/ErrorHandling.h" +#include "llvm/TargetParser/Triple.h" namespace clang { @@ -60,9 +60,7 @@ public: static const auto &getSpelling(Kind ABIKind) { return getSpellingMap().find(ABIKind)->second; } - static bool isABI(StringRef Name) { - return getABIMap().find(Name) != getABIMap().end(); - } + static bool isABI(StringRef Name) { return getABIMap().contains(Name); } // Return true if this target should use the relative vtables C++ ABI by // default. diff --git a/contrib/llvm-project/clang/include/clang/Basic/TargetID.h b/contrib/llvm-project/clang/include/clang/Basic/TargetID.h index f1922942804..cef9cb5f0fb 100644 --- a/contrib/llvm-project/clang/include/clang/Basic/TargetID.h +++ b/contrib/llvm-project/clang/include/clang/Basic/TargetID.h @@ -11,7 +11,7 @@ #include "llvm/ADT/SmallVector.h" #include "llvm/ADT/StringMap.h" -#include "llvm/ADT/Triple.h" +#include "llvm/TargetParser/Triple.h" #include #include diff --git a/contrib/llvm-project/clang/include/clang/Basic/TargetInfo.h b/contrib/llvm-project/clang/include/clang/Basic/TargetInfo.h index bb2a453f465..41ef47eb565 100644 --- a/contrib/llvm-project/clang/include/clang/Basic/TargetInfo.h +++ b/contrib/llvm-project/clang/include/clang/Basic/TargetInfo.h @@ -29,12 +29,13 @@ #include "llvm/ADT/SmallSet.h" #include "llvm/ADT/StringMap.h" #include "llvm/ADT/StringRef.h" -#include "llvm/ADT/Triple.h" +#include "llvm/ADT/StringSet.h" #include "llvm/Frontend/OpenMP/OMPGridValues.h" #include "llvm/IR/DerivedTypes.h" #include "llvm/Support/DataTypes.h" #include "llvm/Support/Error.h" #include "llvm/Support/VersionTuple.h" +#include "llvm/TargetParser/Triple.h" #include #include #include @@ -202,7 +203,7 @@ enum OpenCLTypeKind : uint8_t { /// Exposes information about the current target. /// -class TargetInfo : public virtual TransferrableTargetInfo, +class TargetInfo : public TransferrableTargetInfo, public RefCountedBase { std::shared_ptr TargetOpts; llvm::Triple Triple; @@ -219,13 +220,15 @@ protected: bool HasFloat128; bool HasFloat16; bool HasBFloat16; + bool HasFullBFloat16; // True if the backend supports native bfloat16 + // arithmetic. Used to determine excess precision + // support in the frontend. bool HasIbm128; bool HasLongDouble; bool HasFPReturn; bool HasStrictFP; unsigned char MaxAtomicPromoteWidth, MaxAtomicInlineWidth; - unsigned short SimdDefaultAlign; std::string DataLayoutString; const char *UserLabelPrefix; const char *MCountName; @@ -265,6 +268,12 @@ protected: // as a DataLayout object. void resetDataLayout(StringRef DL, const char *UserLabelPrefix = ""); + // Target features that are read-only and should not be disabled/enabled + // by command line options. Such features are for emitting predefined + // macros or checking availability of builtin functions and can be omitted + // in function attributes in IR. + llvm::StringSet<> ReadOnlyFeatures; + public: /// Construct a target for the given options. /// @@ -649,7 +658,13 @@ public: virtual bool hasFloat16Type() const { return HasFloat16; } /// Determine whether the _BFloat16 type is supported on this target. - virtual bool hasBFloat16Type() const { return HasBFloat16; } + virtual bool hasBFloat16Type() const { + return HasBFloat16 || HasFullBFloat16; + } + + /// Determine whether the BFloat type is fully supported on this target, i.e + /// arithemtic operations. + virtual bool hasFullBFloat16Type() const { return HasFullBFloat16; } /// Determine whether the __ibm128 type is supported on this target. virtual bool hasIbm128Type() const { return HasIbm128; } @@ -757,9 +772,7 @@ public: } /// Return the mangled code of bfloat. - virtual const char *getBFloat16Mangling() const { - llvm_unreachable("bfloat not implemented on this target"); - } + virtual const char *getBFloat16Mangling() const { return "DF16b"; } /// Return the value for the C99 FLT_EVAL_METHOD macro. virtual LangOptions::FPEvalMethodKind getFPEvalMethod() const { @@ -794,10 +807,6 @@ public: /// Return the maximum vector alignment supported for the given target. unsigned getMaxVectorAlign() const { return MaxVectorAlign; } - /// Return default simd alignment for the given target. Generally, this - /// value is type-specific, but this alignment can be used for most of the - /// types for the given target. - unsigned getSimdDefaultAlign() const { return SimdDefaultAlign; } unsigned getMaxOpenCLWorkGroupSize() const { return MaxOpenCLWorkGroupSize; } @@ -1183,7 +1192,7 @@ public: } /// Returns a string of target-specific clobbers, in LLVM format. - virtual const char *getClobbers() const = 0; + virtual std::string_view getClobbers() const = 0; /// Returns true if NaN encoding is IEEE 754-2008. /// Only MIPS allows a different encoding. @@ -1338,12 +1347,16 @@ public: } /// Returns true if feature has an impact on target code - /// generation and get its dependent options in second argument. - virtual bool getFeatureDepOptions(StringRef Feature, - std::string &Options) const { + /// generation. + virtual bool doesFeatureAffectCodeGen(StringRef Feature) const { return true; } + /// For given feature return dependent ones. + virtual StringRef getFeatureDependencies(StringRef Feature) const { + return StringRef(); + } + struct BranchProtectionInfo { LangOptions::SignReturnAddressScopeKind SignReturnAddr = LangOptions::SignReturnAddressScopeKind::None; @@ -1388,6 +1401,11 @@ public: return false; } + /// Determine whether the given target feature is read only. + bool isReadOnlyFeature(StringRef Feature) const { + return ReadOnlyFeatures.count(Feature); + } + /// Identify whether this target supports multiversioning of functions, /// which requires support for cpu_supports and cpu_is functionality. bool supportsMultiVersioning() const { @@ -1705,6 +1723,9 @@ public: : std::optional(); } + /// Whether to support HIP image/texture API's. + virtual bool hasHIPImageSupport() const { return true; } + protected: /// Copy type and layout related info. void copyAuxTarget(const TargetInfo *Aux); diff --git a/contrib/llvm-project/clang/include/clang/Basic/TargetOptions.h b/contrib/llvm-project/clang/include/clang/Basic/TargetOptions.h index f9e5cedbafc..b192c856384 100644 --- a/contrib/llvm-project/clang/include/clang/Basic/TargetOptions.h +++ b/contrib/llvm-project/clang/include/clang/Basic/TargetOptions.h @@ -45,7 +45,7 @@ public: std::string ABI; /// The EABI version to use - llvm::EABI EABIVersion; + llvm::EABI EABIVersion = llvm::EABI::Default; /// If given, the version string of the linker in use. std::string LinkerVersion; @@ -88,7 +88,20 @@ public: COV_5 = 500, }; /// \brief Code object version for AMDGPU. - CodeObjectVersionKind CodeObjectVersion; + CodeObjectVersionKind CodeObjectVersion = CodeObjectVersionKind::COV_None; + + /// \brief Enumeration values for AMDGPU printf lowering scheme + enum class AMDGPUPrintfKind { + /// printf lowering scheme involving hostcalls, currently used by HIP + /// programs by default + Hostcall = 0, + + /// printf lowering scheme involving implicit printf buffers, + Buffered = 1, + }; + + /// \brief AMDGPU Printf lowering scheme + AMDGPUPrintfKind AMDGPUPrintfKindVal = AMDGPUPrintfKind::Hostcall; // The code model to be used as specified by the user. Corresponds to // CodeModel::Model enum defined in include/llvm/Support/CodeGen.h, plus diff --git a/contrib/llvm-project/clang/include/clang/Basic/Thunk.h b/contrib/llvm-project/clang/include/clang/Basic/Thunk.h index 91088be6ae7..0247e279408 100644 --- a/contrib/llvm-project/clang/include/clang/Basic/Thunk.h +++ b/contrib/llvm-project/clang/include/clang/Basic/Thunk.h @@ -26,7 +26,7 @@ class CXXMethodDecl; struct ReturnAdjustment { /// The non-virtual adjustment from the derived object to its /// nearest virtual base. - int64_t NonVirtual; + int64_t NonVirtual = 0; /// Holds the ABI-specific information about the virtual return /// adjustment, if needed. @@ -64,7 +64,7 @@ struct ReturnAdjustment { } } Virtual; - ReturnAdjustment() : NonVirtual(0) {} + ReturnAdjustment() = default; bool isEmpty() const { return !NonVirtual && Virtual.isEmpty(); } @@ -91,7 +91,7 @@ struct ReturnAdjustment { struct ThisAdjustment { /// The non-virtual adjustment from the derived object to its /// nearest virtual base. - int64_t NonVirtual; + int64_t NonVirtual = 0; /// Holds the ABI-specific information about the virtual this /// adjustment, if needed. @@ -131,7 +131,7 @@ struct ThisAdjustment { } } Virtual; - ThisAdjustment() : NonVirtual(0) {} + ThisAdjustment() = default; bool isEmpty() const { return !NonVirtual && Virtual.isEmpty(); } diff --git a/contrib/llvm-project/clang/include/clang/Basic/TokenKinds.def b/contrib/llvm-project/clang/include/clang/Basic/TokenKinds.def index 96feae991cc..ef0dad0f2dc 100644 --- a/contrib/llvm-project/clang/include/clang/Basic/TokenKinds.def +++ b/contrib/llvm-project/clang/include/clang/Basic/TokenKinds.def @@ -85,6 +85,9 @@ #ifndef PRAGMA_ANNOTATION #define PRAGMA_ANNOTATION(X) ANNOTATION(X) #endif +#ifndef INTERESTING_IDENTIFIER +#define INTERESTING_IDENTIFIER(X) +#endif //===----------------------------------------------------------------------===// // Preprocessor keywords. @@ -394,12 +397,12 @@ CXX11_KEYWORD(nullptr , KEYC2X) CXX11_KEYWORD(static_assert , KEYMSCOMPAT|KEYC2X) CXX11_KEYWORD(thread_local , KEYC2X) -// C++20 / coroutines TS keywords +// C++20 / coroutines keywords COROUTINES_KEYWORD(co_await) COROUTINES_KEYWORD(co_return) COROUTINES_KEYWORD(co_yield) -// C++ modules TS keywords +// C++20 keywords MODULES_KEYWORD(module) MODULES_KEYWORD(import) @@ -436,7 +439,9 @@ KEYWORD(__attribute , KEYALL) KEYWORD(__builtin_choose_expr , KEYALL) KEYWORD(__builtin_offsetof , KEYALL) KEYWORD(__builtin_FILE , KEYALL) +KEYWORD(__builtin_FILE_NAME , KEYALL) KEYWORD(__builtin_FUNCTION , KEYALL) +KEYWORD(__builtin_FUNCSIG , KEYMS) KEYWORD(__builtin_LINE , KEYALL) KEYWORD(__builtin_COLUMN , KEYALL) KEYWORD(__builtin_source_location , KEYCXX) @@ -518,11 +523,13 @@ TYPE_TRAIT_1(__has_unique_object_representations, // Clang-only C++ Type Traits TYPE_TRAIT_1(__is_trivially_relocatable, IsTriviallyRelocatable, KEYCXX) +TYPE_TRAIT_1(__is_trivially_equality_comparable, IsTriviallyEqualityComparable, KEYCXX) TYPE_TRAIT_1(__is_bounded_array, IsBoundedArray, KEYCXX) TYPE_TRAIT_1(__is_unbounded_array, IsUnboundedArray, KEYCXX) TYPE_TRAIT_1(__is_nullptr, IsNullPointer, KEYCXX) TYPE_TRAIT_1(__is_scoped_enum, IsScopedEnum, KEYCXX) TYPE_TRAIT_1(__is_referenceable, IsReferenceable, KEYCXX) +TYPE_TRAIT_1(__can_pass_in_regs, CanPassInRegs, KEYCXX) TYPE_TRAIT_2(__reference_binds_to_temporary, ReferenceBindsToTemporary, KEYCXX) // Embarcadero Expression Traits @@ -678,6 +685,9 @@ KEYWORD(_Nullable , KEYALL) KEYWORD(_Nullable_result , KEYALL) KEYWORD(_Null_unspecified , KEYALL) +// WebAssembly Type Extension +KEYWORD(__funcref , KEYALL) + // Microsoft extensions which should be disabled in strict conformance mode KEYWORD(__ptr64 , KEYMS) KEYWORD(__ptr32 , KEYMS) @@ -741,6 +751,12 @@ KEYWORD(__builtin_bit_cast , KEYALL) KEYWORD(__builtin_available , KEYALL) KEYWORD(__builtin_sycl_unique_stable_name, KEYSYCL) +// Keywords defined by Attr.td. +#ifndef KEYWORD_ATTRIBUTE +#define KEYWORD_ATTRIBUTE(X) KEYWORD(X, KEYALL) +#endif +#include "clang/Basic/AttrTokenKinds.inc" + // Clang-specific keywords enabled only in testing. TESTING_KEYWORD(__unknown_anytype , KEYALL) @@ -781,6 +797,17 @@ OBJC_AT_KEYWORD(dynamic) OBJC_AT_KEYWORD(import) OBJC_AT_KEYWORD(available) +//===----------------------------------------------------------------------===// +// Interesting identifiers. +//===----------------------------------------------------------------------===// +INTERESTING_IDENTIFIER(not_interesting) +INTERESTING_IDENTIFIER(FILE) +INTERESTING_IDENTIFIER(jmp_buf) +INTERESTING_IDENTIFIER(sigjmp_buf) +INTERESTING_IDENTIFIER(ucontext_t) +INTERESTING_IDENTIFIER(float_t) +INTERESTING_IDENTIFIER(double_t) + // TODO: What to do about context-sensitive keywords like: // bycopy/byref/in/inout/oneway/out? @@ -936,6 +963,9 @@ ANNOTATION(module_end) // into the name of a header unit. ANNOTATION(header_unit) +// Annotation for end of input in clang-repl. +ANNOTATION(repl_input_end) + #undef PRAGMA_ANNOTATION #undef ANNOTATION #undef TESTING_KEYWORD @@ -958,3 +988,4 @@ ANNOTATION(header_unit) #undef TOK #undef C99_KEYWORD #undef C2X_KEYWORD +#undef INTERESTING_IDENTIFIER diff --git a/contrib/llvm-project/clang/include/clang/Basic/TokenKinds.h b/contrib/llvm-project/clang/include/clang/Basic/TokenKinds.h index 6b7006651f4..e4857405bc7 100644 --- a/contrib/llvm-project/clang/include/clang/Basic/TokenKinds.h +++ b/contrib/llvm-project/clang/include/clang/Basic/TokenKinds.h @@ -44,6 +44,14 @@ enum ObjCKeywordKind { NUM_OBJC_KEYWORDS }; +/// Provides a namespace for interesting identifers such as float_t and +/// double_t. +enum InterestingIdentifierKind { +#define INTERESTING_IDENTIFIER(X) X, +#include "clang/Basic/TokenKinds.def" + NUM_INTERESTING_IDENTIFIERS +}; + /// Defines the possible values of an on-off-switch (C99 6.10.6p2). enum OnOffSwitch { OOS_ON, OOS_OFF, OOS_DEFAULT @@ -99,6 +107,13 @@ bool isAnnotation(TokenKind K); /// Return true if this is an annotation token representing a pragma. bool isPragmaAnnotation(TokenKind K); +inline constexpr bool isRegularKeywordAttribute(TokenKind K) { + return (false +#define KEYWORD_ATTRIBUTE(X) || (K == tok::kw_##X) +#include "clang/Basic/AttrTokenKinds.inc" + ); +} + } // end namespace tok } // end namespace clang diff --git a/contrib/llvm-project/clang/include/clang/Basic/TypeNodes.td b/contrib/llvm-project/clang/include/clang/Basic/TypeNodes.td index f8557d02e5b..649b071cebb 100644 --- a/contrib/llvm-project/clang/include/clang/Basic/TypeNodes.td +++ b/contrib/llvm-project/clang/include/clang/Basic/TypeNodes.td @@ -3,7 +3,7 @@ include "clang/Basic/ASTNode.td" class TypeNode : ASTNode { TypeNode Base = base; bit Abstract = abstract; -} +} /// A type node that is only used to represent dependent types in C++. For /// example, DependentTemplateSpecializationType is used to represent types diff --git a/contrib/llvm-project/clang/include/clang/Basic/WebAssemblyReferenceTypes.def b/contrib/llvm-project/clang/include/clang/Basic/WebAssemblyReferenceTypes.def new file mode 100644 index 00000000000..7c83da15150 --- /dev/null +++ b/contrib/llvm-project/clang/include/clang/Basic/WebAssemblyReferenceTypes.def @@ -0,0 +1,40 @@ +//===-- WebAssemblyReferenceTypes.def - Wasm reference types ----*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +// +// This file defines externref_t. The macros are: +// +// WASM_TYPE(Name, Id, SingletonId) +// WASM_REF_TYPE(Name, MangledName, Id, SingletonId, AS) +// +// where: +// +// - Name is the name of the builtin type. +// +// - MangledNameBase is the base used for name mangling. +// +// - BuiltinType::Id is the enumerator defining the type. +// +// - Context.SingletonId is the global singleton of this type. +// +// - AS indicates the address space for values of this type. +// +// To include this file, define either WASM_REF_TYPE or WASM_TYPE, depending on +// how much information you want. The macros will be undefined after inclusion. +// +//===----------------------------------------------------------------------===// + + +#ifndef WASM_REF_TYPE +#define WASM_REF_TYPE(Name, MangledNameBase, Id, SingletonId, AS) \ + WASM_TYPE(Name, Id, SingletonId) +#endif + +WASM_REF_TYPE("__externref_t", "externref_t", WasmExternRef, WasmExternRefTy, 10) + +#undef WASM_TYPE +#undef WASM_REF_TYPE diff --git a/contrib/llvm-project/clang/include/clang/Basic/arm_bf16.td b/contrib/llvm-project/clang/include/clang/Basic/arm_bf16.td index d837a7666d4..f70c7221f8d 100644 --- a/contrib/llvm-project/clang/include/clang/Basic/arm_bf16.td +++ b/contrib/llvm-project/clang/include/clang/Basic/arm_bf16.td @@ -1,4 +1,4 @@ -//===--- arm_fp16.td - ARM BF16 compiler interface ------------------------===// +//===--- arm_bf16.td - ARM BF16 compiler interface ------------------------===// // // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. // See https://llvm.org/LICENSE.txt for license information. diff --git a/contrib/llvm-project/clang/include/clang/Basic/arm_neon.td b/contrib/llvm-project/clang/include/clang/Basic/arm_neon.td index 94dfe80acc3..ba3764d2f77 100644 --- a/contrib/llvm-project/clang/include/clang/Basic/arm_neon.td +++ b/contrib/llvm-project/clang/include/clang/Basic/arm_neon.td @@ -2086,3 +2086,9 @@ let ArchGuard = "defined(__aarch64__)", TargetGuard = "bf16" in { "csilUcUsUiUlhfdPcPsPlQcQsQiQlQUcQUsQUiQUlQhQfQdQPcQPsQPlQPk", "bQb">; } } + +// v8.9a/v9.4a LRCPC3 intrinsics +let ArchGuard = "defined(__aarch64__)", TargetGuard = "rcpc3" in { + def VLDAP1_LANE : WInst<"vldap1_lane", ".(c*!).I", "QUlQlUlldQdPlQPl">; + def VSTL1_LANE : WInst<"vstl1_lane", "v*(.!)I", "QUlQlUlldQdPlQPl">; +} diff --git a/contrib/llvm-project/clang/include/clang/Basic/arm_sme.td b/contrib/llvm-project/clang/include/clang/Basic/arm_sme.td new file mode 100644 index 00000000000..b950f5cb8ac --- /dev/null +++ b/contrib/llvm-project/clang/include/clang/Basic/arm_sme.td @@ -0,0 +1,259 @@ +//===--- arm_sme.td - ARM SME compiler interface ------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +// +// This file defines the TableGen definitions from which the ARM SME header +// file will be generated. See: +// +// https://developer.arm.com/architectures/system-architectures/software-standards/acle +// +//===----------------------------------------------------------------------===// + +include "arm_sve_sme_incl.td" + +//////////////////////////////////////////////////////////////////////////////// +// Loads + +multiclass ZALoad ch> { + let TargetGuard = "sme" in { + def NAME # _H : MInst<"svld1_hor_" # n_suffix, "vimiPQ", t, + [IsLoad, IsOverloadNone, IsStreaming, IsSharedZA], + MemEltTyDefault, i_prefix # "_horiz", ch>; + + def NAME # _H_VNUM : MInst<"svld1_hor_vnum_" # n_suffix, "vimiPQl", t, + [IsLoad, IsOverloadNone, IsStreaming, IsSharedZA], + MemEltTyDefault, i_prefix # "_horiz", ch>; + + def NAME # _V : MInst<"svld1_ver_" # n_suffix, "vimiPQ", t, + [IsLoad, IsOverloadNone, IsStreaming, IsSharedZA], + MemEltTyDefault, i_prefix # "_vert", ch>; + + def NAME # _V_VNUM : MInst<"svld1_ver_vnum_" # n_suffix, "vimiPQl", t, + [IsLoad, IsOverloadNone, IsStreaming, IsSharedZA], + MemEltTyDefault, i_prefix # "_vert", ch>; + } +} + +defm SVLD1_ZA8 : ZALoad<"za8", "c", "aarch64_sme_ld1b", [ImmCheck<0, ImmCheck0_0>, ImmCheck<2, ImmCheck0_15>]>; +defm SVLD1_ZA16 : ZALoad<"za16", "s", "aarch64_sme_ld1h", [ImmCheck<0, ImmCheck0_1>, ImmCheck<2, ImmCheck0_7>]>; +defm SVLD1_ZA32 : ZALoad<"za32", "i", "aarch64_sme_ld1w", [ImmCheck<0, ImmCheck0_3>, ImmCheck<2, ImmCheck0_3>]>; +defm SVLD1_ZA64 : ZALoad<"za64", "l", "aarch64_sme_ld1d", [ImmCheck<0, ImmCheck0_7>, ImmCheck<2, ImmCheck0_1>]>; +defm SVLD1_ZA128 : ZALoad<"za128", "q", "aarch64_sme_ld1q", [ImmCheck<0, ImmCheck0_15>, ImmCheck<2, ImmCheck0_0>]>; + +def SVLDR_VNUM_ZA : MInst<"svldr_vnum_za", "vmiQ", "", + [IsOverloadNone, IsStreamingCompatible, IsSharedZA], + MemEltTyDefault, "aarch64_sme_ldr", + [ImmCheck<1, ImmCheck0_15>]>; + +//////////////////////////////////////////////////////////////////////////////// +// Stores + +multiclass ZAStore ch> { + let TargetGuard = "sme" in { + def NAME # _H : MInst<"svst1_hor_" # n_suffix, "vimiP%", t, + [IsStore, IsOverloadNone, IsStreaming, IsSharedZA, IsPreservesZA], + MemEltTyDefault, i_prefix # "_horiz", ch>; + + def NAME # _H_VNUM : MInst<"svst1_hor_vnum_" # n_suffix, "vimiP%l", t, + [IsStore, IsOverloadNone, IsStreaming, IsSharedZA, IsPreservesZA], + MemEltTyDefault, i_prefix # "_horiz", ch>; + + def NAME # _V : MInst<"svst1_ver_" # n_suffix, "vimiP%", t, + [IsStore, IsOverloadNone, IsStreaming, IsSharedZA, IsPreservesZA], + MemEltTyDefault, i_prefix # "_vert", ch>; + + def NAME # _V_VNUM : MInst<"svst1_ver_vnum_" # n_suffix, "vimiP%l", t, + [IsStore, IsOverloadNone, IsStreaming, IsSharedZA, IsPreservesZA], + MemEltTyDefault, i_prefix # "_vert", ch>; + } +} + +defm SVST1_ZA8 : ZAStore<"za8", "c", "aarch64_sme_st1b", [ImmCheck<0, ImmCheck0_0>, ImmCheck<2, ImmCheck0_15>]>; +defm SVST1_ZA16 : ZAStore<"za16", "s", "aarch64_sme_st1h", [ImmCheck<0, ImmCheck0_1>, ImmCheck<2, ImmCheck0_7>]>; +defm SVST1_ZA32 : ZAStore<"za32", "i", "aarch64_sme_st1w", [ImmCheck<0, ImmCheck0_3>, ImmCheck<2, ImmCheck0_3>]>; +defm SVST1_ZA64 : ZAStore<"za64", "l", "aarch64_sme_st1d", [ImmCheck<0, ImmCheck0_7>, ImmCheck<2, ImmCheck0_1>]>; +defm SVST1_ZA128 : ZAStore<"za128", "q", "aarch64_sme_st1q", [ImmCheck<0, ImmCheck0_15>, ImmCheck<2, ImmCheck0_0>]>; + +def SVSTR_VNUM_ZA : MInst<"svstr_vnum_za", "vmi%", "", + [IsOverloadNone, IsStreamingCompatible, IsSharedZA, IsPreservesZA], + MemEltTyDefault, "aarch64_sme_str", + [ImmCheck<1, ImmCheck0_15>]>; + +//////////////////////////////////////////////////////////////////////////////// +// Read horizontal/vertical ZA slices + +multiclass ZARead ch> { + let TargetGuard = "sme" in { + def NAME # _H : SInst<"svread_hor_" # n_suffix # "[_{d}]", "ddPimi", t, + MergeOp1, i_prefix # "_horiz", + [IsReadZA, IsStreaming, IsSharedZA, IsPreservesZA], ch>; + + def NAME # _V : SInst<"svread_ver_" # n_suffix # "[_{d}]", "ddPimi", t, + MergeOp1, i_prefix # "_vert", + [IsReadZA, IsStreaming, IsSharedZA, IsPreservesZA], ch>; + } +} + +defm SVREAD_ZA8 : ZARead<"za8", "cUc", "aarch64_sme_read", [ImmCheck<2, ImmCheck0_0>, ImmCheck<4, ImmCheck0_15>]>; +defm SVREAD_ZA16 : ZARead<"za16", "sUshb", "aarch64_sme_read", [ImmCheck<2, ImmCheck0_1>, ImmCheck<4, ImmCheck0_7>]>; +defm SVREAD_ZA32 : ZARead<"za32", "iUif", "aarch64_sme_read", [ImmCheck<2, ImmCheck0_3>, ImmCheck<4, ImmCheck0_3>]>; +defm SVREAD_ZA64 : ZARead<"za64", "lUld", "aarch64_sme_read", [ImmCheck<2, ImmCheck0_7>, ImmCheck<4, ImmCheck0_1>]>; +defm SVREAD_ZA128 : ZARead<"za128", "csilUcUsUiUlhbfd", "aarch64_sme_readq", [ImmCheck<2, ImmCheck0_15>, ImmCheck<4, ImmCheck0_0>]>; + +//////////////////////////////////////////////////////////////////////////////// +// Write horizontal/vertical ZA slices + +multiclass ZAWrite ch> { + let TargetGuard = "sme" in { + def NAME # _H : SInst<"svwrite_hor_" # n_suffix # "[_{d}]", "vimiPd", t, + MergeOp1, i_prefix # "_horiz", + [IsWriteZA, IsStreaming, IsSharedZA], ch>; + + def NAME # _V : SInst<"svwrite_ver_" # n_suffix # "[_{d}]", "vimiPd", t, + MergeOp1, i_prefix # "_vert", + [IsWriteZA, IsStreaming, IsSharedZA], ch>; + } +} + +defm SVWRITE_ZA8 : ZAWrite<"za8", "cUc", "aarch64_sme_write", [ImmCheck<0, ImmCheck0_0>, ImmCheck<2, ImmCheck0_15>]>; +defm SVWRITE_ZA16 : ZAWrite<"za16", "sUshb", "aarch64_sme_write", [ImmCheck<0, ImmCheck0_1>, ImmCheck<2, ImmCheck0_7>]>; +defm SVWRITE_ZA32 : ZAWrite<"za32", "iUif", "aarch64_sme_write", [ImmCheck<0, ImmCheck0_3>, ImmCheck<2, ImmCheck0_3>]>; +defm SVWRITE_ZA64 : ZAWrite<"za64", "lUld", "aarch64_sme_write", [ImmCheck<0, ImmCheck0_7>, ImmCheck<2, ImmCheck0_1>]>; +defm SVWRITE_ZA128 : ZAWrite<"za128", "csilUcUsUiUlhbfd", "aarch64_sme_writeq", [ImmCheck<0, ImmCheck0_15>, ImmCheck<2, ImmCheck0_0>]>; + +//////////////////////////////////////////////////////////////////////////////// +// SME - Zero + +let TargetGuard = "sme" in { + def SVZERO_MASK_ZA : SInst<"svzero_mask_za", "vi", "", MergeNone, "aarch64_sme_zero", + [IsOverloadNone, IsStreamingCompatible, IsSharedZA], + [ImmCheck<0, ImmCheck0_255>]>; + def SVZERO_ZA : SInst<"svzero_za", "v", "", MergeNone, "aarch64_sme_zero", + [IsOverloadNone, IsStreamingCompatible, IsSharedZA]>; +} + +//////////////////////////////////////////////////////////////////////////////// +// SME - Counting elements in a streaming vector + +multiclass ZACount { + let TargetGuard = "sme" in { + def NAME : SInst<"sv" # n_suffix, "nv", "", MergeNone, + "aarch64_sme_" # n_suffix, + [IsOverloadNone, IsStreamingCompatible, IsPreservesZA]>; + } +} + +defm SVCNTSB : ZACount<"cntsb">; +defm SVCNTSH : ZACount<"cntsh">; +defm SVCNTSW : ZACount<"cntsw">; +defm SVCNTSD : ZACount<"cntsd">; + +//////////////////////////////////////////////////////////////////////////////// +// SME - ADDHA/ADDVA + +multiclass ZAAdd { + let TargetGuard = "sme" in { + def NAME # _ZA32: SInst<"sv" # n_suffix # "_za32[_{d}]", "viPPd", "iUi", MergeOp1, + "aarch64_sme_" # n_suffix, [IsStreaming, IsSharedZA], + [ImmCheck<0, ImmCheck0_3>]>; + } + + let TargetGuard = "sme-i16i64" in { + def NAME # _ZA64: SInst<"sv" # n_suffix # "_za64[_{d}]", "viPPd", "lUl", MergeOp1, + "aarch64_sme_" # n_suffix, [IsStreaming, IsSharedZA], + [ImmCheck<0, ImmCheck0_7>]>; + } +} + +defm SVADDHA : ZAAdd<"addha">; +defm SVADDVA : ZAAdd<"addva">; + +//////////////////////////////////////////////////////////////////////////////// +// SME - SMOPA, SMOPS, UMOPA, UMOPS + +multiclass ZAIntOuterProd { + let TargetGuard = "sme" in { + def NAME # _ZA32_B: SInst<"sv" # n_suffix2 # "_za32[_{d}]", + "viPPdd", !cond(!eq(n_suffix1, "s") : "", true: "U") # "c", + MergeOp1, "aarch64_sme_" # n_suffix1 # n_suffix2 # "_wide", + [IsStreaming, IsSharedZA], + [ImmCheck<0, ImmCheck0_3>]>; + } + + let TargetGuard = "sme-i16i64" in { + def NAME # _ZA64_H: SInst<"sv" # n_suffix2 # "_za64[_{d}]", + "viPPdd", !cond(!eq(n_suffix1, "s") : "", true: "U") # "s", + MergeOp1, "aarch64_sme_" # n_suffix1 # n_suffix2 # "_wide", + [IsStreaming, IsSharedZA], + [ImmCheck<0, ImmCheck0_7>]>; + } +} + +defm SVSMOPA : ZAIntOuterProd<"s", "mopa">; +defm SVSMOPS : ZAIntOuterProd<"s", "mops">; +defm SVUMOPA : ZAIntOuterProd<"u", "mopa">; +defm SVUMOPS : ZAIntOuterProd<"u", "mops">; + +//////////////////////////////////////////////////////////////////////////////// +// SME - SUMOPA, SUMOPS, USMOPA, USMOPS + +multiclass ZAIntOuterProdMixedSigns { + let TargetGuard = "sme" in { + def NAME # _ZA32_B: SInst<"sv" # n_suffix1 # n_suffix2 # "_za32[_{d}]", + "viPPd" # !cond(!eq(n_suffix1, "su") : "u", true: "x"), + !cond(!eq(n_suffix1, "su") : "", true: "U") # "c", + MergeOp1, "aarch64_sme_" # n_suffix1 # n_suffix2 # "_wide", + [IsStreaming, IsSharedZA], + [ImmCheck<0, ImmCheck0_3>]>; + } + + let TargetGuard = "sme-i16i64" in { + def NAME # _ZA64_H: SInst<"sv" # n_suffix1 # n_suffix2 # "_za64[_{d}]", + "viPPd" # !cond(!eq(n_suffix1, "su") : "u", true: "x"), + !cond(!eq(n_suffix1, "su") : "", true: "U") # "s", + MergeOp1, "aarch64_sme_" # n_suffix1 # n_suffix2 # "_wide", + [IsStreaming, IsSharedZA], + [ImmCheck<0, ImmCheck0_7>]>; + } +} + +defm SVSUMOPA : ZAIntOuterProdMixedSigns<"su", "mopa">; +defm SVSUMOPS : ZAIntOuterProdMixedSigns<"su", "mops">; +defm SVUSMOPA : ZAIntOuterProdMixedSigns<"us", "mopa">; +defm SVUSMOPS : ZAIntOuterProdMixedSigns<"us", "mops">; + +//////////////////////////////////////////////////////////////////////////////// +// SME - FMOPA, FMOPS + +multiclass ZAFPOuterProd { + let TargetGuard = "sme" in { + def NAME # _ZA32_B: SInst<"sv" # n_suffix # "_za32[_{d}]", "viPPdd", "h", + MergeOp1, "aarch64_sme_" # n_suffix # "_wide", + [IsStreaming, IsSharedZA], + [ImmCheck<0, ImmCheck0_3>]>; + + def NAME # _ZA32_H: SInst<"sv" # n_suffix # "_za32[_{d}]", "viPPdd", "b", + MergeOp1, "aarch64_sme_" # n_suffix # "_wide", + [IsStreaming, IsSharedZA], + [ImmCheck<0, ImmCheck0_3>]>; + + def NAME # _ZA32_S: SInst<"sv" # n_suffix # "_za32[_{d}]", "viPPdd", "f", + MergeOp1, "aarch64_sme_" # n_suffix, + [IsStreaming, IsSharedZA], + [ImmCheck<0, ImmCheck0_3>]>; + } + + let TargetGuard = "sme-f64f64" in { + def NAME # _ZA64_D: SInst<"sv" # n_suffix # "_za64[_{d}]", "viPPdd", "d", + MergeOp1, "aarch64_sme_" # n_suffix, + [IsStreaming, IsSharedZA], + [ImmCheck<0, ImmCheck0_3>]>; + } +} + +defm SVMOPA : ZAFPOuterProd<"mopa">; +defm SVMOPS : ZAFPOuterProd<"mops">; diff --git a/contrib/llvm-project/clang/include/clang/Basic/arm_sve.td b/contrib/llvm-project/clang/include/clang/Basic/arm_sve.td index e547bbd34b5..894a0a1296b 100644 --- a/contrib/llvm-project/clang/include/clang/Basic/arm_sve.td +++ b/contrib/llvm-project/clang/include/clang/Basic/arm_sve.td @@ -13,251 +13,7 @@ // //===----------------------------------------------------------------------===// -//===----------------------------------------------------------------------===// -// Instruction definitions -//===----------------------------------------------------------------------===// -// Every intrinsic subclasses "Inst". An intrinsic has a name, a prototype and -// a sequence of typespecs. -// -// The name is the base name of the intrinsic, for example "svld1". This is -// then mangled by the tblgen backend to add type information ("svld1_s16"). -// -// A typespec is a sequence of uppercase characters (modifiers) followed by one -// lowercase character. A typespec encodes a particular "base type" of the -// intrinsic. -// -// An example typespec is "Us" - unsigned short - svuint16_t. The available -// typespec codes are given below. -// -// The string given to an Inst class is a sequence of typespecs. The intrinsic -// is instantiated for every typespec in the sequence. For example "sdUsUd". -// -// The prototype is a string that defines the return type of the intrinsic -// and the type of each argument. The return type and every argument gets a -// "modifier" that can change in some way the "base type" of the intrinsic. -// -// The modifier 'd' means "default" and does not modify the base type in any -// way. The available modifiers are given below. -// -// Typespecs -// --------- -// c: char -// s: short -// i: int -// l: long -// f: float -// h: half-float -// d: double -// b: bfloat - -// Typespec modifiers -// ------------------ -// P: boolean -// U: unsigned - -// Prototype modifiers -// ------------------- -// prototype: return (arg, arg, ...) -// -// 2,3,4: array of default vectors -// v: void -// x: vector of signed integers -// u: vector of unsigned integers -// d: default -// c: const pointer type -// P: predicate type -// s: scalar of element type -// a: scalar of element type (splat to vector type) -// R: scalar of 1/2 width element type (splat to vector type) -// r: scalar of 1/4 width element type (splat to vector type) -// @: unsigned scalar of 1/4 width element type (splat to vector type) -// e: 1/2 width unsigned elements, 2x element count -// b: 1/4 width unsigned elements, 4x element count -// h: 1/2 width elements, 2x element count -// q: 1/4 width elements, 4x element count -// o: 4x width elements, 1/4 element count -// -// w: vector of element type promoted to 64bits, vector maintains -// signedness of its element type. -// f: element type promoted to uint64_t (splat to vector type) -// j: element type promoted to 64bits (splat to vector type) -// K: element type bitcast to a signed integer (splat to vector type) -// L: element type bitcast to an unsigned integer (splat to vector type) -// -// i: constant uint64_t -// k: int32_t -// l: int64_t -// m: uint32_t -// n: uint64_t - -// t: svint32_t -// z: svuint32_t -// g: svuint64_t -// O: svfloat16_t -// M: svfloat32_t -// N: svfloat64_t - -// J: Prefetch type (sv_prfop) -// A: pointer to int8_t -// B: pointer to int16_t -// C: pointer to int32_t -// D: pointer to int64_t - -// E: pointer to uint8_t -// F: pointer to uint16_t -// G: pointer to uint32_t -// H: pointer to uint64_t - -// Q: const pointer to void - -// S: const pointer to int8_t -// T: const pointer to int16_t -// U: const pointer to int32_t -// V: const pointer to int64_t -// -// W: const pointer to uint8_t -// X: const pointer to uint16_t -// Y: const pointer to uint32_t -// Z: const pointer to uint64_t - -class MergeType { - int Value = val; - string Suffix = suffix; -} -def MergeNone : MergeType<0>; -def MergeAny : MergeType<1, "_x">; -def MergeOp1 : MergeType<2, "_m">; -def MergeZero : MergeType<3, "_z">; -def MergeAnyExp : MergeType<4, "_x">; // Use merged builtin with explicit -def MergeZeroExp : MergeType<5, "_z">; // generation of its inactive argument. - -class EltType { - int Value = val; -} -def EltTyInvalid : EltType<0>; -def EltTyInt8 : EltType<1>; -def EltTyInt16 : EltType<2>; -def EltTyInt32 : EltType<3>; -def EltTyInt64 : EltType<4>; -def EltTyFloat16 : EltType<5>; -def EltTyFloat32 : EltType<6>; -def EltTyFloat64 : EltType<7>; -def EltTyBool8 : EltType<8>; -def EltTyBool16 : EltType<9>; -def EltTyBool32 : EltType<10>; -def EltTyBool64 : EltType<11>; -def EltTyBFloat16 : EltType<12>; - -class MemEltType { - int Value = val; -} -def MemEltTyDefault : MemEltType<0>; -def MemEltTyInt8 : MemEltType<1>; -def MemEltTyInt16 : MemEltType<2>; -def MemEltTyInt32 : MemEltType<3>; -def MemEltTyInt64 : MemEltType<4>; - -class FlagType { - int Value = val; -} - -// These must be kept in sync with the flags in utils/TableGen/SveEmitter.h -// and include/clang/Basic/TargetBuiltins.h -def NoFlags : FlagType<0x00000000>; -def FirstEltType : FlagType<0x00000001>; -// : : -// : : -def EltTypeMask : FlagType<0x0000000f>; -def FirstMemEltType : FlagType<0x00000010>; -// : : -// : : -def MemEltTypeMask : FlagType<0x00000070>; -def FirstMergeTypeMask : FlagType<0x00000080>; -// : : -// : : -def MergeTypeMask : FlagType<0x00000380>; -def FirstSplatOperand : FlagType<0x00000400>; -// : : -// These flags are used to specify which scalar operand -// needs to be duplicated/splatted into a vector. -// : : -def SplatOperandMask : FlagType<0x00001C00>; -def IsLoad : FlagType<0x00002000>; -def IsStore : FlagType<0x00004000>; -def IsGatherLoad : FlagType<0x00008000>; -def IsScatterStore : FlagType<0x00010000>; -def IsStructLoad : FlagType<0x00020000>; -def IsStructStore : FlagType<0x00040000>; -def IsZExtReturn : FlagType<0x00080000>; // Return value is sign-extend by default -def IsOverloadNone : FlagType<0x00100000>; // Intrinsic does not take any overloaded types. -def IsOverloadWhile : FlagType<0x00200000>; // Use {default type, typeof(operand1)} as overloaded types. -def IsOverloadWhileRW : FlagType<0x00400000>; // Use {pred(default type), typeof(operand0)} as overloaded types. -def IsOverloadCvt : FlagType<0x00800000>; // Use {typeof(operand0), typeof(last operand)} as overloaded types. -def OverloadKindMask : FlagType<0x00E00000>; // When the masked values are all '0', the default type is used as overload type. -def IsByteIndexed : FlagType<0x01000000>; -def IsAppendSVALL : FlagType<0x02000000>; // Appends SV_ALL as the last operand. -def IsInsertOp1SVALL : FlagType<0x04000000>; // Inserts SV_ALL as the second operand. -def IsPrefetch : FlagType<0x08000000>; // Contiguous prefetches. -def IsGatherPrefetch : FlagType<0x10000000>; -def ReverseCompare : FlagType<0x20000000>; // Compare operands must be swapped. -def ReverseUSDOT : FlagType<0x40000000>; // Unsigned/signed operands must be swapped. -def IsUndef : FlagType<0x80000000>; // Codegen `undef` of given type. -def IsTupleCreate : FlagType<0x100000000>; -def IsTupleGet : FlagType<0x200000000>; -def IsTupleSet : FlagType<0x400000000>; - -// These must be kept in sync with the flags in include/clang/Basic/TargetBuiltins.h -class ImmCheckType { - int Value = val; -} -def ImmCheck0_31 : ImmCheckType<0>; // 0..31 (used for e.g. predicate patterns) -def ImmCheck1_16 : ImmCheckType<1>; // 1..16 -def ImmCheckExtract : ImmCheckType<2>; // 0..(2048/sizeinbits(elt) - 1) -def ImmCheckShiftRight : ImmCheckType<3>; // 1..sizeinbits(elt) -def ImmCheckShiftRightNarrow : ImmCheckType<4>; // 1..sizeinbits(elt)/2 -def ImmCheckShiftLeft : ImmCheckType<5>; // 0..(sizeinbits(elt) - 1) -def ImmCheck0_7 : ImmCheckType<6>; // 0..7 -def ImmCheckLaneIndex : ImmCheckType<7>; // 0..(128/(1*sizeinbits(elt)) - 1) -def ImmCheckLaneIndexCompRotate : ImmCheckType<8>; // 0..(128/(2*sizeinbits(elt)) - 1) -def ImmCheckLaneIndexDot : ImmCheckType<9>; // 0..(128/(4*sizeinbits(elt)) - 1) -def ImmCheckComplexRot90_270 : ImmCheckType<10>; // [90,270] -def ImmCheckComplexRotAll90 : ImmCheckType<11>; // [0, 90, 180,270] -def ImmCheck0_13 : ImmCheckType<12>; // 0..13 -def ImmCheck0_1 : ImmCheckType<13>; // 0..1 -def ImmCheck0_2 : ImmCheckType<14>; // 0..2 -def ImmCheck0_3 : ImmCheckType<15>; // 0..3 - -class ImmCheck { - int Arg = arg; - int EltSizeArg = eltSizeArg; - ImmCheckType Kind = kind; -} - -class Inst ft, list ch, MemEltType met> { - string Name = n; - string Prototype = p; - string Types = t; - string TargetGuard = "sve"; - int Merge = mt.Value; - string MergeSuffix = mt.Suffix; - string LLVMIntrinsic = i; - list Flags = ft; - list ImmChecks = ch; - int MemEltType = met.Value; -} - -// SInst: Instruction with signed/unsigned suffix (e.g., "s8", "u8") -class SInst ft = [], list ch = []> - : Inst { -} - -// MInst: Instructions which access memory -class MInst f, - MemEltType met = MemEltTyDefault, string i = ""> - : Inst { -} +include "arm_sve_sme_incl.td" //////////////////////////////////////////////////////////////////////////////// // Loads @@ -758,49 +514,49 @@ defm SVNEG : SInstZPZ<"svneg", "csil", "aarch64_sve_neg">; //------------------------------------------------------------------------------ -multiclass SInstZPZZ flags=[]> { - def _M : SInst; - def _X : SInst; - def _Z : SInst; +multiclass SInstZPZZ flags=[]> { + def _M : SInst; + def _X : SInst; + def _Z : SInst; - def _N_M : SInst; - def _N_X : SInst; - def _N_Z : SInst; + def _N_M : SInst; + def _N_X : SInst; + def _N_Z : SInst; } -defm SVABD_S : SInstZPZZ<"svabd", "csil", "aarch64_sve_sabd">; -defm SVABD_U : SInstZPZZ<"svabd", "UcUsUiUl", "aarch64_sve_uabd">; -defm SVADD : SInstZPZZ<"svadd", "csilUcUsUiUl", "aarch64_sve_add">; -defm SVDIV_S : SInstZPZZ<"svdiv", "il", "aarch64_sve_sdiv">; -defm SVDIV_U : SInstZPZZ<"svdiv", "UiUl", "aarch64_sve_udiv">; -defm SVDIVR_S : SInstZPZZ<"svdivr", "il", "aarch64_sve_sdivr">; -defm SVDIVR_U : SInstZPZZ<"svdivr", "UiUl", "aarch64_sve_udivr">; -defm SVMAX_S : SInstZPZZ<"svmax", "csil", "aarch64_sve_smax">; -defm SVMAX_U : SInstZPZZ<"svmax", "UcUsUiUl", "aarch64_sve_umax">; -defm SVMIN_S : SInstZPZZ<"svmin", "csil", "aarch64_sve_smin">; -defm SVMIN_U : SInstZPZZ<"svmin", "UcUsUiUl", "aarch64_sve_umin">; -defm SVMUL : SInstZPZZ<"svmul", "csilUcUsUiUl", "aarch64_sve_mul">; -defm SVMULH_S : SInstZPZZ<"svmulh", "csil", "aarch64_sve_smulh">; -defm SVMULH_U : SInstZPZZ<"svmulh", "UcUsUiUl", "aarch64_sve_umulh">; -defm SVSUB : SInstZPZZ<"svsub", "csilUcUsUiUl", "aarch64_sve_sub">; -defm SVSUBR : SInstZPZZ<"svsubr", "csilUcUsUiUl", "aarch64_sve_subr">; +defm SVABD_S : SInstZPZZ<"svabd", "csil", "aarch64_sve_sabd", "aarch64_sve_sabd_u">; +defm SVABD_U : SInstZPZZ<"svabd", "UcUsUiUl", "aarch64_sve_uabd", "aarch64_sve_uabd_u">; +defm SVADD : SInstZPZZ<"svadd", "csilUcUsUiUl", "aarch64_sve_add", "aarch64_sve_add_u">; +defm SVDIV_S : SInstZPZZ<"svdiv", "il", "aarch64_sve_sdiv", "aarch64_sve_sdiv_u">; +defm SVDIV_U : SInstZPZZ<"svdiv", "UiUl", "aarch64_sve_udiv", "aarch64_sve_udiv_u">; +defm SVDIVR_S : SInstZPZZ<"svdivr", "il", "aarch64_sve_sdivr", "aarch64_sve_sdiv_u", [ReverseMergeAnyBinOp]>; +defm SVDIVR_U : SInstZPZZ<"svdivr", "UiUl", "aarch64_sve_udivr", "aarch64_sve_udiv_u", [ReverseMergeAnyBinOp]>; +defm SVMAX_S : SInstZPZZ<"svmax", "csil", "aarch64_sve_smax", "aarch64_sve_smax_u">; +defm SVMAX_U : SInstZPZZ<"svmax", "UcUsUiUl", "aarch64_sve_umax", "aarch64_sve_umax_u">; +defm SVMIN_S : SInstZPZZ<"svmin", "csil", "aarch64_sve_smin", "aarch64_sve_smin_u">; +defm SVMIN_U : SInstZPZZ<"svmin", "UcUsUiUl", "aarch64_sve_umin", "aarch64_sve_umin_u">; +defm SVMUL : SInstZPZZ<"svmul", "csilUcUsUiUl", "aarch64_sve_mul", "aarch64_sve_mul_u">; +defm SVMULH_S : SInstZPZZ<"svmulh", "csil", "aarch64_sve_smulh", "aarch64_sve_smulh_u">; +defm SVMULH_U : SInstZPZZ<"svmulh", "UcUsUiUl", "aarch64_sve_umulh", "aarch64_sve_umulh_u">; +defm SVSUB : SInstZPZZ<"svsub", "csilUcUsUiUl", "aarch64_sve_sub", "aarch64_sve_sub_u">; +defm SVSUBR : SInstZPZZ<"svsubr", "csilUcUsUiUl", "aarch64_sve_subr", "aarch64_sve_sub_u", [ReverseMergeAnyBinOp]>; //------------------------------------------------------------------------------ -multiclass SInstZPZZZ flags=[]> { - def _M : SInst; - def _X : SInst; - def _Z : SInst; +multiclass SInstZPZZZ flags=[]> { + def _M : SInst; + def _X : SInst; + def _Z : SInst; - def _N_M : SInst; - def _N_X : SInst; - def _N_Z : SInst; + def _N_M : SInst; + def _N_X : SInst; + def _N_Z : SInst; } -defm SVMAD : SInstZPZZZ<"svmad", "csilUcUsUiUl", "aarch64_sve_mad">; -defm SVMLA : SInstZPZZZ<"svmla", "csilUcUsUiUl", "aarch64_sve_mla">; -defm SVMLS : SInstZPZZZ<"svmls", "csilUcUsUiUl", "aarch64_sve_mls">; -defm SVMSB : SInstZPZZZ<"svmsb", "csilUcUsUiUl", "aarch64_sve_msb">; +defm SVMAD : SInstZPZZZ<"svmad", "csilUcUsUiUl", "aarch64_sve_mad", "aarch64_sve_mla_u", [ReverseMergeAnyAccOp]>; +defm SVMLA : SInstZPZZZ<"svmla", "csilUcUsUiUl", "aarch64_sve_mla", "aarch64_sve_mla_u">; +defm SVMLS : SInstZPZZZ<"svmls", "csilUcUsUiUl", "aarch64_sve_mls", "aarch64_sve_mls_u">; +defm SVMSB : SInstZPZZZ<"svmsb", "csilUcUsUiUl", "aarch64_sve_msb", "aarch64_sve_mls_u", [ReverseMergeAnyAccOp]>; //------------------------------------------------------------------------------ @@ -824,10 +580,10 @@ def SVDOT_LANE_U : SInst<"svdot_lane[_{d}]", "ddqqi", "UiUl", MergeNone, "aarc //////////////////////////////////////////////////////////////////////////////// // Logical operations -defm SVAND : SInstZPZZ<"svand", "csilUcUsUiUl", "aarch64_sve_and">; -defm SVBIC : SInstZPZZ<"svbic", "csilUcUsUiUl", "aarch64_sve_bic">; -defm SVEOR : SInstZPZZ<"sveor", "csilUcUsUiUl", "aarch64_sve_eor">; -defm SVORR : SInstZPZZ<"svorr", "csilUcUsUiUl", "aarch64_sve_orr">; +defm SVAND : SInstZPZZ<"svand", "csilUcUsUiUl", "aarch64_sve_and", "aarch64_sve_and_u">; +defm SVBIC : SInstZPZZ<"svbic", "csilUcUsUiUl", "aarch64_sve_bic", "aarch64_sve_bic_u">; +defm SVEOR : SInstZPZZ<"sveor", "csilUcUsUiUl", "aarch64_sve_eor", "aarch64_sve_eor_u">; +defm SVORR : SInstZPZZ<"svorr", "csilUcUsUiUl", "aarch64_sve_orr", "aarch64_sve_orr_u">; defm SVCNOT : SInstZPZ<"svcnot", "csilUcUsUiUl", "aarch64_sve_cnot">; defm SVNOT : SInstZPZ<"svnot", "csilUcUsUiUl", "aarch64_sve_not">; @@ -837,11 +593,11 @@ defm SVNOT : SInstZPZ<"svnot", "csilUcUsUiUl", "aarch64_sve_not">; multiclass SInst_SHIFT { def _M : SInst; - def _X : SInst; + def _X : SInst; def _Z : SInst; def _N_M : SInst; - def _N_X : SInst; + def _N_X : SInst; def _N_Z : SInst; def _WIDE_M : SInst; @@ -979,18 +735,18 @@ defm SVREVW : SInstZPZ<"svrevw", "lUl", "aarch64_sve_revw">; defm SVABS_F : SInstZPZ<"svabs", "hfd", "aarch64_sve_fabs">; defm SVNEG_F : SInstZPZ<"svneg", "hfd", "aarch64_sve_fneg">; -defm SVABD_F : SInstZPZZ<"svabd", "hfd", "aarch64_sve_fabd">; -defm SVADD_F : SInstZPZZ<"svadd", "hfd", "aarch64_sve_fadd">; -defm SVDIV_F : SInstZPZZ<"svdiv", "hfd", "aarch64_sve_fdiv">; -defm SVDIVR_F : SInstZPZZ<"svdivr", "hfd", "aarch64_sve_fdivr">; -defm SVMAX_F : SInstZPZZ<"svmax", "hfd", "aarch64_sve_fmax">; -defm SVMAXNM : SInstZPZZ<"svmaxnm","hfd", "aarch64_sve_fmaxnm">; -defm SVMIN_F : SInstZPZZ<"svmin", "hfd", "aarch64_sve_fmin">; -defm SVMINNM : SInstZPZZ<"svminnm","hfd", "aarch64_sve_fminnm">; -defm SVMUL_F : SInstZPZZ<"svmul", "hfd", "aarch64_sve_fmul">; -defm SVMULX : SInstZPZZ<"svmulx", "hfd", "aarch64_sve_fmulx">; -defm SVSUB_F : SInstZPZZ<"svsub", "hfd", "aarch64_sve_fsub">; -defm SVSUBR_F : SInstZPZZ<"svsubr", "hfd", "aarch64_sve_fsubr">; +defm SVABD_F : SInstZPZZ<"svabd", "hfd", "aarch64_sve_fabd", "aarch64_sve_fabd_u">; +defm SVADD_F : SInstZPZZ<"svadd", "hfd", "aarch64_sve_fadd", "aarch64_sve_fadd_u">; +defm SVDIV_F : SInstZPZZ<"svdiv", "hfd", "aarch64_sve_fdiv", "aarch64_sve_fdiv_u">; +defm SVDIVR_F : SInstZPZZ<"svdivr", "hfd", "aarch64_sve_fdivr", "aarch64_sve_fdiv_u", [ReverseMergeAnyBinOp]>; +defm SVMAX_F : SInstZPZZ<"svmax", "hfd", "aarch64_sve_fmax", "aarch64_sve_fmax_u">; +defm SVMAXNM : SInstZPZZ<"svmaxnm","hfd", "aarch64_sve_fmaxnm", "aarch64_sve_fmaxnm_u">; +defm SVMIN_F : SInstZPZZ<"svmin", "hfd", "aarch64_sve_fmin", "aarch64_sve_fmin_u">; +defm SVMINNM : SInstZPZZ<"svminnm","hfd", "aarch64_sve_fminnm", "aarch64_sve_fminnm_u">; +defm SVMUL_F : SInstZPZZ<"svmul", "hfd", "aarch64_sve_fmul", "aarch64_sve_fmul_u">; +defm SVMULX : SInstZPZZ<"svmulx", "hfd", "aarch64_sve_fmulx", "aarch64_sve_fmulx_u">; +defm SVSUB_F : SInstZPZZ<"svsub", "hfd", "aarch64_sve_fsub", "aarch64_sve_fsub_u">; +defm SVSUBR_F : SInstZPZZ<"svsubr", "hfd", "aarch64_sve_fsubr", "aarch64_sve_fsub_u", [ReverseMergeAnyBinOp]>; defm SVRECPX : SInstZPZ<"svrecpx", "hfd", "aarch64_sve_frecpx">; defm SVRINTA : SInstZPZ<"svrinta", "hfd", "aarch64_sve_frinta">; @@ -1015,14 +771,14 @@ def SVSCALE_N_M : SInst<"svscale[_n_{d}]", "dPdK", "hfd", MergeOp1, "aarch64_sv def SVSCALE_N_X : SInst<"svscale[_n_{d}]", "dPdK", "hfd", MergeAny, "aarch64_sve_fscale">; def SVSCALE_N_Z : SInst<"svscale[_n_{d}]", "dPdK", "hfd", MergeZero, "aarch64_sve_fscale">; -defm SVMAD_F : SInstZPZZZ<"svmad", "hfd", "aarch64_sve_fmad">; -defm SVMLA_F : SInstZPZZZ<"svmla", "hfd", "aarch64_sve_fmla">; -defm SVMLS_F : SInstZPZZZ<"svmls", "hfd", "aarch64_sve_fmls">; -defm SVMSB_F : SInstZPZZZ<"svmsb", "hfd", "aarch64_sve_fmsb">; -defm SVNMAD_F : SInstZPZZZ<"svnmad", "hfd", "aarch64_sve_fnmad">; -defm SVNMLA_F : SInstZPZZZ<"svnmla", "hfd", "aarch64_sve_fnmla">; -defm SVNMLS_F : SInstZPZZZ<"svnmls", "hfd", "aarch64_sve_fnmls">; -defm SVNMSB_F : SInstZPZZZ<"svnmsb", "hfd", "aarch64_sve_fnmsb">; +defm SVMAD_F : SInstZPZZZ<"svmad", "hfd", "aarch64_sve_fmad", "aarch64_sve_fmla_u", [ReverseMergeAnyAccOp]>; +defm SVMLA_F : SInstZPZZZ<"svmla", "hfd", "aarch64_sve_fmla", "aarch64_sve_fmla_u">; +defm SVMLS_F : SInstZPZZZ<"svmls", "hfd", "aarch64_sve_fmls", "aarch64_sve_fmls_u">; +defm SVMSB_F : SInstZPZZZ<"svmsb", "hfd", "aarch64_sve_fmsb", "aarch64_sve_fmls_u", [ReverseMergeAnyAccOp]>; +defm SVNMAD_F : SInstZPZZZ<"svnmad", "hfd", "aarch64_sve_fnmad", "aarch64_sve_fnmla_u", [ReverseMergeAnyAccOp]>; +defm SVNMLA_F : SInstZPZZZ<"svnmla", "hfd", "aarch64_sve_fnmla", "aarch64_sve_fnmla_u">; +defm SVNMLS_F : SInstZPZZZ<"svnmls", "hfd", "aarch64_sve_fnmls", "aarch64_sve_fnmls_u">; +defm SVNMSB_F : SInstZPZZZ<"svnmsb", "hfd", "aarch64_sve_fnmsb", "aarch64_sve_fnmls_u", [ReverseMergeAnyAccOp]>; def SVCADD_M : SInst<"svcadd[_{d}]", "dPddi", "hfd", MergeOp1, "aarch64_sve_fcadd", [], [ImmCheck<3, ImmCheckComplexRot90_270>]>; def SVCADD_X : SInst<"svcadd[_{d}]", "dPddi", "hfd", MergeAny, "aarch64_sve_fcadd", [], [ImmCheck<3, ImmCheckComplexRot90_270>]>; @@ -1513,21 +1269,21 @@ def SVWHILEHS_U64 : SInst<"svwhilege_{d}[_{1}]", "Pnn", "PUcPUsPUiPUl", MergeNon // SVE2 - Uniform DSP operations let TargetGuard = "sve2" in { -defm SVQADD_S : SInstZPZZ<"svqadd", "csli", "aarch64_sve_sqadd">; -defm SVQADD_U : SInstZPZZ<"svqadd", "UcUsUiUl", "aarch64_sve_uqadd">; -defm SVHADD_S : SInstZPZZ<"svhadd", "csli", "aarch64_sve_shadd">; -defm SVHADD_U : SInstZPZZ<"svhadd", "UcUsUiUl", "aarch64_sve_uhadd">; -defm SVRHADD_S : SInstZPZZ<"svrhadd", "csli", "aarch64_sve_srhadd">; -defm SVRHADD_U : SInstZPZZ<"svrhadd", "UcUsUiUl", "aarch64_sve_urhadd">; +defm SVQADD_S : SInstZPZZ<"svqadd", "csli", "aarch64_sve_sqadd", "aarch64_sve_sqadd">; +defm SVQADD_U : SInstZPZZ<"svqadd", "UcUsUiUl", "aarch64_sve_uqadd", "aarch64_sve_uqadd">; +defm SVHADD_S : SInstZPZZ<"svhadd", "csli", "aarch64_sve_shadd", "aarch64_sve_shadd">; +defm SVHADD_U : SInstZPZZ<"svhadd", "UcUsUiUl", "aarch64_sve_uhadd", "aarch64_sve_uhadd">; +defm SVRHADD_S : SInstZPZZ<"svrhadd", "csli", "aarch64_sve_srhadd", "aarch64_sve_srhadd">; +defm SVRHADD_U : SInstZPZZ<"svrhadd", "UcUsUiUl", "aarch64_sve_urhadd", "aarch64_sve_urhadd">; -defm SVQSUB_S : SInstZPZZ<"svqsub", "csli", "aarch64_sve_sqsub">; -defm SVQSUB_U : SInstZPZZ<"svqsub", "UcUsUiUl", "aarch64_sve_uqsub">; -defm SVQSUBR_S : SInstZPZZ<"svqsubr", "csli", "aarch64_sve_sqsubr">; -defm SVQSUBR_U : SInstZPZZ<"svqsubr", "UcUsUiUl", "aarch64_sve_uqsubr">; -defm SVHSUB_S : SInstZPZZ<"svhsub", "csli", "aarch64_sve_shsub">; -defm SVHSUB_U : SInstZPZZ<"svhsub", "UcUsUiUl", "aarch64_sve_uhsub">; -defm SVHSUBR_S : SInstZPZZ<"svhsubr", "csli", "aarch64_sve_shsubr">; -defm SVHSUBR_U : SInstZPZZ<"svhsubr", "UcUsUiUl", "aarch64_sve_uhsubr">; +defm SVQSUB_S : SInstZPZZ<"svqsub", "csli", "aarch64_sve_sqsub", "aarch64_sve_sqsub_u">; +defm SVQSUB_U : SInstZPZZ<"svqsub", "UcUsUiUl", "aarch64_sve_uqsub", "aarch64_sve_uqsub_u">; +defm SVQSUBR_S : SInstZPZZ<"svqsubr", "csli", "aarch64_sve_sqsubr", "aarch64_sve_sqsub_u", [ReverseMergeAnyBinOp]>; +defm SVQSUBR_U : SInstZPZZ<"svqsubr", "UcUsUiUl", "aarch64_sve_uqsubr", "aarch64_sve_uqsub_u", [ReverseMergeAnyBinOp]>; +defm SVHSUB_S : SInstZPZZ<"svhsub", "csli", "aarch64_sve_shsub", "aarch64_sve_shsub">; +defm SVHSUB_U : SInstZPZZ<"svhsub", "UcUsUiUl", "aarch64_sve_uhsub", "aarch64_sve_uhsub">; +defm SVHSUBR_S : SInstZPZZ<"svhsubr", "csli", "aarch64_sve_shsubr", "aarch64_sve_shsubr">; +defm SVHSUBR_U : SInstZPZZ<"svhsubr", "UcUsUiUl", "aarch64_sve_uhsubr", "aarch64_sve_uhsubr">; defm SVQABS : SInstZPZ<"svqabs", "csil", "aarch64_sve_sqabs">; defm SVQNEG : SInstZPZ<"svqneg", "csil", "aarch64_sve_sqneg">; @@ -2102,3 +1858,13 @@ def SVBEXT_N : SInst<"svbext[_n_{d}]", "dda", "UcUsUiUl", MergeNone, "aarch64_sv def SVBGRP : SInst<"svbgrp[_{d}]", "ddd", "UcUsUiUl", MergeNone, "aarch64_sve_bgrp_x">; def SVBGRP_N : SInst<"svbgrp[_n_{d}]", "dda", "UcUsUiUl", MergeNone, "aarch64_sve_bgrp_x">; } + +let TargetGuard = "sve2p1" in { +def SVFCLAMP : SInst<"svclamp[_{d}]", "dddd", "hfd", MergeNone, "aarch64_sve_fclamp", [], []>; +def SVPTRUE_COUNT : SInst<"svptrue_{d}", "}v", "QcQsQiQl", MergeNone, "aarch64_sve_ptrue_{d}", [IsOverloadNone], []>; +} + +let TargetGuard = "sve2p1" in { +def SVSCLAMP : SInst<"svclamp[_{d}]", "dddd", "csil", MergeNone, "aarch64_sve_sclamp", [], []>; +def SVUCLAMP : SInst<"svclamp[_{d}]", "dddd", "UcUsUiUl", MergeNone, "aarch64_sve_uclamp", [], []>; +} diff --git a/contrib/llvm-project/clang/include/clang/Basic/arm_sve_sme_incl.td b/contrib/llvm-project/clang/include/clang/Basic/arm_sve_sme_incl.td new file mode 100644 index 00000000000..74c9b926677 --- /dev/null +++ b/contrib/llvm-project/clang/include/clang/Basic/arm_sve_sme_incl.td @@ -0,0 +1,281 @@ +//===--- arm_sve_sme_incl.td - ARM SVE/SME compiler interface -------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +// +// This file defines common properites of TableGen definitions use for both +// SVE and SME intrinsics. +// +// https://developer.arm.com/architectures/system-architectures/software-standards/acle +// +//===----------------------------------------------------------------------===// + +//===----------------------------------------------------------------------===// +// Instruction definitions +//===----------------------------------------------------------------------===// +// Every intrinsic subclasses "Inst". An intrinsic has a name, a prototype and +// a sequence of typespecs. +// +// The name is the base name of the intrinsic, for example "svld1". This is +// then mangled by the tblgen backend to add type information ("svld1_s16"). +// +// A typespec is a sequence of uppercase characters (modifiers) followed by one +// lowercase character. A typespec encodes a particular "base type" of the +// intrinsic. +// +// An example typespec is "Us" - unsigned short - svuint16_t. The available +// typespec codes are given below. +// +// The string given to an Inst class is a sequence of typespecs. The intrinsic +// is instantiated for every typespec in the sequence. For example "sdUsUd". +// +// The prototype is a string that defines the return type of the intrinsic +// and the type of each argument. The return type and every argument gets a +// "modifier" that can change in some way the "base type" of the intrinsic. +// +// The modifier 'd' means "default" and does not modify the base type in any +// way. The available modifiers are given below. +// +// Typespecs +// --------- +// c: char +// s: short +// i: int +// l: long +// q: int128_t +// f: float +// h: half-float +// d: double +// b: bfloat + +// Typespec modifiers +// ------------------ +// P: boolean +// U: unsigned +// Q: svcount + +// Prototype modifiers +// ------------------- +// prototype: return (arg, arg, ...) +// +// 2,3,4: array of default vectors +// v: void +// x: vector of signed integers +// u: vector of unsigned integers +// d: default +// c: const pointer type +// P: predicate type +// s: scalar of element type +// a: scalar of element type (splat to vector type) +// R: scalar of 1/2 width element type (splat to vector type) +// r: scalar of 1/4 width element type (splat to vector type) +// @: unsigned scalar of 1/4 width element type (splat to vector type) +// e: 1/2 width unsigned elements, 2x element count +// b: 1/4 width unsigned elements, 4x element count +// h: 1/2 width elements, 2x element count +// q: 1/4 width elements, 4x element count +// o: 4x width elements, 1/4 element count +// +// w: vector of element type promoted to 64bits, vector maintains +// signedness of its element type. +// f: element type promoted to uint64_t (splat to vector type) +// j: element type promoted to 64bits (splat to vector type) +// K: element type bitcast to a signed integer (splat to vector type) +// L: element type bitcast to an unsigned integer (splat to vector type) +// +// i: constant uint64_t +// k: int32_t +// l: int64_t +// m: uint32_t +// n: uint64_t + +// t: svint32_t +// z: svuint32_t +// g: svuint64_t +// O: svfloat16_t +// M: svfloat32_t +// N: svfloat64_t + +// J: Prefetch type (sv_prfop) + +// %: pointer to void + +// A: pointer to int8_t +// B: pointer to int16_t +// C: pointer to int32_t +// D: pointer to int64_t + +// E: pointer to uint8_t +// F: pointer to uint16_t +// G: pointer to uint32_t +// H: pointer to uint64_t + +// Q: const pointer to void + +// S: const pointer to int8_t +// T: const pointer to int16_t +// U: const pointer to int32_t +// V: const pointer to int64_t +// +// W: const pointer to uint8_t +// X: const pointer to uint16_t +// Y: const pointer to uint32_t +// Z: const pointer to uint64_t + +// Prototype modifiers added for SVE2p1 +// }: svcount_t + +class MergeType { + int Value = val; + string Suffix = suffix; +} +def MergeNone : MergeType<0>; +def MergeAny : MergeType<1, "_x">; +def MergeOp1 : MergeType<2, "_m">; +def MergeZero : MergeType<3, "_z">; +def MergeAnyExp : MergeType<4, "_x">; // Use merged builtin with explicit +def MergeZeroExp : MergeType<5, "_z">; // generation of its inactive argument. + +class EltType { + int Value = val; +} +def EltTyInvalid : EltType<0>; +def EltTyInt8 : EltType<1>; +def EltTyInt16 : EltType<2>; +def EltTyInt32 : EltType<3>; +def EltTyInt64 : EltType<4>; +def EltTyInt128 : EltType<5>; +def EltTyFloat16 : EltType<6>; +def EltTyFloat32 : EltType<7>; +def EltTyFloat64 : EltType<8>; +def EltTyBool8 : EltType<9>; +def EltTyBool16 : EltType<10>; +def EltTyBool32 : EltType<11>; +def EltTyBool64 : EltType<12>; +def EltTyBFloat16 : EltType<13>; + +class MemEltType { + int Value = val; +} +def MemEltTyDefault : MemEltType<0>; +def MemEltTyInt8 : MemEltType<1>; +def MemEltTyInt16 : MemEltType<2>; +def MemEltTyInt32 : MemEltType<3>; +def MemEltTyInt64 : MemEltType<4>; + +class FlagType { + int Value = val; +} + +// These must be kept in sync with the flags in utils/TableGen/SveEmitter.h +// and include/clang/Basic/TargetBuiltins.h +def NoFlags : FlagType<0x00000000>; +def FirstEltType : FlagType<0x00000001>; +// : : +// : : +def EltTypeMask : FlagType<0x0000000f>; +def FirstMemEltType : FlagType<0x00000010>; +// : : +// : : +def MemEltTypeMask : FlagType<0x00000070>; +def FirstMergeTypeMask : FlagType<0x00000080>; +// : : +// : : +def MergeTypeMask : FlagType<0x00000380>; +def FirstSplatOperand : FlagType<0x00000400>; +// : : +// These flags are used to specify which scalar operand +// needs to be duplicated/splatted into a vector. +// : : +def SplatOperandMask : FlagType<0x00001C00>; +def IsLoad : FlagType<0x00002000>; +def IsStore : FlagType<0x00004000>; +def IsGatherLoad : FlagType<0x00008000>; +def IsScatterStore : FlagType<0x00010000>; +def IsStructLoad : FlagType<0x00020000>; +def IsStructStore : FlagType<0x00040000>; +def IsZExtReturn : FlagType<0x00080000>; // Return value is sign-extend by default +def IsOverloadNone : FlagType<0x00100000>; // Intrinsic does not take any overloaded types. +def IsOverloadWhile : FlagType<0x00200000>; // Use {default type, typeof(operand1)} as overloaded types. +def IsOverloadWhileRW : FlagType<0x00400000>; // Use {pred(default type), typeof(operand0)} as overloaded types. +def IsOverloadCvt : FlagType<0x00800000>; // Use {typeof(operand0), typeof(last operand)} as overloaded types. +def OverloadKindMask : FlagType<0x00E00000>; // When the masked values are all '0', the default type is used as overload type. +def IsByteIndexed : FlagType<0x01000000>; +def IsAppendSVALL : FlagType<0x02000000>; // Appends SV_ALL as the last operand. +def IsInsertOp1SVALL : FlagType<0x04000000>; // Inserts SV_ALL as the second operand. +def IsPrefetch : FlagType<0x08000000>; // Contiguous prefetches. +def IsGatherPrefetch : FlagType<0x10000000>; +def ReverseCompare : FlagType<0x20000000>; // Compare operands must be swapped. +def ReverseUSDOT : FlagType<0x40000000>; // Unsigned/signed operands must be swapped. +def IsUndef : FlagType<0x80000000>; // Codegen `undef` of given type. +def IsTupleCreate : FlagType<0x100000000>; +def IsTupleGet : FlagType<0x200000000>; +def IsTupleSet : FlagType<0x400000000>; +def ReverseMergeAnyBinOp : FlagType<0x800000000>; // e.g. Implement SUBR_X using SUB_X. +def ReverseMergeAnyAccOp : FlagType<0x1000000000>; // e.g. Implement MSB_X using MLS_X. +def IsStreaming : FlagType<0x2000000000>; +def IsStreamingCompatible : FlagType<0x4000000000>; +def IsSharedZA : FlagType<0x8000000000>; +def IsPreservesZA : FlagType<0x10000000000>; +def IsReadZA : FlagType<0x20000000000>; +def IsWriteZA : FlagType<0x40000000000>; + +// These must be kept in sync with the flags in include/clang/Basic/TargetBuiltins.h +class ImmCheckType { + int Value = val; +} +def ImmCheck0_31 : ImmCheckType<0>; // 0..31 (used for e.g. predicate patterns) +def ImmCheck1_16 : ImmCheckType<1>; // 1..16 +def ImmCheckExtract : ImmCheckType<2>; // 0..(2048/sizeinbits(elt) - 1) +def ImmCheckShiftRight : ImmCheckType<3>; // 1..sizeinbits(elt) +def ImmCheckShiftRightNarrow : ImmCheckType<4>; // 1..sizeinbits(elt)/2 +def ImmCheckShiftLeft : ImmCheckType<5>; // 0..(sizeinbits(elt) - 1) +def ImmCheck0_7 : ImmCheckType<6>; // 0..7 +def ImmCheckLaneIndex : ImmCheckType<7>; // 0..(128/(1*sizeinbits(elt)) - 1) +def ImmCheckLaneIndexCompRotate : ImmCheckType<8>; // 0..(128/(2*sizeinbits(elt)) - 1) +def ImmCheckLaneIndexDot : ImmCheckType<9>; // 0..(128/(4*sizeinbits(elt)) - 1) +def ImmCheckComplexRot90_270 : ImmCheckType<10>; // [90,270] +def ImmCheckComplexRotAll90 : ImmCheckType<11>; // [0, 90, 180,270] +def ImmCheck0_13 : ImmCheckType<12>; // 0..13 +def ImmCheck0_1 : ImmCheckType<13>; // 0..1 +def ImmCheck0_2 : ImmCheckType<14>; // 0..2 +def ImmCheck0_3 : ImmCheckType<15>; // 0..3 +def ImmCheck0_0 : ImmCheckType<16>; // 0..0 +def ImmCheck0_15 : ImmCheckType<17>; // 0..15 +def ImmCheck0_255 : ImmCheckType<18>; // 0..255 + +class ImmCheck { + int Arg = arg; + int EltSizeArg = eltSizeArg; + ImmCheckType Kind = kind; +} + +class Inst ft, list ch, MemEltType met> { + string Name = n; + string Prototype = p; + string Types = t; + string TargetGuard = "sve"; + int Merge = mt.Value; + string MergeSuffix = mt.Suffix; + string LLVMIntrinsic = i; + list Flags = ft; + list ImmChecks = ch; + int MemEltType = met.Value; +} + +// SInst: Instruction with signed/unsigned suffix (e.g., "s8", "u8") +class SInst ft = [], list ch = []> + : Inst { +} + +// MInst: Instructions which access memory +class MInst f, + MemEltType met = MemEltTyDefault, string i = "", + list ch = []> + : Inst { +} diff --git a/contrib/llvm-project/clang/include/clang/Basic/riscv_sifive_vector.td b/contrib/llvm-project/clang/include/clang/Basic/riscv_sifive_vector.td new file mode 100644 index 00000000000..0d390be711c --- /dev/null +++ b/contrib/llvm-project/clang/include/clang/Basic/riscv_sifive_vector.td @@ -0,0 +1,105 @@ +//==--- riscv_sifive_vector.td - RISC-V SiFive VCIX function list ---------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +// +// This file defines the builtins for RISC-V SiFive VCIX. See: +// +// https://sifive.cdn.prismic.io/sifive/c3829e36-8552-41f0-a841-79945784241b_vcix-spec-software.pdf +// +//===----------------------------------------------------------------------===// + +include "riscv_vector_common.td" + +//===----------------------------------------------------------------------===// +// Instruction definitions +//===----------------------------------------------------------------------===// + +class VCIXSuffix { + list suffix = !cond(!eq(range, "c"): ["8mf8", "8mf4", "8mf2", "8m1", "8m2", "8m4", "8m8"], + !eq(range, "s"): ["16mf4", "16mf2", "16m1", "16m2", "16m4", "16m8"], + !eq(range, "i"): ["32mf2", "32m1", "32m2", "32m4", "32m8"], + !eq(range, "l"): ["64m1", "64m2", "64m4", "64m8"]); +} + +class VCIXBuiltinSet intrinsic_types> + : RVVBuiltin { + let Name = name; + let OverloadedName = name; + let IRName = IR_name; + let HasMasked = false; + let IntrinsicTypes = intrinsic_types; +} + +multiclass VCIXBuiltinSet intrinsic_types> { + if !find(prototype, "0") then { + def : VCIXBuiltinSet; + } + def : VCIXBuiltinSet; +} + +multiclass RVVVCIXBuiltinSet range, string prototype, + list intrinsic_types, bit UseGPR> { + foreach r = range in + let RequiredFeatures = !if(!and(UseGPR, !eq(r, "l")), + ["Xsfvcp", "RV64"], ["Xsfvcp"]) in + defm : VCIXBuiltinSet; +} + +multiclass RVVVCIXBuiltinSetWVType range, string prototype, + list intrinsic_types, bit UseGPR> { + foreach r = range in + let RequiredFeatures = !if(!and(UseGPR, !eq(r, "l")), + ["Xsfvcp", "RV64"], ["Xsfvcp"]) in + // These intrinsics don't have any vector types in the output and inputs, + // but we still need to add vetvli for them. So we encode different + // VTYPE into the intrinsic names, and then will know which vsetvli is + // correct. + foreach s = VCIXSuffix.suffix in + // Since we already encode the Vtype into the name, so just set + // Log2LMUL to zero. Otherwise the RISCVVEmitter will expand + // lots of redundant intrinsic but have same names. + let Log2LMUL = [0] in + def : VCIXBuiltinSet; +} + +let SupportOverloading = false in { + defm sf_vc_x_se : RVVVCIXBuiltinSetWVType<["c", "s", "i", "l"], "0KzKzKzUe", [0, 3], /*UseGPR*/1>; + defm sf_vc_i_se : RVVVCIXBuiltinSetWVType<["c", "s", "i", "l"], "0KzKzKzKz", [2, 3], /*UseGPR*/0>; + defm sf_vc_xv : RVVVCIXBuiltinSet<["csi", "l"], "0KzKzUvUe", [0, 2, 3], /*UseGPR*/1>; + defm sf_vc_iv : RVVVCIXBuiltinSet<["csi", "l"], "0KzKzUvKz", [0, 2, 3], /*UseGPR*/0>; + defm sf_vc_vv : RVVVCIXBuiltinSet<["csi", "l"], "0KzKzUvUv", [0, 2, 3], /*UseGPR*/0>; + defm sf_vc_fv : RVVVCIXBuiltinSet<["si", "l"], "0KzKzUvFe", [0, 2, 3], /*UseGPR*/0>; + defm sf_vc_xvv : RVVVCIXBuiltinSet<["csi", "l"], "0KzUvUvUe", [0, 1, 3], /*UseGPR*/1>; + defm sf_vc_ivv : RVVVCIXBuiltinSet<["csi", "l"], "0KzUvUvKz", [0, 1, 3], /*UseGPR*/0>; + defm sf_vc_vvv : RVVVCIXBuiltinSet<["csi", "l"], "0KzUvUvUv", [0, 1, 3], /*UseGPR*/0>; + defm sf_vc_fvv : RVVVCIXBuiltinSet<["si", "l"], "0KzUvUvFe", [0, 1, 3], /*UseGPR*/0>; + defm sf_vc_v_x : RVVVCIXBuiltinSet<["csi", "l"], "UvKzKzUe", [-1, 1, 2], /*UseGPR*/1>; + defm sf_vc_v_i : RVVVCIXBuiltinSet<["csi", "l"], "UvKzKzKz", [-1, 1, 2], /*UseGPR*/0>; + defm sf_vc_v_xv : RVVVCIXBuiltinSet<["csi", "l"], "UvKzUvUe", [-1, 0, 2], /*UseGPR*/1>; + defm sf_vc_v_iv : RVVVCIXBuiltinSet<["csi", "l"], "UvKzUvKz", [-1, 0, 2], /*UseGPR*/0>; + defm sf_vc_v_vv : RVVVCIXBuiltinSet<["csi", "l"], "UvKzUvUv", [-1, 0, 2], /*UseGPR*/0>; + defm sf_vc_v_fv : RVVVCIXBuiltinSet<["si", "l"], "UvKzUvFe", [-1, 0, 2], /*UseGPR*/0>; + defm sf_vc_v_xvv : RVVVCIXBuiltinSet<["csi", "l"], "UvKzUvUvUe", [-1, 0, 3], /*UseGPR*/1>; + defm sf_vc_v_ivv : RVVVCIXBuiltinSet<["csi", "l"], "UvKzUvUvKz", [-1, 0, 3], /*UseGPR*/0>; + defm sf_vc_v_vvv : RVVVCIXBuiltinSet<["csi", "l"], "UvKzUvUvUv", [-1, 0, 3], /*UseGPR*/0>; + defm sf_vc_v_fvv : RVVVCIXBuiltinSet<["si", "l"], "UvKzUvUvFe", [-1, 0, 3], /*UseGPR*/0>; + let Log2LMUL = [-3, -2, -1, 0, 1, 2] in { + defm sf_vc_xvw : RVVVCIXBuiltinSet<["csi"], "0KzUwUvUe", [0, 1, 2, 3], /*UseGPR*/1>; + defm sf_vc_ivw : RVVVCIXBuiltinSet<["csi"], "0KzUwUvKz", [0, 1, 2, 3], /*UseGPR*/0>; + defm sf_vc_vvw : RVVVCIXBuiltinSet<["csi"], "0KzUwUvUv", [0, 1, 2, 3], /*UseGPR*/0>; + defm sf_vc_fvw : RVVVCIXBuiltinSet<["si"], "0KzUwUvFe", [0, 1, 2, 3], /*UseGPR*/0>; + defm sf_vc_v_xvw : RVVVCIXBuiltinSet<["csi"], "UwKzUwUvUe", [-1, 0, 2, 3], /*UseGPR*/1>; + defm sf_vc_v_ivw : RVVVCIXBuiltinSet<["csi"], "UwKzUwUvKz", [-1, 0, 2, 3], /*UseGPR*/0>; + defm sf_vc_v_vvw : RVVVCIXBuiltinSet<["csi"], "UwKzUwUvUv", [-1, 0, 2, 3], /*UseGPR*/0>; + defm sf_vc_v_fvw : RVVVCIXBuiltinSet<["si"], "UwKzUwUvFe", [-1, 0, 2, 3], /*UseGPR*/0>; + } +} diff --git a/contrib/llvm-project/clang/include/clang/Basic/riscv_vector.td b/contrib/llvm-project/clang/include/clang/Basic/riscv_vector.td index b23e26ecaa5..7e5889812ae 100644 --- a/contrib/llvm-project/clang/include/clang/Basic/riscv_vector.td +++ b/contrib/llvm-project/clang/include/clang/Basic/riscv_vector.td @@ -12,233 +12,7 @@ // //===----------------------------------------------------------------------===// -//===----------------------------------------------------------------------===// -// Instruction definitions -//===----------------------------------------------------------------------===// -// Each record of the class RVVBuiltin defines a collection of builtins (i.e. -// "def vadd : RVVBuiltin" will be used to define things like "vadd_vv_i32m1", -// "vadd_vv_i32m2", etc). -// -// The elements of this collection are defined by an instantiation process the -// range of which is specified by the cross product of the LMUL attribute and -// every element in the attribute TypeRange. By default builtins have LMUL = [1, -// 2, 4, 8, 1/2, 1/4, 1/8] so the process is repeated 7 times. In tablegen we -// use the Log2LMUL [0, 1, 2, 3, -1, -2, -3] to represent the LMUL. -// -// LMUL represents the fact that the types of values used by that builtin are -// values generated by instructions that are executed under that LMUL. However, -// this does not mean the builtin is necessarily lowered into an instruction -// that executes under the specified LMUL. An example where this happens are -// loads and stores of masks. A mask like `vbool8_t` can be generated, for -// instance, by comparing two `__rvv_int8m1_t` (this is LMUL=1) or comparing two -// `__rvv_int16m2_t` (this is LMUL=2). The actual load or store, however, will -// be performed under LMUL=1 because mask registers are not grouped. -// -// TypeRange is a non-empty sequence of basic types: -// -// c: int8_t (i8) -// s: int16_t (i16) -// i: int32_t (i32) -// l: int64_t (i64) -// x: float16_t (half) -// f: float32_t (float) -// d: float64_t (double) -// -// This way, given an LMUL, a record with a TypeRange "sil" will cause the -// definition of 3 builtins. Each type "t" in the TypeRange (in this example -// they are int16_t, int32_t, int64_t) is used as a parameter that drives the -// definition of that particular builtin (for the given LMUL). -// -// During the instantiation, types can be transformed or modified using type -// transformers. Given a type "t" the following primitive type transformers can -// be applied to it to yield another type. -// -// e: type of "t" as is (identity) -// v: computes a vector type whose element type is "t" for the current LMUL -// w: computes a vector type identical to what 'v' computes except for the -// element type which is twice as wide as the element type of 'v' -// q: computes a vector type identical to what 'v' computes except for the -// element type which is four times as wide as the element type of 'v' -// o: computes a vector type identical to what 'v' computes except for the -// element type which is eight times as wide as the element type of 'v' -// m: computes a vector type identical to what 'v' computes except for the -// element type which is bool -// 0: void type, ignores "t" -// z: size_t, ignores "t" -// t: ptrdiff_t, ignores "t" -// u: unsigned long, ignores "t" -// l: long, ignores "t" -// -// So for instance if t is "i", i.e. int, then "e" will yield int again. "v" -// will yield an RVV vector type (assume LMUL=1), so __rvv_int32m1_t. -// Accordingly "w" would yield __rvv_int64m2_t. -// -// A type transformer can be prefixed by other non-primitive type transformers. -// -// P: constructs a pointer to the current type -// C: adds const to the type -// K: requires the integer type to be a constant expression -// U: given an integer type or vector type, computes its unsigned variant -// I: given a vector type, compute the vector type with integer type -// elements of the same width -// F: given a vector type, compute the vector type with floating-point type -// elements of the same width -// S: given a vector type, computes its equivalent one for LMUL=1. This is a -// no-op if the vector was already LMUL=1 -// (Log2EEW:Value): Log2EEW value could be 3/4/5/6 (8/16/32/64), given a -// vector type (SEW and LMUL) and EEW (8/16/32/64), computes its -// equivalent integer vector type with EEW and corresponding ELMUL (elmul = -// (eew/sew) * lmul). For example, vector type is __rvv_float16m4 -// (SEW=16, LMUL=4) and Log2EEW is 3 (EEW=8), and then equivalent vector -// type is __rvv_uint8m2_t (elmul=(8/16)*4 = 2). Ignore to define a new -// builtins if its equivalent type has illegal lmul. -// (FixedSEW:Value): Given a vector type (SEW and LMUL), and computes another -// vector type which only changed SEW as given value. Ignore to define a new -// builtin if its equivalent type has illegal lmul or the SEW does not changed. -// (SFixedLog2LMUL:Value): Smaller Fixed Log2LMUL. Given a vector type (SEW -// and LMUL), and computes another vector type which only changed LMUL as -// given value. The new LMUL should be smaller than the old one. Ignore to -// define a new builtin if its equivalent type has illegal lmul. -// (LFixedLog2LMUL:Value): Larger Fixed Log2LMUL. Given a vector type (SEW -// and LMUL), and computes another vector type which only changed LMUL as -// given value. The new LMUL should be larger than the old one. Ignore to -// define a new builtin if its equivalent type has illegal lmul. -// -// Following with the example above, if t is "i", then "Ue" will yield unsigned -// int and "Fv" will yield __rvv_float32m1_t (again assuming LMUL=1), Fw would -// yield __rvv_float64m2_t, etc. -// -// Each builtin is then defined by applying each type in TypeRange against the -// sequence of type transformers described in Suffix and Prototype. -// -// The name of the builtin is defined by the Name attribute (which defaults to -// the name of the class) appended (separated with an underscore) the Suffix -// attribute. For instance with Name="foo", Suffix = "v" and TypeRange = "il", -// the builtin generated will be __builtin_rvv_foo_i32m1 and -// __builtin_rvv_foo_i64m1 (under LMUL=1). If Suffix contains more than one -// type transformer (say "vv") each of the types is separated with an -// underscore as in "__builtin_rvv_foo_i32m1_i32m1". -// -// The C/C++ prototype of the builtin is defined by the Prototype attribute. -// Prototype is a non-empty sequence of type transformers, the first of which -// is the return type of the builtin and the rest are the parameters of the -// builtin, in order. For instance if Prototype is "wvv" and TypeRange is "si" -// a first builtin will have type -// __rvv_int32m2_t (__rvv_int16m1_t, __rvv_int16m1_t) and the second builtin -// will have type __rvv_int64m2_t (__rvv_int32m1_t, __rvv_int32m1_t) (again -// under LMUL=1). -// -// There are a number of attributes that are used to constraint the number and -// shape of the builtins generated. Refer to the comments below for them. - -class PolicyScheme{ - int Value = val; -} -def NonePolicy : PolicyScheme<0>; -def HasPassthruOperand : PolicyScheme<1>; -def HasPolicyOperand : PolicyScheme<2>; - -class RVVBuiltin { - // Base name that will be prepended in __builtin_rvv_ and appended the - // computed Suffix. - string Name = NAME; - - // If not empty, each instantiated builtin will have this appended after an - // underscore (_). It is instantiated like Prototype. - string Suffix = suffix; - - // If empty, default OverloadedName is sub string of `Name` which end of first - // '_'. For example, the default overloaded name is `vadd` for Name `vadd_vv`. - // It's used for describe some special naming cases. - string OverloadedName = ""; - - // If not empty, each OverloadedName will have this appended after an - // underscore (_). It is instantiated like Prototype. - string OverloadedSuffix = overloaded_suffix; - - // The different variants of the builtin, parameterised with a type. - string TypeRange = type_range; - - // We use each type described in TypeRange and LMUL with prototype to - // instantiate a specific element of the set of builtins being defined. - // Prototype attribute defines the C/C++ prototype of the builtin. It is a - // non-empty sequence of type transformers, the first of which is the return - // type of the builtin and the rest are the parameters of the builtin, in - // order. For instance if Prototype is "wvv", TypeRange is "si" and LMUL=1, a - // first builtin will have type - // __rvv_int32m2_t (__rvv_int16m1_t, __rvv_int16m1_t), and the second builtin - // will have type __rvv_int64m2_t (__rvv_int32m1_t, __rvv_int32m1_t). - string Prototype = prototype; - - // This builtin has a masked form. - bit HasMasked = true; - - // If HasMasked, this flag states that this builtin has a maskedoff operand. It - // is always the first operand in builtin and IR intrinsic. - bit HasMaskedOffOperand = true; - - // This builtin has a granted vector length parameter. - bit HasVL = true; - - // The policy scheme for masked intrinsic IR. - // It could be NonePolicy or HasPolicyOperand. - // HasPolicyOperand: Has a policy operand. 0 is tail and mask undisturbed, 1 is - // tail agnostic, 2 is mask undisturbed, and 3 is tail and mask agnostic. The - // policy operand is located at the last position. - PolicyScheme MaskedPolicyScheme = HasPolicyOperand; - - // The policy scheme for unmasked intrinsic IR. - // It could be NonePolicy, HasPassthruOperand or HasPolicyOperand. - // HasPassthruOperand: Has a passthru operand to decide tail policy. If it is - // poison, tail policy is tail agnostic, otherwise policy is tail undisturbed. - // HasPolicyOperand: Has a policy operand. 1 is tail agnostic and 0 is tail - // undisturbed. - PolicyScheme UnMaskedPolicyScheme = NonePolicy; - - // This builtin support tail agnostic and undisturbed policy. - bit HasTailPolicy = true; - // This builtin support mask agnostic and undisturbed policy. - bit HasMaskPolicy = true; - - // This builtin prototype with TA or TAMA policy could not support overloading - // API. Other policy intrinsic functions would support overloading API with - // suffix `_tu`, `tumu`, `tuma`, `tamu` and `tama`. - bit SupportOverloading = true; - - // This builtin is valid for the given Log2LMULs. - list Log2LMUL = [0, 1, 2, 3, -1, -2, -3]; - - // Manual code in clang codegen riscv_vector_builtin_cg.inc - code ManualCodegen = [{}]; - - // When emit the automatic clang codegen, it describes what types we have to use - // to obtain the specific LLVM intrinsic. -1 means the return type, otherwise, - // k >= 0 meaning the k-th operand (counting from zero) of the codegen'd - // parameter of the unmasked version. k can't be the mask operand's position. - list IntrinsicTypes = []; - - // If these names are not empty, this is the ID of the LLVM intrinsic - // we want to lower to. - string IRName = NAME; - - // If HasMasked, this is the ID of the LLVM intrinsic we want to lower to. - string MaskedIRName = NAME #"_mask"; - - // Use clang_builtin_alias to save the number of builtins. - bit HasBuiltinAlias = true; - - // Features required to enable for this builtin. - list RequiredFeatures = []; - - // Number of fields for Load/Store Segment instructions. - int NF = 1; -} - -// This is the code emitted in the header. -class RVVHeader { - code HeaderCode; -} +include "riscv_vector_common.td" //===----------------------------------------------------------------------===// // Basic classes with automatic codegen. @@ -316,11 +90,21 @@ multiclass RVVSignedBinBuiltinSet [["vv", "v", "vvv"], ["vx", "v", "vve"]]>; +multiclass RVVSignedBinBuiltinSetRoundingMode + : RVVOutOp1BuiltinSet; + multiclass RVVUnsignedBinBuiltinSet : RVVOutOp1BuiltinSet; +multiclass RVVUnsignedBinBuiltinSetRoundingMode + : RVVOutOp1BuiltinSet; + multiclass RVVIntBinBuiltinSet : RVVSignedBinBuiltinSet, RVVUnsignedBinBuiltinSet; @@ -335,11 +119,21 @@ multiclass RVVSignedShiftBuiltinSet [["vv", "v", "vvUv"], ["vx", "v", "vvz"]]>; +multiclass RVVSignedShiftBuiltinSetRoundingMode + : RVVOutOp1BuiltinSet; + multiclass RVVUnsignedShiftBuiltinSet : RVVOutOp1BuiltinSet; +multiclass RVVUnsignedShiftBuiltinSetRoundingMode + : RVVOutOp1BuiltinSet; + multiclass RVVShiftBuiltinSet : RVVSignedShiftBuiltinSet, RVVUnsignedShiftBuiltinSet; @@ -349,10 +143,22 @@ let Log2LMUL = [-3, -2, -1, 0, 1, 2] in { : RVVOutOp0Op1BuiltinSet; + + multiclass RVVSignedNShiftBuiltinSetRoundingMode + : RVVOutOp0Op1BuiltinSet; + multiclass RVVUnsignedNShiftBuiltinSet : RVVOutOp0Op1BuiltinSet; + + multiclass RVVUnsignedNShiftBuiltinSetRoundingMode + : RVVOutOp0Op1BuiltinSet; + } multiclass RVVCarryinBuiltinSet @@ -405,6 +211,11 @@ let HasMaskedOffOperand = false in { [["vv", "v", "vvvv"], ["vf", "v", "vvev"]]>; } + multiclass RVVFloatingTerBuiltinSetRoundingMode { + defm "" : RVVOutOp1BuiltinSet; + } } let HasMaskedOffOperand = false, Log2LMUL = [-2, -1, 0, 1, 2] in { @@ -413,6 +224,11 @@ let HasMaskedOffOperand = false, Log2LMUL = [-2, -1, 0, 1, 2] in { [["vv", "w", "wwvv"], ["vf", "w", "wwev"]]>; } + multiclass RVVFloatingWidenTerBuiltinSetRoundingMode { + defm "" : RVVOutOp1Op2BuiltinSet; + } } multiclass RVVFloatingBinBuiltinSet @@ -420,10 +236,19 @@ multiclass RVVFloatingBinBuiltinSet [["vv", "v", "vvv"], ["vf", "v", "vve"]]>; +multiclass RVVFloatingBinBuiltinSetRoundingMode + : RVVOutOp1BuiltinSet; + multiclass RVVFloatingBinVFBuiltinSet : RVVOutOp1BuiltinSet; +multiclass RVVFloatingBinVFBuiltinSetRoundingMode + : RVVOutOp1BuiltinSet; + multiclass RVVFloatingMaskOutBuiltinSet : RVVOp0Op1BuiltinSet; +multiclass RVVConvBuiltinSet> suffixes_prototypes> { +let Name = intrinsic_name, + IRName = intrinsic_name, + MaskedIRName = intrinsic_name # "_mask", + IntrinsicTypes = [-1, 0] in { + foreach s_p = suffixes_prototypes in { + defvar suffix = s_p[0]; + defvar prototype = s_p[1]; + def : RVVBuiltin; + } + } +} + + class RVVMaskBinBuiltin : RVVOutBuiltin<"m", "mmm", "c"> { let Name = NAME # "_mm"; let HasMasked = false; @@ -531,10 +371,18 @@ let HasMaskedOffOperand = true in { defm "" : RVVOutOp0BuiltinSet; } + multiclass RVVFloatingReductionBuiltinRoundingMode { + defm "" : RVVOutOp0BuiltinSet; + } multiclass RVVFloatingWidenReductionBuiltin { defm "" : RVVOutOp0BuiltinSet; } + multiclass RVVFloatingWidenReductionBuiltinRoundingMode { + defm "" : RVVOutOp0BuiltinSet; + } } multiclass RVVIntReductionBuiltinSet @@ -598,11 +446,21 @@ multiclass RVVFloatingWidenBinBuiltinSet [["vv", "w", "wvv"], ["vf", "w", "wve"]]>; +multiclass RVVFloatingWidenBinBuiltinSetRoundingMode + : RVVWidenBuiltinSet; + multiclass RVVFloatingWidenOp0BinBuiltinSet : RVVWidenWOp0BuiltinSet; +multiclass RVVFloatingWidenOp0BinBuiltinSetRoundingMode + : RVVWidenWOp0BuiltinSet; + defvar TypeList = ["c","s","i","l","x","f","d"]; defvar EEWList = [["8", "(Log2EEW:3)"], ["16", "(Log2EEW:4)"], @@ -918,269 +776,6 @@ class PVString { !eq(nf, 8): !if(signed, "PvPvPvPvPvPvPvPv", "PUvPUvPUvPUvPUvPUvPUvPUv")); } -multiclass RVVUnitStridedSegLoad { - foreach type = TypeList in { - defvar eew = !cond(!eq(type, "c") : "8", - !eq(type, "s") : "16", - !eq(type, "i") : "32", - !eq(type, "l") : "64", - !eq(type, "x") : "16", - !eq(type, "f") : "32", - !eq(type, "d") : "64"); - foreach nf = NFList in { - let Name = op # nf # "e" # eew # "_v", - IRName = op # nf, - MaskedIRName = op # nf # "_mask", - NF = nf, - ManualCodegen = [{ - { - ResultType = ConvertType(E->getArg(0)->getType()->getPointeeType()); - IntrinsicTypes = {ResultType, Ops.back()->getType()}; - SmallVector Operands; - - // Please refer to comment under 'defvar NFList' in this file - if ((IsMasked && (PolicyAttrs & RVV_VTA) && (PolicyAttrs & RVV_VMA)) || - (!IsMasked && PolicyAttrs & RVV_VTA)) - Operands.append(NF, llvm::PoisonValue::get(ResultType)); - else { - if (IsMasked) - Operands.append(Ops.begin() + NF + 1, Ops.begin() + 2 * NF + 1); - else // Unmasked - Operands.append(Ops.begin() + NF, Ops.begin() + 2 * NF); - } - unsigned PtrOperandIdx = IsMasked ? - ((PolicyAttrs & RVV_VTA) && (PolicyAttrs & RVV_VMA)) ? NF + 1 : 2 * NF + 1 : - (PolicyAttrs & RVV_VTA) ? NF : 2 * NF; - Value *PtrOperand = Ops[PtrOperandIdx]; - Value *VLOperand = Ops[PtrOperandIdx + 1]; - Operands.push_back(PtrOperand); - if (IsMasked) - Operands.push_back(Ops[NF]); - Operands.push_back(VLOperand); - if (IsMasked) - Operands.push_back(ConstantInt::get(Ops.back()->getType(), PolicyAttrs)); - - llvm::Function *F = CGM.getIntrinsic(ID, IntrinsicTypes); - llvm::Value *LoadValue = Builder.CreateCall(F, Operands, ""); - clang::CharUnits Align = - CGM.getNaturalPointeeTypeAlignment(E->getArg(0)->getType()); - llvm::Value *V; - for (unsigned I = 0; I < NF; ++I) { - llvm::Value *Val = Builder.CreateExtractValue(LoadValue, {I}); - V = Builder.CreateStore(Val, Address(Ops[I], Val->getType(), Align)); - } - return V; - } - }] in { - defvar PV = PVString.S; - defvar PUV = PVString.S; - def : RVVBuiltin<"v", "0" # PV # "PCe", type>; - if !not(IsFloat.val) then { - def : RVVBuiltin<"Uv", "0" # PUV # "PCUe", type>; - } - } - } - } -} - -multiclass RVVUnitStridedSegLoadFF { - foreach type = TypeList in { - defvar eew = !cond(!eq(type, "c") : "8", - !eq(type, "s") : "16", - !eq(type, "i") : "32", - !eq(type, "l") : "64", - !eq(type, "x") : "16", - !eq(type, "f") : "32", - !eq(type, "d") : "64"); - foreach nf = NFList in { - let Name = op # nf # "e" # eew # "ff_v", - IRName = op # nf # "ff", - MaskedIRName = op # nf # "ff_mask", - NF = nf, - ManualCodegen = [{ - { - ResultType = ConvertType(E->getArg(0)->getType()->getPointeeType()); - IntrinsicTypes = {ResultType, Ops.back()->getType()}; - SmallVector Operands; - - // Please refer to comment under 'defvar NFList' in this file - if ((IsMasked && (PolicyAttrs & RVV_VTA) && (PolicyAttrs & RVV_VMA)) || - (!IsMasked && PolicyAttrs & RVV_VTA)) - Operands.append(NF, llvm::PoisonValue::get(ResultType)); - else { - if (IsMasked) - Operands.append(Ops.begin() + NF + 1, Ops.begin() + 2 * NF + 1); - else // Unmasked - Operands.append(Ops.begin() + NF, Ops.begin() + 2 * NF); - } - unsigned PtrOperandIdx = IsMasked ? - ((PolicyAttrs & RVV_VTA) && (PolicyAttrs & RVV_VMA)) ? NF + 1 : 2 * NF + 1 : - (PolicyAttrs & RVV_VTA) ? NF : 2 * NF; - Value *PtrOperand = Ops[PtrOperandIdx]; - Value *NewVLOperand = Ops[PtrOperandIdx + 1]; - Value *VLOperand = Ops[PtrOperandIdx + 2]; - Operands.push_back(PtrOperand); - if (IsMasked) - Operands.push_back(Ops[NF]); - Operands.push_back(VLOperand); - if (IsMasked) - Operands.push_back(ConstantInt::get(Ops.back()->getType(), PolicyAttrs)); - - llvm::Function *F = CGM.getIntrinsic(ID, IntrinsicTypes); - llvm::Value *LoadValue = Builder.CreateCall(F, Operands, ""); - clang::CharUnits Align = - CGM.getNaturalPointeeTypeAlignment(E->getArg(0)->getType()); - for (unsigned I = 0; I < NF; ++I) { - llvm::Value *Val = Builder.CreateExtractValue(LoadValue, {I}); - Builder.CreateStore(Val, Address(Ops[I], Val->getType(), Align)); - } - // Store new_vl. - llvm::Value *Val = Builder.CreateExtractValue(LoadValue, {NF}); - return Builder.CreateStore(Val, Address(NewVLOperand, Val->getType(), Align)); - } - }] in { - defvar PV = PVString.S; - defvar PUV = PVString.S; - def : RVVBuiltin<"v", "0" # PV # "PCe" # "Pz", type>; - if !not(IsFloat.val) then { - def : RVVBuiltin<"Uv", "0" # PUV # "PCUe" # "Pz", type>; - } - } - } - } -} - -multiclass RVVStridedSegLoad { - foreach type = TypeList in { - defvar eew = !cond(!eq(type, "c") : "8", - !eq(type, "s") : "16", - !eq(type, "i") : "32", - !eq(type, "l") : "64", - !eq(type, "x") : "16", - !eq(type, "f") : "32", - !eq(type, "d") : "64"); - foreach nf = NFList in { - let Name = op # nf # "e" # eew # "_v", - IRName = op # nf, - MaskedIRName = op # nf # "_mask", - NF = nf, - ManualCodegen = [{ - { - ResultType = ConvertType(E->getArg(0)->getType()->getPointeeType()); - IntrinsicTypes = {ResultType, Ops.back()->getType()}; - SmallVector Operands; - - // Please refer to comment under 'defvar NFList' in this file - if ((IsMasked && (PolicyAttrs & RVV_VTA) && (PolicyAttrs & RVV_VMA)) || - (!IsMasked && PolicyAttrs & RVV_VTA)) - Operands.append(NF, llvm::PoisonValue::get(ResultType)); - else { - if (IsMasked) - Operands.append(Ops.begin() + NF + 1, Ops.begin() + 2 * NF + 1); - else // Unmasked - Operands.append(Ops.begin() + NF, Ops.begin() + 2 * NF); - } - unsigned PtrOperandIdx = IsMasked ? - ((PolicyAttrs & RVV_VTA) && (PolicyAttrs & RVV_VMA)) ? NF + 1 : 2 * NF + 1 : - (PolicyAttrs & RVV_VTA) ? NF : 2 * NF; - Value *PtrOperand = Ops[PtrOperandIdx]; - Value *StrideOperand = Ops[PtrOperandIdx + 1]; - Value *VLOperand = Ops[PtrOperandIdx + 2]; - Operands.push_back(PtrOperand); - Operands.push_back(StrideOperand); - if (IsMasked) - Operands.push_back(Ops[NF]); - Operands.push_back(VLOperand); - if (IsMasked) - Operands.push_back(ConstantInt::get(Ops.back()->getType(), PolicyAttrs)); - - llvm::Function *F = CGM.getIntrinsic(ID, IntrinsicTypes); - llvm::Value *LoadValue = Builder.CreateCall(F, Operands, ""); - clang::CharUnits Align = - CGM.getNaturalPointeeTypeAlignment(E->getArg(0)->getType()); - llvm::Value *V; - for (unsigned I = 0; I < NF; ++I) { - llvm::Value *Val = Builder.CreateExtractValue(LoadValue, {I}); - V = Builder.CreateStore(Val, Address(Ops[I], Val->getType(), Align)); - } - return V; - } - }] in { - defvar PV = PVString.S; - defvar PUV = PVString.S; - def : RVVBuiltin<"v", "0" # PV # "PCe" # "t", type>; - if !not(IsFloat.val) then { - def : RVVBuiltin<"Uv", "0" # PUV # "PCUe" # "t", type>; - } - } - } - } -} - -multiclass RVVIndexedSegLoad { - foreach type = TypeList in { - foreach eew_info = EEWList in { - defvar eew = eew_info[0]; - defvar eew_type = eew_info[1]; - foreach nf = NFList in { - let Name = op # nf # "ei" # eew # "_v", - IRName = op # nf, - MaskedIRName = op # nf # "_mask", - NF = nf, - ManualCodegen = [{ - { - ResultType = ConvertType(E->getArg(0)->getType()->getPointeeType()); - SmallVector Operands; - - // Please refer to comment under 'defvar NFList' in this file - if ((IsMasked && (PolicyAttrs & RVV_VTA) && (PolicyAttrs & RVV_VMA)) || - (!IsMasked && PolicyAttrs & RVV_VTA)) - Operands.append(NF, llvm::PoisonValue::get(ResultType)); - else { - if (IsMasked) - Operands.append(Ops.begin() + NF + 1, Ops.begin() + 2 * NF + 1); - else // Unmasked - Operands.append(Ops.begin() + NF, Ops.begin() + 2 * NF); - } - unsigned PtrOperandIdx = IsMasked ? - ((PolicyAttrs & RVV_VTA) && (PolicyAttrs & RVV_VMA)) ? NF + 1 : 2 * NF + 1 : - (PolicyAttrs & RVV_VTA) ? NF : 2 * NF; - Value *PtrOperand = Ops[PtrOperandIdx]; - Value *IndexOperand = Ops[PtrOperandIdx + 1]; - Value *VLOperand = Ops[PtrOperandIdx + 2]; - Operands.push_back(PtrOperand); - Operands.push_back(IndexOperand); - if (IsMasked) - Operands.push_back(Ops[NF]); - Operands.push_back(VLOperand); - if (IsMasked) - Operands.push_back(ConstantInt::get(Ops.back()->getType(), PolicyAttrs)); - IntrinsicTypes = {ResultType, IndexOperand->getType(), Ops.back()->getType()}; - - llvm::Function *F = CGM.getIntrinsic(ID, IntrinsicTypes); - llvm::Value *LoadValue = Builder.CreateCall(F, Operands, ""); - clang::CharUnits Align = - CGM.getNaturalPointeeTypeAlignment(E->getArg(0)->getType()); - llvm::Value *V; - for (unsigned I = 0; I < NF; ++I) { - llvm::Value *Val = Builder.CreateExtractValue(LoadValue, {I}); - V = Builder.CreateStore(Val, Address(Ops[I], Val->getType(), Align)); - } - return V; - } - }] in { - defvar PV = PVString.S; - defvar PUV = PVString.S; - def : RVVBuiltin<"v", "0" # PV # "PCe" # eew_type # "Uv", type>; - if !not(IsFloat.val) then { - def : RVVBuiltin<"Uv", "0" # PUV # "PCUe" # eew_type # "Uv", type>; - } - } - } - } - } -} - class VString { string S = !cond(!eq(nf, 2): !if(signed, "vv", "UvUv"), !eq(nf, 3): !if(signed, "vvv", "UvUvUv"), @@ -1191,139 +786,6 @@ class VString { !eq(nf, 8): !if(signed, "vvvvvvvv", "UvUvUvUvUvUvUvUv")); } -multiclass RVVUnitStridedSegStore { - foreach type = TypeList in { - defvar eew = !cond(!eq(type, "c") : "8", - !eq(type, "s") : "16", - !eq(type, "i") : "32", - !eq(type, "l") : "64", - !eq(type, "x") : "16", - !eq(type, "f") : "32", - !eq(type, "d") : "64"); - foreach nf = NFList in { - let Name = op # nf # "e" # eew # "_v", - IRName = op # nf, - MaskedIRName = op # nf # "_mask", - NF = nf, - HasMaskedOffOperand = false, - MaskedPolicyScheme = NonePolicy, - ManualCodegen = [{ - { - if (IsMasked) { - // Builtin: (mask, ptr, val0, val1, ..., vl) - // Intrinsic: (val0, val1, ..., ptr, mask, vl) - std::rotate(Ops.begin(), Ops.begin() + 2, Ops.end() - 1); - std::swap(Ops[NF], Ops[NF + 1]); - IntrinsicTypes = {Ops[0]->getType(), Ops[NF + 2]->getType()}; - assert(Ops.size() == NF + 3); - } else { - // Builtin: (ptr, val0, val1, ..., vl) - // Intrinsic: (val0, val1, ..., ptr, vl) - std::rotate(Ops.begin(), Ops.begin() + 1, Ops.end() - 1); - IntrinsicTypes = {Ops[0]->getType(), Ops[NF + 1]->getType()}; - assert(Ops.size() == NF + 2); - } - } - }] in { - defvar V = VString.S; - defvar UV = VString.S; - def : RVVBuiltin<"v", "0Pe" # V, type>; - if !not(IsFloat.val) then { - def : RVVBuiltin<"Uv", "0PUe" # UV, type>; - } - } - } - } -} - -multiclass RVVStridedSegStore { - foreach type = TypeList in { - defvar eew = !cond(!eq(type, "c") : "8", - !eq(type, "s") : "16", - !eq(type, "i") : "32", - !eq(type, "l") : "64", - !eq(type, "x") : "16", - !eq(type, "f") : "32", - !eq(type, "d") : "64"); - foreach nf = NFList in { - let Name = op # nf # "e" # eew # "_v", - IRName = op # nf, - MaskedIRName = op # nf # "_mask", - NF = nf, - HasMaskedOffOperand = false, - MaskedPolicyScheme = NonePolicy, - ManualCodegen = [{ - { - if (IsMasked) { - // Builtin: (mask, ptr, stride, val0, val1, ..., vl). - // Intrinsic: (val0, val1, ..., ptr, stride, mask, vl) - std::rotate(Ops.begin(), Ops.begin() + 3, Ops.end() - 1); - std::rotate(Ops.begin() + NF, Ops.begin() + NF + 1, Ops.begin() + NF + 3); - assert(Ops.size() == NF + 4); - } else { - // Builtin: (ptr, stride, val0, val1, ..., vl). - // Intrinsic: (val0, val1, ..., ptr, stride, vl) - std::rotate(Ops.begin(), Ops.begin() + 2, Ops.end() - 1); - assert(Ops.size() == NF + 3); - } - IntrinsicTypes = {Ops[0]->getType(), Ops[NF + 1]->getType()}; - } - }] in { - defvar V = VString.S; - defvar UV = VString.S; - def : RVVBuiltin<"v", "0Pet" # V, type>; - if !not(IsFloat.val) then { - def : RVVBuiltin<"Uv", "0PUet" # UV, type>; - } - } - } - } -} - -multiclass RVVIndexedSegStore { - foreach type = TypeList in { - foreach eew_info = EEWList in { - defvar eew = eew_info[0]; - defvar eew_type = eew_info[1]; - foreach nf = NFList in { - let Name = op # nf # "ei" # eew # "_v", - IRName = op # nf, - MaskedIRName = op # nf # "_mask", - NF = nf, - HasMaskedOffOperand = false, - MaskedPolicyScheme = NonePolicy, - ManualCodegen = [{ - { - if (IsMasked) { - // Builtin: (mask, ptr, index, val0, val1, ..., vl) - // Intrinsic: (val0, val1, ..., ptr, index, mask, vl) - std::rotate(Ops.begin(), Ops.begin() + 3, Ops.end() - 1); - std::rotate(Ops.begin() + NF, Ops.begin() + NF + 1, Ops.begin() + NF + 3); - IntrinsicTypes = {Ops[0]->getType(), - Ops[NF + 1]->getType(), Ops[NF + 3]->getType()}; - assert(Ops.size() == NF + 4); - } else { - // Builtin: (ptr, index, val0, val1, ..., vl) - // Intrinsic: (val0, val1, ..., ptr, index, vl) - std::rotate(Ops.begin(), Ops.begin() + 2, Ops.end() - 1); - IntrinsicTypes = {Ops[0]->getType(), - Ops[NF + 1]->getType(), Ops[NF + 2]->getType()}; - assert(Ops.size() == NF + 3); - } - } - }] in { - defvar V = VString.S; - defvar UV = VString.S; - def : RVVBuiltin<"v", "0Pe" # eew_type # "Uv" # V, type>; - if !not(IsFloat.val) then { - def : RVVBuiltin<"Uv", "0PUe" # eew_type # "Uv" # UV, type>; - } - } - } - } - } -} - multiclass RVVPseudoUnaryBuiltin { let Name = NAME, IRName = IR, @@ -1504,7 +966,7 @@ multiclass RVVPseudoVNCVTBuiltingetType())); + Ops.insert(Ops.begin() + 2, llvm::Constant::getNullValue(Ops.back()->getType())); if (IsMasked) { Ops.push_back(ConstantInt::get(Ops.back()->getType(), PolicyAttrs)); // maskedoff, op1, xlen, mask, vl @@ -1721,20 +1183,429 @@ defm vle16ff: RVVVLEFFBuiltin<["s","x"]>; defm vle32ff: RVVVLEFFBuiltin<["i", "f"]>; defm vle64ff: RVVVLEFFBuiltin<["l", "d"]>; -// 7.8 Vector Load/Store Segment Instructions -let UnMaskedPolicyScheme = HasPassthruOperand in { -defm : RVVUnitStridedSegLoad<"vlseg">; -defm : RVVUnitStridedSegLoadFF<"vlseg">; -defm : RVVStridedSegLoad<"vlsseg">; -defm : RVVIndexedSegLoad<"vluxseg">; -defm : RVVIndexedSegLoad<"vloxseg">; +multiclass RVVUnitStridedSegLoadTuple { + foreach type = TypeList in { + defvar eew = !cond(!eq(type, "c") : "8", + !eq(type, "s") : "16", + !eq(type, "i") : "32", + !eq(type, "l") : "64", + !eq(type, "x") : "16", + !eq(type, "f") : "32", + !eq(type, "d") : "64"); + foreach nf = NFList in { + let Name = op # nf # "e" # eew # "_v", + IRName = op # nf, + MaskedIRName = op # nf # "_mask", + NF = nf, + ManualCodegen = [{ + { + llvm::Type *ElementVectorType = cast(ResultType)->elements()[0]; + IntrinsicTypes = {ElementVectorType, Ops.back()->getType()}; + SmallVector Operands; + + bool NoPassthru = + (IsMasked && (PolicyAttrs & RVV_VTA) && (PolicyAttrs & RVV_VMA)) | + (!IsMasked && (PolicyAttrs & RVV_VTA)); + unsigned Offset = IsMasked ? NoPassthru ? 1 : 2 : NoPassthru ? 0 : 1; + + if (NoPassthru) { // Push poison into passthru + Operands.append(NF, llvm::PoisonValue::get(ElementVectorType)); + } else { // Push intrinsics operands into passthru + llvm::Value *PassthruOperand = IsMasked ? Ops[1] : Ops[0]; + for (unsigned I = 0; I < NF; ++I) + Operands.push_back(Builder.CreateExtractValue(PassthruOperand, {I})); + } + + Operands.push_back(Ops[Offset]); // Ptr + if (IsMasked) + Operands.push_back(Ops[0]); + Operands.push_back(Ops[Offset + 1]); // VL + if (IsMasked) + Operands.push_back(ConstantInt::get(Ops.back()->getType(), PolicyAttrs)); + + llvm::Function *F = CGM.getIntrinsic(ID, IntrinsicTypes); + + llvm::Value *LoadValue = Builder.CreateCall(F, Operands, ""); + if (ReturnValue.isNull()) + return LoadValue; + else + return Builder.CreateStore(LoadValue, ReturnValue.getValue()); + } + }] in { + defvar T = "(Tuple:" # nf # ")"; + def : RVVBuiltin; + if !not(IsFloat.val) then { + def : RVVBuiltin; + } + } + } + } } + +multiclass RVVUnitStridedSegStoreTuple { + foreach type = TypeList in { + defvar eew = !cond(!eq(type, "c") : "8", + !eq(type, "s") : "16", + !eq(type, "i") : "32", + !eq(type, "l") : "64", + !eq(type, "x") : "16", + !eq(type, "f") : "32", + !eq(type, "d") : "64"); + foreach nf = NFList in { + let Name = op # nf # "e" # eew # "_v", + IRName = op # nf, + MaskedIRName = op # nf # "_mask", + NF = nf, + HasMaskedOffOperand = false, + ManualCodegen = [{ + { + // Masked + // Builtin: (mask, ptr, v_tuple, vl) + // Intrinsic: (val0, val1, ..., ptr, mask, vl) + // Unmasked + // Builtin: (ptr, v_tuple, vl) + // Intrinsic: (val0, val1, ..., ptr, vl) + unsigned Offset = IsMasked ? 1 : 0; + llvm::Value *VTupleOperand = Ops[Offset + 1]; + + SmallVector Operands; + for (unsigned I = 0; I < NF; ++I) { + llvm::Value *V = Builder.CreateExtractValue(VTupleOperand, {I}); + Operands.push_back(V); + } + Operands.push_back(Ops[Offset]); // Ptr + if (IsMasked) + Operands.push_back(Ops[0]); + Operands.push_back(Ops[Offset + 2]); // VL + + IntrinsicTypes = {Operands[0]->getType(), Operands.back()->getType()}; + llvm::Function *F = CGM.getIntrinsic(ID, IntrinsicTypes); + return Builder.CreateCall(F, Operands, ""); + } + }] in { + defvar T = "(Tuple:" # nf # ")"; + def : RVVBuiltin; + if !not(IsFloat.val) then { + def : RVVBuiltin; + } + } + } + } +} + +multiclass RVVUnitStridedSegLoadFFTuple { + foreach type = TypeList in { + defvar eew = !cond(!eq(type, "c") : "8", + !eq(type, "s") : "16", + !eq(type, "i") : "32", + !eq(type, "l") : "64", + !eq(type, "x") : "16", + !eq(type, "f") : "32", + !eq(type, "d") : "64"); + foreach nf = NFList in { + let Name = op # nf # "e" # eew # "ff_v", + IRName = op # nf # "ff", + MaskedIRName = op # nf # "ff_mask", + NF = nf, + ManualCodegen = [{ + { + llvm::Type *ElementVectorType = cast(ResultType)->elements()[0]; + IntrinsicTypes = {ElementVectorType, Ops.back()->getType()}; + SmallVector Operands; + + bool NoPassthru = + (IsMasked && (PolicyAttrs & RVV_VTA) && (PolicyAttrs & RVV_VMA)) | + (!IsMasked && (PolicyAttrs & RVV_VTA)); + unsigned Offset = IsMasked ? NoPassthru ? 1 : 2 : NoPassthru ? 0 : 1; + + if (NoPassthru) { // Push poison into passthru + Operands.append(NF, llvm::PoisonValue::get(ElementVectorType)); + } else { // Push intrinsics operands into passthru + llvm::Value *PassthruOperand = IsMasked ? Ops[1] : Ops[0]; + for (unsigned I = 0; I < NF; ++I) + Operands.push_back(Builder.CreateExtractValue(PassthruOperand, {I})); + } + + Operands.push_back(Ops[Offset]); // Ptr + if (IsMasked) + Operands.push_back(Ops[0]); + Operands.push_back(Ops[Offset + 2]); // vl + if (IsMasked) + Operands.push_back(ConstantInt::get(Ops.back()->getType(), PolicyAttrs)); + + llvm::Function *F = CGM.getIntrinsic(ID, IntrinsicTypes); + + llvm::Value *LoadValue = Builder.CreateCall(F, Operands, ""); + // Get alignment from the new vl operand + clang::CharUnits Align = + CGM.getNaturalPointeeTypeAlignment(E->getArg(Offset + 1)->getType()); + + llvm::Value *ReturnTuple = llvm::PoisonValue::get(ResultType); + for (unsigned I = 0; I < NF; ++I) { + llvm::Value *V = Builder.CreateExtractValue(LoadValue, {I}); + ReturnTuple = Builder.CreateInsertValue(ReturnTuple, V, {I}); + } + + // Store new_vl + llvm::Value *V = Builder.CreateExtractValue(LoadValue, {NF}); + Builder.CreateStore(V, Address(Ops[Offset + 1], V->getType(), Align)); + + if (ReturnValue.isNull()) + return ReturnTuple; + else + return Builder.CreateStore(ReturnTuple, ReturnValue.getValue()); + } + }] in { + defvar T = "(Tuple:" # nf # ")"; + def : RVVBuiltin; + if !not(IsFloat.val) then { + def : RVVBuiltin; + } + } + } + } +} + +multiclass RVVStridedSegLoadTuple { + foreach type = TypeList in { + defvar eew = !cond(!eq(type, "c") : "8", + !eq(type, "s") : "16", + !eq(type, "i") : "32", + !eq(type, "l") : "64", + !eq(type, "x") : "16", + !eq(type, "f") : "32", + !eq(type, "d") : "64"); + foreach nf = NFList in { + let Name = op # nf # "e" # eew # "_v", + IRName = op # nf, + MaskedIRName = op # nf # "_mask", + NF = nf, + ManualCodegen = [{ + { + llvm::Type *ElementVectorType = cast(ResultType)->elements()[0]; + IntrinsicTypes = {ElementVectorType, Ops.back()->getType()}; + SmallVector Operands; + + bool NoPassthru = + (IsMasked && (PolicyAttrs & RVV_VTA) && (PolicyAttrs & RVV_VMA)) | + (!IsMasked && (PolicyAttrs & RVV_VTA)); + unsigned Offset = IsMasked ? NoPassthru ? 1 : 2 : NoPassthru ? 0 : 1; + + if (NoPassthru) { // Push poison into passthru + Operands.append(NF, llvm::PoisonValue::get(ElementVectorType)); + } else { // Push intrinsics operands into passthru + llvm::Value *PassthruOperand = IsMasked ? Ops[1] : Ops[0]; + for (unsigned I = 0; I < NF; ++I) + Operands.push_back(Builder.CreateExtractValue(PassthruOperand, {I})); + } + + Operands.push_back(Ops[Offset]); // Ptr + Operands.push_back(Ops[Offset + 1]); // Stride + if (IsMasked) + Operands.push_back(Ops[0]); + Operands.push_back(Ops[Offset + 2]); // VL + if (IsMasked) + Operands.push_back(ConstantInt::get(Ops.back()->getType(), PolicyAttrs)); + + llvm::Function *F = CGM.getIntrinsic(ID, IntrinsicTypes); + llvm::Value *LoadValue = Builder.CreateCall(F, Operands, ""); + + if (ReturnValue.isNull()) + return LoadValue; + else + return Builder.CreateStore(LoadValue, ReturnValue.getValue()); + } + }] in { + defvar T = "(Tuple:" # nf # ")"; + def : RVVBuiltin; + if !not(IsFloat.val) then { + def : RVVBuiltin; + } + } + } + } +} + +multiclass RVVStridedSegStoreTuple { + foreach type = TypeList in { + defvar eew = !cond(!eq(type, "c") : "8", + !eq(type, "s") : "16", + !eq(type, "i") : "32", + !eq(type, "l") : "64", + !eq(type, "x") : "16", + !eq(type, "f") : "32", + !eq(type, "d") : "64"); + foreach nf = NFList in { + let Name = op # nf # "e" # eew # "_v", + IRName = op # nf, + MaskedIRName = op # nf # "_mask", + NF = nf, + HasMaskedOffOperand = false, + MaskedPolicyScheme = NonePolicy, + ManualCodegen = [{ + { + // Masked + // Builtin: (mask, ptr, stride, v_tuple, vl) + // Intrinsic: (val0, val1, ..., ptr, stride, mask, vl) + // Unmasked + // Builtin: (ptr, stride, v_tuple, vl) + // Intrinsic: (val0, val1, ..., ptr, stride, vl) + unsigned Offset = IsMasked ? 1 : 0; + llvm::Value *VTupleOperand = Ops[Offset + 2]; + + SmallVector Operands; + for (unsigned I = 0; I < NF; ++I) { + llvm::Value *V = Builder.CreateExtractValue(VTupleOperand, {I}); + Operands.push_back(V); + } + Operands.push_back(Ops[Offset]); // Ptr + Operands.push_back(Ops[Offset + 1]); // Stride + if (IsMasked) + Operands.push_back(Ops[0]); + Operands.push_back(Ops[Offset + 3]); // VL + + IntrinsicTypes = {Operands[0]->getType(), Operands.back()->getType()}; + llvm::Function *F = CGM.getIntrinsic(ID, IntrinsicTypes); + return Builder.CreateCall(F, Operands, ""); + } + }] in { + defvar T = "(Tuple:" # nf # ")"; + def : RVVBuiltin; + if !not(IsFloat.val) then { + def : RVVBuiltin; + } + } + } + } +} + +multiclass RVVIndexedSegLoadTuple { + foreach type = TypeList in { + foreach eew_info = EEWList in { + defvar eew = eew_info[0]; + defvar eew_type = eew_info[1]; + foreach nf = NFList in { + let Name = op # nf # "ei" # eew # "_v", + IRName = op # nf, + MaskedIRName = op # nf # "_mask", + NF = nf, + ManualCodegen = [{ + { + llvm::Type *ElementVectorType = cast(ResultType)->elements()[0]; + IntrinsicTypes = {ElementVectorType, Ops.back()->getType()}; + SmallVector Operands; + + bool NoPassthru = + (IsMasked && (PolicyAttrs & RVV_VTA) && (PolicyAttrs & RVV_VMA)) | + (!IsMasked && (PolicyAttrs & RVV_VTA)); + unsigned Offset = IsMasked ? NoPassthru ? 1 : 2 : NoPassthru ? 0 : 1; + + if (NoPassthru) { // Push poison into passthru + Operands.append(NF, llvm::PoisonValue::get(ElementVectorType)); + } else { // Push intrinsics operands into passthru + llvm::Value *PassthruOperand = IsMasked ? Ops[1] : Ops[0]; + for (unsigned I = 0; I < NF; ++I) + Operands.push_back(Builder.CreateExtractValue(PassthruOperand, {I})); + } + + Operands.push_back(Ops[Offset]); // Ptr + Operands.push_back(Ops[Offset + 1]); // Idx + if (IsMasked) + Operands.push_back(Ops[0]); + Operands.push_back(Ops[Offset + 2]); // VL + if (IsMasked) + Operands.push_back(ConstantInt::get(Ops.back()->getType(), PolicyAttrs)); + + IntrinsicTypes = {ElementVectorType, Ops[Offset + 1]->getType(), + Ops.back()->getType()}; + llvm::Function *F = CGM.getIntrinsic(ID, IntrinsicTypes); + llvm::Value *LoadValue = Builder.CreateCall(F, Operands, ""); + + if (ReturnValue.isNull()) + return LoadValue; + else + return Builder.CreateStore(LoadValue, ReturnValue.getValue()); + } + }] in { + defvar T = "(Tuple:" # nf # ")"; + def : RVVBuiltin; + if !not(IsFloat.val) then { + def : RVVBuiltin; + } + } + } + } + } +} + +multiclass RVVIndexedSegStoreTuple { + foreach type = TypeList in { + foreach eew_info = EEWList in { + defvar eew = eew_info[0]; + defvar eew_type = eew_info[1]; + foreach nf = NFList in { + let Name = op # nf # "ei" # eew # "_v", + IRName = op # nf, + MaskedIRName = op # nf # "_mask", + NF = nf, + HasMaskedOffOperand = false, + MaskedPolicyScheme = NonePolicy, + ManualCodegen = [{ + { + // Masked + // Builtin: (mask, ptr, index, v_tuple, vl) + // Intrinsic: (val0, val1, ..., ptr, index, mask, vl) + // Unmasked + // Builtin: (ptr, index, v_tuple, vl) + // Intrinsic: (val0, val1, ..., ptr, index, vl) + unsigned Offset = IsMasked ? 1 : 0; + llvm::Value *VTupleOperand = Ops[Offset + 2]; + + SmallVector Operands; + for (unsigned I = 0; I < NF; ++I) { + llvm::Value *V = Builder.CreateExtractValue(VTupleOperand, {I}); + Operands.push_back(V); + } + Operands.push_back(Ops[Offset]); // Ptr + Operands.push_back(Ops[Offset + 1]); // Idx + if (IsMasked) + Operands.push_back(Ops[0]); + Operands.push_back(Ops[Offset + 3]); // VL + + IntrinsicTypes = {Operands[0]->getType(), Ops[Offset + 1]->getType(), + Operands.back()->getType()}; + llvm::Function *F = CGM.getIntrinsic(ID, IntrinsicTypes); + return Builder.CreateCall(F, Operands, ""); + } + }] in { + defvar T = "(Tuple:" # nf # ")"; + def : RVVBuiltin; + if !not(IsFloat.val) then { + def : RVVBuiltin; + } + } + } + } + } +} + +// 7.8 Vector Load/Store Segment Instructions +let UnMaskedPolicyScheme = HasPassthruOperand, + IsTuple = true in { + defm : RVVUnitStridedSegLoadTuple<"vlseg">; + defm : RVVUnitStridedSegLoadFFTuple<"vlseg">; + defm : RVVStridedSegLoadTuple<"vlsseg">; + defm : RVVIndexedSegLoadTuple<"vluxseg">; + defm : RVVIndexedSegLoadTuple<"vloxseg">; +} + let UnMaskedPolicyScheme = NonePolicy, - MaskedPolicyScheme = NonePolicy in { -defm : RVVUnitStridedSegStore<"vsseg">; -defm : RVVStridedSegStore<"vssseg">; -defm : RVVIndexedSegStore<"vsuxseg">; -defm : RVVIndexedSegStore<"vsoxseg">; + MaskedPolicyScheme = NonePolicy, + IsTuple = true in { +defm : RVVUnitStridedSegStoreTuple<"vsseg">; +defm : RVVStridedSegStoreTuple<"vssseg">; +defm : RVVIndexedSegStoreTuple<"vsuxseg">; +defm : RVVIndexedSegStoreTuple<"vsoxseg">; } // 12. Vector Integer Arithmetic Instructions @@ -1842,13 +1713,11 @@ defm vmax : RVVSignedBinBuiltinSet; // 12.10. Vector Single-Width Integer Multiply Instructions defm vmul : RVVIntBinBuiltinSet; -let RequiredFeatures = ["FullMultiply"] in { defm vmulh : RVVSignedBinBuiltinSet; defm vmulhu : RVVUnsignedBinBuiltinSet; defm vmulhsu : RVVOutOp1BuiltinSet<"vmulhsu", "csil", [["vv", "v", "vvUv"], ["vx", "v", "vvUe"]]>; -} // 12.11. Vector Integer Divide Instructions defm vdivu : RVVUnsignedBinBuiltinSet; @@ -1928,6 +1797,17 @@ let HasMasked = false, } // 13. Vector Fixed-Point Arithmetic Instructions +let HeaderCode = +[{ +enum __RISCV_VXRM { + __RISCV_VXRM_RNU = 0, + __RISCV_VXRM_RNE = 1, + __RISCV_VXRM_RDN = 2, + __RISCV_VXRM_ROD = 3, +}; +}] in +def vxrm_enum : RVVHeader; + // 13.1. Vector Single-Width Saturating Add and Subtract let UnMaskedPolicyScheme = HasPassthruOperand in { defm vsaddu : RVVUnsignedBinBuiltinSet; @@ -1935,80 +1815,434 @@ defm vsadd : RVVSignedBinBuiltinSet; defm vssubu : RVVUnsignedBinBuiltinSet; defm vssub : RVVSignedBinBuiltinSet; -// 13.2. Vector Single-Width Averaging Add and Subtract -defm vaaddu : RVVUnsignedBinBuiltinSet; -defm vaadd : RVVSignedBinBuiltinSet; -defm vasubu : RVVUnsignedBinBuiltinSet; -defm vasub : RVVSignedBinBuiltinSet; +let ManualCodegen = [{ + { + // LLVM intrinsic + // Unmasked: (passthru, op0, op1, round_mode, vl) + // Masked: (passthru, vector_in, vector_in/scalar_in, mask, vxrm, vl, policy) -// 13.3. Vector Single-Width Fractional Multiply with Rounding and Saturation -let RequiredFeatures = ["FullMultiply"] in { -defm vsmul : RVVSignedBinBuiltinSet; + SmallVector Operands; + bool HasMaskedOff = !( + (IsMasked && (PolicyAttrs & RVV_VTA) && (PolicyAttrs & RVV_VMA)) || + (!IsMasked && PolicyAttrs & RVV_VTA)); + unsigned Offset = IsMasked ? + (HasMaskedOff ? 2 : 1) : (HasMaskedOff ? 1 : 0); + + if (!HasMaskedOff) + Operands.push_back(llvm::PoisonValue::get(ResultType)); + else + Operands.push_back(Ops[IsMasked ? 1 : 0]); + + Operands.push_back(Ops[Offset]); // op0 + Operands.push_back(Ops[Offset + 1]); // op1 + + if (IsMasked) + Operands.push_back(Ops[0]); // mask + + Operands.push_back(Ops[Offset + 2]); // vxrm + Operands.push_back(Ops[Offset + 3]); // vl + + if (IsMasked) + Operands.push_back(ConstantInt::get(Ops.back()->getType(), PolicyAttrs)); + + IntrinsicTypes = {ResultType, Ops[Offset + 1]->getType(), Ops.back()->getType()}; + llvm::Function *F = CGM.getIntrinsic(ID, IntrinsicTypes); + return Builder.CreateCall(F, Operands, ""); + } +}] in { + // 13.2. Vector Single-Width Averaging Add and Subtract + defm vaaddu : RVVUnsignedBinBuiltinSetRoundingMode; + defm vaadd : RVVSignedBinBuiltinSetRoundingMode; + defm vasubu : RVVUnsignedBinBuiltinSetRoundingMode; + defm vasub : RVVSignedBinBuiltinSetRoundingMode; + + // 13.3. Vector Single-Width Fractional Multiply with Rounding and Saturation + defm vsmul : RVVSignedBinBuiltinSetRoundingMode; + + // 13.4. Vector Single-Width Scaling Shift Instructions + defm vssrl : RVVUnsignedShiftBuiltinSetRoundingMode; + defm vssra : RVVSignedShiftBuiltinSetRoundingMode; } -// 13.4. Vector Single-Width Scaling Shift Instructions -defm vssrl : RVVUnsignedShiftBuiltinSet; -defm vssra : RVVSignedShiftBuiltinSet; +let ManualCodegen = [{ + { + // LLVM intrinsic + // Unmasked: (passthru, op0, op1, round_mode, vl) + // Masked: (passthru, vector_in, vector_in/scalar_in, mask, vxrm, vl, policy) -// 13.5. Vector Narrowing Fixed-Point Clip Instructions -defm vnclipu : RVVUnsignedNShiftBuiltinSet; -defm vnclip : RVVSignedNShiftBuiltinSet; + SmallVector Operands; + bool HasMaskedOff = !( + (IsMasked && (PolicyAttrs & RVV_VTA) && (PolicyAttrs & RVV_VMA)) || + (!IsMasked && PolicyAttrs & RVV_VTA)); + unsigned Offset = IsMasked ? + (HasMaskedOff ? 2 : 1) : (HasMaskedOff ? 1 : 0); + + if (!HasMaskedOff) + Operands.push_back(llvm::PoisonValue::get(ResultType)); + else + Operands.push_back(Ops[IsMasked ? 1 : 0]); + + Operands.push_back(Ops[Offset]); // op0 + Operands.push_back(Ops[Offset + 1]); // op1 + + if (IsMasked) + Operands.push_back(Ops[0]); // mask + + Operands.push_back(Ops[Offset + 2]); // vxrm + Operands.push_back(Ops[Offset + 3]); // vl + + if (IsMasked) + Operands.push_back(ConstantInt::get(Ops.back()->getType(), PolicyAttrs)); + + IntrinsicTypes = {ResultType, Ops[Offset]->getType(), Ops[Offset + 1]->getType(), + Ops.back()->getType()}; + llvm::Function *F = CGM.getIntrinsic(ID, IntrinsicTypes); + return Builder.CreateCall(F, Operands, ""); + } +}] in { + // 13.5. Vector Narrowing Fixed-Point Clip Instructions + defm vnclipu : RVVUnsignedNShiftBuiltinSetRoundingMode; + defm vnclip : RVVSignedNShiftBuiltinSetRoundingMode; +} +} // 14. Vector Floating-Point Instructions -// 14.2. Vector Single-Width Floating-Point Add/Subtract Instructions -defm vfadd : RVVFloatingBinBuiltinSet; -defm vfsub : RVVFloatingBinBuiltinSet; -defm vfrsub : RVVFloatingBinVFBuiltinSet; +let HeaderCode = +[{ +enum __RISCV_FRM { + __RISCV_FRM_RNE = 0, + __RISCV_FRM_RTZ = 1, + __RISCV_FRM_RDN = 2, + __RISCV_FRM_RUP = 3, + __RISCV_FRM_RMM = 4, +}; +}] in def frm_enum : RVVHeader; -// 14.3. Vector Widening Floating-Point Add/Subtract Instructions -// Widening FP add/subtract, 2*SEW = SEW +/- SEW -defm vfwadd : RVVFloatingWidenBinBuiltinSet; -defm vfwsub : RVVFloatingWidenBinBuiltinSet; -// Widening FP add/subtract, 2*SEW = 2*SEW +/- SEW -defm vfwadd : RVVFloatingWidenOp0BinBuiltinSet; -defm vfwsub : RVVFloatingWidenOp0BinBuiltinSet; - -// 14.4. Vector Single-Width Floating-Point Multiply/Divide Instructions -defm vfmul : RVVFloatingBinBuiltinSet; -defm vfdiv : RVVFloatingBinBuiltinSet; -defm vfrdiv : RVVFloatingBinVFBuiltinSet; - -// 14.5. Vector Widening Floating-Point Multiply -let Log2LMUL = [-2, -1, 0, 1, 2] in { - defm vfwmul : RVVOutOp0Op1BuiltinSet<"vfwmul", "xf", - [["vv", "w", "wvv"], - ["vf", "w", "wve"]]>; -} -} - -// 14.6. Vector Single-Width Floating-Point Fused Multiply-Add Instructions -let UnMaskedPolicyScheme = HasPolicyOperand in { -defm vfmacc : RVVFloatingTerBuiltinSet; -defm vfnmacc : RVVFloatingTerBuiltinSet; -defm vfmsac : RVVFloatingTerBuiltinSet; -defm vfnmsac : RVVFloatingTerBuiltinSet; -defm vfmadd : RVVFloatingTerBuiltinSet; -defm vfnmadd : RVVFloatingTerBuiltinSet; -defm vfmsub : RVVFloatingTerBuiltinSet; -defm vfnmsub : RVVFloatingTerBuiltinSet; - -// 14.7. Vector Widening Floating-Point Fused Multiply-Add Instructions -defm vfwmacc : RVVFloatingWidenTerBuiltinSet; -defm vfwnmacc : RVVFloatingWidenTerBuiltinSet; -defm vfwmsac : RVVFloatingWidenTerBuiltinSet; -defm vfwnmsac : RVVFloatingWidenTerBuiltinSet; -} - -// 14.8. Vector Floating-Point Square-Root Instruction let UnMaskedPolicyScheme = HasPassthruOperand in { -def vfsqrt : RVVFloatingUnaryVVBuiltin; +let ManualCodegen = [{ + { + // LLVM intrinsic + // Unmasked: (passthru, op0, op1, round_mode, vl) + // Masked: (passthru, vector_in, vector_in/scalar_in, mask, frm, vl, policy) + + SmallVector Operands; + bool HasMaskedOff = !( + (IsMasked && (PolicyAttrs & RVV_VTA) && (PolicyAttrs & RVV_VMA)) || + (!IsMasked && PolicyAttrs & RVV_VTA)); + bool HasRoundModeOp = IsMasked ? + (HasMaskedOff ? Ops.size() == 6 : Ops.size() == 5) : + (HasMaskedOff ? Ops.size() == 5 : Ops.size() == 4); + + unsigned Offset = IsMasked ? + (HasMaskedOff ? 2 : 1) : (HasMaskedOff ? 1 : 0); + + if (!HasMaskedOff) + Operands.push_back(llvm::PoisonValue::get(ResultType)); + else + Operands.push_back(Ops[IsMasked ? 1 : 0]); + + Operands.push_back(Ops[Offset]); // op0 + Operands.push_back(Ops[Offset + 1]); // op1 + + if (IsMasked) + Operands.push_back(Ops[0]); // mask + + if (HasRoundModeOp) { + Operands.push_back(Ops[Offset + 2]); // frm + Operands.push_back(Ops[Offset + 3]); // vl + } else { + Operands.push_back(ConstantInt::get(Ops[Offset + 2]->getType(), 7)); // frm + Operands.push_back(Ops[Offset + 2]); // vl + } + + if (IsMasked) + Operands.push_back(ConstantInt::get(Ops.back()->getType(), PolicyAttrs)); + + IntrinsicTypes = {ResultType, Ops[Offset + 1]->getType(), + Operands.back()->getType()}; + llvm::Function *F = CGM.getIntrinsic(ID, IntrinsicTypes); + return Builder.CreateCall(F, Operands, ""); + } +}] in { + let HasFRMRoundModeOp = true in { + // 14.2. Vector Single-Width Floating-Point Add/Subtract Instructions + defm vfadd : RVVFloatingBinBuiltinSetRoundingMode; + defm vfsub : RVVFloatingBinBuiltinSetRoundingMode; + defm vfrsub : RVVFloatingBinVFBuiltinSetRoundingMode; + + // 14.3. Vector Widening Floating-Point Add/Subtract Instructions + // Widening FP add/subtract, 2*SEW = 2*SEW +/- SEW + defm vfwadd : RVVFloatingWidenOp0BinBuiltinSetRoundingMode; + defm vfwsub : RVVFloatingWidenOp0BinBuiltinSetRoundingMode; + + // 14.4. Vector Single-Width Floating-Point Multiply/Divide Instructions + defm vfmul : RVVFloatingBinBuiltinSetRoundingMode; + defm vfdiv : RVVFloatingBinBuiltinSetRoundingMode; + defm vfrdiv : RVVFloatingBinVFBuiltinSetRoundingMode; + } + // 14.2. Vector Single-Width Floating-Point Add/Subtract Instructions + defm vfadd : RVVFloatingBinBuiltinSet; + defm vfsub : RVVFloatingBinBuiltinSet; + defm vfrsub : RVVFloatingBinVFBuiltinSet; + + // 14.3. Vector Widening Floating-Point Add/Subtract Instructions + // Widening FP add/subtract, 2*SEW = 2*SEW +/- SEW + defm vfwadd : RVVFloatingWidenOp0BinBuiltinSet; + defm vfwsub : RVVFloatingWidenOp0BinBuiltinSet; + + // 14.4. Vector Single-Width Floating-Point Multiply/Divide Instructions + defm vfmul : RVVFloatingBinBuiltinSet; + defm vfdiv : RVVFloatingBinBuiltinSet; + defm vfrdiv : RVVFloatingBinVFBuiltinSet; +} + +let ManualCodegen = [{ + { + // LLVM intrinsic + // Unmasked: (passthru, op0, op1, round_mode, vl) + // Masked: (passthru, vector_in, vector_in/scalar_in, mask, frm, vl, policy) + + SmallVector Operands; + bool HasMaskedOff = !( + (IsMasked && (PolicyAttrs & RVV_VTA) && (PolicyAttrs & RVV_VMA)) || + (!IsMasked && PolicyAttrs & RVV_VTA)); + bool HasRoundModeOp = IsMasked ? + (HasMaskedOff ? Ops.size() == 6 : Ops.size() == 5) : + (HasMaskedOff ? Ops.size() == 5 : Ops.size() == 4); + + unsigned Offset = IsMasked ? + (HasMaskedOff ? 2 : 1) : (HasMaskedOff ? 1 : 0); + + if (!HasMaskedOff) + Operands.push_back(llvm::PoisonValue::get(ResultType)); + else + Operands.push_back(Ops[IsMasked ? 1 : 0]); + + Operands.push_back(Ops[Offset]); // op0 + Operands.push_back(Ops[Offset + 1]); // op1 + + if (IsMasked) + Operands.push_back(Ops[0]); // mask + + if (HasRoundModeOp) { + Operands.push_back(Ops[Offset + 2]); // frm + Operands.push_back(Ops[Offset + 3]); // vl + } else { + Operands.push_back(ConstantInt::get(Ops[Offset + 2]->getType(), 7)); // frm + Operands.push_back(Ops[Offset + 2]); // vl + } + + if (IsMasked) + Operands.push_back(ConstantInt::get(Ops.back()->getType(), PolicyAttrs)); + + IntrinsicTypes = {ResultType, Ops[Offset]->getType(), Ops[Offset + 1]->getType(), + Ops.back()->getType()}; + llvm::Function *F = CGM.getIntrinsic(ID, IntrinsicTypes); + return Builder.CreateCall(F, Operands, ""); + } +}] in { + let HasFRMRoundModeOp = true in { + // 14.3. Vector Widening Floating-Point Add/Subtract Instructions + // Widening FP add/subtract, 2*SEW = SEW +/- SEW + defm vfwadd : RVVFloatingWidenBinBuiltinSetRoundingMode; + defm vfwsub : RVVFloatingWidenBinBuiltinSetRoundingMode; + + // 14.5. Vector Widening Floating-Point Multiply + let Log2LMUL = [-2, -1, 0, 1, 2] in { + defm vfwmul : RVVOutOp0Op1BuiltinSet<"vfwmul", "xf", + [["vv", "w", "wvvu"], + ["vf", "w", "wveu"]]>; + } + } + // 14.3. Vector Widening Floating-Point Add/Subtract Instructions + // Widening FP add/subtract, 2*SEW = SEW +/- SEW + defm vfwadd : RVVFloatingWidenBinBuiltinSet; + defm vfwsub : RVVFloatingWidenBinBuiltinSet; + + // 14.5. Vector Widening Floating-Point Multiply + let Log2LMUL = [-2, -1, 0, 1, 2] in { + defm vfwmul : RVVOutOp0Op1BuiltinSet<"vfwmul", "xf", + [["vv", "w", "wvv"], + ["vf", "w", "wve"]]>; + } +} +} + + +let UnMaskedPolicyScheme = HasPolicyOperand in { +let ManualCodegen = [{ + { + // LLVM intrinsic + // Unmasked: (passthru, op0, op1, round_mode, vl) + // Masked: (passthru, vector_in, vector_in/scalar_in, mask, frm, vl, policy) + + SmallVector Operands; + bool HasRoundModeOp = IsMasked ? Ops.size() == 6 : Ops.size() == 5; + + unsigned Offset = IsMasked ? 2 : 1; + + Operands.push_back(Ops[IsMasked ? 1 : 0]); // passthrough + + Operands.push_back(Ops[Offset]); // op0 + Operands.push_back(Ops[Offset + 1]); // op1 + + if (IsMasked) + Operands.push_back(Ops[0]); // mask + + if (HasRoundModeOp) { + Operands.push_back(Ops[Offset + 2]); // frm + Operands.push_back(Ops[Offset + 3]); // vl + } else { + Operands.push_back(ConstantInt::get(Ops[Offset + 2]->getType(), 7)); // frm + Operands.push_back(Ops[Offset + 2]); // vl + } + + Operands.push_back(ConstantInt::get(Ops.back()->getType(), PolicyAttrs)); + + IntrinsicTypes = {ResultType, Ops[Offset]->getType(), + Operands.back()->getType()}; + + llvm::Function *F = CGM.getIntrinsic(ID, IntrinsicTypes); + + return Builder.CreateCall(F, Operands, ""); + } +}] in { + let HasFRMRoundModeOp = 1 in { + // 14.6. Vector Single-Width Floating-Point Fused Multiply-Add Instructions + defm vfmacc : RVVFloatingTerBuiltinSetRoundingMode; + defm vfnmacc : RVVFloatingTerBuiltinSetRoundingMode; + defm vfmsac : RVVFloatingTerBuiltinSetRoundingMode; + defm vfnmsac : RVVFloatingTerBuiltinSetRoundingMode; + defm vfmadd : RVVFloatingTerBuiltinSetRoundingMode; + defm vfnmadd : RVVFloatingTerBuiltinSetRoundingMode; + defm vfmsub : RVVFloatingTerBuiltinSetRoundingMode; + defm vfnmsub : RVVFloatingTerBuiltinSetRoundingMode; + } + // 14.6. Vector Single-Width Floating-Point Fused Multiply-Add Instructions + defm vfmacc : RVVFloatingTerBuiltinSet; + defm vfnmacc : RVVFloatingTerBuiltinSet; + defm vfmsac : RVVFloatingTerBuiltinSet; + defm vfnmsac : RVVFloatingTerBuiltinSet; + defm vfmadd : RVVFloatingTerBuiltinSet; + defm vfnmadd : RVVFloatingTerBuiltinSet; + defm vfmsub : RVVFloatingTerBuiltinSet; + defm vfnmsub : RVVFloatingTerBuiltinSet; +} + +let ManualCodegen = [{ + { + // LLVM intrinsic + // Unmasked: (passthru, op0, op1, round_mode, vl) + // Masked: (passthru, vector_in, vector_in/scalar_in, mask, frm, vl, policy) + + SmallVector Operands; + bool HasRoundModeOp = IsMasked ? Ops.size() == 6 : Ops.size() == 5; + + unsigned Offset = IsMasked ? 2 : 1; + + Operands.push_back(Ops[IsMasked ? 1 : 0]); // passthrough + + Operands.push_back(Ops[Offset]); // op0 + Operands.push_back(Ops[Offset + 1]); // op1 + + if (IsMasked) + Operands.push_back(Ops[0]); // mask + + if (HasRoundModeOp) { + Operands.push_back(Ops[Offset + 2]); // frm + Operands.push_back(Ops[Offset + 3]); // vl + } else { + Operands.push_back(ConstantInt::get(Ops[Offset + 2]->getType(), 7)); // frm + Operands.push_back(Ops[Offset + 2]); // vl + } + + Operands.push_back(ConstantInt::get(Ops.back()->getType(), PolicyAttrs)); + + IntrinsicTypes = {ResultType, Ops[Offset]->getType(), Ops[Offset + 1]->getType(), + Operands.back()->getType()}; + + llvm::Function *F = CGM.getIntrinsic(ID, IntrinsicTypes); + + return Builder.CreateCall(F, Operands, ""); + } +}] in { + let HasFRMRoundModeOp = 1 in { + // 14.7. Vector Widening Floating-Point Fused Multiply-Add Instructions + defm vfwmacc : RVVFloatingWidenTerBuiltinSetRoundingMode; + defm vfwnmacc : RVVFloatingWidenTerBuiltinSetRoundingMode; + defm vfwmsac : RVVFloatingWidenTerBuiltinSetRoundingMode; + defm vfwnmsac : RVVFloatingWidenTerBuiltinSetRoundingMode; + } + // 14.7. Vector Widening Floating-Point Fused Multiply-Add Instructions + defm vfwmacc : RVVFloatingWidenTerBuiltinSet; + defm vfwnmacc : RVVFloatingWidenTerBuiltinSet; + defm vfwmsac : RVVFloatingWidenTerBuiltinSet; + defm vfwnmsac : RVVFloatingWidenTerBuiltinSet; +} + +} + +let UnMaskedPolicyScheme = HasPassthruOperand in { +let ManualCodegen = [{ + { + // LLVM intrinsic + // Unmasked: (passthru, op0, round_mode, vl) + // Masked: (passthru, op0, mask, frm, vl, policy) + + SmallVector Operands; + bool HasMaskedOff = !( + (IsMasked && (PolicyAttrs & RVV_VTA) && (PolicyAttrs & RVV_VMA)) || + (!IsMasked && PolicyAttrs & RVV_VTA)); + bool HasRoundModeOp = IsMasked ? + (HasMaskedOff ? Ops.size() == 5 : Ops.size() == 4) : + (HasMaskedOff ? Ops.size() == 4 : Ops.size() == 3); + + unsigned Offset = IsMasked ? + (HasMaskedOff ? 2 : 1) : (HasMaskedOff ? 1 : 0); + + if (!HasMaskedOff) + Operands.push_back(llvm::PoisonValue::get(ResultType)); + else + Operands.push_back(Ops[IsMasked ? 1 : 0]); + + Operands.push_back(Ops[Offset]); // op0 + + if (IsMasked) + Operands.push_back(Ops[0]); // mask + + if (HasRoundModeOp) { + Operands.push_back(Ops[Offset + 1]); // frm + Operands.push_back(Ops[Offset + 2]); // vl + } else { + Operands.push_back(ConstantInt::get(Ops[Offset + 1]->getType(), 7)); // frm + Operands.push_back(Ops[Offset + 1]); // vl + } + + if (IsMasked) + Operands.push_back(ConstantInt::get(Ops.back()->getType(), PolicyAttrs)); + + IntrinsicTypes = {ResultType, Operands.back()->getType()}; + llvm::Function *F = CGM.getIntrinsic(ID, IntrinsicTypes); + return Builder.CreateCall(F, Operands, ""); + } +}] in { + let HasFRMRoundModeOp = 1 in { + // 14.8. Vector Floating-Point Square-Root Instruction + defm vfsqrt : RVVOutBuiltinSet<"vfsqrt", "xfd", [["v", "v", "vvu"]]>; + + // 14.10. Vector Floating-Point Reciprocal Estimate Instruction + defm vfrec7 : RVVOutBuiltinSet<"vfrec7", "xfd", [["v", "v", "vvu"]]>; + } + // 14.8. Vector Floating-Point Square-Root Instruction + defm vfsqrt : RVVOutBuiltinSet<"vfsqrt", "xfd", [["v", "v", "vv"]]>; + + // 14.10. Vector Floating-Point Reciprocal Estimate Instruction + defm vfrec7 : RVVOutBuiltinSet<"vfrec7", "xfd", [["v", "v", "vv"]]>; +} // 14.9. Vector Floating-Point Reciprocal Square-Root Estimate Instruction def vfrsqrt7 : RVVFloatingUnaryVVBuiltin; -// 14.10. Vector Floating-Point Reciprocal Estimate Instruction -def vfrec7 : RVVFloatingUnaryVVBuiltin; - // 14.11. Vector Floating-Point MIN/MAX Instructions defm vfmin : RVVFloatingBinBuiltinSet; defm vfmax : RVVFloatingBinBuiltinSet; @@ -2064,17 +2298,11 @@ let HasMasked = false, // 14.17. Single-Width Floating-Point/Integer Type-Convert Instructions let UnMaskedPolicyScheme = HasPassthruOperand in { -def vfcvt_xu_f_v : RVVConvToUnsignedBuiltin<"vfcvt_xu">; -def vfcvt_x_f_v : RVVConvToSignedBuiltin<"vfcvt_x">; def vfcvt_rtz_xu_f_v : RVVConvToUnsignedBuiltin<"vfcvt_rtz_xu">; def vfcvt_rtz_x_f_v : RVVConvToSignedBuiltin<"vfcvt_rtz_x">; -def vfcvt_f_xu_v : RVVConvBuiltin<"Fv", "FvUv", "sil", "vfcvt_f">; -def vfcvt_f_x_v : RVVConvBuiltin<"Fv", "Fvv", "sil", "vfcvt_f">; // 14.18. Widening Floating-Point/Integer Type-Convert Instructions let Log2LMUL = [-3, -2, -1, 0, 1, 2] in { - def vfwcvt_xu_f_v : RVVConvToWidenUnsignedBuiltin<"vfwcvt_xu">; - def vfwcvt_x_f_v : RVVConvToWidenSignedBuiltin<"vfwcvt_x">; def vfwcvt_rtz_xu_f_v : RVVConvToWidenUnsignedBuiltin<"vfwcvt_rtz_xu">; def vfwcvt_rtz_x_f_v : RVVConvToWidenSignedBuiltin<"vfwcvt_rtz_x">; def vfwcvt_f_xu_v : RVVConvBuiltin<"Fw", "FwUv", "csi", "vfwcvt_f">; @@ -2084,15 +2312,139 @@ let Log2LMUL = [-3, -2, -1, 0, 1, 2] in { // 14.19. Narrowing Floating-Point/Integer Type-Convert Instructions let Log2LMUL = [-3, -2, -1, 0, 1, 2] in { - def vfncvt_xu_f_w : RVVConvToNarrowingUnsignedBuiltin<"vfncvt_xu">; - def vfncvt_x_f_w : RVVConvToNarrowingSignedBuiltin<"vfncvt_x">; def vfncvt_rtz_xu_f_w : RVVConvToNarrowingUnsignedBuiltin<"vfncvt_rtz_xu">; def vfncvt_rtz_x_f_w : RVVConvToNarrowingSignedBuiltin<"vfncvt_rtz_x">; - def vfncvt_f_xu_w : RVVConvBuiltin<"Fv", "FvUw", "csi", "vfncvt_f">; - def vfncvt_f_x_w : RVVConvBuiltin<"Fv", "Fvw", "csi", "vfncvt_f">; - def vfncvt_f_f_w : RVVConvBuiltin<"v", "vw", "xf", "vfncvt_f">; def vfncvt_rod_f_f_w : RVVConvBuiltin<"v", "vw", "xf", "vfncvt_rod_f">; } +let ManualCodegen = [{ + { + // LLVM intrinsic + // Unmasked: (passthru, op0, frm, vl) + // Masked: (passthru, op0, mask, frm, vl, policy) + SmallVector Operands; + bool HasMaskedOff = !( + (IsMasked && (PolicyAttrs & RVV_VTA) && (PolicyAttrs & RVV_VMA)) || + (!IsMasked && PolicyAttrs & RVV_VTA)); + bool HasRoundModeOp = IsMasked ? + (HasMaskedOff ? Ops.size() == 5 : Ops.size() == 4) : + (HasMaskedOff ? Ops.size() == 4 : Ops.size() == 3); + + unsigned Offset = IsMasked ? + (HasMaskedOff ? 2 : 1) : (HasMaskedOff ? 1 : 0); + + if (!HasMaskedOff) + Operands.push_back(llvm::PoisonValue::get(ResultType)); + else + Operands.push_back(Ops[IsMasked ? 1 : 0]); + + Operands.push_back(Ops[Offset]); // op0 + + if (IsMasked) + Operands.push_back(Ops[0]); // mask + + if (HasRoundModeOp) { + Operands.push_back(Ops[Offset + 1]); // frm + Operands.push_back(Ops[Offset + 2]); // vl + } else { + Operands.push_back(ConstantInt::get(Ops[Offset + 1]->getType(), 7)); // frm + Operands.push_back(Ops[Offset + 1]); // vl + } + + if (IsMasked) + Operands.push_back(ConstantInt::get(Ops.back()->getType(), PolicyAttrs)); + + IntrinsicTypes = {ResultType, Ops[Offset]->getType(), + Operands.back()->getType()}; + llvm::Function *F = CGM.getIntrinsic(ID, IntrinsicTypes); + return Builder.CreateCall(F, Operands, ""); + } +}] in { + let HasFRMRoundModeOp = 1 in { + // 14.17. Single-Width Floating-Point/Integer Type-Convert Instructions + let OverloadedName = "vfcvt_x" in + defm : + RVVConvBuiltinSet<"vfcvt_x_f_v", "xfd", [["Iv", "Ivvu"]]>; + let OverloadedName = "vfcvt_xu" in + defm : + RVVConvBuiltinSet<"vfcvt_xu_f_v", "xfd", [["Uv", "Uvvu"]]>; + let OverloadedName = "vfcvt_f" in { + defm : + RVVConvBuiltinSet<"vfcvt_f_x_v", "sil", [["Fv", "Fvvu"]]>; + defm : + RVVConvBuiltinSet<"vfcvt_f_xu_v", "sil", [["Fv", "FvUvu"]]>; + } + + // 14.18. Widening Floating-Point/Integer Type-Convert Instructions + let Log2LMUL = [-3, -2, -1, 0, 1, 2] in { + let OverloadedName = "vfwcvt_x" in + defm : + RVVConvBuiltinSet<"vfwcvt_x_f_v", "xf", [["Iw", "Iwvu"]]>; + let OverloadedName = "vfwcvt_xu" in + defm : + RVVConvBuiltinSet<"vfwcvt_xu_f_v", "xf", [["Uw", "Uwvu"]]>; + } + // 14.19. Narrowing Floating-Point/Integer Type-Convert Instructions + let Log2LMUL = [-3, -2, -1, 0, 1, 2] in { + let OverloadedName = "vfncvt_x" in + defm : + RVVConvBuiltinSet<"vfncvt_x_f_w", "csi", [["Iv", "IvFwu"]]>; + let OverloadedName = "vfncvt_xu" in + defm : + RVVConvBuiltinSet<"vfncvt_xu_f_w", "csi", [["Uv", "UvFwu"]]>; + let OverloadedName = "vfncvt_f" in { + defm : + RVVConvBuiltinSet<"vfncvt_f_x_w", "csi", [["Fv", "Fvwu"]]>; + defm : + RVVConvBuiltinSet<"vfncvt_f_xu_w", "csi", [["Fv", "FvUwu"]]>; + } + let OverloadedName = "vfncvt_f" in + defm : + RVVConvBuiltinSet<"vfncvt_f_f_w", "xf", [["v", "vwu"]]>; + } + } + + // 14.17. Single-Width Floating-Point/Integer Type-Convert Instructions + let OverloadedName = "vfcvt_x" in + defm : + RVVConvBuiltinSet<"vfcvt_x_f_v", "xfd", [["Iv", "Ivv"]]>; + let OverloadedName = "vfcvt_xu" in + defm : + RVVConvBuiltinSet<"vfcvt_xu_f_v", "xfd", [["Uv", "Uvv"]]>; + let OverloadedName = "vfcvt_f" in { + defm : + RVVConvBuiltinSet<"vfcvt_f_x_v", "sil", [["Fv", "Fvv"]]>; + defm : + RVVConvBuiltinSet<"vfcvt_f_xu_v", "sil", [["Fv", "FvUv"]]>; + } + + // 14.18. Widening Floating-Point/Integer Type-Convert Instructions + let Log2LMUL = [-3, -2, -1, 0, 1, 2] in { + let OverloadedName = "vfwcvt_x" in + defm : + RVVConvBuiltinSet<"vfwcvt_x_f_v", "xf", [["Iw", "Iwv"]]>; + let OverloadedName = "vfwcvt_xu" in + defm : + RVVConvBuiltinSet<"vfwcvt_xu_f_v", "xf", [["Uw", "Uwv"]]>; + } + // 14.19. Narrowing Floating-Point/Integer Type-Convert Instructions + let Log2LMUL = [-3, -2, -1, 0, 1, 2] in { + let OverloadedName = "vfncvt_x" in + defm : + RVVConvBuiltinSet<"vfncvt_x_f_w", "csi", [["Iv", "IvFw"]]>; + let OverloadedName = "vfncvt_xu" in + defm : + RVVConvBuiltinSet<"vfncvt_xu_f_w", "csi", [["Uv", "UvFw"]]>; + let OverloadedName = "vfncvt_f" in { + defm : + RVVConvBuiltinSet<"vfncvt_f_x_w", "csi", [["Fv", "Fvw"]]>; + defm : + RVVConvBuiltinSet<"vfncvt_f_xu_w", "csi", [["Fv", "FvUw"]]>; + } + let OverloadedName = "vfncvt_f" in + defm : + RVVConvBuiltinSet<"vfncvt_f_f_w", "xf", [["v", "vw"]]>; + } +} } // 15. Vector Reduction Operations @@ -2121,12 +2473,65 @@ let HasMaskedOffOperand = true in { // 15.3. Vector Single-Width Floating-Point Reduction Instructions defm vfredmax : RVVFloatingReductionBuiltin; defm vfredmin : RVVFloatingReductionBuiltin; -defm vfredusum : RVVFloatingReductionBuiltin; -defm vfredosum : RVVFloatingReductionBuiltin; +let ManualCodegen = [{ + { + // LLVM intrinsic + // Unmasked: (passthru, op0, op1, round_mode, vl) + // Masked: (passthru, vector_in, vector_in/scalar_in, mask, frm, vl, policy) -// 15.4. Vector Widening Floating-Point Reduction Instructions -defm vfwredusum : RVVFloatingWidenReductionBuiltin; -defm vfwredosum : RVVFloatingWidenReductionBuiltin; + SmallVector Operands; + bool HasMaskedOff = !( + (IsMasked && (PolicyAttrs & RVV_VTA) && (PolicyAttrs & RVV_VMA)) || + (!IsMasked && PolicyAttrs & RVV_VTA)); + bool HasRoundModeOp = IsMasked ? + (HasMaskedOff ? Ops.size() == 6 : Ops.size() == 5) : + (HasMaskedOff ? Ops.size() == 5 : Ops.size() == 4); + + unsigned Offset = IsMasked ? + (HasMaskedOff ? 2 : 1) : (HasMaskedOff ? 1 : 0); + + if (!HasMaskedOff) + Operands.push_back(llvm::PoisonValue::get(ResultType)); + else + Operands.push_back(Ops[IsMasked ? 1 : 0]); + + Operands.push_back(Ops[Offset]); // op0 + Operands.push_back(Ops[Offset + 1]); // op1 + + if (IsMasked) + Operands.push_back(Ops[0]); // mask + + if (HasRoundModeOp) { + Operands.push_back(Ops[Offset + 2]); // frm + Operands.push_back(Ops[Offset + 3]); // vl + } else { + Operands.push_back(ConstantInt::get(Ops[Offset + 2]->getType(), 7)); // frm + Operands.push_back(Ops[Offset + 2]); // vl + } + + IntrinsicTypes = {ResultType, Ops[Offset]->getType(), + Ops.back()->getType()}; + llvm::Function *F = CGM.getIntrinsic(ID, IntrinsicTypes); + return Builder.CreateCall(F, Operands, ""); + } +}] in { + let HasFRMRoundModeOp = 1 in { + // 15.3. Vector Single-Width Floating-Point Reduction Instructions + defm vfredusum : RVVFloatingReductionBuiltinRoundingMode; + defm vfredosum : RVVFloatingReductionBuiltinRoundingMode; + + // 15.4. Vector Widening Floating-Point Reduction Instructions + defm vfwredusum : RVVFloatingWidenReductionBuiltinRoundingMode; + defm vfwredosum : RVVFloatingWidenReductionBuiltinRoundingMode; + } + // 15.3. Vector Single-Width Floating-Point Reduction Instructions + defm vfredusum : RVVFloatingReductionBuiltin; + defm vfredosum : RVVFloatingReductionBuiltin; + + // 15.4. Vector Widening Floating-Point Reduction Instructions + defm vfwredusum : RVVFloatingWidenReductionBuiltin; + defm vfwredosum : RVVFloatingWidenReductionBuiltin; +} } // 16. Vector Mask Instructions @@ -2256,6 +2661,36 @@ let HasMasked = false, let HasMasked = false, HasVL = false, IRName = "" in { let Name = "vreinterpret_v", MaskedPolicyScheme = NonePolicy, ManualCodegen = [{ + if (ResultType->isIntOrIntVectorTy(1) || + Ops[0]->getType()->isIntOrIntVectorTy(1)) { + assert(isa(ResultType) && + isa(Ops[0]->getType())); + + LLVMContext &Context = CGM.getLLVMContext(); + ScalableVectorType *Boolean64Ty = + ScalableVectorType::get(llvm::Type::getInt1Ty(Context), 64); + + if (ResultType->isIntOrIntVectorTy(1)) { + // Casting from m1 vector integer -> vector boolean + // Ex: + // --(bitcast)--------> + // --(vector_extract)-> + llvm::Value *BitCast = Builder.CreateBitCast(Ops[0], Boolean64Ty); + return Builder.CreateExtractVector(ResultType, BitCast, + ConstantInt::get(Int64Ty, 0)); + } else { + // Casting from vector boolean -> m1 vector integer + // Ex: + // --(vector_insert)-> + // --(bitcast)-------> + llvm::Value *Boolean64Val = + Builder.CreateInsertVector(Boolean64Ty, + llvm::PoisonValue::get(Boolean64Ty), + Ops[0], + ConstantInt::get(Int64Ty, 0)); + return Builder.CreateBitCast(Boolean64Val, ResultType); + } + } return Builder.CreateBitCast(Ops[0], ResultType); }] in { // Reinterpret between different type under the same SEW and LMUL @@ -2274,6 +2709,53 @@ let HasMasked = false, HasVL = false, IRName = "" in { def vreinterpret_u_ # dst_sew : RVVBuiltin<"Uv" # dst_sew # "Uv", dst_sew # "UvUv", "csil", dst_sew # "Uv">; } + + // Existing users of FixedSEW - the reinterpretation between different SEW + // and same LMUL has the implicit assumption that if FixedSEW is set to the + // given element width, then the type will be identified as invalid, thus + // skipping definition of reinterpret of SEW=8 to SEW=8. However this blocks + // our usage here of defining all possible combinations of a fixed SEW to + // any boolean. So we need to separately define SEW=8 here. + // Reinterpret from LMUL=1 integer type to vector boolean type + def vreintrepret_m1_b8_signed : + RVVBuiltin<"Svm", + "mSv", + "c", "m">; + def vreintrepret_m1_b8_usigned : + RVVBuiltin<"USvm", + "mUSv", + "c", "m">; + + // Reinterpret from vector boolean type to LMUL=1 integer type + def vreintrepret_b8_m1_signed : + RVVBuiltin<"mSv", + "Svm", + "c", "Sv">; + def vreintrepret_b8_m1_usigned : + RVVBuiltin<"mUSv", + "USvm", + "c", "USv">; + + foreach dst_sew = ["16", "32", "64"] in { + // Reinterpret from LMUL=1 integer type to vector boolean type + def vreinterpret_m1_b # dst_sew # _signed: + RVVBuiltin<"(FixedSEW:" # dst_sew # ")Svm", + "m(FixedSEW:" # dst_sew # ")Sv", + "c", "m">; + def vreinterpret_m1_b # dst_sew # _unsigned: + RVVBuiltin<"(FixedSEW:" # dst_sew # ")USvm", + "m(FixedSEW:" # dst_sew # ")USv", + "c", "m">; + // Reinterpret from vector boolean type to LMUL=1 integer type + def vreinterpret_b # dst_sew # _m1_signed: + RVVBuiltin<"m(FixedSEW:" # dst_sew # ")Sv", + "(FixedSEW:" # dst_sew # ")Svm", + "c", "(FixedSEW:" # dst_sew # ")Sv">; + def vreinterpret_b # dst_sew # _m1_unsigned: + RVVBuiltin<"m(FixedSEW:" # dst_sew # ")USv", + "(FixedSEW:" # dst_sew # ")USvm", + "c", "(FixedSEW:" # dst_sew # ")USv">; + } } let Name = "vundefined", SupportOverloading = false, @@ -2290,10 +2772,8 @@ let HasMasked = false, HasVL = false, IRName = "" in { let Name = "vlmul_trunc_v", OverloadedName = "vlmul_trunc", MaskedPolicyScheme = NonePolicy, ManualCodegen = [{ { - ID = Intrinsic::vector_extract; - IntrinsicTypes = {ResultType, Ops[0]->getType()}; - Ops.push_back(ConstantInt::get(Int64Ty, 0)); - return Builder.CreateCall(CGM.getIntrinsic(ID, IntrinsicTypes), Ops, ""); + return Builder.CreateExtractVector(ResultType, Ops[0], + ConstantInt::get(Int64Ty, 0)); } }] in { foreach dst_lmul = ["(SFixedLog2LMUL:-3)", "(SFixedLog2LMUL:-2)", "(SFixedLog2LMUL:-1)", "(SFixedLog2LMUL:0)", "(SFixedLog2LMUL:1)", "(SFixedLog2LMUL:2)"] in { @@ -2309,12 +2789,9 @@ let HasMasked = false, HasVL = false, IRName = "" in { let Name = "vlmul_ext_v", OverloadedName = "vlmul_ext", MaskedPolicyScheme = NonePolicy, ManualCodegen = [{ - ID = Intrinsic::vector_insert; - IntrinsicTypes = {ResultType, Ops[0]->getType()}; - Ops.push_back(llvm::PoisonValue::get(ResultType)); - std::swap(Ops[0], Ops[1]); - Ops.push_back(ConstantInt::get(Int64Ty, 0)); - return Builder.CreateCall(CGM.getIntrinsic(ID, IntrinsicTypes), Ops, ""); + return Builder.CreateInsertVector(ResultType, + llvm::PoisonValue::get(ResultType), + Ops[0], ConstantInt::get(Int64Ty, 0)); }] in { foreach dst_lmul = ["(LFixedLog2LMUL:-2)", "(LFixedLog2LMUL:-1)", "(LFixedLog2LMUL:-0)", "(LFixedLog2LMUL:1)", "(LFixedLog2LMUL:2)", "(LFixedLog2LMUL:3)"] in { @@ -2328,7 +2805,11 @@ let HasMasked = false, HasVL = false, IRName = "" in { let Name = "vget_v", MaskedPolicyScheme = NonePolicy, ManualCodegen = [{ { - ID = Intrinsic::vector_extract; + if (isa(Ops[0]->getType())) // For tuple type + // Extract value from index (operand 1) of vtuple (operand 0) + return Builder.CreateExtractValue( + Ops[0], + {(unsigned)cast(Ops[1])->getZExtValue()}); auto *VecTy = cast(ResultType); auto *OpVecTy = cast(Ops[0]->getType()); // Mask to only valid indices. @@ -2339,21 +2820,28 @@ let HasMasked = false, HasVL = false, IRName = "" in { Ops[1] = Builder.CreateMul(Ops[1], ConstantInt::get(Ops[1]->getType(), VecTy->getMinNumElements())); - IntrinsicTypes = {ResultType, Ops[0]->getType()}; - return Builder.CreateCall(CGM.getIntrinsic(ID, IntrinsicTypes), Ops, ""); + return Builder.CreateExtractVector(ResultType, Ops[0], Ops[1]); } }] in { foreach dst_lmul = ["(SFixedLog2LMUL:0)", "(SFixedLog2LMUL:1)", "(SFixedLog2LMUL:2)"] in { def : RVVBuiltin<"v" # dst_lmul # "v", dst_lmul # "vvKz", "csilxfd", dst_lmul # "v">; def : RVVBuiltin<"Uv" # dst_lmul # "Uv", dst_lmul # "UvUvKz", "csil", dst_lmul # "Uv">; } + foreach nf = NFList in { + defvar T = "(Tuple:" # nf # ")"; + def : RVVBuiltin; + def : RVVBuiltin; + } } - let Name = "vset_v", Log2LMUL = [0, 1, 2], MaskedPolicyScheme = NonePolicy, + let Name = "vset_v", MaskedPolicyScheme = NonePolicy, ManualCodegen = [{ { - ID = Intrinsic::vector_insert; - IntrinsicTypes = {ResultType, Ops[2]->getType()}; + if (isa(ResultType)) // For tuple type + // Insert value (operand 2) into index (operand 1) of vtuple (operand 0) + return Builder.CreateInsertValue( + Ops[0], Ops[2], + {(unsigned)cast(Ops[1])->getZExtValue()}); auto *ResVecTy = cast(ResultType); auto *VecTy = cast(Ops[2]->getType()); // Mask to only valid indices. @@ -2364,13 +2852,19 @@ let HasMasked = false, HasVL = false, IRName = "" in { Ops[1] = Builder.CreateMul(Ops[1], ConstantInt::get(Ops[1]->getType(), VecTy->getMinNumElements())); - std::swap(Ops[1], Ops[2]); - return Builder.CreateCall(CGM.getIntrinsic(ID, IntrinsicTypes), Ops, ""); + return Builder.CreateInsertVector(ResultType, Ops[0], Ops[2], Ops[1]); } }] in { - foreach dst_lmul = ["(LFixedLog2LMUL:1)", "(LFixedLog2LMUL:2)", "(LFixedLog2LMUL:3)"] in { - def : RVVBuiltin<"v" # dst_lmul # "v", dst_lmul # "v" # dst_lmul # "vKzv", "csilxfd">; - def : RVVBuiltin<"Uv" # dst_lmul # "Uv", dst_lmul # "Uv" # dst_lmul #"UvKzUv", "csil">; + let Log2LMUL = [0, 1, 2] in { + foreach dst_lmul = ["(LFixedLog2LMUL:1)", "(LFixedLog2LMUL:2)", "(LFixedLog2LMUL:3)"] in { + def : RVVBuiltin<"v" # dst_lmul # "v", dst_lmul # "v" # dst_lmul # "vKzv", "csilxfd">; + def : RVVBuiltin<"Uv" # dst_lmul # "Uv", dst_lmul # "Uv" # dst_lmul #"UvKzUv", "csil">; + } + } + foreach nf = NFList in { + defvar T = "(Tuple:" # nf # ")"; + def : RVVBuiltin<"v" # T # "v", T # "v" # T # "vKzv", "csilxfd">; + def : RVVBuiltin<"Uv" # T # "Uv", T # "Uv" # T # "UvKzUv", "csil">; } } } diff --git a/contrib/llvm-project/clang/include/clang/Basic/riscv_vector_common.td b/contrib/llvm-project/clang/include/clang/Basic/riscv_vector_common.td new file mode 100644 index 00000000000..e276e4c3c40 --- /dev/null +++ b/contrib/llvm-project/clang/include/clang/Basic/riscv_vector_common.td @@ -0,0 +1,246 @@ +//==------ riscv_vector_common.td - RISC-V V-ext builtin class ------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +// +// This file defines RVV builtin base class for RISC-V V-extension. +// +//===----------------------------------------------------------------------===// + +//===----------------------------------------------------------------------===// +// Instruction definitions +//===----------------------------------------------------------------------===// +// Each record of the class RVVBuiltin defines a collection of builtins (i.e. +// "def vadd : RVVBuiltin" will be used to define things like "vadd_vv_i32m1", +// "vadd_vv_i32m2", etc). +// +// The elements of this collection are defined by an instantiation process the +// range of which is specified by the cross product of the LMUL attribute and +// every element in the attribute TypeRange. By default builtins have LMUL = [1, +// 2, 4, 8, 1/2, 1/4, 1/8] so the process is repeated 7 times. In tablegen we +// use the Log2LMUL [0, 1, 2, 3, -1, -2, -3] to represent the LMUL. +// +// LMUL represents the fact that the types of values used by that builtin are +// values generated by instructions that are executed under that LMUL. However, +// this does not mean the builtin is necessarily lowered into an instruction +// that executes under the specified LMUL. An example where this happens are +// loads and stores of masks. A mask like `vbool8_t` can be generated, for +// instance, by comparing two `__rvv_int8m1_t` (this is LMUL=1) or comparing two +// `__rvv_int16m2_t` (this is LMUL=2). The actual load or store, however, will +// be performed under LMUL=1 because mask registers are not grouped. +// +// TypeRange is a non-empty sequence of basic types: +// +// c: int8_t (i8) +// s: int16_t (i16) +// i: int32_t (i32) +// l: int64_t (i64) +// x: float16_t (half) +// f: float32_t (float) +// d: float64_t (double) +// +// This way, given an LMUL, a record with a TypeRange "sil" will cause the +// definition of 3 builtins. Each type "t" in the TypeRange (in this example +// they are int16_t, int32_t, int64_t) is used as a parameter that drives the +// definition of that particular builtin (for the given LMUL). +// +// During the instantiation, types can be transformed or modified using type +// transformers. Given a type "t" the following primitive type transformers can +// be applied to it to yield another type. +// +// e: type of "t" as is (identity) +// v: computes a vector type whose element type is "t" for the current LMUL +// w: computes a vector type identical to what 'v' computes except for the +// element type which is twice as wide as the element type of 'v' +// q: computes a vector type identical to what 'v' computes except for the +// element type which is four times as wide as the element type of 'v' +// o: computes a vector type identical to what 'v' computes except for the +// element type which is eight times as wide as the element type of 'v' +// m: computes a vector type identical to what 'v' computes except for the +// element type which is bool +// 0: void type, ignores "t" +// z: size_t, ignores "t" +// t: ptrdiff_t, ignores "t" +// u: unsigned long, ignores "t" +// l: long, ignores "t" +// +// So for instance if t is "i", i.e. int, then "e" will yield int again. "v" +// will yield an RVV vector type (assume LMUL=1), so __rvv_int32m1_t. +// Accordingly "w" would yield __rvv_int64m2_t. +// +// A type transformer can be prefixed by other non-primitive type transformers. +// +// P: constructs a pointer to the current type +// C: adds const to the type +// K: requires the integer type to be a constant expression +// U: given an integer type or vector type, computes its unsigned variant +// I: given a vector type, compute the vector type with integer type +// elements of the same width +// F: given a vector type, compute the vector type with floating-point type +// elements of the same width +// S: given a vector type, computes its equivalent one for LMUL=1. This is a +// no-op if the vector was already LMUL=1 +// (Log2EEW:Value): Log2EEW value could be 3/4/5/6 (8/16/32/64), given a +// vector type (SEW and LMUL) and EEW (8/16/32/64), computes its +// equivalent integer vector type with EEW and corresponding ELMUL (elmul = +// (eew/sew) * lmul). For example, vector type is __rvv_float16m4 +// (SEW=16, LMUL=4) and Log2EEW is 3 (EEW=8), and then equivalent vector +// type is __rvv_uint8m2_t (elmul=(8/16)*4 = 2). Ignore to define a new +// builtins if its equivalent type has illegal lmul. +// (FixedSEW:Value): Given a vector type (SEW and LMUL), and computes another +// vector type which only changed SEW as given value. Ignore to define a new +// builtin if its equivalent type has illegal lmul or the SEW does not changed. +// (SFixedLog2LMUL:Value): Smaller Fixed Log2LMUL. Given a vector type (SEW +// and LMUL), and computes another vector type which only changed LMUL as +// given value. The new LMUL should be smaller than the old one. Ignore to +// define a new builtin if its equivalent type has illegal lmul. +// (LFixedLog2LMUL:Value): Larger Fixed Log2LMUL. Given a vector type (SEW +// and LMUL), and computes another vector type which only changed LMUL as +// given value. The new LMUL should be larger than the old one. Ignore to +// define a new builtin if its equivalent type has illegal lmul. +// +// Following with the example above, if t is "i", then "Ue" will yield unsigned +// int and "Fv" will yield __rvv_float32m1_t (again assuming LMUL=1), Fw would +// yield __rvv_float64m2_t, etc. +// +// Each builtin is then defined by applying each type in TypeRange against the +// sequence of type transformers described in Suffix and Prototype. +// +// The name of the builtin is defined by the Name attribute (which defaults to +// the name of the class) appended (separated with an underscore) the Suffix +// attribute. For instance with Name="foo", Suffix = "v" and TypeRange = "il", +// the builtin generated will be __builtin_rvv_foo_i32m1 and +// __builtin_rvv_foo_i64m1 (under LMUL=1). If Suffix contains more than one +// type transformer (say "vv") each of the types is separated with an +// underscore as in "__builtin_rvv_foo_i32m1_i32m1". +// +// The C/C++ prototype of the builtin is defined by the Prototype attribute. +// Prototype is a non-empty sequence of type transformers, the first of which +// is the return type of the builtin and the rest are the parameters of the +// builtin, in order. For instance if Prototype is "wvv" and TypeRange is "si" +// a first builtin will have type +// __rvv_int32m2_t (__rvv_int16m1_t, __rvv_int16m1_t) and the second builtin +// will have type __rvv_int64m2_t (__rvv_int32m1_t, __rvv_int32m1_t) (again +// under LMUL=1). +// +// There are a number of attributes that are used to constraint the number and +// shape of the builtins generated. Refer to the comments below for them. + +class PolicyScheme{ + int Value = val; +} +def NonePolicy : PolicyScheme<0>; +def HasPassthruOperand : PolicyScheme<1>; +def HasPolicyOperand : PolicyScheme<2>; + +class RVVBuiltin { + // Base name that will be prepended in __builtin_rvv_ and appended the + // computed Suffix. + string Name = NAME; + + // If not empty, each instantiated builtin will have this appended after an + // underscore (_). It is instantiated like Prototype. + string Suffix = suffix; + + // If empty, default OverloadedName is sub string of `Name` which end of first + // '_'. For example, the default overloaded name is `vadd` for Name `vadd_vv`. + // It's used for describe some special naming cases. + string OverloadedName = ""; + + // If not empty, each OverloadedName will have this appended after an + // underscore (_). It is instantiated like Prototype. + string OverloadedSuffix = overloaded_suffix; + + // The different variants of the builtin, parameterised with a type. + string TypeRange = type_range; + + // We use each type described in TypeRange and LMUL with prototype to + // instantiate a specific element of the set of builtins being defined. + // Prototype attribute defines the C/C++ prototype of the builtin. It is a + // non-empty sequence of type transformers, the first of which is the return + // type of the builtin and the rest are the parameters of the builtin, in + // order. For instance if Prototype is "wvv", TypeRange is "si" and LMUL=1, a + // first builtin will have type + // __rvv_int32m2_t (__rvv_int16m1_t, __rvv_int16m1_t), and the second builtin + // will have type __rvv_int64m2_t (__rvv_int32m1_t, __rvv_int32m1_t). + string Prototype = prototype; + + // This builtin has a masked form. + bit HasMasked = true; + + // If HasMasked, this flag states that this builtin has a maskedoff operand. It + // is always the first operand in builtin and IR intrinsic. + bit HasMaskedOffOperand = true; + + // This builtin has a granted vector length parameter. + bit HasVL = true; + + // The policy scheme for masked intrinsic IR. + // It could be NonePolicy or HasPolicyOperand. + // HasPolicyOperand: Has a policy operand. 0 is tail and mask undisturbed, 1 is + // tail agnostic, 2 is mask undisturbed, and 3 is tail and mask agnostic. The + // policy operand is located at the last position. + PolicyScheme MaskedPolicyScheme = HasPolicyOperand; + + // The policy scheme for unmasked intrinsic IR. + // It could be NonePolicy, HasPassthruOperand or HasPolicyOperand. + // HasPassthruOperand: Has a passthru operand to decide tail policy. If it is + // poison, tail policy is tail agnostic, otherwise policy is tail undisturbed. + // HasPolicyOperand: Has a policy operand. 1 is tail agnostic and 0 is tail + // undisturbed. + PolicyScheme UnMaskedPolicyScheme = NonePolicy; + + // This builtin support tail agnostic and undisturbed policy. + bit HasTailPolicy = true; + // This builtin support mask agnostic and undisturbed policy. + bit HasMaskPolicy = true; + + // This builtin prototype with TA or TAMA policy could not support overloading + // API. Other policy intrinsic functions would support overloading API with + // suffix `_tu`, `tumu`, `tuma`, `tamu` and `tama`. + bit SupportOverloading = true; + + // This builtin is valid for the given Log2LMULs. + list Log2LMUL = [0, 1, 2, 3, -1, -2, -3]; + + // Manual code in clang codegen riscv_vector_builtin_cg.inc + code ManualCodegen = [{}]; + + // When emit the automatic clang codegen, it describes what types we have to use + // to obtain the specific LLVM intrinsic. -1 means the return type, otherwise, + // k >= 0 meaning the k-th operand (counting from zero) of the codegen'd + // parameter of the unmasked version. k can't be the mask operand's position. + list IntrinsicTypes = []; + + // If these names are not empty, this is the ID of the LLVM intrinsic + // we want to lower to. + string IRName = NAME; + + // If HasMasked, this is the ID of the LLVM intrinsic we want to lower to. + string MaskedIRName = NAME #"_mask"; + + // Use clang_builtin_alias to save the number of builtins. + bit HasBuiltinAlias = true; + + // Features required to enable for this builtin. + list RequiredFeatures = []; + + // Number of fields for Load/Store Segment instructions. + int NF = 1; + + // Set to true if the builtin is associated with tuple types. + bit IsTuple = false; + + // Set to true if the builtin has a parameter that models floating-point + // rounding mode control + bit HasFRMRoundModeOp = false; +} + +// This is the code emitted in the header. +class RVVHeader { + code HeaderCode; +} diff --git a/contrib/llvm-project/clang/include/clang/CodeGen/BackendUtil.h b/contrib/llvm-project/clang/include/clang/CodeGen/BackendUtil.h index d97af65a3d0..cdbfe4ca5e6 100644 --- a/contrib/llvm-project/clang/include/clang/CodeGen/BackendUtil.h +++ b/contrib/llvm-project/clang/include/clang/CodeGen/BackendUtil.h @@ -16,8 +16,12 @@ namespace llvm { class BitcodeModule; template class Expected; + template class IntrusiveRefCntPtr; class Module; class MemoryBufferRef; + namespace vfs { + class FileSystem; + } // namespace vfs } namespace clang { @@ -40,6 +44,7 @@ namespace clang { const CodeGenOptions &CGOpts, const TargetOptions &TOpts, const LangOptions &LOpts, StringRef TDesc, llvm::Module *M, BackendAction Action, + llvm::IntrusiveRefCntPtr VFS, std::unique_ptr OS); void EmbedBitcode(llvm::Module *M, const CodeGenOptions &CGOpts, diff --git a/contrib/llvm-project/clang/include/clang/CodeGen/CGFunctionInfo.h b/contrib/llvm-project/clang/include/clang/CodeGen/CGFunctionInfo.h index c042bcd9fc5..39c7a578c8c 100644 --- a/contrib/llvm-project/clang/include/clang/CodeGen/CGFunctionInfo.h +++ b/contrib/llvm-project/clang/include/clang/CodeGen/CGFunctionInfo.h @@ -742,7 +742,7 @@ public: /// Set the maximum vector width in the arguments. void setMaxVectorWidth(unsigned Width) { assert(llvm::isPowerOf2_32(Width) && "Expected power of 2 vector"); - MaxVectorWidth = llvm::countTrailingZeros(Width) + 1; + MaxVectorWidth = llvm::countr_zero(Width) + 1; } void Profile(llvm::FoldingSetNodeID &ID) { diff --git a/contrib/llvm-project/clang/include/clang/CodeGen/CodeGenAction.h b/contrib/llvm-project/clang/include/clang/CodeGen/CodeGenAction.h index b5721344046..7ad2988e589 100644 --- a/contrib/llvm-project/clang/include/clang/CodeGen/CodeGenAction.h +++ b/contrib/llvm-project/clang/include/clang/CodeGen/CodeGenAction.h @@ -53,6 +53,9 @@ private: std::unique_ptr loadModule(llvm::MemoryBufferRef MBRef); + /// Load bitcode modules to link into our module from the options. + bool loadLinkModules(CompilerInstance &CI); + protected: /// Create a new code generation action. If the optional \p _VMContext /// parameter is supplied, the action uses it without taking ownership, @@ -80,7 +83,7 @@ public: CodeGenerator *getCodeGenerator() const; - BackendConsumer *BEConsumer; + BackendConsumer *BEConsumer = nullptr; }; class EmitAssemblyAction : public CodeGenAction { diff --git a/contrib/llvm-project/clang/include/clang/CodeGen/ObjectFilePCHContainerOperations.h b/contrib/llvm-project/clang/include/clang/CodeGen/ObjectFilePCHContainerOperations.h index c13e052149d..7a02d872588 100644 --- a/contrib/llvm-project/clang/include/clang/CodeGen/ObjectFilePCHContainerOperations.h +++ b/contrib/llvm-project/clang/include/clang/CodeGen/ObjectFilePCHContainerOperations.h @@ -32,7 +32,7 @@ class ObjectFilePCHContainerWriter : public PCHContainerWriter { /// A PCHContainerReader implementation that uses LLVM to /// wraps Clang modules inside a COFF, ELF, or Mach-O container. class ObjectFilePCHContainerReader : public PCHContainerReader { - StringRef getFormat() const override { return "obj"; } + ArrayRef getFormats() const override; /// Returns the serialized AST inside the PCH container Buffer. StringRef ExtractPCH(llvm::MemoryBufferRef Buffer) const override; diff --git a/contrib/llvm-project/clang/include/clang/Driver/Action.h b/contrib/llvm-project/clang/include/clang/Driver/Action.h index f8b0621543c..04fa8b01b41 100644 --- a/contrib/llvm-project/clang/include/clang/Driver/Action.h +++ b/contrib/llvm-project/clang/include/clang/Driver/Action.h @@ -75,9 +75,10 @@ public: OffloadPackagerJobClass, LinkerWrapperJobClass, StaticLibJobClass, + BinaryAnalyzeJobClass, JobClassFirst = PreprocessJobClass, - JobClassLast = StaticLibJobClass + JobClassLast = BinaryAnalyzeJobClass }; // The offloading kind determines if this action is binded to a particular @@ -674,6 +675,17 @@ public: } }; +class BinaryAnalyzeJobAction : public JobAction { + void anchor() override; + +public: + BinaryAnalyzeJobAction(Action *Input, types::ID Type); + + static bool classof(const Action *A) { + return A->getKind() == BinaryAnalyzeJobClass; + } +}; + } // namespace driver } // namespace clang diff --git a/contrib/llvm-project/clang/include/clang/Driver/Compilation.h b/contrib/llvm-project/clang/include/clang/Driver/Compilation.h index f58b5a8cc9f..36ae85c4245 100644 --- a/contrib/llvm-project/clang/include/clang/Driver/Compilation.h +++ b/contrib/llvm-project/clang/include/clang/Driver/Compilation.h @@ -112,6 +112,9 @@ class Compilation { /// only be removed if we crash. ArgStringMap FailureResultFiles; + /// -ftime-trace result files. + ArgStringMap TimeTraceFiles; + /// Optional redirection for stdin, stdout, stderr. std::vector> Redirects; @@ -269,6 +272,14 @@ public: return Name; } + const char *getTimeTraceFile(const JobAction *JA) const { + return TimeTraceFiles.lookup(JA); + } + void addTimeTraceFile(const char *Name, const JobAction *JA) { + assert(!TimeTraceFiles.contains(JA)); + TimeTraceFiles[JA] = Name; + } + /// CleanupFile - Delete a given file. /// /// \param IssueErrors - Report failures as errors. diff --git a/contrib/llvm-project/clang/include/clang/Driver/Distro.h b/contrib/llvm-project/clang/include/clang/Driver/Distro.h index 1aaf93ddb7c..8291f6575a7 100644 --- a/contrib/llvm-project/clang/include/clang/Driver/Distro.h +++ b/contrib/llvm-project/clang/include/clang/Driver/Distro.h @@ -9,8 +9,8 @@ #ifndef LLVM_CLANG_DRIVER_DISTRO_H #define LLVM_CLANG_DRIVER_DISTRO_H -#include "llvm/ADT/Triple.h" #include "llvm/Support/VirtualFileSystem.h" +#include "llvm/TargetParser/Triple.h" namespace clang { namespace driver { @@ -77,6 +77,7 @@ public: UbuntuJammy, UbuntuKinetic, UbuntuLunar, + UbuntuMantic, UnknownDistro }; @@ -128,7 +129,7 @@ public: } bool IsUbuntu() const { - return DistroVal >= UbuntuHardy && DistroVal <= UbuntuLunar; + return DistroVal >= UbuntuHardy && DistroVal <= UbuntuMantic; } bool IsAlpineLinux() const { return DistroVal == AlpineLinux; } diff --git a/contrib/llvm-project/clang/include/clang/Driver/Driver.h b/contrib/llvm-project/clang/include/clang/Driver/Driver.h index 4bbb113b6cf..e3e98bad991 100644 --- a/contrib/llvm-project/clang/include/clang/Driver/Driver.h +++ b/contrib/llvm-project/clang/include/clang/Driver/Driver.h @@ -21,6 +21,7 @@ #include "clang/Driver/Types.h" #include "clang/Driver/Util.h" #include "llvm/ADT/ArrayRef.h" +#include "llvm/ADT/STLFunctionalExtras.h" #include "llvm/ADT/StringMap.h" #include "llvm/ADT/StringRef.h" #include "llvm/Option/Arg.h" @@ -193,6 +194,9 @@ public: /// The file to log CC_PRINT_PROC_STAT_FILE output to, if enabled. std::string CCPrintStatReportFilename; + /// The file to log CC_PRINT_INTERNAL_STAT_FILE output to, if enabled. + std::string CCPrintInternalStatReportFilename; + /// The file to log CC_PRINT_OPTIONS output to, if enabled. std::string CCPrintOptionsFilename; @@ -257,11 +261,16 @@ public: /// performance report to CC_PRINT_PROC_STAT_FILE or to stdout. unsigned CCPrintProcessStats : 1; + /// Set CC_PRINT_INTERNAL_STAT mode, which causes the driver to dump internal + /// performance report to CC_PRINT_INTERNAL_STAT_FILE or to stdout. + unsigned CCPrintInternalStats : 1; + /// Pointer to the ExecuteCC1Tool function, if available. /// When the clangDriver lib is used through clang.exe, this provides a /// shortcut for executing the -cc1 command-line directly, in the same /// process. - typedef int (*CC1ToolFunc)(SmallVectorImpl &ArgV); + using CC1ToolFunc = + llvm::function_ref &ArgV)>; CC1ToolFunc CC1Main = nullptr; private: @@ -286,6 +295,12 @@ private: /// Arguments originated from command line. std::unique_ptr CLOptions; + /// If this is non-null, the driver will prepend this argument before + /// reinvoking clang. This is useful for the llvm-driver where clang's + /// realpath will be to the llvm binary and not clang, so it must pass + /// "clang" as it's first argument. + const char *PrependArg; + /// Whether to check that input files exist when constructing compilation /// jobs. unsigned CheckInputsExist : 1; @@ -383,6 +398,9 @@ public: bool getProbePrecompiled() const { return ProbePrecompiled; } void setProbePrecompiled(bool Value) { ProbePrecompiled = Value; } + const char *getPrependArg() const { return PrependArg; } + void setPrependArg(const char *Value) { PrependArg = Value; } + void setTargetAndMode(const ParsedClangName &TM) { ClangNameParts = TM; } const std::string &getTitle() { return DriverTitle; } @@ -616,10 +634,19 @@ public: /// Returns the default name for linked images (e.g., "a.out"). const char *getDefaultImageName() const; - // Creates a temp file with $Prefix-%%%%%%.$Suffix + /// Creates a temp file. + /// 1. If \p MultipleArch is false or \p BoundArch is empty, the temp file is + /// in the temporary directory with name $Prefix-%%%%%%.$Suffix. + /// 2. If \p MultipleArch is true and \p BoundArch is not empty, + /// 2a. If \p NeedUniqueDirectory is false, the temp file is in the + /// temporary directory with name $Prefix-$BoundArch-%%%%%.$Suffix. + /// 2b. If \p NeedUniqueDirectory is true, the temp file is in a unique + /// subdiretory with random name under the temporary directory, and + /// the temp file itself has name $Prefix-$BoundArch.$Suffix. const char *CreateTempFile(Compilation &C, StringRef Prefix, StringRef Suffix, bool MultipleArchs = false, - StringRef BoundArch = {}) const; + StringRef BoundArch = {}, + bool NeedUniqueDirectory = false) const; /// GetNamedOutputPath - Return the name to use for the output of /// the action \p JA. The result is appended to the compilation's @@ -788,6 +815,16 @@ llvm::StringRef getDriverMode(StringRef ProgName, ArrayRef Args); /// Checks whether the value produced by getDriverMode is for CL mode. bool IsClangCL(StringRef DriverMode); +/// Expand response files from a clang driver or cc1 invocation. +/// +/// \param Args The arguments that will be expanded. +/// \param ClangCLMode Whether clang is in CL mode. +/// \param Alloc Allocator for new arguments. +/// \param FS Filesystem to use when expanding files. +llvm::Error expandResponseFiles(SmallVectorImpl &Args, + bool ClangCLMode, llvm::BumpPtrAllocator &Alloc, + llvm::vfs::FileSystem *FS = nullptr); + } // end namespace driver } // end namespace clang diff --git a/contrib/llvm-project/clang/include/clang/Driver/Job.h b/contrib/llvm-project/clang/include/clang/Driver/Job.h index e3fa92d6ad5..df9449463c5 100644 --- a/contrib/llvm-project/clang/include/clang/Driver/Job.h +++ b/contrib/llvm-project/clang/include/clang/Driver/Job.h @@ -116,6 +116,9 @@ class Command { /// The executable to run. const char *Executable; + /// Optional argument to prepend. + const char *PrependArg; + /// The list of program arguments (not including the implicit first /// argument, which will be the executable). llvm::opt::ArgStringList Arguments; @@ -169,7 +172,8 @@ public: Command(const Action &Source, const Tool &Creator, ResponseFileSupport ResponseSupport, const char *Executable, const llvm::opt::ArgStringList &Arguments, ArrayRef Inputs, - ArrayRef Outputs = std::nullopt); + ArrayRef Outputs = std::nullopt, + const char *PrependArg = nullptr); // FIXME: This really shouldn't be copyable, but is currently copied in some // error handling in Driver::generateCompilationDiagnostics. Command(const Command &) = default; @@ -242,7 +246,8 @@ public: ResponseFileSupport ResponseSupport, const char *Executable, const llvm::opt::ArgStringList &Arguments, ArrayRef Inputs, - ArrayRef Outputs = std::nullopt); + ArrayRef Outputs = std::nullopt, + const char *PrependArg = nullptr); void Print(llvm::raw_ostream &OS, const char *Terminator, bool Quote, CrashReportInfo *CrashInfo = nullptr) const override; @@ -253,23 +258,6 @@ public: void setEnvironment(llvm::ArrayRef NewEnvironment) override; }; -/// Like Command, but always pretends that the wrapped command succeeded. -class ForceSuccessCommand : public Command { -public: - ForceSuccessCommand(const Action &Source_, const Tool &Creator_, - ResponseFileSupport ResponseSupport, - const char *Executable_, - const llvm::opt::ArgStringList &Arguments_, - ArrayRef Inputs, - ArrayRef Outputs = std::nullopt); - - void Print(llvm::raw_ostream &OS, const char *Terminator, bool Quote, - CrashReportInfo *CrashInfo = nullptr) const override; - - int Execute(ArrayRef> Redirects, std::string *ErrMsg, - bool *ExecutionFailed) const override; -}; - /// JobList - A sequence of jobs to perform. class JobList { public: diff --git a/contrib/llvm-project/clang/include/clang/Driver/Multilib.h b/contrib/llvm-project/clang/include/clang/Driver/Multilib.h index cf2dbf6ff58..1416559414f 100644 --- a/contrib/llvm-project/clang/include/clang/Driver/Multilib.h +++ b/contrib/llvm-project/clang/include/clang/Driver/Multilib.h @@ -13,7 +13,9 @@ #include "llvm/ADT/ArrayRef.h" #include "llvm/ADT/STLExtras.h" #include "llvm/ADT/StringRef.h" +#include "llvm/ADT/StringSet.h" #include "llvm/Support/Compiler.h" +#include "llvm/Support/SourceMgr.h" #include #include #include @@ -24,7 +26,9 @@ namespace clang { namespace driver { /// This corresponds to a single GCC Multilib, or a segment of one controlled -/// by a command line flag +/// by a command line flag. +/// See also MultilibBuilder for building a multilib by mutating it +/// incrementally. class Multilib { public: using flags_list = std::vector; @@ -34,74 +38,35 @@ private: std::string OSSuffix; std::string IncludeSuffix; flags_list Flags; - int Priority; public: + /// GCCSuffix, OSSuffix & IncludeSuffix will be appended directly to the + /// sysroot string so they must either be empty or begin with a '/' character. + /// This is enforced with an assert in the constructor. Multilib(StringRef GCCSuffix = {}, StringRef OSSuffix = {}, - StringRef IncludeSuffix = {}, int Priority = 0); + StringRef IncludeSuffix = {}, + const flags_list &Flags = flags_list()); /// Get the detected GCC installation path suffix for the multi-arch /// target variant. Always starts with a '/', unless empty - const std::string &gccSuffix() const { - assert(GCCSuffix.empty() || - (StringRef(GCCSuffix).front() == '/' && GCCSuffix.size() > 1)); - return GCCSuffix; - } - - /// Set the GCC installation path suffix. - Multilib &gccSuffix(StringRef S); + const std::string &gccSuffix() const { return GCCSuffix; } /// Get the detected os path suffix for the multi-arch /// target variant. Always starts with a '/', unless empty - const std::string &osSuffix() const { - assert(OSSuffix.empty() || - (StringRef(OSSuffix).front() == '/' && OSSuffix.size() > 1)); - return OSSuffix; - } - - /// Set the os path suffix. - Multilib &osSuffix(StringRef S); + const std::string &osSuffix() const { return OSSuffix; } /// Get the include directory suffix. Always starts with a '/', unless /// empty - const std::string &includeSuffix() const { - assert(IncludeSuffix.empty() || - (StringRef(IncludeSuffix).front() == '/' && IncludeSuffix.size() > 1)); - return IncludeSuffix; - } - - /// Set the include directory suffix - Multilib &includeSuffix(StringRef S); + const std::string &includeSuffix() const { return IncludeSuffix; } /// Get the flags that indicate or contraindicate this multilib's use - /// All elements begin with either '+' or '-' + /// All elements begin with either '-' or '!' const flags_list &flags() const { return Flags; } - flags_list &flags() { return Flags; } - - /// Returns the multilib priority. When more than one multilib matches flags, - /// the one with the highest priority is selected, with 0 being the default. - int priority() const { return Priority; } - - /// Add a flag to the flags list - /// \p Flag must be a flag accepted by the driver with its leading '-' removed, - /// and replaced with either: - /// '-' which contraindicates using this multilib with that flag - /// or: - /// '+' which promotes using this multilib in the presence of that flag - /// otherwise '-print-multi-lib' will not emit them correctly. - Multilib &flag(StringRef F) { - assert(F.front() == '+' || F.front() == '-'); - Flags.push_back(std::string(F)); - return *this; - } LLVM_DUMP_METHOD void dump() const; /// print summary of the Multilib void print(raw_ostream &OS) const; - /// Check whether any of the 'against' flags contradict the 'for' flags. - bool isValid() const; - /// Check whether the default is selected bool isDefault() const { return GCCSuffix.empty() && OSSuffix.empty() && IncludeSuffix.empty(); } @@ -111,63 +76,57 @@ public: raw_ostream &operator<<(raw_ostream &OS, const Multilib &M); +/// See also MultilibSetBuilder for combining multilibs into a set. class MultilibSet { public: using multilib_list = std::vector; - using iterator = multilib_list::iterator; using const_iterator = multilib_list::const_iterator; using IncludeDirsFunc = std::function(const Multilib &M)>; using FilterCallback = llvm::function_ref; + /// Uses regular expressions to simplify flags used for multilib selection. + /// For example, we may wish both -mfloat-abi=soft and -mfloat-abi=softfp to + /// be treated as -mfloat-abi=soft. + struct FlagMatcher { + std::string Match; + std::vector Flags; + }; + private: multilib_list Multilibs; + std::vector FlagMatchers; IncludeDirsFunc IncludeCallback; IncludeDirsFunc FilePathsCallback; public: MultilibSet() = default; + MultilibSet(multilib_list &&Multilibs, + std::vector &&FlagMatchers = {}) + : Multilibs(Multilibs), FlagMatchers(FlagMatchers) {} - /// Add an optional Multilib segment - MultilibSet &Maybe(const Multilib &M); - - /// Add a set of mutually incompatible Multilib segments - MultilibSet &Either(const Multilib &M1, const Multilib &M2); - MultilibSet &Either(const Multilib &M1, const Multilib &M2, - const Multilib &M3); - MultilibSet &Either(const Multilib &M1, const Multilib &M2, - const Multilib &M3, const Multilib &M4); - MultilibSet &Either(const Multilib &M1, const Multilib &M2, - const Multilib &M3, const Multilib &M4, - const Multilib &M5); - MultilibSet &Either(ArrayRef Ms); + const multilib_list &getMultilibs() { return Multilibs; } /// Filter out some subset of the Multilibs using a user defined callback MultilibSet &FilterOut(FilterCallback F); - /// Filter out those Multilibs whose gccSuffix matches the given expression - MultilibSet &FilterOut(const char *Regex); - /// Add a completed Multilib to the set void push_back(const Multilib &M); - /// Union this set of multilibs with another - void combineWith(const MultilibSet &MS); - - /// Remove all of the multilibs from the set - void clear() { Multilibs.clear(); } - - iterator begin() { return Multilibs.begin(); } const_iterator begin() const { return Multilibs.begin(); } - - iterator end() { return Multilibs.end(); } const_iterator end() const { return Multilibs.end(); } - /// Pick the best multilib in the set, \returns false if none are compatible - bool select(const Multilib::flags_list &Flags, Multilib &M) const; + /// Select compatible variants, \returns false if none are compatible + bool select(const Multilib::flags_list &Flags, + llvm::SmallVector &) const; unsigned size() const { return Multilibs.size(); } + /// Get the given flags plus flags found by matching them against the + /// FlagMatchers and choosing the Flags of each accordingly. The select method + /// calls this method so in most cases it's not necessary to call it directly. + llvm::StringSet<> expandFlags(const Multilib::flags_list &) const; + LLVM_DUMP_METHOD void dump() const; void print(raw_ostream &OS) const; @@ -185,12 +144,9 @@ public: const IncludeDirsFunc &filePathsCallback() const { return FilePathsCallback; } -private: - /// Apply the filter to Multilibs and return the subset that remains - static multilib_list filterCopy(FilterCallback F, const multilib_list &Ms); - - /// Apply the filter to the multilib_list, removing those that don't match - static void filterInPlace(FilterCallback F, multilib_list &Ms); + static llvm::ErrorOr + parseYaml(llvm::MemoryBufferRef, llvm::SourceMgr::DiagHandlerTy = nullptr, + void *DiagHandlerCtxt = nullptr); }; raw_ostream &operator<<(raw_ostream &OS, const MultilibSet &MS); diff --git a/contrib/llvm-project/clang/include/clang/Driver/MultilibBuilder.h b/contrib/llvm-project/clang/include/clang/Driver/MultilibBuilder.h new file mode 100644 index 00000000000..61596c5c573 --- /dev/null +++ b/contrib/llvm-project/clang/include/clang/Driver/MultilibBuilder.h @@ -0,0 +1,134 @@ +//===- MultilibBuilder.h +//-----------------------------------------------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CLANG_DRIVER_MULTILIBBUILDER_H +#define LLVM_CLANG_DRIVER_MULTILIBBUILDER_H + +#include "clang/Driver/Multilib.h" + +namespace clang { +namespace driver { + +/// This corresponds to a single GCC multilib, or a segment of one controlled +/// by a command line flag. This class can be used to create a Multilib, and +/// contains helper functions to mutate it before creating a Multilib instance +/// with makeMultilib(). +class MultilibBuilder { +public: + using flags_list = std::vector; + +private: + std::string GCCSuffix; + std::string OSSuffix; + std::string IncludeSuffix; + flags_list Flags; + +public: + MultilibBuilder(StringRef GCCSuffix, StringRef OSSuffix, + StringRef IncludeSuffix); + + /// Initializes GCCSuffix, OSSuffix & IncludeSuffix to the same value. + MultilibBuilder(StringRef Suffix = {}); + + /// Get the detected GCC installation path suffix for the multi-arch + /// target variant. Always starts with a '/', unless empty + const std::string &gccSuffix() const { + assert(GCCSuffix.empty() || + (StringRef(GCCSuffix).front() == '/' && GCCSuffix.size() > 1)); + return GCCSuffix; + } + + /// Set the GCC installation path suffix. + MultilibBuilder &gccSuffix(StringRef S); + + /// Get the detected os path suffix for the multi-arch + /// target variant. Always starts with a '/', unless empty + const std::string &osSuffix() const { + assert(OSSuffix.empty() || + (StringRef(OSSuffix).front() == '/' && OSSuffix.size() > 1)); + return OSSuffix; + } + + /// Set the os path suffix. + MultilibBuilder &osSuffix(StringRef S); + + /// Get the include directory suffix. Always starts with a '/', unless + /// empty + const std::string &includeSuffix() const { + assert(IncludeSuffix.empty() || (StringRef(IncludeSuffix).front() == '/' && + IncludeSuffix.size() > 1)); + return IncludeSuffix; + } + + /// Set the include directory suffix + MultilibBuilder &includeSuffix(StringRef S); + + /// Get the flags that indicate or contraindicate this multilib's use + /// All elements begin with either '-' or '!' + const flags_list &flags() const { return Flags; } + flags_list &flags() { return Flags; } + + /// Add a flag to the flags list + /// \p Flag must be a flag accepted by the driver. + /// \p Disallow defines whether the flag is negated and therefore disallowed. + MultilibBuilder &flag(StringRef Flag, bool Disallow = false); + + Multilib makeMultilib() const; + + /// Check whether any of the 'against' flags contradict the 'for' flags. + bool isValid() const; + + /// Check whether the default is selected + bool isDefault() const { + return GCCSuffix.empty() && OSSuffix.empty() && IncludeSuffix.empty(); + } +}; + +/// This class can be used to create a MultilibSet, and contains helper +/// functions to add combinations of multilibs before creating a MultilibSet +/// instance with makeMultilibSet(). +class MultilibSetBuilder { +public: + using multilib_list = std::vector; + + MultilibSetBuilder() = default; + + /// Add an optional Multilib segment + MultilibSetBuilder &Maybe(const MultilibBuilder &M); + + /// Add a set of mutually incompatible Multilib segments + MultilibSetBuilder &Either(const MultilibBuilder &M1, + const MultilibBuilder &M2); + MultilibSetBuilder &Either(const MultilibBuilder &M1, + const MultilibBuilder &M2, + const MultilibBuilder &M3); + MultilibSetBuilder &Either(const MultilibBuilder &M1, + const MultilibBuilder &M2, + const MultilibBuilder &M3, + const MultilibBuilder &M4); + MultilibSetBuilder &Either(const MultilibBuilder &M1, + const MultilibBuilder &M2, + const MultilibBuilder &M3, + const MultilibBuilder &M4, + const MultilibBuilder &M5); + MultilibSetBuilder &Either(ArrayRef Ms); + + /// Filter out those Multilibs whose gccSuffix matches the given expression + MultilibSetBuilder &FilterOut(const char *Regex); + + MultilibSet makeMultilibSet() const; + +private: + multilib_list Multilibs; +}; + +} // namespace driver +} // namespace clang + +#endif // LLVM_CLANG_DRIVER_MULTILIBBUILDER_H diff --git a/contrib/llvm-project/clang/include/clang/Driver/OffloadBundler.h b/contrib/llvm-project/clang/include/clang/Driver/OffloadBundler.h index d7f927c2238..28473c53662 100644 --- a/contrib/llvm-project/clang/include/clang/Driver/OffloadBundler.h +++ b/contrib/llvm-project/clang/include/clang/Driver/OffloadBundler.h @@ -17,8 +17,8 @@ #ifndef LLVM_CLANG_DRIVER_OFFLOADBUNDLER_H #define LLVM_CLANG_DRIVER_OFFLOADBUNDLER_H -#include "llvm/ADT/Triple.h" #include "llvm/Support/Error.h" +#include "llvm/TargetParser/Triple.h" #include #include diff --git a/contrib/llvm-project/clang/include/clang/Driver/Options.h b/contrib/llvm-project/clang/include/clang/Driver/Options.h index f7ee154b7a7..54c6f5faa37 100644 --- a/contrib/llvm-project/clang/include/clang/Driver/Options.h +++ b/contrib/llvm-project/clang/include/clang/Driver/Options.h @@ -38,6 +38,7 @@ enum ClangFlags { DXCOption = (1 << 17), CLDXCOption = (1 << 18), Ignored = (1 << 19), + TargetSpecific = (1 << 20), }; enum ID { diff --git a/contrib/llvm-project/clang/include/clang/Driver/Options.td b/contrib/llvm-project/clang/include/clang/Driver/Options.td index 652c15afcce..229f6141c75 100644 --- a/contrib/llvm-project/clang/include/clang/Driver/Options.td +++ b/contrib/llvm-project/clang/include/clang/Driver/Options.td @@ -75,6 +75,10 @@ def FlangOnlyOption : OptionFlag; // FC1Option - This option should be accepted by flang -fc1. def FC1Option : OptionFlag; +// This is a target-specific option for compilation. Using it on an unsupported +// target will lead to an err_drv_unsupported_opt_for_target error. +def TargetSpecific : OptionFlag; + // A short name to show in documentation. The name will be interpreted as rST. class DocName { string DocName = name; } @@ -89,6 +93,8 @@ class DocFlatten { bit DocFlatten = 1; } // GCC compatibility. class IgnoredGCCCompat : Flags<[HelpHidden]> {} +class TargetSpecific : Flags<[TargetSpecific]> {} + ///////// // Groups @@ -185,7 +191,7 @@ def m_wasm_Features_Driver_Group : OptionGroup<"">, def m_x86_Features_Group : OptionGroup<"">, Group, Flags<[CoreOption]>, DocName<"X86">; def m_riscv_Features_Group : OptionGroup<"">, - Group, DocName<"RISCV">; + Group, DocName<"RISC-V">; def m_libc_Group : OptionGroup<"">, Group, Flags<[HelpHidden]>; @@ -235,12 +241,20 @@ def clang_ignored_f_Group : OptionGroup<"">, def clang_ignored_m_Group : OptionGroup<"">, Group, Flags<[Ignored]>; +// Unsupported flang groups +def flang_ignored_w_Group : OptionGroup<"">, + Group, Flags<[FlangOnlyOption, Ignored]>; + // Group for clang options in the process of deprecation. // Please include the version that deprecated the flag as comment to allow // easier garbage collection. def clang_ignored_legacy_options_Group : OptionGroup<"">, Group, Flags<[Ignored]>; +def LongDouble_Group : OptionGroup<"">, Group, + DocName<"Long double flags">, + DocBrief<[{Selects the long double implementation}]>; + // Retired with clang-5.0 def : Flag<["-"], "fslp-vectorize-aggressive">, Group; def : Flag<["-"], "fno-slp-vectorize-aggressive">, Group; @@ -482,6 +496,40 @@ multiclass BoolGOption; } +// Works like BoolOption except without marshalling +multiclass BoolOptionWithoutMarshalling> { + defvar flag1 = FlagDefExpanded.Result, prefix, + NAME, spelling_base>; + + defvar flag2 = FlagDefExpanded.Result, prefix, + NAME, spelling_base>; + + // The flags must have different polarity, different values, and only + // one can be implied. + assert !xor(flag1.Polarity, flag2.Polarity), + "the flags must have different polarity: flag1: " # + flag1.Polarity # ", flag2: " # flag2.Polarity; + assert !ne(flag1.Value, flag2.Value), + "the flags must have different values: flag1: " # + flag1.Value # ", flag2: " # flag2.Value; + assert !not(!and(flag1.CanBeImplied, flag2.CanBeImplied)), + "only one of the flags can be implied: flag1: " # + flag1.CanBeImplied # ", flag2: " # flag2.CanBeImplied; + + defvar implied = !if(flag1.CanBeImplied, flag1, flag2); + + def flag1.RecordName : Flag<["-"], flag1.Spelling>, Flags, + HelpText, + ImpliedByAnyOf + {} + def flag2.RecordName : Flag<["-"], flag2.Spelling>, Flags, + HelpText, + ImpliedByAnyOf + {} +} + // FIXME: Diagnose if target does not support protected visibility. class MarshallingInfoVisibility : MarshallingInfoEnum, @@ -679,7 +727,7 @@ def E : Flag<["-"], "E">, Flags<[NoXarchOption,CC1Option, FlangOption, FC1Option HelpText<"Only run the preprocessor">; def F : JoinedOrSeparate<["-"], "F">, Flags<[RenderJoined,CC1Option]>, HelpText<"Add directory to framework include search path">; -def G : JoinedOrSeparate<["-"], "G">, Flags<[NoXarchOption]>, Group, +def G : JoinedOrSeparate<["-"], "G">, Flags<[NoXarchOption,TargetSpecific]>, Group, MetaVarName<"">, HelpText<"Put objects of at most bytes " "into small data section (MIPS / Hexagon)">; def G_EQ : Joined<["-"], "G=">, Flags<[NoXarchOption]>, Group, Alias; @@ -929,8 +977,10 @@ def cxx_isystem : JoinedOrSeparate<["-"], "cxx-isystem">, Group, MetaVarName<"">; def c : Flag<["-"], "c">, Flags<[NoXarchOption, FlangOption]>, Group, HelpText<"Only run preprocess, compile, and assemble steps">; -def fconvergent_functions : Flag<["-"], "fconvergent-functions">, Group, Flags<[CC1Option]>, - HelpText<"Assume functions may be convergent">; +defm convergent_functions : BoolFOption<"convergent-functions", + LangOpts<"ConvergentFunctions">, DefaultFalse, + NegFlag, + PosFlag>; def gpu_use_aux_triple_only : Flag<["--"], "gpu-use-aux-triple-only">, InternalDriverOpt, HelpText<"Prepare '-aux-triple' only without populating " @@ -987,6 +1037,17 @@ defm cuda_short_ptr : BoolFOption<"cuda-short-ptr", TargetOpts<"NVPTXUseShortPointers">, DefaultFalse, PosFlag, NegFlag>; +def mprintf_kind_EQ : Joined<["-"], "mprintf-kind=">, Group, + HelpText<"Specify the printf lowering scheme (AMDGPU only), allowed values are " + "\"hostcall\"(printing happens during kernel execution, this scheme " + "relies on hostcalls which require system to support pcie atomics) " + "and \"buffered\"(printing happens after all kernel threads exit, " + "this uses a printf buffer and does not rely on pcie atomic support)">, + Flags<[CC1Option]>, + Values<"hostcall,buffered">, + NormalizedValuesScope<"TargetOptions::AMDGPUPrintfKind">, + NormalizedValues<["Hostcall", "Buffered"]>, + MarshallingInfoEnum, "Hostcall">; def fgpu_default_stream_EQ : Joined<["-"], "fgpu-default-stream=">, HelpText<"Specify default stream. The default value is 'legacy'. (HIP only)">, Flags<[CC1Option]>, @@ -1063,6 +1124,10 @@ def gpu_bundle_output : Flag<["--"], "gpu-bundle-output">, Group, HelpText<"Bundle output files of HIP device compilation">; def no_gpu_bundle_output : Flag<["--"], "no-gpu-bundle-output">, Group, HelpText<"Do not bundle output files of HIP device compilation">; +def fhip_emit_relocatable : Flag<["-"], "fhip-emit-relocatable">, Group, + HelpText<"Compile HIP source to relocatable">; +def fno_hip_emit_relocatable : Flag<["-"], "fno-hip-emit-relocatable">, Group, + HelpText<"Do not override toolchain to compile HIP source to relocatable">; def cuid_EQ : Joined<["-"], "cuid=">, Flags<[CC1Option]>, HelpText<"An ID for compilation unit, which should be the same for the same " "compilation unit but different for different compilation units. " @@ -1102,6 +1167,10 @@ def module_dependency_dir : Separate<["-"], "module-dependency-dir">, def dsym_dir : JoinedOrSeparate<["-"], "dsym-dir">, Flags<[NoXarchOption, RenderAsInput]>, HelpText<"Directory to output dSYM's (if any) to">, MetaVarName<"">; +// GCC style -dumpdir. We intentionally don't implement the less useful -dumpbase{,-ext}. +def dumpdir : Separate<["-"], "dumpdir">, Flags<[CC1Option]>, + MetaVarName<"">, + HelpText<"Use as a prefix to form auxiliary and dump file names">; def dumpmachine : Flag<["-"], "dumpmachine">; def dumpspecs : Flag<["-"], "dumpspecs">, Flags<[Unsupported]>; def dumpversion : Flag<["-"], "dumpversion">; @@ -1129,9 +1198,12 @@ def extract_api : Flag<["-"], "extract-api">, Flags<[CC1Option]>, Group; def product_name_EQ: Joined<["--"], "product-name=">, Flags<[CC1Option]>, MarshallingInfoString>; -def extract_api_ignores_EQ: Joined<["--"], "extract-api-ignores=">, Flags<[CC1Option]>, - HelpText<"File containing a new line separated list of API symbols to ignore when extracting API information.">, - MarshallingInfoString>; +def emit_symbol_graph_EQ: JoinedOrSeparate<["--"], "emit-symbol-graph=">, Flags<[CC1Option]>, + HelpText<"Generate Extract API information as a side effect of compilation.">, + MarshallingInfoString>; +def extract_api_ignores_EQ: CommaJoined<["--"], "extract-api-ignores=">, Flags<[CC1Option]>, + HelpText<"Comma separated list of files containing a new line separated list of API symbols to ignore when extracting API information.">, + MarshallingInfoStringVector>; def e : JoinedOrSeparate<["-"], "e">, Flags<[LinkerInput]>, Group; def fmax_tokens_EQ : Joined<["-"], "fmax-tokens=">, Group, Flags<[CC1Option]>, HelpText<"Max total number of preprocessed tokens for -Wmax-tokens.">, @@ -1177,10 +1249,17 @@ defm xl_pragma_pack : BoolFOption<"xl-pragma-pack", def shared_libsan : Flag<["-"], "shared-libsan">, HelpText<"Dynamically link the sanitizer runtime">; def static_libsan : Flag<["-"], "static-libsan">, - HelpText<"Statically link the sanitizer runtime">; + HelpText<"Statically link the sanitizer runtime (Not supported for ASan, TSan or UBSan on darwin)">; def : Flag<["-"], "shared-libasan">, Alias; def fasm : Flag<["-"], "fasm">, Group; +defm assume_unique_vtables : BoolFOption<"assume-unique-vtables", + CodeGenOpts<"AssumeUniqueVTables">, DefaultTrue, + PosFlag, + NegFlag, + BothFlags<[CoreOption]>>; + def fassume_sane_operator_new : Flag<["-"], "fassume-sane-operator-new">, Group; def fastcp : Flag<["-"], "fastcp">, Group; def fastf : Flag<["-"], "fastf">, Group; @@ -1188,9 +1267,7 @@ def fast : Flag<["-"], "fast">, Group; def fasynchronous_unwind_tables : Flag<["-"], "fasynchronous-unwind-tables">, Group; defm double_square_bracket_attributes : BoolFOption<"double-square-bracket-attributes", - LangOpts<"DoubleSquareBracketAttributes">, Default, - PosFlag, NegFlag, - BothFlags<[NoXarchOption, CC1Option], " '[[]]' attributes in all C and C++ language modes">>; + LangOpts<"DoubleSquareBracketAttributes">, DefaultTrue, PosFlag, NegFlag>; defm autolink : BoolFOption<"autolink", CodeGenOpts<"Autolink">, DefaultTrue, @@ -1203,10 +1280,10 @@ defm autolink : BoolFOption<"autolink", def offload_EQ : CommaJoined<["--"], "offload=">, Flags<[NoXarchOption]>, HelpText<"Specify comma-separated list of offloading target triples (CUDA and HIP only)">; -// C++ Coroutines TS -defm coroutines_ts : BoolFOption<"coroutines-ts", +// C++ Coroutines +defm coroutines : BoolFOption<"coroutines", LangOpts<"Coroutines">, Default, - PosFlag, + PosFlag, NegFlag>; defm coro_aligned_allocation : BoolFOption<"coro-aligned-allocation", @@ -1224,7 +1301,7 @@ defm experimental_library : BoolFOption<"experimental-library", NegFlag>; def fembed_offload_object_EQ : Joined<["-"], "fembed-offload-object=">, - Group, Flags<[NoXarchOption, CC1Option]>, + Group, Flags<[NoXarchOption, CC1Option, FC1Option]>, HelpText<"Embed Offloading device-side binary into host object file as a section.">, MarshallingInfoStringVector>; def fembed_bitcode_EQ : Joined<["-"], "fembed-bitcode=">, @@ -1344,22 +1421,20 @@ def fno_profile_instr_use : Flag<["-"], "fno-profile-instr-use">, HelpText<"Disable using instrumentation data for profile-guided optimization">; def fno_profile_use : Flag<["-"], "fno-profile-use">, Alias; -defm profile_arcs : BoolFOption<"profile-arcs", - CodeGenOpts<"EmitGcovArcs">, DefaultFalse, - PosFlag, NegFlag>; -defm test_coverage : BoolFOption<"test-coverage", - CodeGenOpts<"EmitGcovNotes">, DefaultFalse, - PosFlag, NegFlag>; +def ftest_coverage : Flag<["-"], "ftest-coverage">, Group, + HelpText<"Produce gcov notes files (*.gcno)">; +def fno_test_coverage : Flag<["-"], "fno-test-coverage">, Group; +def fprofile_arcs : Flag<["-"], "fprofile-arcs">, Group, + HelpText<"Instrument code to produce gcov data files (*.gcda)">; +def fno_profile_arcs : Flag<["-"], "fno-profile-arcs">, Group; def fprofile_filter_files_EQ : Joined<["-"], "fprofile-filter-files=">, Group, Flags<[CC1Option, CoreOption]>, HelpText<"Instrument only functions from files where names match any regex separated by a semi-colon">, - MarshallingInfoString>, - ShouldParseIf; + MarshallingInfoString>; def fprofile_exclude_files_EQ : Joined<["-"], "fprofile-exclude-files=">, Group, Flags<[CC1Option, CoreOption]>, HelpText<"Instrument only functions from files where names don't match all the regexes separated by a semi-colon">, - MarshallingInfoString>, - ShouldParseIf; + MarshallingInfoString>; def fprofile_update_EQ : Joined<["-"], "fprofile-update=">, Group, Flags<[CC1Option, CoreOption]>, Values<"atomic,prefer-atomic,single">, MetaVarName<"">, HelpText<"Set update method of profile counters">, @@ -1373,7 +1448,8 @@ def forder_file_instrumentation : Flag<["-"], "forder-file-instrumentation">, HelpText<"Generate instrumented code to collect order file into default.profraw file (overridden by '=' form of option or LLVM_PROFILE_FILE env var)">; def fprofile_list_EQ : Joined<["-"], "fprofile-list=">, Group, Flags<[CC1Option, CoreOption]>, - HelpText<"Filename defining the list of functions/files to instrument">, + HelpText<"Filename defining the list of functions/files to instrument. " + "The file uses the sanitizer special case list format.">, MarshallingInfoStringVector>; def fprofile_function_groups : Joined<["-"], "fprofile-function-groups=">, Group, Flags<[CC1Option]>, MetaVarName<"">, @@ -1429,6 +1505,13 @@ def fcomment_block_commands : CommaJoined<["-"], "fcomment-block-commands=">, Gr def fparse_all_comments : Flag<["-"], "fparse-all-comments">, Group, Flags<[CC1Option]>, MarshallingInfoFlag>; def frecord_command_line : Flag<["-"], "frecord-command-line">, + DocBrief<[{Generate a section named ".GCC.command.line" containing the clang +driver command-line. After linking, the section may contain multiple command +lines, which will be individually terminated by null bytes. Separate arguments +within a command line are combined with spaces; spaces and backslashes within an +argument are escaped with backslashes. This format differs from the format of +the equivalent section produced by GCC with the -frecord-gcc-switches flag. +This option is currently only supported on ELF targets.}]>, Group; def fno_record_command_line : Flag<["-"], "fno-record-command-line">, Group; @@ -1436,7 +1519,10 @@ def : Flag<["-"], "frecord-gcc-switches">, Alias; def : Flag<["-"], "fno-record-gcc-switches">, Alias; def fcommon : Flag<["-"], "fcommon">, Group, Flags<[CoreOption, CC1Option]>, HelpText<"Place uninitialized global variables in a common block">, - MarshallingInfoNegativeFlag>; + MarshallingInfoNegativeFlag>, + DocBrief<[{Place definitions of variables with no storage class and no initializer +(tentative definitions) in a common block, instead of generating individual +zero-initialized definitions (default -fno-common).}]>; def fcompile_resource_EQ : Joined<["-"], "fcompile-resource=">, Group; defm complete_member_pointers : BoolOption<"f", "complete-member-pointers", LangOpts<"CompleteMemberPointers">, DefaultFalse, @@ -1454,13 +1540,18 @@ defm constant_cfstrings : BoolFOption<"constant-cfstrings", NegFlag, PosFlag>; def fconstant_string_class_EQ : Joined<["-"], "fconstant-string-class=">, Group; -def fconstexpr_depth_EQ : Joined<["-"], "fconstexpr-depth=">, Group; -def fconstexpr_steps_EQ : Joined<["-"], "fconstexpr-steps=">, Group; +def fconstexpr_depth_EQ : Joined<["-"], "fconstexpr-depth=">, Group, Flags<[CC1Option]>, + HelpText<"Set the maximum depth of recursive constexpr function calls">, + MarshallingInfoInt, "512">; +def fconstexpr_steps_EQ : Joined<["-"], "fconstexpr-steps=">, Group, Flags<[CC1Option]>, + HelpText<"Set the maximum number of steps in constexpr function evaluation">, + MarshallingInfoInt, "1048576">; def fexperimental_new_constant_interpreter : Flag<["-"], "fexperimental-new-constant-interpreter">, Group, HelpText<"Enable the experimental new constant interpreter">, Flags<[CC1Option]>, MarshallingInfoFlag>; -def fconstexpr_backtrace_limit_EQ : Joined<["-"], "fconstexpr-backtrace-limit=">, - Group; +def fconstexpr_backtrace_limit_EQ : Joined<["-"], "fconstexpr-backtrace-limit=">, Group, Flags<[CC1Option]>, + HelpText<"Set the maximum number of entries to print in a constexpr evaluation backtrace (0 = no limit)">, + MarshallingInfoInt, "DiagnosticOptions::DefaultConstexprBacktraceLimit">; def fcrash_diagnostics_EQ : Joined<["-"], "fcrash-diagnostics=">, Group, Flags<[NoArgumentUnused, CoreOption]>, HelpText<"Set level of crash diagnostic reporting, (option: off, compiler, all)">; def fcrash_diagnostics : Flag<["-"], "fcrash-diagnostics">, Group, Flags<[NoArgumentUnused, CoreOption]>, @@ -1522,6 +1613,11 @@ def fdiagnostics_show_template_tree : Flag<["-"], "fdiagnostics-show-template-tr Group, Flags<[CC1Option]>, HelpText<"Print a template comparison tree for differing templates">, MarshallingInfoFlag>; +defm safe_buffer_usage_suggestions : BoolFOption<"safe-buffer-usage-suggestions", + DiagnosticOpts<"ShowSafeBufferUsageSuggestions">, DefaultFalse, + PosFlag, + NegFlag>; def fdiscard_value_names : Flag<["-"], "fdiscard-value-names">, Group, HelpText<"Discard value names in LLVM IR">, Flags<[NoXarchOption]>; def fno_discard_value_names : Flag<["-"], "fno-discard-value-names">, Group, @@ -1552,7 +1648,7 @@ def femit_all_decls : Flag<["-"], "femit-all-decls">, Group, Flags<[CC1 defm emulated_tls : BoolFOption<"emulated-tls", CodeGenOpts<"EmulatedTLS">, DefaultFalse, PosFlag, - NegFlag, BothFlags<[CC1Option]>>; + NegFlag>; def fencoding_EQ : Joined<["-"], "fencoding=">, Group; def ferror_limit_EQ : Joined<["-"], "ferror-limit=">, Group, Flags<[CoreOption]>; defm exceptions : BoolFOption<"exceptions", @@ -1595,6 +1691,15 @@ def ffloat16_excess_precision_EQ : Joined<["-"], "ffloat16-excess-precision=">, Values<"standard,fast,none">, NormalizedValuesScope<"LangOptions">, NormalizedValues<["FPP_Standard", "FPP_Fast", "FPP_None"]>, MarshallingInfoEnum, "FPP_Standard">; +def fbfloat16_excess_precision_EQ : Joined<["-"], "fbfloat16-excess-precision=">, + Group, Flags<[CC1Option, NoDriverOption]>, + HelpText<"Allows control over excess precision on targets where native " + "support for BFloat16 precision types is not available. By default, excess " + "precision is used to calculate intermediate results following the " + "rules specified in ISO C99.">, + Values<"standard,fast,none">, NormalizedValuesScope<"LangOptions">, + NormalizedValues<["FPP_Standard", "FPP_Fast", "FPP_None"]>, + MarshallingInfoEnum, "FPP_Standard">; def : Flag<["-"], "fexpensive-optimizations">, Group; def : Flag<["-"], "fno-expensive-optimizations">, Group; def fextdirs_EQ : Joined<["-"], "fextdirs=">, Group; @@ -1656,7 +1761,11 @@ defm force_enable_int128 : BoolFOption<"force-enable-int128", defm keep_static_consts : BoolFOption<"keep-static-consts", CodeGenOpts<"KeepStaticConsts">, DefaultFalse, PosFlag, NegFlag, - BothFlags<[NoXarchOption], " static const variables if unused">>; + BothFlags<[NoXarchOption], " static const variables even if unused">>; +defm keep_persistent_storage_variables : BoolFOption<"keep-persistent-storage-variables", + CodeGenOpts<"KeepPersistentStorageVariables">, DefaultFalse, + PosFlag, NegFlag, + BothFlags<[NoXarchOption], " keeping all variables that have a persistent storage duration, including global, static and thread-local variables, to guarantee that they can be directly addressed">>; defm fixed_point : BoolFOption<"fixed-point", LangOpts<"FixedPoint">, DefaultFalse, PosFlag, NegFlag, @@ -1672,6 +1781,10 @@ defm memory_profile : OptInCC1FFlag<"memory-profile", "Enable", "Disable", " hea def fmemory_profile_EQ : Joined<["-"], "fmemory-profile=">, Group, Flags<[CC1Option]>, MetaVarName<"">, HelpText<"Enable heap memory profiling and dump results into ">; +def fmemory_profile_use_EQ : Joined<["-"], "fmemory-profile-use=">, + Group, Flags<[CC1Option, CoreOption]>, MetaVarName<"">, + HelpText<"Use memory profile for profile-guided memory optimization">, + MarshallingInfoString>; // Begin sanitizer flags. These should all be core options exposed in all driver // modes. @@ -1692,9 +1805,6 @@ def : Joined<["-"], "fsanitize-blacklist=">, def fsanitize_system_ignorelist_EQ : Joined<["-"], "fsanitize-system-ignorelist=">, HelpText<"Path to system ignorelist file for sanitizers">, Flags<[CC1Option]>; -def : Joined<["-"], "fsanitize-system-blacklist=">, - HelpText<"Alias for -fsanitize-system-ignorelist=">, - Flags<[CC1Option, HelpHidden]>, Alias; def fno_sanitize_ignorelist : Flag<["-"], "fno-sanitize-ignorelist">, Group, HelpText<"Don't use ignorelist file for sanitizers">; @@ -1725,6 +1835,10 @@ def fexperimental_sanitize_metadata_EQ : CommaJoined<["-"], "fexperimental-sanit def fno_experimental_sanitize_metadata_EQ : CommaJoined<["-"], "fno-experimental-sanitize-metadata=">, Group, Flags<[CoreOption]>, HelpText<"Disable emitting metadata for binary analysis sanitizers">; +def fexperimental_sanitize_metadata_ignorelist_EQ : Joined<["-"], "fexperimental-sanitize-metadata-ignorelist=">, + Group, Flags<[CoreOption]>, + HelpText<"Disable sanitizer metadata for modules and functions that match the provided special case list">, + MarshallingInfoStringVector>; def fsanitize_memory_track_origins_EQ : Joined<["-"], "fsanitize-memory-track-origins=">, Group, HelpText<"Enable origins tracking in MemorySanitizer">, @@ -1743,6 +1857,10 @@ def fsanitize_address_outline_instrumentation : Flag<["-"], "fsanitize-address-o def fno_sanitize_address_outline_instrumentation : Flag<["-"], "fno-sanitize-address-outline-instrumentation">, Group, HelpText<"Use default code inlining logic for the address sanitizer">; +defm sanitize_stable_abi + : OptInCC1FFlag<"sanitize-stable-abi", "Stable ", "Conventional ", + "ABI instrumentation for sanitizer runtime. Default: Conventional">; + def fsanitize_memtag_mode_EQ : Joined<["-"], "fsanitize-memtag-mode=">, Group, HelpText<"Set default MTE mode to 'sync' (default) or 'async'">; @@ -1782,6 +1900,17 @@ defm sanitize_address_poison_custom_array_cookie : BoolOption<"f", "sanitize-add CodeGenOpts<"SanitizeAddressPoisonCustomArrayCookie">, DefaultFalse, PosFlag, NegFlag, BothFlags<[], " poisoning array cookies when using custom operator new[] in AddressSanitizer">>, + DocBrief<[{Enable "poisoning" array cookies when allocating arrays with a +custom operator new\[\] in Address Sanitizer, preventing accesses to the +cookies from user code. An array cookie is a small implementation-defined +header added to certain array allocations to record metadata such as the +length of the array. Accesses to array cookies from user code are technically +allowed by the standard but are more likely to be the result of an +out-of-bounds array access. + +An operator new\[\] is "custom" if it is not one of the allocation functions +provided by the C++ standard library. Array cookies from non-custom allocation +functions are always poisoned.}]>, Group; defm sanitize_address_globals_dead_stripping : BoolOption<"f", "sanitize-address-globals-dead-stripping", CodeGenOpts<"SanitizeAddressGlobalsDeadStripping">, DefaultFalse, @@ -1797,7 +1926,10 @@ defm sanitize_address_use_odr_indicator : BoolOption<"f", "sanitize-address-use- def sanitize_address_destructor_EQ : Joined<["-"], "fsanitize-address-destructor=">, Flags<[CC1Option]>, - HelpText<"Set destructor type used in ASan instrumentation">, + HelpText<"Set the kind of module destructors emitted by " + "AddressSanitizer instrumentation. These destructors are " + "emitted to unregister instrumented global variables when " + "code is unloaded (e.g. via `dlclose()`).">, Group, Values<"none,global">, NormalizedValuesScope<"llvm::AsanDtorKind">, @@ -1869,6 +2001,10 @@ def fsanitize_cfi_icall_generalize_pointers : Flag<["-"], "fsanitize-cfi-icall-g Group, HelpText<"Generalize pointers in CFI indirect call type signature checks">, MarshallingInfoFlag>; +def fsanitize_cfi_icall_normalize_integers : Flag<["-"], "fsanitize-cfi-icall-experimental-normalize-integers">, + Group, + HelpText<"Normalize integers in CFI indirect call type signature checks">, + MarshallingInfoFlag>; defm sanitize_cfi_canonical_jump_tables : BoolOption<"f", "sanitize-cfi-canonical-jump-tables", CodeGenOpts<"SanitizeCfiCanonicalJumpTables">, DefaultFalse, PosFlag, NegFlag, @@ -1929,16 +2065,24 @@ defm approx_func : BoolFOption<"approx-func", LangOpts<"ApproxFunc">, DefaultFal NegFlag>; defm finite_math_only : BoolFOption<"finite-math-only", LangOpts<"FiniteMathOnly">, DefaultFalse, - PosFlag, + PosFlag, NegFlag>; defm signed_zeros : BoolFOption<"signed-zeros", LangOpts<"NoSignedZero">, DefaultFalse, NegFlag, PosFlag>; -def fhonor_nans : Flag<["-"], "fhonor-nans">, Group; +def fhonor_nans : Flag<["-"], "fhonor-nans">, Group, + HelpText<"Specify that floating-point optimizations are not allowed that " + "assume arguments and results are not NANs.">; def fno_honor_nans : Flag<["-"], "fno-honor-nans">, Group; -def fhonor_infinities : Flag<["-"], "fhonor-infinities">, Group; +def fhonor_infinities : Flag<["-"], "fhonor-infinities">, + Group, + HelpText<"Specify that floating-point optimizations are not allowed that " + "assume arguments and results are not +-inf.">; def fno_honor_infinities : Flag<["-"], "fno-honor-infinities">, Group; // This option was originally misspelt "infinites" [sic]. def : Flag<["-"], "fhonor-infinites">, Alias; @@ -1989,19 +2133,25 @@ defm delete_null_pointer_checks : BoolFOption<"delete-null-pointer-checks", CodeGenOpts<"NullPointerIsValid">, DefaultFalse, NegFlag, PosFlag, - BothFlags<[CoreOption]>>; - -def frewrite_map_file_EQ : Joined<["-"], "frewrite-map-file=">, - Group, - Flags<[NoXarchOption, CC1Option]>, - MarshallingInfoStringVector>; + BothFlags<[CoreOption]>>, + DocBrief<[{When enabled, treat null pointer dereference, creation of a reference to null, +or passing a null pointer to a function parameter annotated with the "nonnull" +attribute as undefined behavior. (And, thus the optimizer may assume that any +pointer used in such a way must not have been null and optimize away the +branches accordingly.) On by default.}]>; defm use_line_directives : BoolFOption<"use-line-directives", PreprocessorOutputOpts<"UseLineDirectives">, DefaultFalse, PosFlag, NegFlag>; defm minimize_whitespace : BoolFOption<"minimize-whitespace", PreprocessorOutputOpts<"MinimizeWhitespace">, DefaultFalse, - PosFlag, NegFlag>; + PosFlag, NegFlag>; def ffreestanding : Flag<["-"], "ffreestanding">, Group, Flags<[CC1Option]>, HelpText<"Assert that the compilation takes place in a freestanding environment">, @@ -2049,7 +2199,7 @@ def fexperimental_isel : Flag<["-"], "fexperimental-isel">, Group Alias; def fexperimental_strict_floating_point : Flag<["-"], "fexperimental-strict-floating-point">, Group, Flags<[CC1Option]>, - HelpText<"Enables experimental strict floating point in LLVM.">, + HelpText<"Enables the use of non-default rounding modes and non-default exception handling on targets that are not currently ready.">, MarshallingInfoFlag>; def finput_charset_EQ : Joined<["-"], "finput-charset=">, Flags<[FlangOption, FC1Option]>, Group, HelpText<"Specify the default character set for source files">; @@ -2130,16 +2280,14 @@ defm xray_ignore_loops : BoolFOption<"xray-ignore-loops", NegFlag>; defm xray_function_index : BoolFOption<"xray-function-index", - CodeGenOpts<"XRayOmitFunctionIndex">, DefaultTrue, + CodeGenOpts<"XRayFunctionIndex">, DefaultTrue, + PosFlag, NegFlag, - PosFlag>; + " expense of single-function patching performance">>; def fxray_link_deps : Flag<["-"], "fxray-link-deps">, Group, - Flags<[CC1Option]>, - HelpText<"Tells clang to add the link dependencies for XRay.">; -def fnoxray_link_deps : Flag<["-"], "fnoxray-link-deps">, Group, - Flags<[CC1Option]>; + HelpText<"Link XRay runtime library when -fxray-instrument is specified (default)">; +def fno_xray_link_deps : Flag<["-"], "fno-xray-link-deps">, Group; def fxray_instrumentation_bundle : Joined<["-"], "fxray-instrumentation-bundle=">, @@ -2194,14 +2342,19 @@ def flax_vector_conversions : Flag<["-"], "flax-vector-conversions">, Group, Group, HelpText<"Force linking the clang builtins runtime library">; -def flto_EQ : Joined<["-"], "flto=">, Flags<[CoreOption, CC1Option]>, Group, +def flto_EQ : Joined<["-"], "flto=">, Flags<[CoreOption, CC1Option, FC1Option, FlangOption]>, Group, HelpText<"Set LTO mode">, Values<"thin,full">; def flto_EQ_jobserver : Flag<["-"], "flto=jobserver">, Group, Alias, AliasArgs<["full"]>, HelpText<"Enable LTO in 'full' mode">; def flto_EQ_auto : Flag<["-"], "flto=auto">, Group, Alias, AliasArgs<["full"]>, HelpText<"Enable LTO in 'full' mode">; -def flto : Flag<["-"], "flto">, Flags<[CoreOption, CC1Option]>, Group, +def flto : Flag<["-"], "flto">, Flags<[CoreOption, CC1Option, FC1Option, FlangOption]>, Group, Alias, AliasArgs<["full"]>, HelpText<"Enable LTO in 'full' mode">; +defm unified_lto : BoolFOption<"unified-lto", + CodeGenOpts<"UnifiedLTO">, DefaultFalse, + PosFlag, + NegFlag, + BothFlags<[CC1Option], "">>; def fno_lto : Flag<["-"], "fno-lto">, Flags<[CoreOption, CC1Option]>, Group, HelpText<"Disable LTO mode (default)">; def foffload_lto_EQ : Joined<["-"], "foffload-lto=">, Flags<[CoreOption]>, Group, @@ -2222,8 +2375,20 @@ def fthin_link_bitcode_EQ : Joined<["-"], "fthin-link-bitcode=">, Flags<[CoreOption, CC1Option]>, Group, HelpText<"Write minimized bitcode to for the ThinLTO thin link only">, MarshallingInfoString>; +defm fat_lto_objects : BoolFOption<"fat-lto-objects", + CodeGenOpts<"FatLTO">, DefaultFalse, + PosFlag, + NegFlag, + BothFlags<[CC1Option], " fat LTO object support">>; def fmacro_backtrace_limit_EQ : Joined<["-"], "fmacro-backtrace-limit=">, - Group, Flags<[NoXarchOption, CoreOption]>; + Group, Flags<[NoXarchOption, CC1Option, CoreOption]>, + HelpText<"Set the maximum number of entries to print in a macro expansion backtrace (0 = no limit)">, + MarshallingInfoInt, "DiagnosticOptions::DefaultMacroBacktraceLimit">; +def fcaret_diagnostics_max_lines_EQ : + Joined<["-"], "fcaret-diagnostics-max-lines=">, + Group, Flags<[CC1Option, CoreOption]>, + HelpText<"Set the maximum number of source lines to show in a caret diagnostic (0 = no limit).">, + MarshallingInfoInt, "DiagnosticOptions::DefaultSnippetLineLimit">; defm merge_all_constants : BoolFOption<"merge-all-constants", CodeGenOpts<"MergeAllConstants">, DefaultFalse, PosFlag, NegFlag, @@ -2388,11 +2553,8 @@ def fimplicit_module_maps : Flag <["-"], "fimplicit-module-maps">, Group, HelpText<"Implicitly search the file system for module map files.">, MarshallingInfoFlag>; -def fmodules_ts : Flag <["-"], "fmodules-ts">, Group, - Flags<[CC1Option]>, HelpText<"Enable support for the C++ Modules TS">, - MarshallingInfoFlag>; defm modules : BoolFOption<"modules", - LangOpts<"Modules">, Default, + LangOpts<"Modules">, Default, PosFlag, NegFlag, BothFlags<[NoXarchOption, CoreOption]>>; def fmodule_maps : Flag <["-"], "fmodule-maps">, Flags<[CoreOption]>, Alias; @@ -2431,6 +2593,10 @@ defm modules_search_all : BoolFOption<"modules-search-all", defm implicit_modules : BoolFOption<"implicit-modules", LangOpts<"ImplicitModules">, DefaultTrue, NegFlag, PosFlag, BothFlags<[NoXarchOption,CoreOption]>>; +def fno_modules_check_relocated : Joined<["-"], "fno-modules-check-relocated">, + Group, Flags<[CC1Option]>, + HelpText<"Skip checks for relocated modules when loading PCM files">, + MarshallingInfoNegativeFlag>; def fretain_comments_from_system_headers : Flag<["-"], "fretain-comments-from-system-headers">, Group, Flags<[CC1Option]>, MarshallingInfoFlag>; def fmodule_header : Flag <["-"], "fmodule-header">, Group, @@ -2473,10 +2639,10 @@ def fno_experimental_isel : Flag<["-"], "fno-experimental-isel">, Group; def fveclib : Joined<["-"], "fveclib=">, Group, Flags<[CC1Option]>, HelpText<"Use the given vector functions library">, - Values<"Accelerate,libmvec,MASSV,SVML,SLEEF,Darwin_libsystem_m,none">, + Values<"Accelerate,libmvec,MASSV,SVML,SLEEF,Darwin_libsystem_m,ArmPL,none">, NormalizedValuesScope<"CodeGenOptions">, NormalizedValues<["Accelerate", "LIBMVEC", "MASSV", "SVML", "SLEEF", - "Darwin_libsystem_m", "NoLibrary"]>, + "Darwin_libsystem_m", "ArmPL", "NoLibrary"]>, MarshallingInfoEnum, "NoLibrary">; def fno_lax_vector_conversions : Flag<["-"], "fno-lax-vector-conversions">, Group, Alias, AliasArgs<["none"]>; @@ -2503,6 +2669,10 @@ defm operator_names : BoolFOption<"operator-names", def fdiagnostics_absolute_paths : Flag<["-"], "fdiagnostics-absolute-paths">, Group, Flags<[CC1Option, CoreOption]>, HelpText<"Print absolute paths in diagnostics">, MarshallingInfoFlag>; +defm diagnostics_show_line_numbers : BoolFOption<"diagnostics-show-line-numbers", + DiagnosticOpts<"ShowLineNumbers">, DefaultTrue, + NegFlag, + PosFlag>; def fno_stack_protector : Flag<["-"], "fno-stack-protector">, Group, HelpText<"Disable the use of stack protectors">; def fno_strict_aliasing : Flag<["-"], "fno-strict-aliasing">, Group, @@ -2598,12 +2768,16 @@ defm objc_avoid_heapify_local_blocks : BoolFOption<"objc-avoid-heapify-local-blo NegFlag, BothFlags<[CC1Option, NoDriverOption], " to avoid heapifying local blocks">>; -def fomit_frame_pointer : Flag<["-"], "fomit-frame-pointer">, Group; +def fomit_frame_pointer : Flag<["-"], "fomit-frame-pointer">, Group, + HelpText<"Omit the frame pointer from functions that don't need it. " + "Some stack unwinding cases, such as profilers and sanitizers, may prefer specifying -fno-omit-frame-pointer. " + "On many targets, -O1 and higher omit the frame pointer by default. " + "-m[no-]omit-leaf-frame-pointer takes precedence for leaf functions">; def fopenmp : Flag<["-"], "fopenmp">, Group, Flags<[CC1Option, NoArgumentUnused, FlangOption, FC1Option]>, HelpText<"Parse OpenMP pragmas and generate parallel code.">; def fno_openmp : Flag<["-"], "fno-openmp">, Group, Flags<[NoArgumentUnused]>; -def fopenmp_version_EQ : Joined<["-"], "fopenmp-version=">, Group, Flags<[CC1Option, NoArgumentUnused]>, - HelpText<"Set OpenMP version (e.g. 45 for OpenMP 4.5, 50 for OpenMP 5.0). Default value is 50.">; +def fopenmp_version_EQ : Joined<["-"], "fopenmp-version=">, Group, Flags<[CC1Option, NoArgumentUnused, FlangOption, FC1Option]>, + HelpText<"Set OpenMP version (e.g. 45 for OpenMP 4.5, 50 for OpenMP 5.0). Default value is 50 for Clang and 11 for Flang">; defm openmp_extensions: BoolFOption<"openmp-extensions", LangOpts<"OpenMPExtensions">, DefaultTrue, PosFlag, Group, Flags<[CC1Option, NoArgumentUnused]>, + +//===----------------------------------------------------------------------===// +// Shared cc1 + fc1 OpenMP Target Options +//===----------------------------------------------------------------------===// + +let Flags = [CC1Option, FC1Option, NoArgumentUnused] in { +let Group = f_Group in { + +def fopenmp_target_debug : Flag<["-"], "fopenmp-target-debug">, HelpText<"Enable debugging in the OpenMP offloading device RTL">; -def fno_openmp_target_debug : Flag<["-"], "fno-openmp-target-debug">, Group, Flags<[NoArgumentUnused]>; -def fopenmp_target_debug_EQ : Joined<["-"], "fopenmp-target-debug=">, Group, Flags<[CC1Option, NoArgumentUnused, HelpHidden]>; -def fopenmp_assume_teams_oversubscription : Flag<["-"], "fopenmp-assume-teams-oversubscription">, - Group, Flags<[CC1Option, NoArgumentUnused, HelpHidden]>; -def fopenmp_assume_threads_oversubscription : Flag<["-"], "fopenmp-assume-threads-oversubscription">, - Group, Flags<[CC1Option, NoArgumentUnused, HelpHidden]>; -def fno_openmp_assume_teams_oversubscription : Flag<["-"], "fno-openmp-assume-teams-oversubscription">, - Group, Flags<[CC1Option, NoArgumentUnused, HelpHidden]>; -def fno_openmp_assume_threads_oversubscription : Flag<["-"], "fno-openmp-assume-threads-oversubscription">, - Group, Flags<[CC1Option, NoArgumentUnused, HelpHidden]>; -def fopenmp_assume_no_thread_state : Flag<["-"], "fopenmp-assume-no-thread-state">, Group, - Flags<[CC1Option, NoArgumentUnused, HelpHidden]>, +def fno_openmp_target_debug : Flag<["-"], "fno-openmp-target-debug">; + +} // let Group = f_Group +} // let Flags = [CC1Option, FC1Option, NoArgumentUnused] + +let Flags = [CC1Option, FC1Option, NoArgumentUnused, HelpHidden] in { +let Group = f_Group in { + +def fopenmp_target_debug_EQ : Joined<["-"], "fopenmp-target-debug=">; +def fopenmp_assume_teams_oversubscription : Flag<["-"], "fopenmp-assume-teams-oversubscription">; +def fopenmp_assume_threads_oversubscription : Flag<["-"], "fopenmp-assume-threads-oversubscription">; +def fno_openmp_assume_teams_oversubscription : Flag<["-"], "fno-openmp-assume-teams-oversubscription">; +def fno_openmp_assume_threads_oversubscription : Flag<["-"], "fno-openmp-assume-threads-oversubscription">; +def fopenmp_assume_no_thread_state : Flag<["-"], "fopenmp-assume-no-thread-state">, HelpText<"Assert no thread in a parallel region modifies an ICV">, MarshallingInfoFlag>; -def fopenmp_assume_no_nested_parallelism : Flag<["-"], "fopenmp-assume-no-nested-parallelism">, Group, - Flags<[CC1Option, NoArgumentUnused, HelpHidden]>, +def fopenmp_assume_no_nested_parallelism : Flag<["-"], "fopenmp-assume-no-nested-parallelism">, HelpText<"Assert no nested parallel regions in the GPU">, MarshallingInfoFlag>; + +} // let Group = f_Group +} // let Flags = [CC1Option, FC1Option, NoArgumentUnused, HelpHidden] + def fopenmp_offload_mandatory : Flag<["-"], "fopenmp-offload-mandatory">, Group, Flags<[CC1Option, NoArgumentUnused]>, HelpText<"Do not create a host fallback if offloading to the device fails.">, @@ -2678,11 +2865,11 @@ def offload_new_driver : Flag<["--"], "offload-new-driver">, Flags<[CC1Option]>, MarshallingInfoFlag>, HelpText<"Use the new driver for offloading compilation.">; def no_offload_new_driver : Flag<["--"], "no-offload-new-driver">, Flags<[CC1Option]>, Group, HelpText<"Don't Use the new driver for offloading compilation.">; -def offload_device_only : Flag<["--"], "offload-device-only">, +def offload_device_only : Flag<["--"], "offload-device-only">, Flags<[FlangOption]>, HelpText<"Only compile for the offloading device.">; -def offload_host_only : Flag<["--"], "offload-host-only">, +def offload_host_only : Flag<["--"], "offload-host-only">, Flags<[FlangOption]>, HelpText<"Only compile for the offloading host.">; -def offload_host_device : Flag<["--"], "offload-host-device">, +def offload_host_device : Flag<["--"], "offload-host-device">, Flags<[FlangOption]>, HelpText<"Only compile for the offloading host.">; def cuda_device_only : Flag<["--"], "cuda-device-only">, Alias, HelpText<"Compile CUDA code for device only">; @@ -2809,7 +2996,9 @@ defm show_source_location : BoolFOption<"show-source-location", defm spell_checking : BoolFOption<"spell-checking", LangOpts<"SpellChecking">, DefaultTrue, NegFlag, PosFlag>; -def fspell_checking_limit_EQ : Joined<["-"], "fspell-checking-limit=">, Group; +def fspell_checking_limit_EQ : Joined<["-"], "fspell-checking-limit=">, Group, Flags<[CC1Option]>, + HelpText<"Set the maximum number of times to perform spell checking on unrecognized identifiers (0 = no limit)">, + MarshallingInfoInt, "DiagnosticOptions::DefaultSpellCheckingLimit">; def fsigned_bitfields : Flag<["-"], "fsigned-bitfields">, Group; defm signed_char : BoolFOption<"signed-char", LangOpts<"CharIsSigned">, DefaultTrue, @@ -2824,7 +3013,8 @@ def fstack_protector_all : Flag<["-"], "fstack-protector-all">, Group, defm stack_clash_protection : BoolFOption<"stack-clash-protection", CodeGenOpts<"StackClashProtector">, DefaultFalse, PosFlag, NegFlag, - BothFlags<[], " stack clash protection">>; + BothFlags<[], " stack clash protection">>, + DocBrief<"Instrument stack allocation to prevent stack clash attacks">; def fstack_protector_strong : Flag<["-"], "fstack-protector-strong">, Group, HelpText<"Enable stack protectors for some functions vulnerable to stack smashing. " "Compared to -fstack-protector, this uses a stronger heuristic " @@ -2878,12 +3068,16 @@ def fsyntax_only : Flag<["-"], "fsyntax-only">, Flags<[NoXarchOption,CoreOption,CC1Option,FC1Option,FlangOption]>, Group, HelpText<"Run the preprocessor, parser and semantic analysis stages">; def ftabstop_EQ : Joined<["-"], "ftabstop=">, Group; -def ftemplate_depth_EQ : Joined<["-"], "ftemplate-depth=">, Group; -def ftemplate_depth_ : Joined<["-"], "ftemplate-depth-">, Group; -def ftemplate_backtrace_limit_EQ : Joined<["-"], "ftemplate-backtrace-limit=">, - Group; -def foperator_arrow_depth_EQ : Joined<["-"], "foperator-arrow-depth=">, - Group; +def ftemplate_depth_EQ : Joined<["-"], "ftemplate-depth=">, Group, Flags<[CC1Option]>, + HelpText<"Set the maximum depth of recursive template instantiation">, + MarshallingInfoInt, "1024">; +def : Joined<["-"], "ftemplate-depth-">, Group, Alias; +def ftemplate_backtrace_limit_EQ : Joined<["-"], "ftemplate-backtrace-limit=">, Group, Flags<[CC1Option]>, + HelpText<"Set the maximum number of entries to print in a template instantiation backtrace (0 = no limit)">, + MarshallingInfoInt, "DiagnosticOptions::DefaultTemplateBacktraceLimit">; +def foperator_arrow_depth_EQ : Joined<["-"], "foperator-arrow-depth=">, Group, Flags<[CC1Option]>, + HelpText<"Maximum number of 'operator->'s to call for a member access">, + MarshallingInfoInt, "256">; def fsave_optimization_record : Flag<["-"], "fsave-optimization-record">, Group, HelpText<"Generate a YAML optimization record file">; @@ -2946,8 +3140,7 @@ def ftime_trace : Flag<["-"], "ftime-trace">, Group, Turn on time profiler. Generates JSON file based on output filename. Results can be analyzed with chrome://tracing or `Speedscope App `_ for flamegraph visualization.}]>, - Flags<[CC1Option, CoreOption]>, - MarshallingInfoFlag>; + Flags<[CoreOption]>; def ftime_trace_granularity_EQ : Joined<["-"], "ftime-trace-granularity=">, Group, HelpText<"Minimum time granularity (in microseconds) traced by time profiler">, Flags<[CC1Option, CoreOption]>, @@ -3050,7 +3243,7 @@ def mdefault_visibility_export_mapping_EQ : Joined<["-"], "mdefault-visibility-e NormalizedValuesScope<"LangOptions::DefaultVisiblityExportMapping">, NormalizedValues<["None", "Explicit", "All"]>, HelpText<"Mapping between default visibility and export">, - Group, Flags<[CC1Option]>, + Group, Flags<[CC1Option,TargetSpecific]>, MarshallingInfoEnum,"None">; defm new_infallible : BoolFOption<"new-infallible", LangOpts<"NewInfallible">, DefaultFalse, @@ -3068,7 +3261,10 @@ defm split_lto_unit : BoolFOption<"split-lto-unit", defm force_emit_vtables : BoolFOption<"force-emit-vtables", CodeGenOpts<"ForceEmitVTables">, DefaultFalse, PosFlag, - NegFlag, BothFlags<[CoreOption]>>; + NegFlag, BothFlags<[CoreOption]>>, + DocBrief<[{In order to improve devirtualization, forces emitting of vtables even in +modules where it isn't necessary. It causes more inline virtual functions +to be emitted.}]>; defm virtual_function_elimination : BoolFOption<"virtual-function-elimination", CodeGenOpts<"VirtualFunctionElimination">, DefaultFalse, PosFlag, @@ -3164,11 +3360,13 @@ def fdebug_default_version: Joined<["-"], "fdebug-default-version=">, Group; + MetaVarName<"=">, + HelpText<"For paths in debug info, remap directory to . If multiple options match a path, the last option wins">; def fcoverage_prefix_map_EQ : Joined<["-"], "fcoverage-prefix-map=">, Group, Flags<[CC1Option]>, - HelpText<"remap file source paths in coverage mapping">; + MetaVarName<"=">, + HelpText<"remap file source paths to in coverage mapping. If there are multiple options, prefix replacement is applied in reverse order starting from the last one">; def ffile_prefix_map_EQ : Joined<["-"], "ffile-prefix-map=">, Group, HelpText<"remap file source paths in debug info, predefined preprocessor " @@ -3187,10 +3385,13 @@ def femit_dwarf_unwind_EQ : Joined<["-"], "femit-dwarf-unwind=">, NormalizedValues<["Always", "NoCompactUnwind", "Default"]>, NormalizedValuesScope<"llvm::EmitDwarfUnwindType">, MarshallingInfoEnum, "Default">; +defm emit_compact_unwind_non_canonical : BoolFOption<"emit-compact-unwind-non-canonical", + CodeGenOpts<"EmitCompactUnwindNonCanonical">, DefaultFalse, + PosFlag, NegFlag>; def g_Flag : Flag<["-"], "g">, Group, - HelpText<"Generate source-level debug information">; + Flags<[CoreOption,FlangOption]>, HelpText<"Generate source-level debug information">; def gline_tables_only : Flag<["-"], "gline-tables-only">, Group, - Flags<[CoreOption]>, HelpText<"Emit debug line number tables only">; + Flags<[CoreOption,FlangOption]>, HelpText<"Emit debug line number tables only">; def gline_directives_only : Flag<["-"], "gline-directives-only">, Group, Flags<[CoreOption]>, HelpText<"Emit debug line info directives only">; def gmlt : Flag<["-"], "gmlt">, Alias; @@ -3259,17 +3460,21 @@ def : Flag<["-"], "grecord-gcc-switches">, Alias; def : Flag<["-"], "gno-record-gcc-switches">, Alias; defm strict_dwarf : BoolOption<"g", "strict-dwarf", CodeGenOpts<"DebugStrictDwarf">, DefaultFalse, - PosFlag, NegFlag, BothFlags<[CoreOption]>>, + PosFlag, + NegFlag, BothFlags<[CoreOption]>>, Group; defm column_info : BoolOption<"g", "column-info", CodeGenOpts<"DebugColumnInfo">, DefaultTrue, NegFlag, PosFlag, BothFlags<[CoreOption]>>, Group; -def gsplit_dwarf : Flag<["-"], "gsplit-dwarf">, Group; +def gsplit_dwarf : Flag<["-"], "gsplit-dwarf">, Group, + Flags<[CoreOption]>; def gsplit_dwarf_EQ : Joined<["-"], "gsplit-dwarf=">, Group, - HelpText<"Set DWARF fission mode">, + Flags<[CoreOption]>, HelpText<"Set DWARF fission mode">, Values<"split,single">; -def gno_split_dwarf : Flag<["-"], "gno-split-dwarf">, Group; +def gno_split_dwarf : Flag<["-"], "gno-split-dwarf">, Group, + Flags<[CoreOption]>; def gsimple_template_names : Flag<["-"], "gsimple-template-names">, Group; def gsimple_template_names_EQ : Joined<["-"], "gsimple-template-names=">, @@ -3306,7 +3511,7 @@ def headerpad__max__install__names : Joined<["-"], "headerpad_max_install_names" def help : Flag<["-", "--"], "help">, Flags<[CC1Option,CC1AsOption, FC1Option, FlangOption]>, HelpText<"Display available options">, MarshallingInfoFlag>; -def ibuiltininc : Flag<["-"], "ibuiltininc">, +def ibuiltininc : Flag<["-"], "ibuiltininc">, Group, HelpText<"Enable builtin #include directories even when -nostdinc is used " "before or after -ibuiltininc. " "Using -nobuiltininc after the option disables it">; @@ -3361,62 +3566,73 @@ def iwithsysroot : JoinedOrSeparate<["-"], "iwithsysroot">, Group Flags<[CC1Option]>; def ivfsoverlay : JoinedOrSeparate<["-"], "ivfsoverlay">, Group, Flags<[CC1Option]>, HelpText<"Overlay the virtual filesystem described by file over the real file system">; +def vfsoverlay : JoinedOrSeparate<["-", "--"], "vfsoverlay">, Flags<[CC1Option, CoreOption]>, + HelpText<"Overlay the virtual filesystem described by file over the real file system. " + "Additionally, pass this overlay file to the linker if it supports it">; def imultilib : Separate<["-"], "imultilib">, Group; +def K : Flag<["-"], "K">, Flags<[LinkerInput]>; def keep__private__externs : Flag<["-"], "keep_private_externs">; def l : JoinedOrSeparate<["-"], "l">, Flags<[LinkerInput, RenderJoined]>, Group; def lazy__framework : Separate<["-"], "lazy_framework">, Flags<[LinkerInput]>; def lazy__library : Separate<["-"], "lazy_library">, Flags<[LinkerInput]>; -def mlittle_endian : Flag<["-"], "mlittle-endian">, Flags<[NoXarchOption]>; +def mlittle_endian : Flag<["-"], "mlittle-endian">, Group, Flags<[NoXarchOption,TargetSpecific]>; def EL : Flag<["-"], "EL">, Alias; -def mbig_endian : Flag<["-"], "mbig-endian">, Flags<[NoXarchOption]>; +def mbig_endian : Flag<["-"], "mbig-endian">, Group, Flags<[NoXarchOption,TargetSpecific]>; def EB : Flag<["-"], "EB">, Alias; def m16 : Flag<["-"], "m16">, Group, Flags<[NoXarchOption, CoreOption]>; def m32 : Flag<["-"], "m32">, Group, Flags<[NoXarchOption, CoreOption]>; +def maix32 : Flag<["-"], "maix32">, Group, Flags<[NoXarchOption]>; def mqdsp6_compat : Flag<["-"], "mqdsp6-compat">, Group, Flags<[NoXarchOption,CC1Option]>, HelpText<"Enable hexagon-qdsp6 backward compatibility">, MarshallingInfoFlag>; def m64 : Flag<["-"], "m64">, Group, Flags<[NoXarchOption, CoreOption]>; +def maix64 : Flag<["-"], "maix64">, Group, Flags<[NoXarchOption]>; def mx32 : Flag<["-"], "mx32">, Group, Flags<[NoXarchOption, CoreOption]>; -def mabi_EQ : Joined<["-"], "mabi=">, Group; def miamcu : Flag<["-"], "miamcu">, Group, Flags<[NoXarchOption, CoreOption]>, HelpText<"Use Intel MCU ABI">; def mno_iamcu : Flag<["-"], "mno-iamcu">, Group, Flags<[NoXarchOption, CoreOption]>; def malign_functions_EQ : Joined<["-"], "malign-functions=">, Group; def malign_loops_EQ : Joined<["-"], "malign-loops=">, Group; def malign_jumps_EQ : Joined<["-"], "malign-jumps=">, Group; -def malign_branch_EQ : CommaJoined<["-"], "malign-branch=">, Group, Flags<[NoXarchOption]>, + +let Flags = [TargetSpecific] in { +def mabi_EQ : Joined<["-"], "mabi=">, Group; +def malign_branch_EQ : CommaJoined<["-"], "malign-branch=">, Group, HelpText<"Specify types of branches to align">; -def malign_branch_boundary_EQ : Joined<["-"], "malign-branch-boundary=">, Group, Flags<[NoXarchOption]>, +def malign_branch_boundary_EQ : Joined<["-"], "malign-branch-boundary=">, Group, HelpText<"Specify the boundary's size to align branches">; -def mpad_max_prefix_size_EQ : Joined<["-"], "mpad-max-prefix-size=">, Group, Flags<[NoXarchOption]>, +def mpad_max_prefix_size_EQ : Joined<["-"], "mpad-max-prefix-size=">, Group, HelpText<"Specify maximum number of prefixes to use for padding">; -def mbranches_within_32B_boundaries : Flag<["-"], "mbranches-within-32B-boundaries">, Flags<[NoXarchOption]>, Group, +def mbranches_within_32B_boundaries : Flag<["-"], "mbranches-within-32B-boundaries">, Group, HelpText<"Align selected branches (fused, jcc, jmp) within 32-byte boundary">; def mfancy_math_387 : Flag<["-"], "mfancy-math-387">, Group; def mlong_calls : Flag<["-"], "mlong-calls">, Group, HelpText<"Generate branches with extended addressability, usually via indirect jumps.">; +} // let Flags = [TargetSpecific] def mdouble_EQ : Joined<["-"], "mdouble=">, Group, MetaVarName<", Values<"32,64">, Flags<[CC1Option]>, HelpText<"Force double to be bits">, MarshallingInfoInt, "0">; -def LongDouble_Group : OptionGroup<"">, Group, - DocName<"Long double flags">, - DocBrief<[{Selects the long double implementation}]>; def mlong_double_64 : Flag<["-"], "mlong-double-64">, Group, Flags<[CC1Option]>, HelpText<"Force long double to be 64 bits">; def mlong_double_80 : Flag<["-"], "mlong-double-80">, Group, Flags<[CC1Option]>, HelpText<"Force long double to be 80 bits, padded to 128 bits for storage">; def mlong_double_128 : Flag<["-"], "mlong-double-128">, Group, Flags<[CC1Option]>, HelpText<"Force long double to be 128 bits">; +let Flags = [TargetSpecific] in { def mno_long_calls : Flag<["-"], "mno-long-calls">, Group, HelpText<"Restore the default behaviour of not generating long calls">; +} // let Flags = [TargetSpecific] def mexecute_only : Flag<["-"], "mexecute-only">, Group, HelpText<"Disallow generation of data access to code sections (ARM only)">; def mno_execute_only : Flag<["-"], "mno-execute-only">, Group, HelpText<"Allow generation of data access to code sections (ARM only)">; -def mtp_mode_EQ : Joined<["-"], "mtp=">, Group, Values<"soft,cp15,el0,el1,el2,el3">, - HelpText<"Thread pointer access method (AArch32/AArch64 only)">; +let Flags = [TargetSpecific] in { +def mtp_mode_EQ : Joined<["-"], "mtp=">, Group, Values<"soft,cp15,tpidrurw,tpidruro,tpidrprw,el0,el1,el2,el3,tpidr_el0,tpidr_el1,tpidr_el2,tpidr_el3,tpidrro_el0">, + HelpText<"Thread pointer access method. " + "For AArch32: 'soft' uses a function call, or 'tpidrurw', 'tpidruro' or 'tpidrprw' use the three CP15 registers. 'cp15' is an alias for 'tpidruro'. " + "For AArch64: 'tpidr_el0', 'tpidr_el1', 'tpidr_el2', 'tpidr_el3' or 'tpidrro_el0' use the five system registers. 'elN' is an alias for 'tpidr_elN'.">; def mpure_code : Flag<["-"], "mpure-code">, Alias; // Alias for GCC compatibility def mno_pure_code : Flag<["-"], "mno-pure-code">, Alias; def mtvos_version_min_EQ : Joined<["-"], "mtvos-version-min=">, Group; @@ -3424,9 +3640,11 @@ def mappletvos_version_min_EQ : Joined<["-"], "mappletvos-version-min=">, Alias< def mtvos_simulator_version_min_EQ : Joined<["-"], "mtvos-simulator-version-min=">; def mappletvsimulator_version_min_EQ : Joined<["-"], "mappletvsimulator-version-min=">, Alias; def mwatchos_version_min_EQ : Joined<["-"], "mwatchos-version-min=">, Group; -def mwatchos_simulator_version_min_EQ : Joined<["-"], "mwatchos-simulator-version-min=">; +def mwatchos_simulator_version_min_EQ : Joined<["-"], "mwatchos-simulator-version-min=">, Group; def mwatchsimulator_version_min_EQ : Joined<["-"], "mwatchsimulator-version-min=">, Alias; -def march_EQ : Joined<["-"], "march=">, Group, Flags<[CoreOption]>; +} // let Flags = [TargetSpecific] +def march_EQ : Joined<["-"], "march=">, Group, Flags<[CoreOption,TargetSpecific]>, + HelpText<"For a list of available architectures for the target use '-mcpu=help'">; def masm_EQ : Joined<["-"], "masm=">, Group, Flags<[NoXarchOption]>; def inline_asm_EQ : Joined<["-"], "inline-asm=">, Group, Flags<[CC1Option]>, Values<"att,intel">, @@ -3441,16 +3659,18 @@ def mtls_size_EQ : Joined<["-"], "mtls-size=">, Group, Flags<[NoXarchOp def mimplicit_it_EQ : Joined<["-"], "mimplicit-it=">, Group; def mdefault_build_attributes : Joined<["-"], "mdefault-build-attributes">, Group; def mno_default_build_attributes : Joined<["-"], "mno-default-build-attributes">, Group; +let Flags = [TargetSpecific] in { def mconstant_cfstrings : Flag<["-"], "mconstant-cfstrings">, Group; -def mconsole : Joined<["-"], "mconsole">, Group, Flags<[NoXarchOption]>; -def mwindows : Joined<["-"], "mwindows">, Group, Flags<[NoXarchOption]>; -def mdll : Joined<["-"], "mdll">, Group, Flags<[NoXarchOption]>; -def municode : Joined<["-"], "municode">, Group, Flags<[NoXarchOption]>; -def mthreads : Joined<["-"], "mthreads">, Group, Flags<[NoXarchOption]>; -def mguard_EQ : Joined<["-"], "mguard=">, Group, Flags<[NoXarchOption]>, +def mconsole : Joined<["-"], "mconsole">, Group; +def mwindows : Joined<["-"], "mwindows">, Group; +def mdll : Joined<["-"], "mdll">, Group; +def municode : Joined<["-"], "municode">, Group; +def mthreads : Joined<["-"], "mthreads">, Group; +def mguard_EQ : Joined<["-"], "mguard=">, Group, HelpText<"Enable or disable Control Flow Guard checks and guard tables emission">, Values<"none,cf,cf-nochecks">; -def mcpu_EQ : Joined<["-"], "mcpu=">, Group; +def mcpu_EQ : Joined<["-"], "mcpu=">, Group, + HelpText<"For a list of available CPUs for the target use '-mcpu=help'">; def mmcu_EQ : Joined<["-"], "mmcu=">, Group; def msim : Flag<["-"], "msim">, Group; def mdynamic_no_pic : Joined<["-"], "mdynamic-no-pic">, Group; @@ -3458,29 +3678,35 @@ def mfix_and_continue : Flag<["-"], "mfix-and-continue">, Group, Group; def minline_all_stringops : Flag<["-"], "minline-all-stringops">, Group; def mno_inline_all_stringops : Flag<["-"], "mno-inline-all-stringops">, Group; +} // let Flags = [TargetSpecific] def malign_double : Flag<["-"], "malign-double">, Group, Flags<[CC1Option]>, HelpText<"Align doubles to two words in structs (x86 only)">, MarshallingInfoFlag>; +let Flags = [TargetSpecific] in { def mfloat_abi_EQ : Joined<["-"], "mfloat-abi=">, Group, Values<"soft,softfp,hard">; def mfpmath_EQ : Joined<["-"], "mfpmath=">, Group; def mfpu_EQ : Joined<["-"], "mfpu=">, Group; def mhwdiv_EQ : Joined<["-"], "mhwdiv=">, Group; def mhwmult_EQ : Joined<["-"], "mhwmult=">, Group; +} // let Flags = [TargetSpecific] def mglobal_merge : Flag<["-"], "mglobal-merge">, Group, Flags<[CC1Option]>, HelpText<"Enable merging of globals">; +let Flags = [TargetSpecific] in { def mhard_float : Flag<["-"], "mhard-float">, Group; def mios_version_min_EQ : Joined<["-"], "mios-version-min=">, Group, HelpText<"Set iOS deployment target">; def : Joined<["-"], "miphoneos-version-min=">, Group, Alias; -def mios_simulator_version_min_EQ : Joined<["-"], "mios-simulator-version-min=">; +def mios_simulator_version_min_EQ : Joined<["-"], "mios-simulator-version-min=">, Group; def : Joined<["-"], "miphonesimulator-version-min=">, Alias; def mkernel : Flag<["-"], "mkernel">, Group; -def mlinker_version_EQ : Joined<["-"], "mlinker-version=">, - Flags<[NoXarchOption]>; +def mlinker_version_EQ : Joined<["-"], "mlinker-version=">, Group, Flags<[NoXarchOption]>; +} // let Flags = [TargetSpecific] def mllvm : Separate<["-"], "mllvm">,Flags<[CC1Option,CC1AsOption,CoreOption,FC1Option,FlangOption]>, HelpText<"Additional arguments to forward to LLVM's option processing">, MarshallingInfoStringVector>; +def : Joined<["-"], "mllvm=">, Flags<[CoreOption,FlangOption]>, Alias, + HelpText<"Alias for -mllvm">, MetaVarName<"">; def mmlir : Separate<["-"], "mmlir">, Flags<[CoreOption,FC1Option,FlangOption]>, HelpText<"Additional arguments to forward to MLIR's option processing">; def ffuchsia_api_level_EQ : Joined<["-"], "ffuchsia-api-level=">, @@ -3514,6 +3740,8 @@ def mstack_probe_size : Joined<["-"], "mstack-probe-size=">, Group, Fla MarshallingInfoInt, "4096">; def mstack_arg_probe : Flag<["-"], "mstack-arg-probe">, Group, HelpText<"Enable stack probes">; +def mzos_sys_include_EQ : Joined<["-"], "mzos-sys-include=">, MetaVarName<"">, + HelpText<"Path to system headers on z/OS">; def mno_stack_arg_probe : Flag<["-"], "mno-stack-arg-probe">, Group, Flags<[CC1Option]>, HelpText<"Disable stack probes which are enabled by default">, MarshallingInfoFlag>; @@ -3528,6 +3756,12 @@ def meabi : Separate<["-"], "meabi">, Group, Flags<[CC1Option]>, NormalizedValues<["Default", "EABI4", "EABI5", "GNU"]>; def mtargetos_EQ : Joined<["-"], "mtargetos=">, Group, HelpText<"Set the deployment target to be the specified OS and OS version">; +def mzos_hlq_le_EQ : Joined<["-"], "mzos-hlq-le=">, MetaVarName<"">, + HelpText<"High level qualifier for z/OS Language Environment datasets">; +def mzos_hlq_clang_EQ : Joined<["-"], "mzos-hlq-clang=">, MetaVarName<"">, + HelpText<"High level qualifier for z/OS C++RT side deck datasets">; +def mzos_hlq_csslib_EQ : Joined<["-"], "mzos-hlq-csslib=">, MetaVarName<"">, + HelpText<"High level qualifier for z/OS CSSLIB dataset">; def mno_constant_cfstrings : Flag<["-"], "mno-constant-cfstrings">, Group; def mno_global_merge : Flag<["-"], "mno-global-merge">, Group, Flags<[CC1Option]>, @@ -3539,9 +3773,11 @@ def mno_tls_direct_seg_refs : Flag<["-"], "mno-tls-direct-seg-refs">, Group, MarshallingInfoFlag>; def mno_relax_all : Flag<["-"], "mno-relax-all">, Group; +let Flags = [TargetSpecific] in { def mno_rtd: Flag<["-"], "mno-rtd">, Group; def mno_soft_float : Flag<["-"], "mno-soft-float">, Group; def mno_stackrealign : Flag<["-"], "mno-stackrealign">, Group; +} // let Flags = [TargetSpecific] def mretpoline : Flag<["-"], "mretpoline">, Group, Flags<[CoreOption,NoXarchOption]>; def mno_retpoline : Flag<["-"], "mno-retpoline">, Group, Flags<[CoreOption,NoXarchOption]>; @@ -3570,28 +3806,41 @@ def mno_relax : Flag<["-"], "mno-relax">, Group, def msmall_data_limit_EQ : Joined<["-"], "msmall-data-limit=">, Group, Alias, HelpText<"Put global and static data smaller than the limit into a special section">; +let Flags = [TargetSpecific] in { def msave_restore : Flag<["-"], "msave-restore">, Group, HelpText<"Enable using library calls for save and restore">; def mno_save_restore : Flag<["-"], "mno-save-restore">, Group, HelpText<"Disable using library calls for save and restore">; +} // let Flags = [TargetSpecific] def mcmodel_EQ_medlow : Flag<["-"], "mcmodel=medlow">, Group, Flags<[CC1Option]>, Alias, AliasArgs<["small"]>, HelpText<"Equivalent to -mcmodel=small, compatible with RISC-V gcc.">; def mcmodel_EQ_medany : Flag<["-"], "mcmodel=medany">, Group, Flags<[CC1Option]>, Alias, AliasArgs<["medium"]>, HelpText<"Equivalent to -mcmodel=medium, compatible with RISC-V gcc.">; +let Flags = [TargetSpecific] in { def menable_experimental_extensions : Flag<["-"], "menable-experimental-extensions">, Group, HelpText<"Enable use of experimental RISC-V extensions.">; +def mrvv_vector_bits_EQ : Joined<["-"], "mrvv-vector-bits=">, Group, + HelpText<"Specify the size in bits of an RVV vector register. Defaults to " + "the vector length agnostic value of \"scalable\". Accepts power of " + "2 values between 64 and 65536. Also accepts \"zvl\" " + "to use the value implied by -march/-mcpu. Value will be reflected " + "in __riscv_v_fixed_vlen preprocessor define (RISC-V only)">; -def munaligned_access : Flag<["-"], "munaligned-access">, Group, - HelpText<"Allow memory accesses to be unaligned (AArch32/AArch64 only)">; -def mno_unaligned_access : Flag<["-"], "mno-unaligned-access">, Group, - HelpText<"Force all memory accesses to be aligned (AArch32/AArch64 only)">; +def munaligned_access : Flag<["-"], "munaligned-access">, Group, + HelpText<"Allow memory accesses to be unaligned (AArch32/AArch64/LoongArch only)">; +def mno_unaligned_access : Flag<["-"], "mno-unaligned-access">, Group, + HelpText<"Force all memory accesses to be aligned (AArch32/AArch64/LoongArch only)">; +} // let Flags = [TargetSpecific] def mstrict_align : Flag<["-"], "mstrict-align">, Alias, Flags<[CC1Option,HelpHidden]>, HelpText<"Force all memory accesses to be aligned (same as mno-unaligned-access)">; +def mno_strict_align : Flag<["-"], "mno-strict-align">, Alias, Flags<[CC1Option,HelpHidden]>, + HelpText<"Allow memory accesses to be unaligned (same as munaligned-access)">; +let Flags = [TargetSpecific] in { def mno_thumb : Flag<["-"], "mno-thumb">, Group; def mrestrict_it: Flag<["-"], "mrestrict-it">, Group, - HelpText<"Disallow generation of complex IT blocks.">; + HelpText<"Disallow generation of complex IT blocks. It is off by default.">; def mno_restrict_it: Flag<["-"], "mno-restrict-it">, Group, HelpText<"Allow generation of complex IT blocks.">; def marm : Flag<["-"], "marm">, Alias; @@ -3605,6 +3854,7 @@ def mnocrc : Flag<["-"], "mnocrc">, Group, HelpText<"Disallow use of CRC instructions (ARM only)">; def mno_neg_immediates: Flag<["-"], "mno-neg-immediates">, Group, HelpText<"Disallow converting instructions with negative immediates to their negation or inversion.">; +} // let Flags = [TargetSpecific] def mcmse : Flag<["-"], "mcmse">, Group, Flags<[NoXarchOption,CC1Option]>, HelpText<"Allow use of CMSE (Armv8-M Security Extensions)">, @@ -3619,6 +3869,7 @@ defm aapcs_bitfield_width : BoolOption<"f", "aapcs-bitfield-width", BothFlags<[NoXarchOption, CC1Option], " the AAPCS standard requirement stating that" " volatile bit-field width is dictated by the field container type. (ARM only).">>, Group; +let Flags = [TargetSpecific] in { def mframe_chain : Joined<["-"], "mframe-chain=">, Group, Values<"none,aapcs,aapcs+leaf">, HelpText<"Select the frame chain model used to emit frame records (Arm only).">; @@ -3669,25 +3920,27 @@ foreach i = {8-15,18} in def msve_vector_bits_EQ : Joined<["-"], "msve-vector-bits=">, Group, HelpText<"Specify the size in bits of an SVE vector register. Defaults to the" " vector length agnostic value of \"scalable\". (AArch64 only)">; +} // let Flags = [TargetSpecific] def mvscale_min_EQ : Joined<["-"], "mvscale-min=">, Group, Flags<[NoXarchOption,CC1Option]>, - HelpText<"Specify the vscale minimum. Defaults to \"1\". (AArch64 only)">, + HelpText<"Specify the vscale minimum. Defaults to \"1\". (AArch64/RISC-V only)">, MarshallingInfoInt>; def mvscale_max_EQ : Joined<["-"], "mvscale-max=">, Group, Flags<[NoXarchOption,CC1Option]>, HelpText<"Specify the vscale maximum. Defaults to the" - " vector length agnostic value of \"0\". (AArch64 only)">, + " vector length agnostic value of \"0\". (AArch64/RISC-V only)">, MarshallingInfoInt>; def msign_return_address_EQ : Joined<["-"], "msign-return-address=">, Flags<[CC1Option]>, Group, Values<"none,all,non-leaf">, HelpText<"Select return address signing scope">; +let Flags = [TargetSpecific] in { def mbranch_protection_EQ : Joined<["-"], "mbranch-protection=">, Group, HelpText<"Enforce targets of indirect branches and function returns">; -def mharden_sls_EQ : Joined<["-"], "mharden-sls=">, +def mharden_sls_EQ : Joined<["-"], "mharden-sls=">, Group, HelpText<"Select straight-line speculation hardening scope (ARM/AArch64/X86" " only). must be: all, none, retbr(ARM/AArch64)," " blr(ARM/AArch64), comdat(ARM/AArch64), nocomdat(ARM/AArch64)," @@ -3719,7 +3972,12 @@ def mextended_const : Flag<["-"], "mextended-const">, Group, Group; def mexec_model_EQ : Joined<["-"], "mexec-model=">, Group, Values<"command,reactor">, - HelpText<"Execution model (WebAssembly only)">; + HelpText<"Execution model (WebAssembly only)">, + DocBrief<"Select between \"command\" and \"reactor\" executable models. " + "Commands have a main-function which scopes the lifetime of the " + "program. Reactors are activated and remain active until " + "explicitly terminated.">; +} // let Flags = [TargetSpecific] defm amdgpu_ieee : BoolOption<"m", "amdgpu-ieee", CodeGenOpts<"EmitIEEENaNCompliantInsts">, DefaultTrue, @@ -3737,10 +3995,6 @@ def mcode_object_version_EQ : Joined<["-"], "mcode-object-version=">, Group, MarshallingInfoEnum, "COV_4">; -defm code_object_v3_legacy : SimpleMFlag<"code-object-v3", - "Legacy option to specify code object ABI V3", - "Legacy option to specify code object ABI V2", - " (AMDGPU only)">; defm cumode : SimpleMFlag<"cumode", "Specify CU wavefront", "Specify WGP wavefront", " execution mode (AMDGPU only)", m_amdgpu_Features_Group>; @@ -3752,12 +4006,17 @@ defm wavefrontsize64 : SimpleMFlag<"wavefrontsize64", defm unsafe_fp_atomics : BoolOption<"m", "unsafe-fp-atomics", TargetOpts<"AllowAMDGPUUnsafeFPAtomics">, DefaultFalse, - PosFlag, + PosFlag, NegFlag>, Group; def faltivec : Flag<["-"], "faltivec">, Group, Flags<[NoXarchOption]>; def fno_altivec : Flag<["-"], "fno-altivec">, Group, Flags<[NoXarchOption]>; -def maltivec : Flag<["-"], "maltivec">, Group; +let Flags = [TargetSpecific] in { +def maltivec : Flag<["-"], "maltivec">, Group, + HelpText<"Enable AltiVec vector initializer syntax">; def mno_altivec : Flag<["-"], "mno-altivec">, Group; def mpcrel: Flag<["-"], "mpcrel">, Group; def mno_pcrel: Flag<["-"], "mno-pcrel">, Group; @@ -3766,15 +4025,12 @@ def mno_prefixed: Flag<["-"], "mno-prefixed">, Group; def mspe : Flag<["-"], "mspe">, Group; def mno_spe : Flag<["-"], "mno-spe">, Group; def mefpu2 : Flag<["-"], "mefpu2">, Group; -def mabi_EQ_vec_extabi : Flag<["-"], "mabi=vec-extabi">, Group, Flags<[CC1Option]>, - HelpText<"Enable the extended Altivec ABI on AIX (AIX only). Uses volatile and nonvolatile vector registers">, - MarshallingInfoFlag>; -def mabi_EQ_vec_default : Flag<["-"], "mabi=vec-default">, Group, Flags<[CC1Option]>, - HelpText<"Enable the default Altivec ABI on AIX (AIX only). Uses only volatile vector registers.">; +} // let Flags = [TargetSpecific] def mabi_EQ_quadword_atomics : Flag<["-"], "mabi=quadword-atomics">, Group, Flags<[CC1Option]>, HelpText<"Enable quadword atomics ABI on AIX (AIX PPC64 only). Uses lqarx/stqcx. instructions.">, MarshallingInfoFlag>; +let Flags = [TargetSpecific] in { def mvsx : Flag<["-"], "mvsx">, Group; def mno_vsx : Flag<["-"], "mno-vsx">, Group; def msecure_plt : Flag<["-"], "msecure-plt">, Group; @@ -3816,7 +4072,11 @@ def mno_mfocrf : Flag<["-"], "mno-mfocrf">, Group; def mno_mfcrf : Flag<["-"], "mno-mfcrf">, Alias; def mpopcntd : Flag<["-"], "mpopcntd">, Group; def mno_popcntd : Flag<["-"], "mno-popcntd">, Group; -def mcrbits : Flag<["-"], "mcrbits">, Group; +def mcrbits : Flag<["-"], "mcrbits">, Group, + HelpText<"Control the CR-bit tracking feature on PowerPC. ``-mcrbits`` " + "(the enablement of CR-bit tracking support) is the default for " + "POWER8 and above, as well as for all other CPUs when " + "optimization is applied (-O2 and above).">; def mno_crbits : Flag<["-"], "mno-crbits">, Group; def minvariant_function_descriptors : Flag<["-"], "minvariant-function-descriptors">, Group; @@ -3837,15 +4097,26 @@ def mrop_protect : Flag<["-"], "mrop-protect">, Group; def mprivileged : Flag<["-"], "mprivileged">, Group; +} // let Flags = [TargetSpecific] def maix_struct_return : Flag<["-"], "maix-struct-return">, Group, Flags<[CC1Option]>, - HelpText<"Return all structs in memory (PPC32 only)">; + HelpText<"Return all structs in memory (PPC32 only)">, + DocBrief<"Override the default ABI for 32-bit targets to return all " + "structs in memory, as in the Power 32-bit ABI for Linux (2011), " + "and on AIX and Darwin.">; def msvr4_struct_return : Flag<["-"], "msvr4-struct-return">, Group, Flags<[CC1Option]>, - HelpText<"Return small structs in registers (PPC32 only)">; + HelpText<"Return small structs in registers (PPC32 only)">, + DocBrief<"Override the default ABI for 32-bit targets to return small " + "structs in registers, as in the System V ABI (1995).">; +def mxcoff_roptr : Flag<["-"], "mxcoff-roptr">, Group, Flags<[CC1Option,TargetSpecific]>, + HelpText<"Place constant objects with relocatable address values in the RO data section and add -bforceimprw to the linker flags (AIX only)">; +def mno_xcoff_roptr : Flag<["-"], "mno-xcoff-roptr">, Group, TargetSpecific; +let Flags = [TargetSpecific] in { def mvx : Flag<["-"], "mvx">, Group; def mno_vx : Flag<["-"], "mno-vx">, Group; +} // let Flags = [TargetSpecific] defm zvector : BoolFOption<"zvector", LangOpts<"ZVector">, DefaultFalse, @@ -3854,9 +4125,11 @@ defm zvector : BoolFOption<"zvector", def mzvector : Flag<["-"], "mzvector">, Alias; def mno_zvector : Flag<["-"], "mno-zvector">, Alias; +def mxcoff_build_id_EQ : Joined<["-"], "mxcoff-build-id=">, Group, MetaVarName<"<0xHEXSTRING>">, + HelpText<"On AIX, request creation of a build-id string, \"0xHEXSTRING\", in the string table of the loader section inside the linked binary">; def mignore_xcoff_visibility : Flag<["-"], "mignore-xcoff-visibility">, Group, HelpText<"Not emit the visibility attribute for asm in AIX OS or give all symbols 'unspecified' visibility in XCOFF object file">, - Flags<[CC1Option]>; + Flags<[CC1Option,TargetSpecific]>; defm backchain : BoolOption<"m", "backchain", CodeGenOpts<"Backchain">, DefaultFalse, PosFlag, @@ -3897,8 +4170,12 @@ def mno_outline_atomics : Flag<["-"], "mno-outline-atomics">, Group, Group, HelpText<"Don't generate implicit floating point or vector instructions">; def mimplicit_float : Flag<["-"], "mimplicit-float">, Group; -def mrecip : Flag<["-"], "mrecip">, Group; +def mrecip : Flag<["-"], "mrecip">, Group, + HelpText<"Equivalent to '-mrecip=all'">; def mrecip_EQ : CommaJoined<["-"], "mrecip=">, Group, Flags<[CC1Option]>, + HelpText<"Control use of approximate reciprocal and reciprocal square root instructions followed by iterations of " + "Newton-Raphson refinement. " + " = ( ['!'] ['vec-'] ('rcp'|'sqrt') [('h'|'s'|'d')] [':'] ) | 'all' | 'default' | 'none'">, MarshallingInfoStringVector>; def mprefer_vector_width_EQ : Joined<["-"], "mprefer-vector-width=">, Group, Flags<[CC1Option]>, HelpText<"Specifies preferred vector width for auto-vectorization. Defaults to 'none' which allows target specific decisions.">, @@ -3928,6 +4205,8 @@ def mpacked_stack : Flag<["-"], "mpacked-stack">, HelpText<"Use packed stack lay Flags<[CC1Option]>, Group, MarshallingInfoFlag>; def mno_packed_stack : Flag<["-"], "mno-packed-stack">, Flags<[CC1Option]>, Group; + +let Flags = [TargetSpecific] in { def mips16 : Flag<["-"], "mips16">, Group; def mno_mips16 : Flag<["-"], "mno-mips16">, Group; def mmicromips : Flag<["-"], "mmicromips">, Group; @@ -3943,10 +4222,12 @@ def mno_check_zero_division : Flag<["-"], "mno-check-zero-division">, def mfix4300 : Flag<["-"], "mfix4300">, Group; def mcompact_branches_EQ : Joined<["-"], "mcompact-branches=">, Group; +} // let Flags = [TargetSpecific] def mbranch_likely : Flag<["-"], "mbranch-likely">, Group, IgnoredGCCCompat; def mno_branch_likely : Flag<["-"], "mno-branch-likely">, Group, IgnoredGCCCompat; +let Flags = [TargetSpecific] in { def mindirect_jump_EQ : Joined<["-"], "mindirect-jump=">, Group, HelpText<"Change indirect jump instructions to inhibit speculation">; @@ -4012,6 +4293,7 @@ def mvirt : Flag<["-"], "mvirt">, Group; def mno_virt : Flag<["-"], "mno-virt">, Group; def mginv : Flag<["-"], "mginv">, Group; def mno_ginv : Flag<["-"], "mno-ginv">, Group; +} // let Flags = [TargetSpecific] def mips1 : Flag<["-"], "mips1">, Alias, AliasArgs<["mips1"]>, Group, HelpText<"Equivalent to -march=mips1">, Flags<[HelpHidden]>; @@ -4093,12 +4375,13 @@ def no_cpp_precomp : Flag<["-"], "no-cpp-precomp">, Group def no_integrated_cpp : Flag<["-", "--"], "no-integrated-cpp">, Flags<[NoXarchOption]>; def no_pedantic : Flag<["-", "--"], "no-pedantic">, Group; def no__dead__strip__inits__and__terms : Flag<["-"], "no_dead_strip_inits_and_terms">; -def nobuiltininc : Flag<["-"], "nobuiltininc">, Flags<[CC1Option, CoreOption]>, +def nobuiltininc : Flag<["-"], "nobuiltininc">, Flags<[CC1Option, CoreOption]>, Group, HelpText<"Disable builtin #include directories">, MarshallingInfoNegativeFlag>; -def nogpuinc : Flag<["-"], "nogpuinc">, HelpText<"Do not add include paths for CUDA/HIP and" +def nogpuinc : Flag<["-"], "nogpuinc">, Group, + HelpText<"Do not add include paths for CUDA/HIP and" " do not include the default CUDA/HIP wrapper headers">; -def nohipwrapperinc : Flag<["-"], "nohipwrapperinc">, +def nohipwrapperinc : Flag<["-"], "nohipwrapperinc">, Group, HelpText<"Do not include the default HIP wrapper headers and include paths">; def : Flag<["-"], "nocudainc">, Alias; def nogpulib : Flag<["-"], "nogpulib">, MarshallingInfoFlag>, @@ -4115,9 +4398,9 @@ def noprebind : Flag<["-"], "noprebind">; def noprofilelib : Flag<["-"], "noprofilelib">; def noseglinkedit : Flag<["-"], "noseglinkedit">; def nostartfiles : Flag<["-"], "nostartfiles">, Group; -def nostdinc : Flag<["-"], "nostdinc">, Flags<[CoreOption]>; -def nostdlibinc : Flag<["-"], "nostdlibinc">; -def nostdincxx : Flag<["-"], "nostdinc++">, Flags<[CC1Option]>, +def nostdinc : Flag<["-"], "nostdinc">, Flags<[CoreOption]>, Group; +def nostdlibinc : Flag<["-"], "nostdlibinc">, Group; +def nostdincxx : Flag<["-"], "nostdinc++">, Flags<[CC1Option]>, Group, HelpText<"Disable standard #include directories for the C++ standard library">, MarshallingInfoNegativeFlag>; def nostdlib : Flag<["-"], "nostdlib">, Group; @@ -4138,6 +4421,7 @@ def pedantic_errors : Flag<["-", "--"], "pedantic-errors">, Group>; def pedantic : Flag<["-", "--"], "pedantic">, Group, Flags<[CC1Option,FlangOption,FC1Option]>, HelpText<"Warn on language extensions">, MarshallingInfoFlag>; +def p : Flag<["-"], "p">, HelpText<"Enable mcount instrumentation with prof">; def pg : Flag<["-"], "pg">, HelpText<"Enable mcount instrumentation">, Flags<[CC1Option]>, MarshallingInfoFlag>; def pipe : Flag<["-", "--"], "pipe">, @@ -4155,6 +4439,8 @@ def print_libgcc_file_name : Flag<["-", "--"], "print-libgcc-file-name">, "library (\"libgcc.a\" or \"libclang_rt.builtins.*.a\")">; def print_multi_directory : Flag<["-", "--"], "print-multi-directory">; def print_multi_lib : Flag<["-", "--"], "print-multi-lib">; +def print_multi_flags : Flag<["-", "--"], "print-multi-flags-experimental">, + HelpText<"Print the flags used for selecting multilibs (experimental)">; def print_multi_os_directory : Flag<["-", "--"], "print-multi-os-directory">, Flags<[Unsupported]>; def print_target_triple : Flag<["-", "--"], "print-target-triple">, @@ -4184,7 +4470,6 @@ defm pthread : BoolOption<"", "pthread", LangOpts<"POSIXThreads">, DefaultFalse, PosFlag, NegFlag, BothFlags<[CC1Option]>>; -def p : Flag<["-"], "p">; def pie : Flag<["-"], "pie">, Group; def static_pie : Flag<["-"], "static-pie">, Group; def read__only__relocs : Separate<["-"], "read_only_relocs">; @@ -4204,24 +4489,20 @@ def rpath : Separate<["-"], "rpath">, Flags<[LinkerInput]>, Group; def rtlib_EQ : Joined<["-", "--"], "rtlib=">, HelpText<"Compiler runtime library to use">; def frtlib_add_rpath: Flag<["-"], "frtlib-add-rpath">, Flags<[NoArgumentUnused]>, - HelpText<"Add -rpath with architecture-specific resource directory to the linker flags">; + HelpText<"Add -rpath with architecture-specific resource directory to the linker flags. " + "When --hip-link is specified, also add -rpath with HIP runtime library directory to the linker flags">; def fno_rtlib_add_rpath: Flag<["-"], "fno-rtlib-add-rpath">, Flags<[NoArgumentUnused]>, - HelpText<"Do not add -rpath with architecture-specific resource directory to the linker flags">; + HelpText<"Do not add -rpath with architecture-specific resource directory to the linker flags. " + "When --hip-link is specified, do not add -rpath with HIP runtime library directory to the linker flags">; def offload_add_rpath: Flag<["--"], "offload-add-rpath">, Flags<[NoArgumentUnused]>, - HelpText<"Add -rpath with HIP runtime library directory to the linker flags">; + Alias; def no_offload_add_rpath: Flag<["--"], "no-offload-add-rpath">, Flags<[NoArgumentUnused]>, - HelpText<"Do not add -rpath with HIP runtime library directory to the linker flags">; -defm openmp_implicit_rpath: BoolFOption<"openmp-implicit-rpath", - LangOpts<"OpenMP">, - DefaultTrue, - PosFlag, - NegFlag, - BothFlags<[NoArgumentUnused]>>; + Alias; def r : Flag<["-"], "r">, Flags<[LinkerInput,NoArgumentUnused]>, Group; -def save_temps_EQ : Joined<["-", "--"], "save-temps=">, Flags<[CC1Option, FlangOption, NoXarchOption]>, +def save_temps_EQ : Joined<["-", "--"], "save-temps=">, Flags<[CC1Option, FlangOption, FC1Option, NoXarchOption]>, HelpText<"Save intermediate compilation results.">; -def save_temps : Flag<["-", "--"], "save-temps">, Flags<[FlangOption, NoXarchOption]>, +def save_temps : Flag<["-", "--"], "save-temps">, Flags<[FlangOption, FC1Option, NoXarchOption]>, Alias, AliasArgs<["cwd"]>, HelpText<"Save intermediate compilation results">; def save_stats_EQ : Joined<["-", "--"], "save-stats=">, Flags<[NoXarchOption]>, @@ -4296,8 +4577,8 @@ def print_supported_cpus : Flag<["-", "--"], "print-supported-cpus">, HelpText<"Print supported cpu models for the given target (if target is not specified," " it will print the supported cpus for the default target)">, MarshallingInfoFlag>; -def mcpu_EQ_QUESTION : Flag<["-"], "mcpu=?">, Alias; -def mtune_EQ_QUESTION : Flag<["-"], "mtune=?">, Alias; +def : Flag<["-"], "mcpu=help">, Alias; +def : Flag<["-"], "mtune=help">, Alias; def time : Flag<["-"], "time">, HelpText<"Time individual commands">; def traditional_cpp : Flag<["-", "--"], "traditional-cpp">, Flags<[CC1Option]>, @@ -4490,6 +4771,7 @@ def _write_user_dependencies : Flag<["--"], "write-user-dependencies">, Alias, Flags<[Unsupported]>; // Hexagon feature flags. +let Flags = [TargetSpecific] in { def mieee_rnd_near : Flag<["-"], "mieee-rnd-near">, Group; def mv5 : Flag<["-"], "mv5">, Group, Alias, @@ -4541,8 +4823,9 @@ def mhexagon_hvx_ieee_fp : Flag<["-"], "mhvx-ieee-fp">, def mno_hexagon_hvx_ieee_fp : Flag<["-"], "mno-hvx-ieee-fp">, Group, HelpText<"Disable Hexagon HVX IEEE floating-point">; -def ffixed_r19: Flag<["-"], "ffixed-r19">, +def ffixed_r19: Flag<["-"], "ffixed-r19">, Group, HelpText<"Reserve register r19 (Hexagon only)">; +} // let Flags = [TargetSpecific] def mmemops : Flag<["-"], "mmemops">, Group, Flags<[CC1Option]>, HelpText<"Enable generation of memop instructions">; def mno_memops : Flag<["-"], "mno-memops">, Group, @@ -4563,6 +4846,7 @@ def mcabac: Flag<["-"], "mcabac">, Group, HelpText<"Enable CABAC instructions">; // SPARC feature flags +let Flags = [TargetSpecific] in { def mfpu : Flag<["-"], "mfpu">, Group; def mno_fpu : Flag<["-"], "mno-fpu">, Group; def mfsmuld : Flag<["-"], "mfsmuld">, Group; @@ -4577,8 +4861,10 @@ def mvis3 : Flag<["-"], "mvis3">, Group; def mno_vis3 : Flag<["-"], "mno-vis3">, Group; def mhard_quad_float : Flag<["-"], "mhard-quad-float">, Group; def msoft_quad_float : Flag<["-"], "msoft-quad-float">, Group; +} // let Flags = [TargetSpecific] // M68k features flags +let Flags = [TargetSpecific] in { def m68000 : Flag<["-"], "m68000">, Group; def m68010 : Flag<["-"], "m68010">, Group; def m68020 : Flag<["-"], "m68020">, Group; @@ -4586,12 +4872,15 @@ def m68030 : Flag<["-"], "m68030">, Group; def m68040 : Flag<["-"], "m68040">, Group; def m68060 : Flag<["-"], "m68060">, Group; +def m68881 : Flag<["-"], "m68881">, Group; + foreach i = {0-6} in def ffixed_a#i : Flag<["-"], "ffixed-a"#i>, Group, HelpText<"Reserve the a"#i#" register (M68k only)">; foreach i = {0-7} in def ffixed_d#i : Flag<["-"], "ffixed-d"#i>, Group, HelpText<"Reserve the d"#i#" register (M68k only)">; +} // let Flags = [TargetSpecific] // X86 feature flags def mx87 : Flag<["-"], "mx87">, Group; @@ -4607,6 +4896,8 @@ def m3dnowa : Flag<["-"], "m3dnowa">, Group; def mno_3dnowa : Flag<["-"], "mno-3dnowa">, Group; def mamx_bf16 : Flag<["-"], "mamx-bf16">, Group; def mno_amx_bf16 : Flag<["-"], "mno-amx-bf16">, Group; +def mamx_complex : Flag<["-"], "mamx-complex">, Group; +def mno_amx_complex : Flag<["-"], "mno-amx-complex">, Group; def mamx_fp16 : Flag<["-"], "mamx-fp16">, Group; def mno_amx_fp16 : Flag<["-"], "mno-amx-fp16">, Group; def mamx_int8 : Flag<["-"], "mamx-int8">, Group; @@ -4674,6 +4965,8 @@ def mavxifma : Flag<["-"], "mavxifma">, Group; def mno_avxifma : Flag<["-"], "mno-avxifma">, Group; def mavxneconvert : Flag<["-"], "mavxneconvert">, Group; def mno_avxneconvert : Flag<["-"], "mno-avxneconvert">, Group; +def mavxvnniint16 : Flag<["-"], "mavxvnniint16">, Group; +def mno_avxvnniint16 : Flag<["-"], "mno-avxvnniint16">, Group; def mavxvnniint8 : Flag<["-"], "mavxvnniint8">, Group; def mno_avxvnniint8 : Flag<["-"], "mno-avxvnniint8">, Group; def mavxvnni : Flag<["-"], "mavxvnni">, Group; @@ -4770,6 +5063,12 @@ def msgx : Flag<["-"], "msgx">, Group; def mno_sgx : Flag<["-"], "mno-sgx">, Group; def msha : Flag<["-"], "msha">, Group; def mno_sha : Flag<["-"], "mno-sha">, Group; +def msha512 : Flag<["-"], "msha512">, Group; +def mno_sha512 : Flag<["-"], "mno-sha512">, Group; +def msm3 : Flag<["-"], "msm3">, Group; +def mno_sm3 : Flag<["-"], "mno-sm3">, Group; +def msm4 : Flag<["-"], "msm4">, Group; +def mno_sm4 : Flag<["-"], "mno-sm4">, Group; def mtbm : Flag<["-"], "mtbm">, Group; def mno_tbm : Flag<["-"], "mno-tbm">, Group; def mtsxldtrk : Flag<["-"], "mtsxldtrk">, Group; @@ -4826,6 +5125,10 @@ multiclass BooleanFFlag { def fno_#NAME : Flag<["-"], "fno-"#name>; } +multiclass FlangIgnoredDiagOpt { + def unsupported_warning_w#NAME : Flag<["-", "--"], "W"#name>, Group; +} + defm : BooleanFFlag<"keep-inline-functions">, Group; def fprofile_dir : Joined<["-"], "fprofile-dir=">, Group; @@ -4850,12 +5153,15 @@ def falign_jumps_EQ : Joined<["-"], "falign-jumps=">, Group, Group; +defm check_new : BoolOption<"f", "check-new", + LangOpts<"CheckNew">, DefaultFalse, + PosFlag, + NegFlag, BothFlags<[CC1Option]>>; + defm caller_saves : BooleanFFlag<"caller-saves">, Group; defm reorder_blocks : BooleanFFlag<"reorder-blocks">, Group; defm branch_count_reg : BooleanFFlag<"branch-count-reg">, Group; defm default_inline : BooleanFFlag<"default-inline">, Group; -defm fat_lto_objects : BooleanFFlag<"fat-lto-objects">, Group; defm float_store : BooleanFFlag<"float-store">, Group; defm friend_injection : BooleanFFlag<"friend-injection">, Group; defm function_attribute_list : BooleanFFlag<"function-attribute-list">, Group; @@ -4881,7 +5187,10 @@ defm ipa_cp : BooleanFFlag<"ipa-cp">, defm ivopts : BooleanFFlag<"ivopts">, Group; defm semantic_interposition : BoolFOption<"semantic-interposition", LangOpts<"SemanticInterposition">, DefaultFalse, - PosFlag, NegFlag>; + PosFlag, NegFlag>, + DocBrief<[{Enable semantic interposition. Semantic interposition allows for the +interposition of a symbol by another at runtime, thus preventing a range of +inter-procedural optimisation.}]>; defm non_call_exceptions : BooleanFFlag<"non-call-exceptions">, Group; defm peel_loops : BooleanFFlag<"peel-loops">, Group; defm permissive : BooleanFFlag<"permissive">, Group; @@ -4983,10 +5292,38 @@ defm recursive : BooleanFFlag<"recursive">, Group; defm repack_arrays : BooleanFFlag<"repack-arrays">, Group; defm second_underscore : BooleanFFlag<"second-underscore">, Group; defm sign_zero : BooleanFFlag<"sign-zero">, Group; -defm stack_arrays : BooleanFFlag<"stack-arrays">, Group; -defm underscoring : BooleanFFlag<"underscoring">, Group; defm whole_file : BooleanFFlag<"whole-file">, Group; +// -W options unsupported by the flang compiler +// If any of these options are passed into flang's compiler driver, +// a warning will be raised and the argument will be claimed +defm : FlangIgnoredDiagOpt<"extra">; +defm : FlangIgnoredDiagOpt<"aliasing">; +defm : FlangIgnoredDiagOpt<"ampersand">; +defm : FlangIgnoredDiagOpt<"array-bounds">; +defm : FlangIgnoredDiagOpt<"c-binding-type">; +defm : FlangIgnoredDiagOpt<"character-truncation">; +defm : FlangIgnoredDiagOpt<"conversion">; +defm : FlangIgnoredDiagOpt<"do-subscript">; +defm : FlangIgnoredDiagOpt<"function-elimination">; +defm : FlangIgnoredDiagOpt<"implicit-interface">; +defm : FlangIgnoredDiagOpt<"implicit-procedure">; +defm : FlangIgnoredDiagOpt<"intrinsic-shadow">; +defm : FlangIgnoredDiagOpt<"use-without-only">; +defm : FlangIgnoredDiagOpt<"intrinsics-std">; +defm : FlangIgnoredDiagOpt<"line-truncation">; +defm : FlangIgnoredDiagOpt<"no-align-commons">; +defm : FlangIgnoredDiagOpt<"no-overwrite-recursive">; +defm : FlangIgnoredDiagOpt<"no-tabs">; +defm : FlangIgnoredDiagOpt<"real-q-constant">; +defm : FlangIgnoredDiagOpt<"surprising">; +defm : FlangIgnoredDiagOpt<"underflow">; +defm : FlangIgnoredDiagOpt<"unused-parameter">; +defm : FlangIgnoredDiagOpt<"realloc-lhs">; +defm : FlangIgnoredDiagOpt<"realloc-lhs-all">; +defm : FlangIgnoredDiagOpt<"frontend-loop-interchange">; +defm : FlangIgnoredDiagOpt<"target-lifetime">; + // C++ SYCL options def fsycl : Flag<["-"], "fsycl">, Flags<[NoXarchOption, CoreOption]>, Group, HelpText<"Enables SYCL kernels compilation for device">; @@ -4997,9 +5334,14 @@ def fno_sycl : Flag<["-"], "fno-sycl">, Flags<[NoXarchOption, CoreOption]>, // FLangOption + NoXarchOption //===----------------------------------------------------------------------===// -def flang_experimental_exec : Flag<["-"], "flang-experimental-exec">, - Flags<[FlangOption, FlangOnlyOption, NoXarchOption, HelpHidden]>, - HelpText<"Enable support for generating executables (experimental)">; +def flang_experimental_hlfir : Flag<["-"], "flang-experimental-hlfir">, + Flags<[FlangOption, FC1Option, FlangOnlyOption, NoXarchOption, HelpHidden]>, + HelpText<"Use HLFIR lowering (experimental)">; + +def flang_experimental_polymorphism : Flag<["-"], "flang-experimental-polymorphism">, + Flags<[FlangOption, FC1Option, FlangOnlyOption, NoXarchOption, HelpHidden]>, + HelpText<"Enable Fortran 2003 polymorphism (experimental)">; + //===----------------------------------------------------------------------===// // FLangOption + CoreOption + NoXarchOption @@ -5042,7 +5384,7 @@ def fopenacc : Flag<["-"], "fopenacc">, Group, def fdefault_double_8 : Flag<["-"],"fdefault-double-8">, Group, HelpText<"Set the default double precision kind to an 8 byte wide type">; def fdefault_integer_8 : Flag<["-"],"fdefault-integer-8">, Group, - HelpText<"Set the default integer kind to an 8 byte wide type">; + HelpText<"Set the default integer and logical kind to an 8 byte wide type">; def fdefault_real_8 : Flag<["-"],"fdefault-real-8">, Group, HelpText<"Set the default real kind to an 8 byte wide type">; def flarge_sizes : Flag<["-"],"flarge-sizes">, Group, @@ -5059,10 +5401,17 @@ defm backslash : OptInFC1FFlag<"backslash", "Specify that backslash in string in defm xor_operator : OptInFC1FFlag<"xor-operator", "Enable .XOR. as a synonym of .NEQV.">; defm logical_abbreviations : OptInFC1FFlag<"logical-abbreviations", "Enable logical abbreviations">; defm implicit_none : OptInFC1FFlag<"implicit-none", "No implicit typing allowed unless overridden by IMPLICIT statements">; +defm underscoring : OptInFC1FFlag<"underscoring", "Appends one trailing underscore to external names">; def fno_automatic : Flag<["-"], "fno-automatic">, Group, HelpText<"Implies the SAVE attribute for non-automatic local objects in subprograms unless RECURSIVE">; +defm stack_arrays : BoolOptionWithoutMarshalling<"f", "stack-arrays", + PosFlag, + NegFlag>; +defm loop_versioning : BoolOptionWithoutMarshalling<"f", "version-loops-for-stride", + PosFlag, + NegFlag>; } // let Flags = [FC1Option, FlangOption, FlangOnlyOption] def J : JoinedOrSeparate<["-"], "J">, @@ -5124,9 +5473,12 @@ def fno_reformat : Flag<["-"], "fno-reformat">, Group, HelpText<"Dump the cooked character stream in -E mode">; defm analyzed_objects_for_unparse : OptOutFC1FFlag<"analyzed-objects-for-unparse", "", "Do not use the analyzed objects when unparsing">; -def emit_mlir : Flag<["-"], "emit-mlir">, Group, - HelpText<"Build the parse tree, then lower it to MLIR">; -def emit_fir : Flag<["-"], "emit-fir">, Alias; +def emit_fir : Flag<["-"], "emit-fir">, Group, + HelpText<"Build the parse tree, then lower it to FIR">; +def emit_mlir : Flag<["-"], "emit-mlir">, Alias; + +def emit_hlfir : Flag<["-"], "emit-hlfir">, Group, + HelpText<"Build the parse tree, then lower it to HLFIR">; } // let Flags = [FC1Option, FlangOnlyOption] @@ -5376,12 +5728,12 @@ def mrelocation_model : Separate<["-"], "mrelocation-model">, NormalizedValuesScope<"llvm::Reloc">, NormalizedValues<["Static", "PIC_", "ROPI", "RWPI", "ROPI_RWPI", "DynamicNoPIC"]>, MarshallingInfoEnum, "PIC_">; +def debug_info_kind_EQ : Joined<["-"], "debug-info-kind=">; } // let Flags = [CC1Option, CC1AsOption, FC1Option, NoDriverOption] let Flags = [CC1Option, CC1AsOption, NoDriverOption] in { -def debug_info_kind_EQ : Joined<["-"], "debug-info-kind=">; def debug_info_macro : Flag<["-"], "debug-info-macro">, HelpText<"Emit macro debug information">, MarshallingInfoFlag>; @@ -5441,6 +5793,9 @@ def as_secure_log_file : Separate<["-"], "as-secure-log-file">, let Flags = [CC1Option, NoDriverOption] in { +def llvm_verify_each : Flag<["-"], "llvm-verify-each">, + HelpText<"Run the LLVM verifier after every LLVM pass">, + MarshallingInfoFlag>; def disable_llvm_verifier : Flag<["-"], "disable-llvm-verifier">, HelpText<"Don't run the LLVM IR verifier pass">, MarshallingInfoNegativeFlag>; @@ -5486,14 +5841,12 @@ def fmerge_functions : Flag<["-"], "fmerge-functions">, MarshallingInfoFlag>; def coverage_data_file : Separate<["-"], "coverage-data-file">, HelpText<"Emit coverage data to this filename.">, - MarshallingInfoString>, - ShouldParseIf; + MarshallingInfoString>; def coverage_data_file_EQ : Joined<["-"], "coverage-data-file=">, Alias; def coverage_notes_file : Separate<["-"], "coverage-notes-file">, HelpText<"Emit coverage notes to this filename.">, - MarshallingInfoString>, - ShouldParseIf; + MarshallingInfoString>; def coverage_notes_file_EQ : Joined<["-"], "coverage-notes-file=">, Alias; def coverage_version_EQ : Joined<["-"], "coverage-version=">, @@ -5522,6 +5875,9 @@ def mframe_pointer_EQ : Joined<["-"], "mframe-pointer=">, def mabi_EQ_ieeelongdouble : Flag<["-"], "mabi=ieeelongdouble">, HelpText<"Use IEEE 754 quadruple-precision for long double">, MarshallingInfoFlag>; +def mabi_EQ_vec_extabi : Flag<["-"], "mabi=vec-extabi">, + HelpText<"Enable the extended Altivec ABI on AIX. Use volatile and nonvolatile vector registers">, + MarshallingInfoFlag>; def mfloat_abi : Separate<["-"], "mfloat-abi">, HelpText<"The float ABI to use">, MarshallingInfoString>; @@ -5706,11 +6062,11 @@ def fctor_dtor_return_this : Flag<["-"], "fctor-dtor-return-this">, "and non-deleting destructors. (No effect on Microsoft ABI)">, MarshallingInfoFlag>; -defm experimental_assignment_tracking : - BoolOption<"f", "experimental-assignment-tracking", - CodeGenOpts<"EnableAssignmentTracking">, DefaultFalse, - PosFlag, NegFlag, BothFlags<[CoreOption]>>, - Group; +def fexperimental_assignment_tracking_EQ : Joined<["-"], "fexperimental-assignment-tracking=">, + Group, CodeGenOpts<"EnableAssignmentTracking">, + NormalizedValuesScope<"CodeGenOptions::AssignmentTrackingOpts">, + Values<"disabled,enabled,forced">, NormalizedValues<["Disabled","Enabled","Forced"]>, + MarshallingInfoEnum, "Enabled">; } // let Flags = [CC1Option, NoDriverOption] @@ -5723,6 +6079,9 @@ let Flags = [CC1Option, NoDriverOption] in { def sys_header_deps : Flag<["-"], "sys-header-deps">, HelpText<"Include system headers in dependency output">, MarshallingInfoFlag>; +def canonical_system_headers : Flag<["-"], "canonical-system-headers">, + HelpText<"Canonicalize system headers in dependency output">, + MarshallingInfoFlag>; def module_file_deps : Flag<["-"], "module-file-deps">, HelpText<"Include module files in dependency output">, MarshallingInfoFlag>; @@ -5774,22 +6133,6 @@ def ftabstop : Separate<["-"], "ftabstop">, MetaVarName<"">, def ferror_limit : Separate<["-"], "ferror-limit">, MetaVarName<"">, HelpText<"Set the maximum number of errors to emit before stopping (0 = no limit).">, MarshallingInfoInt>; -def fmacro_backtrace_limit : Separate<["-"], "fmacro-backtrace-limit">, MetaVarName<"">, - HelpText<"Set the maximum number of entries to print in a macro expansion backtrace (0 = no limit).">, - MarshallingInfoInt, "DiagnosticOptions::DefaultMacroBacktraceLimit">; -def ftemplate_backtrace_limit : Separate<["-"], "ftemplate-backtrace-limit">, MetaVarName<"">, - HelpText<"Set the maximum number of entries to print in a template instantiation backtrace (0 = no limit).">, - MarshallingInfoInt, "DiagnosticOptions::DefaultTemplateBacktraceLimit">; -def fconstexpr_backtrace_limit : Separate<["-"], "fconstexpr-backtrace-limit">, MetaVarName<"">, - HelpText<"Set the maximum number of entries to print in a constexpr evaluation backtrace (0 = no limit).">, - MarshallingInfoInt, "DiagnosticOptions::DefaultConstexprBacktraceLimit">; -def fspell_checking_limit : Separate<["-"], "fspell-checking-limit">, MetaVarName<"">, - HelpText<"Set the maximum number of times to perform spell checking on unrecognized identifiers (0 = no limit).">, - MarshallingInfoInt, "DiagnosticOptions::DefaultSpellCheckingLimit">; -def fcaret_diagnostics_max_lines : - Separate<["-"], "fcaret-diagnostics-max-lines">, MetaVarName<"">, - HelpText<"Set the maximum number of source lines to show in a caret diagnostic">, - MarshallingInfoInt, "DiagnosticOptions::DefaultSnippetLineLimit">; def verify_EQ : CommaJoined<["-"], "verify=">, MetaVarName<"">, HelpText<"Verify diagnostic output using comment directives that start with" @@ -5871,13 +6214,6 @@ defm enable_noundef_analysis : BoolOption<"", PosFlag, NegFlag, BothFlags<[], " analyzing function argument and return types for mandatory definedness">>; -defm opaque_pointers : BoolOption<"", - "opaque-pointers", - CodeGenOpts<"OpaquePointers">, - DefaultTrue, - PosFlag, - NegFlag, - BothFlags<[], " opaque pointers">>; def discard_value_names : Flag<["-"], "discard-value-names">, HelpText<"Discard value names in LLVM IR">, MarshallingInfoFlag>; @@ -5928,14 +6264,14 @@ defm fimplicit_modules_use_lock : BoolOption<"f", "implicit-modules-use-lock", PosFlag>; -// FIXME: We only need this in C++ modules / Modules TS if we might textually +// FIXME: We only need this in C++ modules if we might textually // enter a different module (eg, when building a header unit). def fmodules_local_submodule_visibility : Flag<["-"], "fmodules-local-submodule-visibility">, HelpText<"Enforce name visibility rules across submodules of the same " "top-level module.">, MarshallingInfoFlag>, - ImpliedByAnyOf<[fmodules_ts.KeyPath, fcxx_modules.KeyPath]>; + ImpliedByAnyOf<[fcxx_modules.KeyPath]>; def fmodules_codegen : Flag<["-"], "fmodules-codegen">, HelpText<"Generate code for uses of this module that assumes an explicit " @@ -6063,6 +6399,9 @@ def print_stats : Flag<["-"], "print-stats">, def stats_file : Joined<["-"], "stats-file=">, HelpText<"Filename to write statistics to">, MarshallingInfoString>; +def stats_file_append : Flag<["-"], "stats-file-append">, + HelpText<"If stats should be appended to stats-file instead of overwriting it">, + MarshallingInfoFlag>; def fdump_record_layouts_simple : Flag<["-"], "fdump-record-layouts-simple">, HelpText<"Dump record layout information in a simple form used for testing">, MarshallingInfoFlag>; @@ -6240,18 +6579,6 @@ def ftype_visibility : Joined<["-"], "ftype-visibility=">, def fapply_global_visibility_to_externs : Flag<["-"], "fapply-global-visibility-to-externs">, HelpText<"Apply global symbol visibility to external declarations without an explicit visibility">, MarshallingInfoFlag>; -def ftemplate_depth : Separate<["-"], "ftemplate-depth">, - HelpText<"Maximum depth of recursive template instantiation">, - MarshallingInfoInt, "1024">; -def foperator_arrow_depth : Separate<["-"], "foperator-arrow-depth">, - HelpText<"Maximum number of 'operator->'s to call for a member access">, - MarshallingInfoInt, "256">; -def fconstexpr_depth : Separate<["-"], "fconstexpr-depth">, - HelpText<"Maximum depth of recursive constexpr function calls">, - MarshallingInfoInt, "512">; -def fconstexpr_steps : Separate<["-"], "fconstexpr-steps">, - HelpText<"Maximum number of steps in constexpr function evaluation">, - MarshallingInfoInt, "1048576">; def fbracket_depth : Separate<["-"], "fbracket-depth">, HelpText<"Maximum nesting level for parentheses, brackets, and braces">, MarshallingInfoInt, "256">; @@ -6442,12 +6769,15 @@ def fno_cuda_host_device_constexpr : Flag<["-"], "fno-cuda-host-device-constexpr // OpenMP Options //===----------------------------------------------------------------------===// -def fopenmp_is_device : Flag<["-"], "fopenmp-is-device">, - HelpText<"Generate code only for an OpenMP target device.">, - Flags<[CC1Option, NoDriverOption]>; +let Flags = [CC1Option, FC1Option, NoDriverOption] in { + +def fopenmp_is_target_device : Flag<["-"], "fopenmp-is-target-device">, + HelpText<"Generate code only for an OpenMP target device.">; +def : Flag<["-"], "fopenmp-is-device">, Alias; def fopenmp_host_ir_file_path : Separate<["-"], "fopenmp-host-ir-file-path">, - HelpText<"Path to the IR file produced by the frontend for the host.">, - Flags<[CC1Option, NoDriverOption]>; + HelpText<"Path to the IR file produced by the frontend for the host.">; + +} // let Flags = [CC1Option, FC1Option, NoDriverOption] //===----------------------------------------------------------------------===// // SYCL Options @@ -6958,6 +7288,16 @@ def _SLASH_Gv : CLFlag<"Gv">, def _SLASH_Gregcall : CLFlag<"Gregcall">, HelpText<"Set __regcall as a default calling convention">; +// GNU Driver aliases + +def : Separate<["-"], "Xmicrosoft-visualc-tools-root">, Alias<_SLASH_vctoolsdir>; +def : Separate<["-"], "Xmicrosoft-visualc-tools-version">, + Alias<_SLASH_vctoolsversion>; +def : Separate<["-"], "Xmicrosoft-windows-sdk-root">, + Alias<_SLASH_winsdkdir>; +def : Separate<["-"], "Xmicrosoft-windows-sdk-version">, + Alias<_SLASH_winsdkversion>; + // Ignored: def _SLASH_analyze_ : CLIgnoredFlag<"analyze-">; @@ -7112,3 +7452,7 @@ def dxc_entrypoint : Option<["--", "/", "-"], "E", KIND_JOINED_OR_SEPARATE>, Group, Flags<[DXCOption, NoXarchOption]>, HelpText<"Entry point name">; +def dxc_validator_path_EQ : Joined<["--"], "dxv-path=">, Group, + HelpText<"DXIL validator installation path">; +def dxc_disable_validation : DXCFlag<"Vd">, + HelpText<"Disable validation">; diff --git a/contrib/llvm-project/clang/include/clang/Driver/SanitizerArgs.h b/contrib/llvm-project/clang/include/clang/Driver/SanitizerArgs.h index 52889c3fe18..047b50626c4 100644 --- a/contrib/llvm-project/clang/include/clang/Driver/SanitizerArgs.h +++ b/contrib/llvm-project/clang/include/clang/Driver/SanitizerArgs.h @@ -30,6 +30,7 @@ class SanitizerArgs { std::vector SystemIgnorelistFiles; std::vector CoverageAllowlistFiles; std::vector CoverageIgnorelistFiles; + std::vector BinaryMetadataIgnorelistFiles; int CoverageFeatures = 0; int BinaryMetadataFeatures = 0; int MsanTrackOrigins = 0; @@ -37,9 +38,11 @@ class SanitizerArgs { bool MsanParamRetval = true; bool CfiCrossDso = false; bool CfiICallGeneralizePointers = false; + bool CfiICallNormalizeIntegers = false; bool CfiCanonicalJumpTables = false; int AsanFieldPadding = 0; bool SharedRuntime = false; + bool StableABI = false; bool AsanUseAfterScope = true; bool AsanPoisonCustomArrayCookie = false; bool AsanGlobalsDeadStripping = false; @@ -117,6 +120,10 @@ public: return MemtagMode; } + bool hasShadowCallStack() const { + return Sanitizers.has(SanitizerKind::ShadowCallStack); + } + bool requiresPIE() const; bool needsUnwindTables() const; bool needsLTO() const; diff --git a/contrib/llvm-project/clang/include/clang/Driver/ToolChain.h b/contrib/llvm-project/clang/include/clang/Driver/ToolChain.h index f75f35dc9e6..e3fcbd9322b 100644 --- a/contrib/llvm-project/clang/include/clang/Driver/ToolChain.h +++ b/contrib/llvm-project/clang/include/clang/Driver/ToolChain.h @@ -9,7 +9,6 @@ #ifndef LLVM_CLANG_DRIVER_TOOLCHAIN_H #define LLVM_CLANG_DRIVER_TOOLCHAIN_H -#include "clang/Basic/DebugInfoOptions.h" #include "clang/Basic/LLVM.h" #include "clang/Basic/LangOptions.h" #include "clang/Basic/Sanitizers.h" @@ -21,11 +20,12 @@ #include "llvm/ADT/FloatingPointMode.h" #include "llvm/ADT/SmallVector.h" #include "llvm/ADT/StringRef.h" -#include "llvm/ADT/Triple.h" +#include "llvm/Frontend/Debug/Options.h" #include "llvm/MC/MCTargetOptions.h" #include "llvm/Option/Option.h" #include "llvm/Support/VersionTuple.h" #include "llvm/Target/TargetOptions.h" +#include "llvm/TargetParser/Triple.h" #include #include #include @@ -187,7 +187,7 @@ private: protected: MultilibSet Multilibs; - Multilib SelectedMultilib; + llvm::SmallVector SelectedMultilibs; ToolChain(const Driver &D, const llvm::Triple &T, const llvm::opt::ArgList &Args); @@ -283,7 +283,21 @@ public: const MultilibSet &getMultilibs() const { return Multilibs; } - const Multilib &getMultilib() const { return SelectedMultilib; } + const llvm::SmallVector &getSelectedMultilibs() const { + return SelectedMultilibs; + } + + /// Get flags suitable for multilib selection, based on the provided clang + /// command line arguments. The command line arguments aren't suitable to be + /// used directly for multilib selection because they are not normalized and + /// normalization is a complex process. The result of this function is similar + /// to clang command line arguments except that the list of arguments is + /// incomplete. Only certain command line arguments are processed. If more + /// command line arguments are needed for multilib selection then this + /// function should be extended. + /// To allow users to find out what flags are returned, clang accepts a + /// -print-multi-flags-experimental argument. + Multilib::flags_list getMultilibFlags(const llvm::opt::ArgList &) const; SanitizerArgs getSanitizerArgs(const llvm::opt::ArgList &JobArgs) const; @@ -398,7 +412,7 @@ public: /// IsIntegratedAssemblerDefault - Does this tool chain enable -integrated-as /// by default. - virtual bool IsIntegratedAssemblerDefault() const { return false; } + virtual bool IsIntegratedAssemblerDefault() const { return true; } /// IsIntegratedBackendDefault - Does this tool chain enable /// -fintegrated-objemitter by default. @@ -492,9 +506,9 @@ public: // Returns target specific standard library paths. path_list getStdlibPaths() const; - // Returns /lib//. This is used by runtimes (such - // as OpenMP) to find arch-specific libraries. - std::string getArchSpecificLibPath() const; + // Returns /lib// or /lib/. + // This is used by runtimes (such as OpenMP) to find arch-specific libraries. + virtual path_list getArchSpecificLibPaths() const; // Returns part of above. virtual StringRef getOSLibName() const; @@ -534,8 +548,8 @@ public: virtual void CheckObjCARC() const {} /// Get the default debug info format. Typically, this is DWARF. - virtual codegenoptions::DebugInfoFormat getDefaultDebugFormat() const { - return codegenoptions::DIF_DWARF; + virtual llvm::codegenoptions::DebugInfoFormat getDefaultDebugFormat() const { + return llvm::codegenoptions::DIF_DWARF; } /// UseDwarfDebugFlags - Embed the compile options to clang into the Dwarf @@ -571,8 +585,9 @@ public: } /// Adjust debug information kind considering all passed options. - virtual void adjustDebugInfoKind(codegenoptions::DebugInfoKind &DebugInfoKind, - const llvm::opt::ArgList &Args) const {} + virtual void + adjustDebugInfoKind(llvm::codegenoptions::DebugInfoKind &DebugInfoKind, + const llvm::opt::ArgList &Args) const {} /// GetExceptionModel - Return the tool chain exception model. virtual llvm::ExceptionHandling diff --git a/contrib/llvm-project/clang/include/clang/Driver/Types.def b/contrib/llvm-project/clang/include/clang/Driver/Types.def index 2960f0ba5e9..aaea3ec0f9c 100644 --- a/contrib/llvm-project/clang/include/clang/Driver/Types.def +++ b/contrib/llvm-project/clang/include/clang/Driver/Types.def @@ -107,4 +107,5 @@ TYPE("dependencies", Dependencies, INVALID, "d", phases TYPE("cuda-fatbin", CUDA_FATBIN, INVALID, "fatbin", phases::Compile, phases::Backend, phases::Assemble, phases::Link) TYPE("hip-fatbin", HIP_FATBIN, INVALID, "hipfb", phases::Compile, phases::Backend, phases::Assemble, phases::Link) TYPE("api-information", API_INFO, INVALID, "json", phases::Precompile) +TYPE("dx-container", DX_CONTAINER, INVALID, "dxo", phases::Compile, phases::Backend) TYPE("none", Nothing, INVALID, nullptr, phases::Compile, phases::Backend, phases::Assemble, phases::Link) diff --git a/contrib/llvm-project/clang/include/clang/Driver/XRayArgs.h b/contrib/llvm-project/clang/include/clang/Driver/XRayArgs.h index 6ed99a12766..bdd3d979547 100644 --- a/contrib/llvm-project/clang/include/clang/Driver/XRayArgs.h +++ b/contrib/llvm-project/clang/include/clang/Driver/XRayArgs.h @@ -25,15 +25,8 @@ class XRayArgs { std::vector ExtraDeps; std::vector Modes; XRayInstrSet InstrumentationBundle; - bool XRayInstrument = false; - int InstructionThreshold = 200; - bool XRayAlwaysEmitCustomEvents = false; - bool XRayAlwaysEmitTypedEvents = false; + llvm::opt::Arg *XRayInstrument = nullptr; bool XRayRT = true; - bool XRayIgnoreLoops = false; - bool XRayFunctionIndex; - int XRayFunctionGroups = 1; - int XRaySelectedFunctionGroup = 0; public: /// Parses the XRay arguments from an argument list. diff --git a/contrib/llvm-project/clang/include/clang/ExtractAPI/API.h b/contrib/llvm-project/clang/include/clang/ExtractAPI/API.h index f3c1cce3fe4..a18879f3964 100644 --- a/contrib/llvm-project/clang/include/clang/ExtractAPI/API.h +++ b/contrib/llvm-project/clang/include/clang/ExtractAPI/API.h @@ -26,9 +26,9 @@ #include "clang/ExtractAPI/DeclarationFragments.h" #include "llvm/ADT/MapVector.h" #include "llvm/ADT/StringRef.h" -#include "llvm/ADT/Triple.h" #include "llvm/Support/Allocator.h" #include "llvm/Support/Casting.h" +#include "llvm/TargetParser/Triple.h" #include #include diff --git a/contrib/llvm-project/clang/include/clang/ExtractAPI/APIIgnoresList.h b/contrib/llvm-project/clang/include/clang/ExtractAPI/APIIgnoresList.h index 43c546102a2..3eee8e336cb 100644 --- a/contrib/llvm-project/clang/include/clang/ExtractAPI/APIIgnoresList.h +++ b/contrib/llvm-project/clang/include/clang/ExtractAPI/APIIgnoresList.h @@ -7,7 +7,7 @@ //===----------------------------------------------------------------------===// /// /// \file This file defines APIIgnoresList which is a type that allows querying -/// a file containing symbols to ignore when extracting API information. +/// files containing symbols to ignore when extracting API information. /// //===----------------------------------------------------------------------===// @@ -44,11 +44,13 @@ struct IgnoresFileNotFound : public llvm::ErrorInfo { /// A type that provides access to a new line separated list of symbol names to /// ignore when extracting API information. struct APIIgnoresList { - /// The API to use for generating from the file at \p IgnoresFilePath. + using FilePathList = std::vector; + + /// The API to use for generating from the files at \p IgnoresFilePathList. /// /// \returns an initialized APIIgnoresList or an Error. - static llvm::Expected create(llvm::StringRef IgnoresFilePath, - FileManager &FM); + static llvm::Expected + create(const FilePathList &IgnoresFilePathList, FileManager &FM); APIIgnoresList() = default; @@ -58,14 +60,14 @@ struct APIIgnoresList { private: using SymbolNameList = llvm::SmallVector; + using BufferList = llvm::SmallVector>; - APIIgnoresList(SymbolNameList SymbolsToIgnore, - std::unique_ptr Buffer) - : SymbolsToIgnore(std::move(SymbolsToIgnore)), Buffer(std::move(Buffer)) { - } + APIIgnoresList(SymbolNameList SymbolsToIgnore, BufferList Buffers) + : SymbolsToIgnore(std::move(SymbolsToIgnore)), + Buffers(std::move(Buffers)) {} SymbolNameList SymbolsToIgnore; - std::unique_ptr Buffer; + BufferList Buffers; }; } // namespace extractapi diff --git a/contrib/llvm-project/clang/include/clang/ExtractAPI/AvailabilityInfo.h b/contrib/llvm-project/clang/include/clang/ExtractAPI/AvailabilityInfo.h index a258bc52c12..0af373135b6 100644 --- a/contrib/llvm-project/clang/include/clang/ExtractAPI/AvailabilityInfo.h +++ b/contrib/llvm-project/clang/include/clang/ExtractAPI/AvailabilityInfo.h @@ -33,12 +33,14 @@ struct AvailabilityInfo { VersionTuple Introduced; VersionTuple Deprecated; VersionTuple Obsoleted; + bool Unavailable; AvailabilityInfo() = default; AvailabilityInfo(StringRef Domain, VersionTuple I, VersionTuple D, - VersionTuple O) - : Domain(Domain), Introduced(I), Deprecated(D), Obsoleted(O) {} + VersionTuple O, bool U) + : Domain(Domain), Introduced(I), Deprecated(D), Obsoleted(O), + Unavailable(U) {} }; class AvailabilitySet { diff --git a/contrib/llvm-project/clang/include/clang/ExtractAPI/DeclarationFragments.h b/contrib/llvm-project/clang/include/clang/ExtractAPI/DeclarationFragments.h index a5db4d23e8b..82f0c42ab8a 100644 --- a/contrib/llvm-project/clang/include/clang/ExtractAPI/DeclarationFragments.h +++ b/contrib/llvm-project/clang/include/clang/ExtractAPI/DeclarationFragments.h @@ -97,8 +97,37 @@ public: Declaration(Declaration) {} }; + using FragmentIterator = std::vector::iterator; + using ConstFragmentIterator = std::vector::const_iterator; + const std::vector &getFragments() const { return Fragments; } + FragmentIterator begin() { return Fragments.begin(); } + + FragmentIterator end() { return Fragments.end(); } + + ConstFragmentIterator cbegin() const { return Fragments.cbegin(); } + + ConstFragmentIterator cend() const { return Fragments.cend(); } + + // Add a new Fragment at an arbitrary offset. + DeclarationFragments &insert(FragmentIterator It, StringRef Spelling, + FragmentKind Kind, + StringRef PreciseIdentifier = "", + const Decl *Declaration = nullptr) { + Fragments.insert(It, + Fragment(Spelling, Kind, PreciseIdentifier, Declaration)); + return *this; + } + + DeclarationFragments &insert(FragmentIterator It, + DeclarationFragments &&Other) { + Fragments.insert(It, std::make_move_iterator(Other.Fragments.begin()), + std::make_move_iterator(Other.Fragments.end())); + Other.Fragments.clear(); + return *this; + } + /// Append a new Fragment to the end of the Fragments. /// /// \returns a reference to the DeclarationFragments object itself after diff --git a/contrib/llvm-project/clang/include/clang/ExtractAPI/ExtractAPIActionBase.h b/contrib/llvm-project/clang/include/clang/ExtractAPI/ExtractAPIActionBase.h new file mode 100644 index 00000000000..ac4f391db5f --- /dev/null +++ b/contrib/llvm-project/clang/include/clang/ExtractAPI/ExtractAPIActionBase.h @@ -0,0 +1,54 @@ +//===- ExtractAPI/ExtractAPIActionBase.h -----------------------------*- C++ +//-*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +/// +/// \file +/// This file defines the ExtractAPIActionBase class. +/// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CLANG_EXTRACTAPI_ACTION_BASE_H +#define LLVM_CLANG_EXTRACTAPI_ACTION_BASE_H + +#include "clang/ExtractAPI/API.h" +#include "clang/ExtractAPI/APIIgnoresList.h" + +namespace clang { + +/// Base class to be used by front end actions to generate ExtarctAPI info +/// +/// Deriving from this class equips an action with all the necessary tools to +/// generate ExractAPI information in form of symbol-graphs +class ExtractAPIActionBase { +protected: + /// A representation of the APIs this action extracts. + std::unique_ptr API; + + /// A stream to the output file of this action. + std::unique_ptr OS; + + /// The product this action is extracting API information for. + std::string ProductName; + + /// The synthesized input buffer that contains all the provided input header + /// files. + std::unique_ptr Buffer; + + /// The list of symbols to ignore during serialization + extractapi::APIIgnoresList IgnoresList; + + /// Implements EndSourceFileAction for Symbol-Graph generation + /// + /// Use the serializer to generate output symbol graph files from + /// the information gathered during the execution of Action. + void ImplEndSourceFileAction(); +}; + +} // namespace clang + +#endif // LLVM_CLANG_EXTRACTAPI_ACTION_BASE_H diff --git a/contrib/llvm-project/clang/include/clang/ExtractAPI/ExtractAPIVisitor.h b/contrib/llvm-project/clang/include/clang/ExtractAPI/ExtractAPIVisitor.h index f6546fb4776..f0882afb5a6 100644 --- a/contrib/llvm-project/clang/include/clang/ExtractAPI/ExtractAPIVisitor.h +++ b/contrib/llvm-project/clang/include/clang/ExtractAPI/ExtractAPIVisitor.h @@ -14,24 +14,28 @@ #ifndef LLVM_CLANG_EXTRACTAPI_EXTRACT_API_VISITOR_H #define LLVM_CLANG_EXTRACTAPI_EXTRACT_API_VISITOR_H +#include "llvm/ADT/FunctionExtras.h" + +#include "clang/AST/ASTContext.h" +#include "clang/AST/ParentMapContext.h" #include "clang/AST/RecursiveASTVisitor.h" #include "clang/Basic/SourceManager.h" #include "clang/ExtractAPI/API.h" -#include "llvm/ADT/FunctionExtras.h" +#include "clang/ExtractAPI/TypedefUnderlyingTypeResolver.h" +#include "llvm/ADT/StringRef.h" +#include namespace clang { namespace extractapi { +namespace impl { + +template +class ExtractAPIVisitorBase : public RecursiveASTVisitor { +protected: + ExtractAPIVisitorBase(ASTContext &Context, APISet &API) + : Context(Context), API(API) {} -/// The RecursiveASTVisitor to traverse symbol declarations and collect API -/// information. -class ExtractAPIVisitor : public RecursiveASTVisitor { public: - ExtractAPIVisitor(ASTContext &Context, - llvm::unique_function LocationChecker, - APISet &API) - : Context(Context), API(API), - LocationChecker(std::move(LocationChecker)) {} - const APISet &getAPI() const { return API; } bool VisitVarDecl(const VarDecl *Decl); @@ -50,7 +54,11 @@ public: bool VisitObjCCategoryDecl(const ObjCCategoryDecl *Decl); -private: + bool shouldDeclBeIncluded(const Decl *Decl) const; + + const RawComment *fetchRawCommentForDecl(const Decl *Decl) const; + +protected: /// Collect API information for the enum constants and associate with the /// parent enum. void recordEnumConstants(EnumRecord *EnumRecord, @@ -77,9 +85,616 @@ private: void recordObjCProtocols(ObjCContainerRecord *Container, ObjCInterfaceDecl::protocol_range Protocols); + ASTContext &Context; APISet &API; - llvm::unique_function LocationChecker; + + StringRef getTypedefName(const TagDecl *Decl) { + if (const auto *TypedefDecl = Decl->getTypedefNameForAnonDecl()) + return TypedefDecl->getName(); + + return {}; + } + + bool isInSystemHeader(const Decl *D) { + return Context.getSourceManager().isInSystemHeader(D->getLocation()); + } + +private: + Derived &getDerivedExtractAPIVisitor() { + return *static_cast(this); + } +}; + +template +static void modifyRecords(const T &Records, const StringRef &Name) { + for (const auto &Record : Records) { + if (Name == Record.second.get()->Name) { + auto &DeclFragment = Record.second->Declaration; + DeclFragment.insert(DeclFragment.begin(), " ", + DeclarationFragments::FragmentKind::Text); + DeclFragment.insert(DeclFragment.begin(), "typedef", + DeclarationFragments::FragmentKind::Keyword, "", + nullptr); + DeclFragment.insert(--DeclFragment.end(), " { ... } ", + DeclarationFragments::FragmentKind::Text); + DeclFragment.insert(--DeclFragment.end(), Name, + DeclarationFragments::FragmentKind::Identifier); + break; + } + } +} + +template +bool ExtractAPIVisitorBase::VisitVarDecl(const VarDecl *Decl) { + // skip function parameters. + if (isa(Decl)) + return true; + + // Skip non-global variables in records (struct/union/class). + if (Decl->getDeclContext()->isRecord()) + return true; + + // Skip local variables inside function or method. + if (!Decl->isDefinedOutsideFunctionOrMethod()) + return true; + + // If this is a template but not specialization or instantiation, skip. + if (Decl->getASTContext().getTemplateOrSpecializationInfo(Decl) && + Decl->getTemplateSpecializationKind() == TSK_Undeclared) + return true; + + if (!getDerivedExtractAPIVisitor().shouldDeclBeIncluded(Decl)) + return true; + + // Collect symbol information. + StringRef Name = Decl->getName(); + StringRef USR = API.recordUSR(Decl); + PresumedLoc Loc = + Context.getSourceManager().getPresumedLoc(Decl->getLocation()); + LinkageInfo Linkage = Decl->getLinkageAndVisibility(); + DocComment Comment; + if (auto *RawComment = + getDerivedExtractAPIVisitor().fetchRawCommentForDecl(Decl)) + Comment = RawComment->getFormattedLines(Context.getSourceManager(), + Context.getDiagnostics()); + + // Build declaration fragments and sub-heading for the variable. + DeclarationFragments Declaration = + DeclarationFragmentsBuilder::getFragmentsForVar(Decl); + DeclarationFragments SubHeading = + DeclarationFragmentsBuilder::getSubHeading(Decl); + + // Add the global variable record to the API set. + API.addGlobalVar(Name, USR, Loc, AvailabilitySet(Decl), Linkage, Comment, + Declaration, SubHeading, isInSystemHeader(Decl)); + return true; +} + +template +bool ExtractAPIVisitorBase::VisitFunctionDecl( + const FunctionDecl *Decl) { + if (const auto *Method = dyn_cast(Decl)) { + // Skip member function in class templates. + if (Method->getParent()->getDescribedClassTemplate() != nullptr) + return true; + + // Skip methods in records. + for (const auto &P : Context.getParents(*Method)) { + if (P.template get()) + return true; + } + + // Skip ConstructorDecl and DestructorDecl. + if (isa(Method) || isa(Method)) + return true; + } + + // Skip templated functions. + switch (Decl->getTemplatedKind()) { + case FunctionDecl::TK_NonTemplate: + case FunctionDecl::TK_DependentNonTemplate: + break; + case FunctionDecl::TK_MemberSpecialization: + case FunctionDecl::TK_FunctionTemplateSpecialization: + if (auto *TemplateInfo = Decl->getTemplateSpecializationInfo()) { + if (!TemplateInfo->isExplicitInstantiationOrSpecialization()) + return true; + } + break; + case FunctionDecl::TK_FunctionTemplate: + case FunctionDecl::TK_DependentFunctionTemplateSpecialization: + return true; + } + + if (!getDerivedExtractAPIVisitor().shouldDeclBeIncluded(Decl)) + return true; + + // Collect symbol information. + StringRef Name = Decl->getName(); + StringRef USR = API.recordUSR(Decl); + PresumedLoc Loc = + Context.getSourceManager().getPresumedLoc(Decl->getLocation()); + LinkageInfo Linkage = Decl->getLinkageAndVisibility(); + DocComment Comment; + if (auto *RawComment = + getDerivedExtractAPIVisitor().fetchRawCommentForDecl(Decl)) + Comment = RawComment->getFormattedLines(Context.getSourceManager(), + Context.getDiagnostics()); + + // Build declaration fragments, sub-heading, and signature of the function. + DeclarationFragments Declaration = + DeclarationFragmentsBuilder::getFragmentsForFunction(Decl); + DeclarationFragments SubHeading = + DeclarationFragmentsBuilder::getSubHeading(Decl); + FunctionSignature Signature = + DeclarationFragmentsBuilder::getFunctionSignature(Decl); + + // Add the function record to the API set. + API.addGlobalFunction(Name, USR, Loc, AvailabilitySet(Decl), Linkage, Comment, + Declaration, SubHeading, Signature, + isInSystemHeader(Decl)); + return true; +} + +template +bool ExtractAPIVisitorBase::VisitEnumDecl(const EnumDecl *Decl) { + if (!getDerivedExtractAPIVisitor().shouldDeclBeIncluded(Decl)) + return true; + + SmallString<128> QualifiedNameBuffer; + // Collect symbol information. + StringRef Name = Decl->getName(); + if (Name.empty()) + Name = getTypedefName(Decl); + if (Name.empty()) { + llvm::raw_svector_ostream OS(QualifiedNameBuffer); + Decl->printQualifiedName(OS); + Name = QualifiedNameBuffer.str(); + } + + StringRef USR = API.recordUSR(Decl); + PresumedLoc Loc = + Context.getSourceManager().getPresumedLoc(Decl->getLocation()); + DocComment Comment; + if (auto *RawComment = + getDerivedExtractAPIVisitor().fetchRawCommentForDecl(Decl)) + Comment = RawComment->getFormattedLines(Context.getSourceManager(), + Context.getDiagnostics()); + + // Build declaration fragments and sub-heading for the enum. + DeclarationFragments Declaration = + DeclarationFragmentsBuilder::getFragmentsForEnum(Decl); + DeclarationFragments SubHeading = + DeclarationFragmentsBuilder::getSubHeading(Decl); + + EnumRecord *EnumRecord = + API.addEnum(API.copyString(Name), USR, Loc, AvailabilitySet(Decl), + Comment, Declaration, SubHeading, isInSystemHeader(Decl)); + + // Now collect information about the enumerators in this enum. + getDerivedExtractAPIVisitor().recordEnumConstants(EnumRecord, + Decl->enumerators()); + + return true; +} + +template +bool ExtractAPIVisitorBase::VisitRecordDecl(const RecordDecl *Decl) { + // Skip C++ structs/classes/unions + // TODO: support C++ records + if (isa(Decl)) + return true; + + if (!getDerivedExtractAPIVisitor().shouldDeclBeIncluded(Decl)) + return true; + + // Collect symbol information. + StringRef Name = Decl->getName(); + if (Name.empty()) + Name = getTypedefName(Decl); + if (Name.empty()) + return true; + + StringRef USR = API.recordUSR(Decl); + PresumedLoc Loc = + Context.getSourceManager().getPresumedLoc(Decl->getLocation()); + DocComment Comment; + if (auto *RawComment = + getDerivedExtractAPIVisitor().fetchRawCommentForDecl(Decl)) + Comment = RawComment->getFormattedLines(Context.getSourceManager(), + Context.getDiagnostics()); + + // Build declaration fragments and sub-heading for the struct. + DeclarationFragments Declaration = + DeclarationFragmentsBuilder::getFragmentsForStruct(Decl); + DeclarationFragments SubHeading = + DeclarationFragmentsBuilder::getSubHeading(Decl); + + StructRecord *StructRecord = + API.addStruct(Name, USR, Loc, AvailabilitySet(Decl), Comment, Declaration, + SubHeading, isInSystemHeader(Decl)); + + // Now collect information about the fields in this struct. + getDerivedExtractAPIVisitor().recordStructFields(StructRecord, + Decl->fields()); + + return true; +} + +template +bool ExtractAPIVisitorBase::VisitObjCInterfaceDecl( + const ObjCInterfaceDecl *Decl) { + if (!getDerivedExtractAPIVisitor().shouldDeclBeIncluded(Decl)) + return true; + + // Collect symbol information. + StringRef Name = Decl->getName(); + StringRef USR = API.recordUSR(Decl); + PresumedLoc Loc = + Context.getSourceManager().getPresumedLoc(Decl->getLocation()); + LinkageInfo Linkage = Decl->getLinkageAndVisibility(); + DocComment Comment; + if (auto *RawComment = + getDerivedExtractAPIVisitor().fetchRawCommentForDecl(Decl)) + Comment = RawComment->getFormattedLines(Context.getSourceManager(), + Context.getDiagnostics()); + + // Build declaration fragments and sub-heading for the interface. + DeclarationFragments Declaration = + DeclarationFragmentsBuilder::getFragmentsForObjCInterface(Decl); + DeclarationFragments SubHeading = + DeclarationFragmentsBuilder::getSubHeading(Decl); + + // Collect super class information. + SymbolReference SuperClass; + if (const auto *SuperClassDecl = Decl->getSuperClass()) { + SuperClass.Name = SuperClassDecl->getObjCRuntimeNameAsString(); + SuperClass.USR = API.recordUSR(SuperClassDecl); + } + + ObjCInterfaceRecord *ObjCInterfaceRecord = API.addObjCInterface( + Name, USR, Loc, AvailabilitySet(Decl), Linkage, Comment, Declaration, + SubHeading, SuperClass, isInSystemHeader(Decl)); + + // Record all methods (selectors). This doesn't include automatically + // synthesized property methods. + getDerivedExtractAPIVisitor().recordObjCMethods(ObjCInterfaceRecord, + Decl->methods()); + getDerivedExtractAPIVisitor().recordObjCProperties(ObjCInterfaceRecord, + Decl->properties()); + getDerivedExtractAPIVisitor().recordObjCInstanceVariables(ObjCInterfaceRecord, + Decl->ivars()); + getDerivedExtractAPIVisitor().recordObjCProtocols(ObjCInterfaceRecord, + Decl->protocols()); + + return true; +} + +template +bool ExtractAPIVisitorBase::VisitObjCProtocolDecl( + const ObjCProtocolDecl *Decl) { + if (!getDerivedExtractAPIVisitor().shouldDeclBeIncluded(Decl)) + return true; + + // Collect symbol information. + StringRef Name = Decl->getName(); + StringRef USR = API.recordUSR(Decl); + PresumedLoc Loc = + Context.getSourceManager().getPresumedLoc(Decl->getLocation()); + DocComment Comment; + if (auto *RawComment = + getDerivedExtractAPIVisitor().fetchRawCommentForDecl(Decl)) + Comment = RawComment->getFormattedLines(Context.getSourceManager(), + Context.getDiagnostics()); + + // Build declaration fragments and sub-heading for the protocol. + DeclarationFragments Declaration = + DeclarationFragmentsBuilder::getFragmentsForObjCProtocol(Decl); + DeclarationFragments SubHeading = + DeclarationFragmentsBuilder::getSubHeading(Decl); + + ObjCProtocolRecord *ObjCProtocolRecord = + API.addObjCProtocol(Name, USR, Loc, AvailabilitySet(Decl), Comment, + Declaration, SubHeading, isInSystemHeader(Decl)); + + getDerivedExtractAPIVisitor().recordObjCMethods(ObjCProtocolRecord, + Decl->methods()); + getDerivedExtractAPIVisitor().recordObjCProperties(ObjCProtocolRecord, + Decl->properties()); + getDerivedExtractAPIVisitor().recordObjCProtocols(ObjCProtocolRecord, + Decl->protocols()); + + return true; +} + +template +bool ExtractAPIVisitorBase::VisitTypedefNameDecl( + const TypedefNameDecl *Decl) { + // Skip ObjC Type Parameter for now. + if (isa(Decl)) + return true; + + if (!Decl->isDefinedOutsideFunctionOrMethod()) + return true; + + if (!getDerivedExtractAPIVisitor().shouldDeclBeIncluded(Decl)) + return true; + + // Add the notion of typedef for tag type (struct or enum) of the same name. + if (const ElaboratedType *ET = + dyn_cast(Decl->getUnderlyingType())) { + if (const TagType *TagTy = dyn_cast(ET->desugar())) { + if (Decl->getName() == TagTy->getDecl()->getName()) { + if (TagTy->getDecl()->isStruct()) { + modifyRecords(API.getStructs(), Decl->getName()); + } + if (TagTy->getDecl()->isEnum()) { + modifyRecords(API.getEnums(), Decl->getName()); + } + } + } + } + + PresumedLoc Loc = + Context.getSourceManager().getPresumedLoc(Decl->getLocation()); + StringRef Name = Decl->getName(); + StringRef USR = API.recordUSR(Decl); + DocComment Comment; + if (auto *RawComment = + getDerivedExtractAPIVisitor().fetchRawCommentForDecl(Decl)) + Comment = RawComment->getFormattedLines(Context.getSourceManager(), + Context.getDiagnostics()); + + QualType Type = Decl->getUnderlyingType(); + SymbolReference SymRef = + TypedefUnderlyingTypeResolver(Context).getSymbolReferenceForType(Type, + API); + + API.addTypedef(Name, USR, Loc, AvailabilitySet(Decl), Comment, + DeclarationFragmentsBuilder::getFragmentsForTypedef(Decl), + DeclarationFragmentsBuilder::getSubHeading(Decl), SymRef, + isInSystemHeader(Decl)); + + return true; +} + +template +bool ExtractAPIVisitorBase::VisitObjCCategoryDecl( + const ObjCCategoryDecl *Decl) { + if (!getDerivedExtractAPIVisitor().shouldDeclBeIncluded(Decl)) + return true; + + StringRef Name = Decl->getName(); + StringRef USR = API.recordUSR(Decl); + PresumedLoc Loc = + Context.getSourceManager().getPresumedLoc(Decl->getLocation()); + DocComment Comment; + if (auto *RawComment = + getDerivedExtractAPIVisitor().fetchRawCommentForDecl(Decl)) + Comment = RawComment->getFormattedLines(Context.getSourceManager(), + Context.getDiagnostics()); + // Build declaration fragments and sub-heading for the category. + DeclarationFragments Declaration = + DeclarationFragmentsBuilder::getFragmentsForObjCCategory(Decl); + DeclarationFragments SubHeading = + DeclarationFragmentsBuilder::getSubHeading(Decl); + + const ObjCInterfaceDecl *InterfaceDecl = Decl->getClassInterface(); + SymbolReference Interface(InterfaceDecl->getName(), + API.recordUSR(InterfaceDecl)); + + ObjCCategoryRecord *ObjCCategoryRecord = API.addObjCCategory( + Name, USR, Loc, AvailabilitySet(Decl), Comment, Declaration, SubHeading, + Interface, isInSystemHeader(Decl)); + + getDerivedExtractAPIVisitor().recordObjCMethods(ObjCCategoryRecord, + Decl->methods()); + getDerivedExtractAPIVisitor().recordObjCProperties(ObjCCategoryRecord, + Decl->properties()); + getDerivedExtractAPIVisitor().recordObjCInstanceVariables(ObjCCategoryRecord, + Decl->ivars()); + getDerivedExtractAPIVisitor().recordObjCProtocols(ObjCCategoryRecord, + Decl->protocols()); + + return true; +} + +/// Collect API information for the enum constants and associate with the +/// parent enum. +template +void ExtractAPIVisitorBase::recordEnumConstants( + EnumRecord *EnumRecord, const EnumDecl::enumerator_range Constants) { + for (const auto *Constant : Constants) { + // Collect symbol information. + StringRef Name = Constant->getName(); + StringRef USR = API.recordUSR(Constant); + PresumedLoc Loc = + Context.getSourceManager().getPresumedLoc(Constant->getLocation()); + DocComment Comment; + if (auto *RawComment = + getDerivedExtractAPIVisitor().fetchRawCommentForDecl(Constant)) + Comment = RawComment->getFormattedLines(Context.getSourceManager(), + Context.getDiagnostics()); + + // Build declaration fragments and sub-heading for the enum constant. + DeclarationFragments Declaration = + DeclarationFragmentsBuilder::getFragmentsForEnumConstant(Constant); + DeclarationFragments SubHeading = + DeclarationFragmentsBuilder::getSubHeading(Constant); + + API.addEnumConstant(EnumRecord, Name, USR, Loc, AvailabilitySet(Constant), + Comment, Declaration, SubHeading, + isInSystemHeader(Constant)); + } +} + +/// Collect API information for the struct fields and associate with the +/// parent struct. +template +void ExtractAPIVisitorBase::recordStructFields( + StructRecord *StructRecord, const RecordDecl::field_range Fields) { + for (const auto *Field : Fields) { + // Collect symbol information. + StringRef Name = Field->getName(); + StringRef USR = API.recordUSR(Field); + PresumedLoc Loc = + Context.getSourceManager().getPresumedLoc(Field->getLocation()); + DocComment Comment; + if (auto *RawComment = + getDerivedExtractAPIVisitor().fetchRawCommentForDecl(Field)) + Comment = RawComment->getFormattedLines(Context.getSourceManager(), + Context.getDiagnostics()); + + // Build declaration fragments and sub-heading for the struct field. + DeclarationFragments Declaration = + DeclarationFragmentsBuilder::getFragmentsForField(Field); + DeclarationFragments SubHeading = + DeclarationFragmentsBuilder::getSubHeading(Field); + + API.addStructField(StructRecord, Name, USR, Loc, AvailabilitySet(Field), + Comment, Declaration, SubHeading, + isInSystemHeader(Field)); + } +} + +/// Collect API information for the Objective-C methods and associate with the +/// parent container. +template +void ExtractAPIVisitorBase::recordObjCMethods( + ObjCContainerRecord *Container, + const ObjCContainerDecl::method_range Methods) { + for (const auto *Method : Methods) { + // Don't record selectors for properties. + if (Method->isPropertyAccessor()) + continue; + + StringRef Name = API.copyString(Method->getSelector().getAsString()); + StringRef USR = API.recordUSR(Method); + PresumedLoc Loc = + Context.getSourceManager().getPresumedLoc(Method->getLocation()); + DocComment Comment; + if (auto *RawComment = + getDerivedExtractAPIVisitor().fetchRawCommentForDecl(Method)) + Comment = RawComment->getFormattedLines(Context.getSourceManager(), + Context.getDiagnostics()); + + // Build declaration fragments, sub-heading, and signature for the method. + DeclarationFragments Declaration = + DeclarationFragmentsBuilder::getFragmentsForObjCMethod(Method); + DeclarationFragments SubHeading = + DeclarationFragmentsBuilder::getSubHeading(Method); + FunctionSignature Signature = + DeclarationFragmentsBuilder::getFunctionSignature(Method); + + API.addObjCMethod(Container, Name, USR, Loc, AvailabilitySet(Method), + Comment, Declaration, SubHeading, Signature, + Method->isInstanceMethod(), isInSystemHeader(Method)); + } +} + +template +void ExtractAPIVisitorBase::recordObjCProperties( + ObjCContainerRecord *Container, + const ObjCContainerDecl::prop_range Properties) { + for (const auto *Property : Properties) { + StringRef Name = Property->getName(); + StringRef USR = API.recordUSR(Property); + PresumedLoc Loc = + Context.getSourceManager().getPresumedLoc(Property->getLocation()); + DocComment Comment; + if (auto *RawComment = + getDerivedExtractAPIVisitor().fetchRawCommentForDecl(Property)) + Comment = RawComment->getFormattedLines(Context.getSourceManager(), + Context.getDiagnostics()); + + // Build declaration fragments and sub-heading for the property. + DeclarationFragments Declaration = + DeclarationFragmentsBuilder::getFragmentsForObjCProperty(Property); + DeclarationFragments SubHeading = + DeclarationFragmentsBuilder::getSubHeading(Property); + + StringRef GetterName = + API.copyString(Property->getGetterName().getAsString()); + StringRef SetterName = + API.copyString(Property->getSetterName().getAsString()); + + // Get the attributes for property. + unsigned Attributes = ObjCPropertyRecord::NoAttr; + if (Property->getPropertyAttributes() & + ObjCPropertyAttribute::kind_readonly) + Attributes |= ObjCPropertyRecord::ReadOnly; + + API.addObjCProperty( + Container, Name, USR, Loc, AvailabilitySet(Property), Comment, + Declaration, SubHeading, + static_cast(Attributes), GetterName, + SetterName, Property->isOptional(), + !(Property->getPropertyAttributes() & + ObjCPropertyAttribute::kind_class), + isInSystemHeader(Property)); + } +} + +template +void ExtractAPIVisitorBase::recordObjCInstanceVariables( + ObjCContainerRecord *Container, + const llvm::iterator_range< + DeclContext::specific_decl_iterator> + Ivars) { + for (const auto *Ivar : Ivars) { + StringRef Name = Ivar->getName(); + StringRef USR = API.recordUSR(Ivar); + PresumedLoc Loc = + Context.getSourceManager().getPresumedLoc(Ivar->getLocation()); + DocComment Comment; + if (auto *RawComment = + getDerivedExtractAPIVisitor().fetchRawCommentForDecl(Ivar)) + Comment = RawComment->getFormattedLines(Context.getSourceManager(), + Context.getDiagnostics()); + + // Build declaration fragments and sub-heading for the instance variable. + DeclarationFragments Declaration = + DeclarationFragmentsBuilder::getFragmentsForField(Ivar); + DeclarationFragments SubHeading = + DeclarationFragmentsBuilder::getSubHeading(Ivar); + + ObjCInstanceVariableRecord::AccessControl Access = + Ivar->getCanonicalAccessControl(); + + API.addObjCInstanceVariable(Container, Name, USR, Loc, + AvailabilitySet(Ivar), Comment, Declaration, + SubHeading, Access, isInSystemHeader(Ivar)); + } +} + +template +void ExtractAPIVisitorBase::recordObjCProtocols( + ObjCContainerRecord *Container, + ObjCInterfaceDecl::protocol_range Protocols) { + for (const auto *Protocol : Protocols) + Container->Protocols.emplace_back(Protocol->getName(), + API.recordUSR(Protocol)); +} + +} // namespace impl + +/// The RecursiveASTVisitor to traverse symbol declarations and collect API +/// information. +template +class ExtractAPIVisitor + : public impl::ExtractAPIVisitorBase, ExtractAPIVisitor<>, Derived>> { + using Base = impl::ExtractAPIVisitorBase, ExtractAPIVisitor<>, Derived>>; + +public: + ExtractAPIVisitor(ASTContext &Context, APISet &API) : Base(Context, API) {} + + bool shouldDeclBeIncluded(const Decl *D) const { return true; } + const RawComment *fetchRawCommentForDecl(const Decl *D) const { + return this->Context.getRawCommentForDeclNoCache(D); + } }; } // namespace extractapi diff --git a/contrib/llvm-project/clang/include/clang/ExtractAPI/FrontendActions.h b/contrib/llvm-project/clang/include/clang/ExtractAPI/FrontendActions.h index e946b33abbd..c67864aac9a 100644 --- a/contrib/llvm-project/clang/include/clang/ExtractAPI/FrontendActions.h +++ b/contrib/llvm-project/clang/include/clang/ExtractAPI/FrontendActions.h @@ -7,41 +7,27 @@ //===----------------------------------------------------------------------===// /// /// \file -/// This file defines the ExtractAPIAction frontend action. +/// This file defines the ExtractAPIAction and WrappingExtractAPIAction frontend +/// actions. /// //===----------------------------------------------------------------------===// #ifndef LLVM_CLANG_EXTRACTAPI_FRONTEND_ACTIONS_H #define LLVM_CLANG_EXTRACTAPI_FRONTEND_ACTIONS_H -#include "clang/ExtractAPI/API.h" -#include "clang/ExtractAPI/APIIgnoresList.h" +#include "clang/ExtractAPI/ExtractAPIActionBase.h" #include "clang/Frontend/FrontendAction.h" namespace clang { /// ExtractAPIAction sets up the output file and creates the ExtractAPIVisitor. -class ExtractAPIAction : public ASTFrontendAction { +class ExtractAPIAction : public ASTFrontendAction, + private ExtractAPIActionBase { protected: std::unique_ptr CreateASTConsumer(CompilerInstance &CI, StringRef InFile) override; private: - /// A representation of the APIs this action extracts. - std::unique_ptr API; - - /// A stream to the output file of this action. - std::unique_ptr OS; - - /// The product this action is extracting API information for. - std::string ProductName; - - /// The synthesized input buffer that contains all the provided input header - /// files. - std::unique_ptr Buffer; - - /// The list of symbols to ignore during serialization - extractapi::APIIgnoresList IgnoresList; /// The input file originally provided on the command line. /// @@ -62,10 +48,46 @@ private: /// emit them in this callback. void EndSourceFileAction() override; + static StringRef getInputBufferName() { return ""; } + static std::unique_ptr CreateOutputFile(CompilerInstance &CI, StringRef InFile); +}; - static StringRef getInputBufferName() { return ""; } +/// Wrap ExtractAPIAction on top of a pre-existing action +/// +/// Used when the ExtractAPI action needs to be executed as a side effect of a +/// regular compilation job. Unlike ExtarctAPIAction, this is meant to be used +/// on regular source files ( .m , .c files) instead of header files +class WrappingExtractAPIAction : public WrapperFrontendAction, + private ExtractAPIActionBase { +public: + WrappingExtractAPIAction(std::unique_ptr WrappedAction) + : WrapperFrontendAction(std::move(WrappedAction)) {} + +protected: + /// Create ExtractAPI consumer multiplexed on another consumer. + /// + /// This allows us to execute ExtractAPI action while on top of + std::unique_ptr CreateASTConsumer(CompilerInstance &CI, + StringRef InFile) override; + +private: + /// Flag to check if the wrapper front end action's consumer is + /// craeted or not + bool CreatedASTConsumer = false; + + void EndSourceFile() override { FrontendAction::EndSourceFile(); } + + /// Called after executing the action on the synthesized input buffer. + /// + /// Executes both Wrapper and ExtractAPIBase end source file + /// actions. This is the place where all the gathered symbol graph + /// information is emited. + void EndSourceFileAction() override; + + static std::unique_ptr + CreateOutputFile(CompilerInstance &CI, StringRef InFile); }; } // namespace clang diff --git a/contrib/llvm-project/clang/include/clang/ExtractAPI/Serialization/SerializerBase.h b/contrib/llvm-project/clang/include/clang/ExtractAPI/Serialization/SerializerBase.h index d8aa826e3f4..006e92be295 100644 --- a/contrib/llvm-project/clang/include/clang/ExtractAPI/Serialization/SerializerBase.h +++ b/contrib/llvm-project/clang/include/clang/ExtractAPI/Serialization/SerializerBase.h @@ -7,7 +7,7 @@ //===----------------------------------------------------------------------===// /// /// \file -/// This file defines the ExtractAPI APISerializer interface. +/// This file defines the ExtractAPI APISetVisitor interface. /// //===----------------------------------------------------------------------===// @@ -15,47 +15,107 @@ #define LLVM_CLANG_EXTRACTAPI_SERIALIZATION_SERIALIZERBASE_H #include "clang/ExtractAPI/API.h" -#include "clang/ExtractAPI/APIIgnoresList.h" -#include "llvm/Support/raw_ostream.h" namespace clang { namespace extractapi { -/// Common options to customize the serializer output. -struct APISerializerOption { - /// Do not include unnecessary whitespaces to save space. - bool Compact; -}; - -/// The base interface of serializers for API information. -class APISerializer { +/// The base interface of visitors for API information. +template class APISetVisitor { public: - /// Serialize the API information to \p os. - virtual void serialize(raw_ostream &os) = 0; + void traverseAPISet() { + getDerived()->traverseGlobalVariableRecords(); + + getDerived()->traverseGlobalFunctionRecords(); + + getDerived()->traverseEnumRecords(); + + getDerived()->traverseStructRecords(); + + getDerived()->traverseObjCInterfaces(); + + getDerived()->traverseObjCProtocols(); + + getDerived()->traverseMacroDefinitionRecords(); + + getDerived()->traverseTypedefRecords(); + } + + void traverseGlobalFunctionRecords() { + for (const auto &GlobalFunction : API.getGlobalFunctions()) + getDerived()->visitGlobalFunctionRecord(*GlobalFunction.second); + } + + void traverseGlobalVariableRecords() { + for (const auto &GlobalVariable : API.getGlobalVariables()) + getDerived()->visitGlobalVariableRecord(*GlobalVariable.second); + } + + void traverseEnumRecords() { + for (const auto &Enum : API.getEnums()) + getDerived()->visitEnumRecord(*Enum.second); + } + + void traverseStructRecords() { + for (const auto &Struct : API.getStructs()) + getDerived()->visitStructRecord(*Struct.second); + } + + void traverseObjCInterfaces() { + for (const auto &Interface : API.getObjCInterfaces()) + getDerived()->visitObjCContainerRecord(*Interface.second); + } + + void traverseObjCProtocols() { + for (const auto &Protocol : API.getObjCProtocols()) + getDerived()->visitObjCContainerRecord(*Protocol.second); + } + + void traverseMacroDefinitionRecords() { + for (const auto &Macro : API.getMacros()) + getDerived()->visitMacroDefinitionRecord(*Macro.second); + } + + void traverseTypedefRecords() { + for (const auto &Typedef : API.getTypedefs()) + getDerived()->visitTypedefRecord(*Typedef.second); + } + + /// Visit a global function record. + void visitGlobalFunctionRecord(const GlobalFunctionRecord &Record){}; + + /// Visit a global variable record. + void visitGlobalVariableRecord(const GlobalVariableRecord &Record){}; + + /// Visit an enum record. + void visitEnumRecord(const EnumRecord &Record){}; + + /// Visit a struct record. + void visitStructRecord(const StructRecord &Record){}; + + /// Visit an Objective-C container record. + void visitObjCContainerRecord(const ObjCContainerRecord &Record){}; + + /// Visit a macro definition record. + void visitMacroDefinitionRecord(const MacroDefinitionRecord &Record){}; + + /// Visit a typedef record. + void visitTypedefRecord(const TypedefRecord &Record){}; protected: const APISet &API; - /// The list of symbols to ignore. - /// - /// Note: This should be consulted before emitting a symbol. - const APIIgnoresList &IgnoresList; - - APISerializerOption Options; - public: - APISerializer() = delete; - APISerializer(const APISerializer &) = delete; - APISerializer(APISerializer &&) = delete; - APISerializer &operator=(const APISerializer &) = delete; - APISerializer &operator=(APISerializer &&) = delete; + APISetVisitor() = delete; + APISetVisitor(const APISetVisitor &) = delete; + APISetVisitor(APISetVisitor &&) = delete; + APISetVisitor &operator=(const APISetVisitor &) = delete; + APISetVisitor &operator=(APISetVisitor &&) = delete; protected: - APISerializer(const APISet &API, const APIIgnoresList &IgnoresList, - APISerializerOption Options = {}) - : API(API), IgnoresList(IgnoresList), Options(Options) {} + APISetVisitor(const APISet &API) : API(API) {} + ~APISetVisitor() = default; - virtual ~APISerializer() = default; + Derived *getDerived() { return static_cast(this); }; }; } // namespace extractapi diff --git a/contrib/llvm-project/clang/include/clang/ExtractAPI/Serialization/SymbolGraphSerializer.h b/contrib/llvm-project/clang/include/clang/ExtractAPI/Serialization/SymbolGraphSerializer.h index 55c7bb32054..e77903f8ba0 100644 --- a/contrib/llvm-project/clang/include/clang/ExtractAPI/Serialization/SymbolGraphSerializer.h +++ b/contrib/llvm-project/clang/include/clang/ExtractAPI/Serialization/SymbolGraphSerializer.h @@ -9,8 +9,8 @@ /// \file /// This file defines the SymbolGraphSerializer class. /// -/// Implement an APISerializer for the Symbol Graph format for ExtractAPI. -/// See https://github.com/apple/swift-docc-symbolkit. +/// Implement an APISetVisitor to serialize the APISet into the Symbol Graph +/// format for ExtractAPI. See https://github.com/apple/swift-docc-symbolkit. /// //===----------------------------------------------------------------------===// @@ -31,14 +31,18 @@ namespace extractapi { using namespace llvm::json; -/// The serializer that organizes API information in the Symbol Graph format. +/// Common options to customize the visitor output. +struct SymbolGraphSerializerOption { + /// Do not include unnecessary whitespaces to save space. + bool Compact; +}; + +/// The visitor that organizes API information in the Symbol Graph format. /// /// The Symbol Graph format (https://github.com/apple/swift-docc-symbolkit) /// models an API set as a directed graph, where nodes are symbol declarations, /// and edges are relationships between the connected symbols. -class SymbolGraphSerializer : public APISerializer { - virtual void anchor(); - +class SymbolGraphSerializer : public APISetVisitor { /// A JSON array of formatted symbols in \c APISet. Array Symbols; @@ -48,7 +52,7 @@ class SymbolGraphSerializer : public APISerializer { /// The Symbol Graph format version used by this serializer. static const VersionTuple FormatVersion; - /// Indicates whether child symbols should be serialized. This is mainly + /// Indicates whether child symbols should be visited. This is mainly /// useful for \c serializeSingleSymbolSGF. bool ShouldRecurse; @@ -59,15 +63,14 @@ public: /// Symbol Graph. Object serialize(); - /// Implement the APISerializer::serialize interface. Wrap serialize(void) and - /// write out the serialized JSON object to \p os. - void serialize(raw_ostream &os) override; + /// Wrap serialize(void) and write out the serialized JSON object to \p os. + void serialize(raw_ostream &os); /// Serialize a single symbol SGF. This is primarily used for libclang. /// /// \returns an optional JSON Object representing the payload that libclang /// expects for providing symbol information for a single symbol. If this is - /// not a known symbol returns \c None. + /// not a known symbol returns \c std::nullopt. static std::optional serializeSingleSymbolSGF(StringRef USR, const APISet &API); @@ -136,35 +139,44 @@ private: void serializeRelationship(RelationshipKind Kind, SymbolReference Source, SymbolReference Target); - /// Serialize a global function record. - void serializeGlobalFunctionRecord(const GlobalFunctionRecord &Record); +protected: + /// The list of symbols to ignore. + /// + /// Note: This should be consulted before emitting a symbol. + const APIIgnoresList &IgnoresList; - /// Serialize a global variable record. - void serializeGlobalVariableRecord(const GlobalVariableRecord &Record); - - /// Serialize an enum record. - void serializeEnumRecord(const EnumRecord &Record); - - /// Serialize a struct record. - void serializeStructRecord(const StructRecord &Record); - - /// Serialize an Objective-C container record. - void serializeObjCContainerRecord(const ObjCContainerRecord &Record); - - /// Serialize a macro definition record. - void serializeMacroDefinitionRecord(const MacroDefinitionRecord &Record); - - /// Serialize a typedef record. - void serializeTypedefRecord(const TypedefRecord &Record); - - void serializeSingleRecord(const APIRecord *Record); + SymbolGraphSerializerOption Options; public: + /// Visit a global function record. + void visitGlobalFunctionRecord(const GlobalFunctionRecord &Record); + + /// Visit a global variable record. + void visitGlobalVariableRecord(const GlobalVariableRecord &Record); + + /// Visit an enum record. + void visitEnumRecord(const EnumRecord &Record); + + /// Visit a struct record. + void visitStructRecord(const StructRecord &Record); + + /// Visit an Objective-C container record. + void visitObjCContainerRecord(const ObjCContainerRecord &Record); + + /// Visit a macro definition record. + void visitMacroDefinitionRecord(const MacroDefinitionRecord &Record); + + /// Visit a typedef record. + void visitTypedefRecord(const TypedefRecord &Record); + + /// Serialize a single record. + void serializeSingleRecord(const APIRecord *Record); + SymbolGraphSerializer(const APISet &API, const APIIgnoresList &IgnoresList, - APISerializerOption Options = {}, + SymbolGraphSerializerOption Options = {}, bool ShouldRecurse = true) - : APISerializer(API, IgnoresList, Options), ShouldRecurse(ShouldRecurse) { - } + : APISetVisitor(API), ShouldRecurse(ShouldRecurse), + IgnoresList(IgnoresList), Options(Options) {} }; } // namespace extractapi diff --git a/contrib/llvm-project/clang/lib/ExtractAPI/TypedefUnderlyingTypeResolver.h b/contrib/llvm-project/clang/include/clang/ExtractAPI/TypedefUnderlyingTypeResolver.h similarity index 100% rename from contrib/llvm-project/clang/lib/ExtractAPI/TypedefUnderlyingTypeResolver.h rename to contrib/llvm-project/clang/include/clang/ExtractAPI/TypedefUnderlyingTypeResolver.h diff --git a/contrib/llvm-project/clang/include/clang/Format/Format.h b/contrib/llvm-project/clang/include/clang/Format/Format.h index 7a313460d88..8bcf6e6f58f 100755 --- a/contrib/llvm-project/clang/include/clang/Format/Format.h +++ b/contrib/llvm-project/clang/include/clang/Format/Format.h @@ -92,9 +92,10 @@ struct FormatStyle { /// ) /// \endcode /// - /// \warning - /// Note: This currently only applies to parentheses. - /// \endwarning + /// \note + /// This currently only applies to braced initializer lists (when + /// ``Cpp11BracedListStyle`` is ``true``) and parentheses. + /// \endnote BAS_BlockIndent, }; @@ -133,8 +134,10 @@ struct FormatStyle { /// if not ``None``, when using initialization for an array of structs /// aligns the fields into columns. /// - /// NOTE: As of clang-format 15 this option only applied to arrays with equal - /// number of columns per row. + /// \note + /// As of clang-format 15 this option only applied to arrays with equal + /// number of columns per row. + /// \endnote /// /// \version 13 ArrayInitializerAlignmentStyle AlignArrayOfStructures; @@ -296,6 +299,103 @@ struct FormatStyle { /// \version 3.8 AlignConsecutiveStyle AlignConsecutiveDeclarations; + /// Alignment options. + /// + struct ShortCaseStatementsAlignmentStyle { + /// Whether aligning is enabled. + /// \code + /// true: + /// switch (level) { + /// case log::info: return "info:"; + /// case log::warning: return "warning:"; + /// default: return ""; + /// } + /// + /// false: + /// switch (level) { + /// case log::info: return "info:"; + /// case log::warning: return "warning:"; + /// default: return ""; + /// } + /// \endcode + bool Enabled; + /// Whether to align across empty lines. + /// \code + /// true: + /// switch (level) { + /// case log::info: return "info:"; + /// case log::warning: return "warning:"; + /// + /// default: return ""; + /// } + /// + /// false: + /// switch (level) { + /// case log::info: return "info:"; + /// case log::warning: return "warning:"; + /// + /// default: return ""; + /// } + /// \endcode + bool AcrossEmptyLines; + /// Whether to align across comments. + /// \code + /// true: + /// switch (level) { + /// case log::info: return "info:"; + /// case log::warning: return "warning:"; + /// /* A comment. */ + /// default: return ""; + /// } + /// + /// false: + /// switch (level) { + /// case log::info: return "info:"; + /// case log::warning: return "warning:"; + /// /* A comment. */ + /// default: return ""; + /// } + /// \endcode + bool AcrossComments; + /// Whether aligned case labels are aligned on the colon, or on the + /// , or on the tokens after the colon. + /// \code + /// true: + /// switch (level) { + /// case log::info : return "info:"; + /// case log::warning: return "warning:"; + /// default : return ""; + /// } + /// + /// false: + /// switch (level) { + /// case log::info: return "info:"; + /// case log::warning: return "warning:"; + /// default: return ""; + /// } + /// \endcode + bool AlignCaseColons; + bool operator==(const ShortCaseStatementsAlignmentStyle &R) const { + return Enabled == R.Enabled && AcrossEmptyLines == R.AcrossEmptyLines && + AcrossComments == R.AcrossComments && + AlignCaseColons == R.AlignCaseColons; + } + }; + + /// Style of aligning consecutive short case labels. + /// Only applies if ``AllowShortCaseLabelsOnASingleLine`` is ``true``. + /// + /// \code{.yaml} + /// # Example of usage: + /// AlignConsecutiveShortCaseStatements: + /// Enabled: true + /// AcrossEmptyLines: true + /// AcrossComments: true + /// AlignCaseColons: false + /// \endcode + /// \version 17 + ShortCaseStatementsAlignmentStyle AlignConsecutiveShortCaseStatements; + /// Different styles for aligning escaped newlines. enum EscapedNewlineAlignmentStyle : int8_t { /// Don't align escaped newlines. @@ -439,8 +539,10 @@ struct FormatStyle { /// Control of trailing comments. /// - /// NOTE: As of clang-format 16 this option is not a bool but can be set - /// to the options. Conventional bool options still can be parsed as before. + /// \note + /// As of clang-format 16 this option is not a bool but can be set + /// to the options. Conventional bool options still can be parsed as before. + /// \endnote /// /// \code{.yaml} /// # Example of usage: @@ -944,6 +1046,39 @@ struct FormatStyle { /// \version 12 BitFieldColonSpacingStyle BitFieldColonSpacing; + /// The number of columns to use to indent the contents of braced init lists. + /// If unset, ``ContinuationIndentWidth`` is used. + /// \code + /// AlignAfterOpenBracket: AlwaysBreak + /// BracedInitializerIndentWidth: 2 + /// + /// void f() { + /// SomeClass c{ + /// "foo", + /// "bar", + /// "baz", + /// }; + /// auto s = SomeStruct{ + /// .foo = "foo", + /// .bar = "bar", + /// .baz = "baz", + /// }; + /// SomeArrayT a[3] = { + /// { + /// foo, + /// bar, + /// }, + /// { + /// foo, + /// bar, + /// }, + /// SomeArrayT{}, + /// }; + /// } + /// \endcode + /// \version 17 + std::optional BracedInitializerIndentWidth; + /// Different ways to wrap braces after control statements. enum BraceWrappingAfterControlStatementStyle : int8_t { /// Never wrap braces after a control statement. @@ -1060,8 +1195,10 @@ struct FormatStyle { /// \endcode bool AfterNamespace; /// Wrap ObjC definitions (interfaces, implementations...). - /// \note @autoreleasepool and @synchronized blocks are wrapped - /// according to `AfterControlStatement` flag. + /// \note + /// @autoreleasepool and @synchronized blocks are wrapped + /// according to ``AfterControlStatement`` flag. + /// \endnote bool AfterObjCDeclaration; /// Wrap struct definitions. /// \code @@ -1170,9 +1307,10 @@ struct FormatStyle { bool IndentBraces; /// If ``false``, empty function body can be put on a single line. /// This option is used only if the opening brace of the function has - /// already been wrapped, i.e. the `AfterFunction` brace wrapping mode is + /// already been wrapped, i.e. the ``AfterFunction`` brace wrapping mode is /// set, and the function could/should not be put on a single line (as per - /// `AllowShortFunctionsOnASingleLine` and constructor formatting options). + /// ``AllowShortFunctionsOnASingleLine`` and constructor formatting + /// options). /// \code /// false: true: /// int f() vs. int f() @@ -1183,7 +1321,7 @@ struct FormatStyle { bool SplitEmptyFunction; /// If ``false``, empty record (e.g. class, struct or union) body /// can be put on a single line. This option is used only if the opening - /// brace of the record has already been wrapped, i.e. the `AfterClass` + /// brace of the record has already been wrapped, i.e. the ``AfterClass`` /// (for classes) brace wrapping mode is set. /// \code /// false: true: @@ -1195,7 +1333,7 @@ struct FormatStyle { bool SplitEmptyRecord; /// If ``false``, empty namespace body can be put on a single line. /// This option is used only if the opening brace of the namespace has - /// already been wrapped, i.e. the `AfterNamespace` brace wrapping mode is + /// already been wrapped, i.e. the ``AfterNamespace`` brace wrapping mode is /// set. /// \code /// false: true: @@ -1252,11 +1390,13 @@ struct FormatStyle { /// \version 16 AttributeBreakingStyle BreakAfterAttributes; - /// If ``true``, clang-format will always break after a Json array `[` - /// otherwise it will scan until the closing `]` to determine if it should add - /// newlines between elements (prettier compatible). + /// If ``true``, clang-format will always break after a Json array ``[`` + /// otherwise it will scan until the closing ``]`` to determine if it should + /// add newlines between elements (prettier compatible). /// - /// NOTE: This is currently only for formatting JSON. + /// \note + /// This is currently only for formatting JSON. + /// \endnote /// \code /// true: false: /// [ vs. [1, 2, 3, 4] @@ -1751,7 +1891,7 @@ struct FormatStyle { /// } // namespace N /// \endcode BS_WebKit, - /// Configure each individual brace in `BraceWrapping`. + /// Configure each individual brace in ``BraceWrapping``. BS_Custom }; @@ -1768,7 +1908,7 @@ struct FormatStyle { BBCDS_Never, /// Breaking between template declaration and ``concept`` is allowed. The /// actual behavior depends on the content and line breaking rules and - /// penalities. + /// penalties. BBCDS_Allowed, /// Always break before ``concept``, putting it in the line after the /// template declaration. @@ -2146,8 +2286,10 @@ struct FormatStyle { /// made, clang-format analyzes whether there are other bin-packed cases in /// the input file and act accordingly. /// - /// NOTE: This is an experimental flag, that might go away or be renamed. Do - /// not use this in config files, etc. Use at your own risk. + /// \note + /// This is an experimental flag, that might go away or be renamed. Do + /// not use this in config files, etc. Use at your own risk. + /// \endnote /// \version 3.7 bool ExperimentalAutoDetectBinPacking; @@ -2423,9 +2565,9 @@ struct FormatStyle { /// and ``while``) in C++ unless the control statements are inside macro /// definitions or the braces would enclose preprocessor directives. /// \warning - /// Setting this option to `true` could lead to incorrect code formatting due - /// to clang-format's lack of complete semantic information. As such, extra - /// care should be taken to review code changes made by this option. + /// Setting this option to ``true`` could lead to incorrect code formatting + /// due to clang-format's lack of complete semantic information. As such, + /// extra care should be taken to review code changes made by this option. /// \endwarning /// \code /// false: true: @@ -2642,6 +2784,10 @@ struct FormatStyle { bool JavaScriptWrapImports; // clang-format on + /// Keep empty lines (up to ``MaxEmptyLinesToKeep``) at end of file. + /// \version 17 + bool KeepEmptyLinesAtEOF; + /// If true, the empty line at the start of blocks is kept. /// \code /// true: false: @@ -2670,6 +2816,11 @@ struct FormatStyle { /// [](SomeReallyLongLambdaSignatureArgument foo) { /// return; /// }); + /// + /// someMethod(someOtherMethod( + /// [](SomeReallyLongLambdaSignatureArgument foo) { + /// return; + /// })); /// \endcode LBI_OuterScope, }; @@ -2678,11 +2829,7 @@ struct FormatStyle { /// causes the lambda body to be indented one additional level relative to /// the indentation level of the signature. ``OuterScope`` forces the lambda /// body to be indented one additional level relative to the parent scope - /// containing the lambda signature. For callback-heavy code, it may improve - /// readability to have the signature indented two levels and to use - /// ``OuterScope``. The KJ style guide requires ``OuterScope``. - /// `KJ style guide - /// `_ + /// containing the lambda signature. /// \version 13 LambdaBodyIndentationKind LambdaBodyIndentation; @@ -2779,6 +2926,46 @@ struct FormatStyle { /// \version 3.7 std::string MacroBlockEnd; + /// A list of macros of the form \c = . + /// + /// Code will be parsed with macros expanded, in order to determine how to + /// interpret and format the macro arguments. + /// + /// For example, the code: + /// \code + /// A(a*b); + /// \endcode + /// + /// will usually be interpreted as a call to a function A, and the + /// multiplication expression will be formatted as ``a * b``. + /// + /// If we specify the macro definition: + /// \code{.yaml} + /// Macros: + /// - A(x)=x + /// \endcode + /// + /// the code will now be parsed as a declaration of the variable b of type a*, + /// and formatted as ``a* b`` (depending on pointer-binding rules). + /// + /// Features and restrictions: + /// * Both function-like macros and object-like macros are supported. + /// * Macro arguments must be used exactly once in the expansion. + /// * No recursive expansion; macros referencing other macros will be + /// ignored. + /// * Overloading by arity is supported: for example, given the macro + /// definitions A=x, A()=y, A(a)=a + /// + /// \code + /// A; -> x; + /// A(); -> y; + /// A(z); -> z; + /// A(a, b); // will not be expanded. + /// \endcode + /// + /// \version 17.0 + std::vector Macros; + /// The maximum number of consecutive empty lines to keep. /// \code /// MaxEmptyLinesToKeep: 1 vs. MaxEmptyLinesToKeep: 0 @@ -2963,6 +3150,21 @@ struct FormatStyle { /// cccccccccccccccccccc() /// \endcode PCIS_NextLine, + /// Put all constructor initializers on the next line if they fit. + /// Otherwise, put each one on its own line. + /// \code + /// Constructor() + /// : a(), b() + /// + /// Constructor() + /// : aaaaaaaaaaaaaaaaaaaa(), bbbbbbbbbbbbbbbbbbbb(), ddddddddddddd() + /// + /// Constructor() + /// : aaaaaaaaaaaaaaaaaaaa(), + /// bbbbbbbbbbbbbbbbbbbb(), + /// cccccccccccccccccccc() + /// \endcode + PCIS_NextLineOnly, }; /// The pack constructor initializers style to use. @@ -3085,7 +3287,7 @@ struct FormatStyle { /// Different ways to arrange specifiers and qualifiers (e.g. const/volatile). /// \warning - /// Setting ``QualifierAlignment`` to something other than `Leave`, COULD + /// Setting ``QualifierAlignment`` to something other than ``Leave``, COULD /// lead to incorrect code formatting due to incorrect decisions made due to /// clang-formats lack of complete semantic information. /// As such extra care should be taken to review code changes made by the use @@ -3106,10 +3308,13 @@ struct FormatStyle { /// * restrict /// * type /// - /// Note: it MUST contain 'type'. + /// \note + /// it MUST contain 'type'. + /// \endnote + /// /// Items to the left of 'type' will be placed to the left of the type and - /// aligned in the order supplied. Items to the right of 'type' will be placed - /// to the right of the type and aligned in the order supplied. + /// aligned in the order supplied. Items to the right of 'type' will be + /// placed to the right of the type and aligned in the order supplied. /// /// \code{.yaml} /// QualifierOrder: ['inline', 'static', 'type', 'const', 'volatile' ] @@ -3228,9 +3433,9 @@ struct FormatStyle { /// This option will be renamed and expanded to support other styles. /// \endwarning /// \warning - /// Setting this option to `true` could lead to incorrect code formatting due - /// to clang-format's lack of complete semantic information. As such, extra - /// care should be taken to review code changes made by this option. + /// Setting this option to ``true`` could lead to incorrect code formatting + /// due to clang-format's lack of complete semantic information. As such, + /// extra care should be taken to review code changes made by this option. /// \endwarning /// \code /// false: true: @@ -3276,11 +3481,47 @@ struct FormatStyle { /// \version 14 bool RemoveBracesLLVM; + /// Types of redundant parentheses to remove. + enum RemoveParenthesesStyle : int8_t { + /// Do not remove parentheses. + /// \code + /// class __declspec((dllimport)) X {}; + /// co_return (((0))); + /// return ((a + b) - ((c + d))); + /// \endcode + RPS_Leave, + /// Replace multiple parentheses with single parentheses. + /// \code + /// class __declspec(dllimport) X {}; + /// co_return (0); + /// return ((a + b) - (c + d)); + /// \endcode + RPS_MultipleParentheses, + /// Also remove parentheses enclosing the expression in a + /// ``return``/``co_return`` statement. + /// \code + /// class __declspec(dllimport) X {}; + /// co_return 0; + /// return (a + b) - (c + d); + /// \endcode + RPS_ReturnStatement, + }; + + /// Remove redundant parentheses. + /// \warning + /// Setting this option to any value other than ``Leave`` could lead to + /// incorrect code formatting due to clang-format's lack of complete semantic + /// information. As such, extra care should be taken to review code changes + /// made by this option. + /// \endwarning + /// \version 17 + RemoveParenthesesStyle RemoveParentheses; + /// Remove semicolons after the closing brace of a non-empty function. /// \warning - /// Setting this option to `true` could lead to incorrect code formatting due - /// to clang-format's lack of complete semantic information. As such, extra - /// care should be taken to review code changes made by this option. + /// Setting this option to ``true`` could lead to incorrect code formatting + /// due to clang-format's lack of complete semantic information. As such, + /// extra care should be taken to review code changes made by this option. /// \endwarning /// \code /// false: true: @@ -3386,7 +3627,7 @@ struct FormatStyle { /// } /// \endcode REI_OuterScope, - /// Align requires expression body relative to the `requires` keyword. + /// Align requires expression body relative to the ``requires`` keyword. /// \code /// template /// concept C = requires(T t) { @@ -3512,11 +3753,6 @@ struct FormatStyle { }; /// Controls if and how clang-format will sort ``#includes``. - /// If ``Never``, includes are never sorted. - /// If ``CaseInsensitive``, includes are sorted in an ASCIIbetical or case - /// insensitive fashion. - /// If ``CaseSensitive``, includes are sorted in an alphabetical or case - /// sensitive fashion. /// \version 3.8 SortIncludesOptions SortIncludes; @@ -3693,6 +3929,17 @@ struct FormatStyle { /// \version 7 bool SpaceBeforeInheritanceColon; + /// If ``true``, a space will be added before a JSON colon. For other + /// languages, e.g. JavaScript, use ``SpacesInContainerLiterals`` instead. + /// \code + /// true: false: + /// { { + /// "key" : "value" vs. "key": "value" + /// } } + /// \endcode + /// \version 17 + bool SpaceBeforeJsonColon; + /// Different ways to put a space before opening parentheses. enum SpaceBeforeParensStyle : int8_t { /// Never put a space before opening parentheses. @@ -3751,7 +3998,7 @@ struct FormatStyle { /// \endcode SBPO_Always, /// Configure each individual space before parentheses in - /// `SpaceBeforeParensOptions`. + /// ``SpaceBeforeParensOptions``. SBPO_Custom, }; @@ -3904,24 +4151,20 @@ struct FormatStyle { bool SpaceInEmptyBlock; /// If ``true``, spaces may be inserted into ``()``. - /// \code - /// true: false: - /// void f( ) { vs. void f() { - /// int x[] = {foo( ), bar( )}; int x[] = {foo(), bar()}; - /// if (true) { if (true) { - /// f( ); f(); - /// } } - /// } } - /// \endcode + /// This option is **deprecated**. See ``InEmptyParentheses`` of + /// ``SpacesInParensOptions``. /// \version 3.7 - bool SpaceInEmptyParentheses; + // bool SpaceInEmptyParentheses; /// The number of spaces before trailing line comments /// (``//`` - comments). /// - /// This does not affect trailing block comments (``/*`` - comments) as - /// those commonly have different usage patterns and a number of special - /// cases. + /// This does not affect trailing block comments (``/*`` - comments) as those + /// commonly have different usage patterns and a number of special cases. In + /// the case of Verilog, it doesn't affect a comment right after the opening + /// parenthesis in the port or parameter list in a module header, because it + /// is probably for the port on the following line instead of the parenthesis + /// it follows. /// \code /// SpacesBeforeTrailingComments: 3 /// void f() { @@ -3933,7 +4176,7 @@ struct FormatStyle { /// \version 3.7 unsigned SpacesBeforeTrailingComments; - /// Styles for adding spacing after ``<`` and before ``>` + /// Styles for adding spacing after ``<`` and before ``>`` /// in template argument lists. enum SpacesInAnglesStyle : int8_t { /// Remove spaces after ``<`` and before ``>``. @@ -3958,16 +4201,14 @@ struct FormatStyle { /// If ``true``, spaces will be inserted around if/for/switch/while /// conditions. - /// \code - /// true: false: - /// if ( a ) { ... } vs. if (a) { ... } - /// while ( i < 5 ) { ... } while (i < 5) { ... } - /// \endcode + /// This option is **deprecated**. See ``InConditionalStatements`` of + /// ``SpacesInParensOptions``. /// \version 10 - bool SpacesInConditionalStatement; + // bool SpacesInConditionalStatement; - /// If ``true``, spaces are inserted inside container literals (e.g. - /// ObjC and Javascript array and dict literals). + /// If ``true``, spaces are inserted inside container literals (e.g. ObjC and + /// Javascript array and dict literals). For JSON, use + /// ``SpaceBeforeJsonColon`` instead. /// \code{.js} /// true: false: /// var arr = [ 1, 2, 3 ]; vs. var arr = [1, 2, 3]; @@ -3977,12 +4218,10 @@ struct FormatStyle { bool SpacesInContainerLiterals; /// If ``true``, spaces may be inserted into C style casts. - /// \code - /// true: false: - /// x = ( int32 )y vs. x = (int32)y - /// \endcode + /// This option is **deprecated**. See ``InCStyleCasts`` of + /// ``SpacesInParensOptions``. /// \version 3.7 - bool SpacesInCStyleCastParentheses; + // bool SpacesInCStyleCastParentheses; /// Control of spaces within a single line comment. struct SpacesInLineComment { @@ -4026,13 +4265,112 @@ struct FormatStyle { /// \version 13 SpacesInLineComment SpacesInLineCommentPrefix; - /// If ``true``, spaces will be inserted after ``(`` and before ``)``. - /// \code - /// true: false: - /// t f( Deleted & ) & = delete; vs. t f(Deleted &) & = delete; - /// \endcode + /// Different ways to put a space before opening and closing parentheses. + enum SpacesInParensStyle : int8_t { + /// Never put a space in parentheses. + /// \code + /// void f() { + /// if(true) { + /// f(); + /// } + /// } + /// \endcode + SIPO_Never, + /// Configure each individual space in parentheses in + /// `SpacesInParensOptions`. + SIPO_Custom, + }; + + /// If ``true'', spaces will be inserted after ``(`` and before ``)``. + /// This option is **deprecated**. The previous behavior is preserved by using + /// ``SpacesInParens`` with ``Custom`` and by setting all + /// ``SpacesInParensOptions`` to ``true`` except for ``InCStyleCasts`` and + /// ``InEmptyParentheses``. /// \version 3.7 - bool SpacesInParentheses; + // bool SpacesInParentheses; + + /// Defines in which cases spaces will be inserted after ``(`` and before + /// ``)``. + /// \version 17 + SpacesInParensStyle SpacesInParens; + + /// Precise control over the spacing in parentheses. + /// \code + /// # Should be declared this way: + /// SpacesInParens: Custom + /// SpacesInParensOptions: + /// InConditionalStatements: true + /// Other: true + /// \endcode + struct SpacesInParensCustom { + /// Put a space in parentheses only inside conditional statements + /// (``for/if/while/switch...``). + /// \code + /// true: false: + /// if ( a ) { ... } vs. if (a) { ... } + /// while ( i < 5 ) { ... } while (i < 5) { ... } + /// \endcode + bool InConditionalStatements; + /// Put a space in C style casts. + /// \code + /// true: false: + /// x = ( int32 )y vs. x = (int32)y + /// \endcode + bool InCStyleCasts; + /// Put a space in parentheses only if the parentheses are empty i.e. '()' + /// \code + /// true: false: + /// void f( ) { vs. void f() { + /// int x[] = {foo( ), bar( )}; int x[] = {foo(), bar()}; + /// if (true) { if (true) { + /// f( ); f(); + /// } } + /// } } + /// \endcode + bool InEmptyParentheses; + /// Put a space in parentheses not covered by preceding options. + /// \code + /// true: false: + /// t f( Deleted & ) & = delete; vs. t f(Deleted &) & = delete; + /// \endcode + bool Other; + + SpacesInParensCustom() + : InConditionalStatements(false), InCStyleCasts(false), + InEmptyParentheses(false), Other(false) {} + + SpacesInParensCustom(bool InConditionalStatements, bool InCStyleCasts, + bool InEmptyParentheses, bool Other) + : InConditionalStatements(InConditionalStatements), + InCStyleCasts(InCStyleCasts), + InEmptyParentheses(InEmptyParentheses), + Other(Other) {} + + bool operator==(const SpacesInParensCustom &R) const { + return InConditionalStatements == R.InConditionalStatements && + InCStyleCasts == R.InCStyleCasts && + InEmptyParentheses == R.InEmptyParentheses && + Other == R.Other; + } + bool operator!=(const SpacesInParensCustom &R) const { + return !(*this == R); + } + }; + + /// Control of individual spaces in parentheses. + /// + /// If ``SpacesInParens`` is set to ``Custom``, use this to specify + /// how each individual space in parentheses case should be handled. + /// Otherwise, this is ignored. + /// \code{.yaml} + /// # Example of usage: + /// SpacesInParens: Custom + /// SpacesInParensOptions: + /// InConditionalStatements: true + /// InEmptyParentheses: true + /// \endcode + /// \version 17 + SpacesInParensCustom SpacesInParensOptions; /// If ``true``, spaces will be inserted after ``[`` and before ``]``. /// Lambdas without arguments or unspecified size array declarations will not @@ -4112,6 +4450,16 @@ struct FormatStyle { /// \version 3.7 unsigned TabWidth; + /// A vector of non-keyword identifiers that should be interpreted as type + /// names. + /// + /// A ``*``, ``&``, or ``&&`` between a type name and another non-keyword + /// identifier is annotated as a pointer or reference token instead of a + /// binary operator. + /// + /// \version 17 + std::vector TypeNames; + /// \brief A vector of macros that should be interpreted as type declarations /// instead of as function calls. /// @@ -4154,6 +4502,20 @@ struct FormatStyle { /// \version 3.7 UseTabStyle UseTab; + /// For Verilog, put each port on its own line in module instantiations. + /// \code + /// true: + /// ffnand ff1(.q(), + /// .qbar(out1), + /// .clear(in1), + /// .preset(in2)); + /// + /// false: + /// ffnand ff1(.q(), .qbar(out1), .clear(in1), .preset(in2)); + /// \endcode + /// \version 17 + bool VerilogBreakBetweenInstancePorts; + /// A vector of macros which are whitespace-sensitive and should not /// be touched. /// @@ -4179,6 +4541,8 @@ struct FormatStyle { AlignConsecutiveBitFields == R.AlignConsecutiveBitFields && AlignConsecutiveDeclarations == R.AlignConsecutiveDeclarations && AlignConsecutiveMacros == R.AlignConsecutiveMacros && + AlignConsecutiveShortCaseStatements == + R.AlignConsecutiveShortCaseStatements && AlignEscapedNewlines == R.AlignEscapedNewlines && AlignOperands == R.AlignOperands && AlignTrailingComments == R.AlignTrailingComments && @@ -4204,6 +4568,7 @@ struct FormatStyle { BinPackArguments == R.BinPackArguments && BinPackParameters == R.BinPackParameters && BitFieldColonSpacing == R.BitFieldColonSpacing && + BracedInitializerIndentWidth == R.BracedInitializerIndentWidth && BreakAfterAttributes == R.BreakAfterAttributes && BreakAfterJavaFieldAnnotations == R.BreakAfterJavaFieldAnnotations && BreakArrays == R.BreakArrays && @@ -4250,12 +4615,13 @@ struct FormatStyle { JavaImportGroups == R.JavaImportGroups && JavaScriptQuotes == R.JavaScriptQuotes && JavaScriptWrapImports == R.JavaScriptWrapImports && + KeepEmptyLinesAtEOF == R.KeepEmptyLinesAtEOF && KeepEmptyLinesAtTheStartOfBlocks == R.KeepEmptyLinesAtTheStartOfBlocks && Language == R.Language && LambdaBodyIndentation == R.LambdaBodyIndentation && LineEnding == R.LineEnding && MacroBlockBegin == R.MacroBlockBegin && - MacroBlockEnd == R.MacroBlockEnd && + MacroBlockEnd == R.MacroBlockEnd && Macros == R.Macros && MaxEmptyLinesToKeep == R.MaxEmptyLinesToKeep && NamespaceIndentation == R.NamespaceIndentation && NamespaceMacros == R.NamespaceMacros && @@ -4283,6 +4649,7 @@ struct FormatStyle { RawStringFormats == R.RawStringFormats && ReferenceAlignment == R.ReferenceAlignment && RemoveBracesLLVM == R.RemoveBracesLLVM && + RemoveParentheses == R.RemoveParentheses && RemoveSemicolon == R.RemoveSemicolon && RequiresClausePosition == R.RequiresClausePosition && RequiresExpressionIndentation == R.RequiresExpressionIndentation && @@ -4299,6 +4666,7 @@ struct FormatStyle { SpaceBeforeCtorInitializerColon == R.SpaceBeforeCtorInitializerColon && SpaceBeforeInheritanceColon == R.SpaceBeforeInheritanceColon && + SpaceBeforeJsonColon == R.SpaceBeforeJsonColon && SpaceBeforeParens == R.SpaceBeforeParens && SpaceBeforeParensOptions == R.SpaceBeforeParensOptions && SpaceAroundPointerQualifiers == R.SpaceAroundPointerQualifiers && @@ -4306,22 +4674,23 @@ struct FormatStyle { R.SpaceBeforeRangeBasedForLoopColon && SpaceBeforeSquareBrackets == R.SpaceBeforeSquareBrackets && SpaceInEmptyBlock == R.SpaceInEmptyBlock && - SpaceInEmptyParentheses == R.SpaceInEmptyParentheses && SpacesBeforeTrailingComments == R.SpacesBeforeTrailingComments && SpacesInAngles == R.SpacesInAngles && - SpacesInConditionalStatement == R.SpacesInConditionalStatement && SpacesInContainerLiterals == R.SpacesInContainerLiterals && - SpacesInCStyleCastParentheses == R.SpacesInCStyleCastParentheses && SpacesInLineCommentPrefix.Minimum == R.SpacesInLineCommentPrefix.Minimum && SpacesInLineCommentPrefix.Maximum == R.SpacesInLineCommentPrefix.Maximum && - SpacesInParentheses == R.SpacesInParentheses && + SpacesInParens == R.SpacesInParens && + SpacesInParensOptions == R.SpacesInParensOptions && SpacesInSquareBrackets == R.SpacesInSquareBrackets && Standard == R.Standard && StatementAttributeLikeMacros == R.StatementAttributeLikeMacros && StatementMacros == R.StatementMacros && TabWidth == R.TabWidth && - TypenameMacros == R.TypenameMacros && UseTab == R.UseTab && + TypeNames == R.TypeNames && TypenameMacros == R.TypenameMacros && + UseTab == R.UseTab && + VerilogBreakBetweenInstancePorts == + R.VerilogBreakBetweenInstancePorts && WhitespaceSensitiveMacros == R.WhitespaceSensitiveMacros; } @@ -4464,7 +4833,7 @@ formatReplacements(StringRef Code, const tooling::Replacements &Replaces, /// - If a replacement has offset UINT_MAX, length 1, and a replacement text /// that is the name of the header to be removed, the header will be removed /// from \p Code if it exists. -/// The include manipulation is done via `tooling::HeaderInclude`, see its +/// The include manipulation is done via ``tooling::HeaderInclude``, see its /// documentation for more details on how include insertion points are found and /// what edits are produced. llvm::Expected @@ -4555,11 +4924,11 @@ LangOptions getFormattingLangOpts(const FormatStyle &Style = getLLVMStyle()); extern const char *StyleOptionHelpDescription; /// The suggested format style to use by default. This allows tools using -/// `getStyle` to have a consistent default style. +/// ``getStyle`` to have a consistent default style. /// Different builds can modify the value to the preferred styles. extern const char *DefaultFormatStyle; -/// The suggested predefined style to use as the fallback style in `getStyle`. +/// The suggested predefined style to use as the fallback style in ``getStyle``. /// Different builds can modify the value to the preferred styles. extern const char *DefaultFallbackStyle; @@ -4630,6 +4999,9 @@ inline StringRef getLanguageName(FormatStyle::LanguageKind Language) { } } +bool isClangFormatOn(StringRef Comment); +bool isClangFormatOff(StringRef Comment); + } // end namespace format } // end namespace clang diff --git a/contrib/llvm-project/clang/include/clang/Frontend/ASTUnit.h b/contrib/llvm-project/clang/include/clang/Frontend/ASTUnit.h index c7920289027..b762be1c9b1 100644 --- a/contrib/llvm-project/clang/include/clang/Frontend/ASTUnit.h +++ b/contrib/llvm-project/clang/include/clang/Frontend/ASTUnit.h @@ -119,11 +119,13 @@ private: std::shared_ptr PPOpts; IntrusiveRefCntPtr Reader; bool HadModuleLoaderFatalFailure = false; + bool StorePreamblesInMemory = false; struct ASTWriterData; std::unique_ptr WriterData; FileSystemOptions FileSystemOpts; + std::string PreambleStoragePath; /// The AST consumer that received information about the translation /// unit as it was parsed or loaded. @@ -641,7 +643,7 @@ public: bool visitLocalTopLevelDecls(void *context, DeclVisitorFn Fn); /// Get the PCH file if one was included. - const FileEntry *getPCHFile(); + OptionalFileEntryRef getPCHFile(); /// Returns true if the ASTUnit was constructed from a serialized /// module file. @@ -692,6 +694,7 @@ public: const PCHContainerReader &PCHContainerRdr, WhatToLoad ToLoad, IntrusiveRefCntPtr Diags, const FileSystemOptions &FileSystemOpts, + std::shared_ptr HSOpts, bool UseDebugInfo = false, bool OnlyLocalDecls = false, CaptureDiagsKind CaptureDiagnostics = CaptureDiagsKind::None, bool AllowASTWithCompilerErrors = false, @@ -802,6 +805,13 @@ public: /// /// \param ResourceFilesPath - The path to the compiler resource files. /// + /// \param StorePreamblesInMemory - Whether to store PCH in memory. If false, + /// PCH are stored in temporary files. + /// + /// \param PreambleStoragePath - The path to a directory, in which to create + /// temporary PCH files. If empty, the default system temporary directory is + /// used. This parameter is ignored if \p StorePreamblesInMemory is true. + /// /// \param ModuleFormat - If provided, uses the specific module format. /// /// \param ErrAST - If non-null and parsing failed without any AST to return @@ -816,11 +826,12 @@ public: /// // FIXME: Move OnlyLocalDecls, UseBumpAllocator to setters on the ASTUnit, we // shouldn't need to specify them at construction time. - static ASTUnit *LoadFromCommandLine( + static std::unique_ptr LoadFromCommandLine( const char **ArgBegin, const char **ArgEnd, std::shared_ptr PCHContainerOps, IntrusiveRefCntPtr Diags, StringRef ResourceFilesPath, - bool OnlyLocalDecls = false, + bool StorePreamblesInMemory = false, + StringRef PreambleStoragePath = StringRef(), bool OnlyLocalDecls = false, CaptureDiagsKind CaptureDiagnostics = CaptureDiagsKind::None, ArrayRef RemappedFiles = std::nullopt, bool RemappedFilesKeepOriginalName = true, diff --git a/contrib/llvm-project/clang/include/clang/Frontend/CompilerInstance.h b/contrib/llvm-project/clang/include/clang/Frontend/CompilerInstance.h index f132c961c8a..c6af1fd5dd0 100644 --- a/contrib/llvm-project/clang/include/clang/Frontend/CompilerInstance.h +++ b/contrib/llvm-project/clang/include/clang/Frontend/CompilerInstance.h @@ -12,6 +12,7 @@ #include "clang/AST/ASTConsumer.h" #include "clang/Basic/Diagnostic.h" #include "clang/Basic/SourceManager.h" +#include "clang/Basic/TargetInfo.h" #include "clang/Frontend/CompilerInvocation.h" #include "clang/Frontend/PCHContainerOperations.h" #include "clang/Frontend/Utils.h" @@ -233,6 +234,8 @@ public: return *Invocation; } + std::shared_ptr getInvocationPtr() { return Invocation; } + /// setInvocation - Replace the current invocation. void setInvocation(std::shared_ptr Value); @@ -338,6 +341,11 @@ public: return *Diagnostics; } + IntrusiveRefCntPtr getDiagnosticsPtr() const { + assert(Diagnostics && "Compiler instance has no diagnostics!"); + return Diagnostics; + } + /// setDiagnostics - Replace the current diagnostics engine. void setDiagnostics(DiagnosticsEngine *Value); @@ -373,6 +381,11 @@ public: return *Target; } + IntrusiveRefCntPtr getTargetPtr() const { + assert(Target && "Compiler instance has no target!"); + return Target; + } + /// Replace the current Target. void setTarget(TargetInfo *Value); @@ -406,6 +419,11 @@ public: return *FileMgr; } + IntrusiveRefCntPtr getFileManagerPtr() const { + assert(FileMgr && "Compiler instance has no file manager!"); + return FileMgr; + } + void resetAndLeakFileManager() { llvm::BuryPointer(FileMgr.get()); FileMgr.resetWithoutRelease(); @@ -426,6 +444,11 @@ public: return *SourceMgr; } + IntrusiveRefCntPtr getSourceManagerPtr() const { + assert(SourceMgr && "Compiler instance has no source manager!"); + return SourceMgr; + } + void resetAndLeakSourceManager() { llvm::BuryPointer(SourceMgr.get()); SourceMgr.resetWithoutRelease(); @@ -466,6 +489,11 @@ public: return *Context; } + IntrusiveRefCntPtr getASTContextPtr() const { + assert(Context && "Compiler instance has no AST context!"); + return Context; + } + void resetAndLeakASTContext() { llvm::BuryPointer(Context.get()); Context.resetWithoutRelease(); diff --git a/contrib/llvm-project/clang/include/clang/Frontend/CompilerInvocation.h b/contrib/llvm-project/clang/include/clang/Frontend/CompilerInvocation.h index 254f048ed3c..1dbd1eda62b 100644 --- a/contrib/llvm-project/clang/include/clang/Frontend/CompilerInvocation.h +++ b/contrib/llvm-project/clang/include/clang/Frontend/CompilerInvocation.h @@ -241,6 +241,17 @@ public: /// This is a (less-efficient) wrapper over generateCC1CommandLine(). std::vector getCC1CommandLine() const; + /// Check that \p Args can be parsed and re-serialized without change, + /// emiting diagnostics for any differences. + /// + /// This check is only suitable for command-lines that are expected to already + /// be canonical. + /// + /// \return false if there are any errors. + static bool checkCC1RoundTrip(ArrayRef Args, + DiagnosticsEngine &Diags, + const char *Argv0 = nullptr); + /// Reset all of the options that are not considered when building a /// module. void resetNonModularOptions(); diff --git a/contrib/llvm-project/clang/include/clang/Frontend/DependencyOutputOptions.h b/contrib/llvm-project/clang/include/clang/Frontend/DependencyOutputOptions.h index e0f445bb597..e4b26d92647 100644 --- a/contrib/llvm-project/clang/include/clang/Frontend/DependencyOutputOptions.h +++ b/contrib/llvm-project/clang/include/clang/Frontend/DependencyOutputOptions.h @@ -34,6 +34,8 @@ enum ExtraDepKind { class DependencyOutputOptions { public: unsigned IncludeSystemHeaders : 1; ///< Include system header dependencies. + unsigned + CanonicalSystemHeaders : 1; ///< canonicalize system header dependencies. unsigned ShowHeaderIncludes : 1; ///< Show header inclusions (-H). unsigned UsePhonyTargets : 1; ///< Include phony targets for each /// dependency, which can avoid some 'make' @@ -74,9 +76,6 @@ public: /// target. std::vector> ExtraDeps; - /// In /showIncludes mode, pretend the main TU is a header with this name. - std::string ShowIncludesPretendHeader; - /// The file to write GraphViz-formatted header dependencies to. std::string DOTOutputFile; @@ -85,10 +84,11 @@ public: public: DependencyOutputOptions() - : IncludeSystemHeaders(0), ShowHeaderIncludes(0), UsePhonyTargets(0), - AddMissingHeaderDeps(0), IncludeModuleFiles(0), - ShowSkippedHeaderIncludes(0), HeaderIncludeFormat(HIFMT_Textual), - HeaderIncludeFiltering(HIFIL_None) {} + : IncludeSystemHeaders(0), CanonicalSystemHeaders(0), + ShowHeaderIncludes(0), UsePhonyTargets(0), AddMissingHeaderDeps(0), + IncludeModuleFiles(0), ShowSkippedHeaderIncludes(0), + HeaderIncludeFormat(HIFMT_Textual), HeaderIncludeFiltering(HIFIL_None) { + } }; } // end namespace clang diff --git a/contrib/llvm-project/clang/include/clang/Frontend/FrontendActions.h b/contrib/llvm-project/clang/include/clang/Frontend/FrontendActions.h index 9e6ed1ace19..3940e00eeb8 100644 --- a/contrib/llvm-project/clang/include/clang/Frontend/FrontendActions.h +++ b/contrib/llvm-project/clang/include/clang/Frontend/FrontendActions.h @@ -177,9 +177,8 @@ public: /// Dump information about the given module file, to be used for /// basic debugging and discovery. class DumpModuleInfoAction : public ASTFrontendAction { -public: // Allow other tools (ex lldb) to direct output for their use. - llvm::raw_ostream *OutputStream = nullptr; + std::shared_ptr OutputStream; protected: std::unique_ptr CreateASTConsumer(CompilerInstance &CI, @@ -188,6 +187,9 @@ protected: void ExecuteAction() override; public: + DumpModuleInfoAction() = default; + explicit DumpModuleInfoAction(std::shared_ptr Out) + : OutputStream(Out) {} bool hasPCHSupport() const override { return false; } bool hasASTFileSupport() const override { return true; } bool hasIRSupport() const override { return false; } diff --git a/contrib/llvm-project/clang/include/clang/Frontend/FrontendOptions.h b/contrib/llvm-project/clang/include/clang/Frontend/FrontendOptions.h index 6efe3cdd580..3132c11705d 100644 --- a/contrib/llvm-project/clang/include/clang/Frontend/FrontendOptions.h +++ b/contrib/llvm-project/clang/include/clang/Frontend/FrontendOptions.h @@ -278,12 +278,11 @@ public: /// Show frontend performance metrics and statistics. unsigned ShowStats : 1; + unsigned AppendStats : 1; + /// print the supported cpus for the current target unsigned PrintSupportedCPUs : 1; - /// Output time trace profile. - unsigned TimeTrace : 1; - /// Show the -version text. unsigned ShowVersion : 1; @@ -453,8 +452,15 @@ public: std::string ProductName; // Currently this is only used as part of the `-extract-api` action. - /// The file providing a list of APIs to ignore when extracting documentation - std::string ExtractAPIIgnoresFile; + // A comma seperated list of files providing a list of APIs to + // ignore when extracting documentation. + std::vector ExtractAPIIgnoresFileList; + + // Currently this is only used as part of the `-emit-symbol-graph` + // action. + // Location of output directory where symbol graph information would + // be dumped + std::string SymbolGraphOutputDir; /// Args to pass to the plugins std::map> PluginArgs; @@ -510,7 +516,7 @@ public: public: FrontendOptions() : DisableFree(false), RelocatablePCH(false), ShowHelp(false), - ShowStats(false), TimeTrace(false), ShowVersion(false), + ShowStats(false), AppendStats(false), ShowVersion(false), FixWhatYouCan(false), FixOnlyWarnings(false), FixAndRecompile(false), FixToTemporaries(false), ARCMTMigrateEmitARCErrors(false), SkipFunctionBodies(false), UseGlobalModuleIndex(true), diff --git a/contrib/llvm-project/clang/include/clang/Frontend/LayoutOverrideSource.h b/contrib/llvm-project/clang/include/clang/Frontend/LayoutOverrideSource.h index ea1611470a7..c6e2d731118 100644 --- a/contrib/llvm-project/clang/include/clang/Frontend/LayoutOverrideSource.h +++ b/contrib/llvm-project/clang/include/clang/Frontend/LayoutOverrideSource.h @@ -30,6 +30,12 @@ namespace clang { /// The alignment of the record. uint64_t Align; + /// The offsets of non-virtual base classes in the record. + SmallVector BaseOffsets; + + /// The offsets of virtual base classes in the record. + SmallVector VBaseOffsets; + /// The offsets of the fields, in source order. SmallVector FieldOffsets; }; diff --git a/contrib/llvm-project/clang/include/clang/Frontend/PrecompiledPreamble.h b/contrib/llvm-project/clang/include/clang/Frontend/PrecompiledPreamble.h index db9f33ae596..798870bf24f 100644 --- a/contrib/llvm-project/clang/include/clang/Frontend/PrecompiledPreamble.h +++ b/contrib/llvm-project/clang/include/clang/Frontend/PrecompiledPreamble.h @@ -75,6 +75,10 @@ public: /// \param StoreInMemory Store PCH in memory. If false, PCH will be stored in /// a temporary file. /// + /// \param StoragePath The path to a directory, in which to create a temporary + /// file to store PCH in. If empty, the default system temporary directory is + /// used. This parameter is ignored if \p StoreInMemory is true. + /// /// \param Callbacks A set of callbacks to be executed when building /// the preamble. static llvm::ErrorOr @@ -83,7 +87,8 @@ public: DiagnosticsEngine &Diagnostics, IntrusiveRefCntPtr VFS, std::shared_ptr PCHContainerOps, - bool StoreInMemory, PreambleCallbacks &Callbacks); + bool StoreInMemory, StringRef StoragePath, + PreambleCallbacks &Callbacks); PrecompiledPreamble(PrecompiledPreamble &&); PrecompiledPreamble &operator=(PrecompiledPreamble &&); diff --git a/contrib/llvm-project/clang/include/clang/Frontend/TextDiagnostic.h b/contrib/llvm-project/clang/include/clang/Frontend/TextDiagnostic.h index a2eec46becc..7eb0ab0cdc9 100644 --- a/contrib/llvm-project/clang/include/clang/Frontend/TextDiagnostic.h +++ b/contrib/llvm-project/clang/include/clang/Frontend/TextDiagnostic.h @@ -103,7 +103,8 @@ private: SmallVectorImpl &Ranges, ArrayRef Hints); - void emitSnippet(StringRef SourceLine); + void emitSnippet(StringRef SourceLine, unsigned MaxLineNoDisplayWidth, + unsigned LineNo); void emitParseableFixits(ArrayRef Hints, const SourceManager &SM); }; diff --git a/contrib/llvm-project/clang/include/clang/Frontend/Utils.h b/contrib/llvm-project/clang/include/clang/Frontend/Utils.h index 143cf4359f0..8300e45d15f 100644 --- a/contrib/llvm-project/clang/include/clang/Frontend/Utils.h +++ b/contrib/llvm-project/clang/include/clang/Frontend/Utils.h @@ -41,6 +41,7 @@ class ExternalSemaSource; class FrontendOptions; class PCHContainerReader; class Preprocessor; +class FileManager; class PreprocessorOptions; class PreprocessorOutputOptions; @@ -79,11 +80,14 @@ public: /// Return true if system files should be passed to sawDependency(). virtual bool needSystemDependencies() { return false; } + /// Return true if system files should be canonicalized. + virtual bool shouldCanonicalizeSystemDependencies() { return false; } + /// Add a dependency \p Filename if it has not been seen before and /// sawDependency() returns true. virtual void maybeAddDependency(StringRef Filename, bool FromModule, bool IsSystem, bool IsModuleFile, - bool IsMissing); + FileManager *FileMgr, bool IsMissing); protected: /// Return true if the filename was added to the list of dependencies, false @@ -112,6 +116,10 @@ public: bool sawDependency(StringRef Filename, bool FromModule, bool IsSystem, bool IsModuleFile, bool IsMissing) final; + bool shouldCanonicalizeSystemDependencies() override { + return CanonicalSystemHeaders; + } + protected: void outputDependencyFile(llvm::raw_ostream &OS); @@ -121,6 +129,7 @@ private: std::string OutputFile; std::vector Targets; bool IncludeSystemHeaders; + bool CanonicalSystemHeaders; bool PhonyTarget; bool AddMissingHeaderDeps; bool SeenMissingHeader; diff --git a/contrib/llvm-project/clang/include/clang/Interpreter/Interpreter.h b/contrib/llvm-project/clang/include/clang/Interpreter/Interpreter.h index fd22af97661..43573fb1a4b 100644 --- a/contrib/llvm-project/clang/include/clang/Interpreter/Interpreter.h +++ b/contrib/llvm-project/clang/include/clang/Interpreter/Interpreter.h @@ -14,13 +14,15 @@ #ifndef LLVM_CLANG_INTERPRETER_INTERPRETER_H #define LLVM_CLANG_INTERPRETER_INTERPRETER_H -#include "clang/Interpreter/PartialTranslationUnit.h" - +#include "clang/AST/Decl.h" #include "clang/AST/GlobalDecl.h" +#include "clang/Interpreter/PartialTranslationUnit.h" +#include "clang/Interpreter/Value.h" +#include "llvm/ADT/DenseMap.h" #include "llvm/ExecutionEngine/JITSymbol.h" +#include "llvm/ExecutionEngine/Orc/Shared/ExecutorAddress.h" #include "llvm/Support/Error.h" - #include #include @@ -28,7 +30,7 @@ namespace llvm { namespace orc { class LLJIT; class ThreadSafeContext; -} +} // namespace orc } // namespace llvm namespace clang { @@ -40,8 +42,34 @@ class IncrementalParser; /// Create a pre-configured \c CompilerInstance for incremental processing. class IncrementalCompilerBuilder { public: + IncrementalCompilerBuilder() {} + + void SetCompilerArgs(const std::vector &Args) { + UserArgs = Args; + } + + // General C++ + llvm::Expected> CreateCpp(); + + // Offload options + void SetOffloadArch(llvm::StringRef Arch) { OffloadArch = Arch; }; + + // CUDA specific + void SetCudaSDK(llvm::StringRef path) { CudaSDKPath = path; }; + + llvm::Expected> CreateCudaHost(); + llvm::Expected> CreateCudaDevice(); + +private: static llvm::Expected> create(std::vector &ClangArgv); + + llvm::Expected> createCuda(bool device); + + std::vector UserArgs; + + llvm::StringRef OffloadArch; + llvm::StringRef CudaSDKPath; }; /// Provides top-level interfaces for incremental compilation and execution. @@ -50,41 +78,72 @@ class Interpreter { std::unique_ptr IncrParser; std::unique_ptr IncrExecutor; + // An optional parser for CUDA offloading + std::unique_ptr DeviceParser; + Interpreter(std::unique_ptr CI, llvm::Error &Err); + llvm::Error CreateExecutor(); + unsigned InitPTUSize = 0; + + // This member holds the last result of the value printing. It's a class + // member because we might want to access it after more inputs. If no value + // printing happens, it's in an invalid state. + Value LastValue; + public: ~Interpreter(); static llvm::Expected> create(std::unique_ptr CI); + static llvm::Expected> + createWithCUDA(std::unique_ptr CI, + std::unique_ptr DCI); + const ASTContext &getASTContext() const; + ASTContext &getASTContext(); const CompilerInstance *getCompilerInstance() const; - const llvm::orc::LLJIT *getExecutionEngine() const; + llvm::Expected getExecutionEngine(); + llvm::Expected Parse(llvm::StringRef Code); llvm::Error Execute(PartialTranslationUnit &T); - llvm::Error ParseAndExecute(llvm::StringRef Code) { - auto PTU = Parse(Code); - if (!PTU) - return PTU.takeError(); - if (PTU->TheModule) - return Execute(*PTU); - return llvm::Error::success(); - } + llvm::Error ParseAndExecute(llvm::StringRef Code, Value *V = nullptr); + llvm::Expected CompileDtorCall(CXXRecordDecl *CXXRD); /// Undo N previous incremental inputs. llvm::Error Undo(unsigned N = 1); - /// \returns the \c JITTargetAddress of a \c GlobalDecl. This interface uses + /// Link a dynamic library + llvm::Error LoadDynamicLibrary(const char *name); + + /// \returns the \c ExecutorAddr of a \c GlobalDecl. This interface uses /// the CodeGenModule's internal mangling cache to avoid recomputing the /// mangled name. - llvm::Expected getSymbolAddress(GlobalDecl GD) const; + llvm::Expected getSymbolAddress(GlobalDecl GD) const; - /// \returns the \c JITTargetAddress of a given name as written in the IR. - llvm::Expected + /// \returns the \c ExecutorAddr of a given name as written in the IR. + llvm::Expected getSymbolAddress(llvm::StringRef IRName) const; - /// \returns the \c JITTargetAddress of a given name as written in the object + /// \returns the \c ExecutorAddr of a given name as written in the object /// file. - llvm::Expected + llvm::Expected getSymbolAddressFromLinkerName(llvm::StringRef LinkerName) const; + + enum InterfaceKind { NoAlloc, WithAlloc, CopyArray }; + + const llvm::SmallVectorImpl &getValuePrintingInfo() const { + return ValuePrintingInfo; + } + + Expr *SynthesizeExpr(Expr *E); + +private: + size_t getEffectivePTUSize() const; + + bool FindRuntimeInterface(); + + llvm::DenseMap Dtors; + + llvm::SmallVector ValuePrintingInfo; }; } // namespace clang diff --git a/contrib/llvm-project/clang/include/clang/Interpreter/Value.h b/contrib/llvm-project/clang/include/clang/Interpreter/Value.h new file mode 100644 index 00000000000..c380cd91550 --- /dev/null +++ b/contrib/llvm-project/clang/include/clang/Interpreter/Value.h @@ -0,0 +1,208 @@ +//===--- Value.h - Definition of interpreter value --------------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +// +// Value is a lightweight struct that is used for carrying execution results in +// clang-repl. It's a special runtime that acts like a messager between compiled +// code and interpreted code. This makes it possible to exchange interesting +// information between the compiled & interpreted world. +// +// A typical usage is like the below: +// +// Value V; +// Interp.ParseAndExecute("int x = 42;"); +// Interp.ParseAndExecute("x", &V); +// V.getType(); // <-- Yields a clang::QualType. +// V.getInt(); // <-- Yields 42. +// +// The current design is still highly experimental and nobody should rely on the +// API being stable because we're hopefully going to make significant changes to +// it in the relatively near future. For example, Value also intends to be used +// as an exchange token for JIT support enabling remote execution on the embed +// devices where the JIT infrastructure cannot fit. To support that we will need +// to split the memory storage in a different place and perhaps add a resource +// header is similar to intrinsics headers which have stricter performance +// constraints. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CLANG_INTERPRETER_VALUE_H +#define LLVM_CLANG_INTERPRETER_VALUE_H + +#include "llvm/Support/Compiler.h" +#include + +// NOTE: Since the REPL itself could also include this runtime, extreme caution +// should be taken when MAKING CHANGES to this file, especially when INCLUDE NEW +// HEADERS, like , and etc. (That pulls a large number of +// tokens and will impact the runtime performance of the REPL) + +namespace llvm { +class raw_ostream; + +} // namespace llvm + +namespace clang { + +class ASTContext; +class Interpreter; +class QualType; + +#if defined(_WIN32) +// REPL_EXTERNAL_VISIBILITY are symbols that we need to be able to locate +// at runtime. On Windows, this requires them to be exported from any of the +// modules loaded at runtime. Marking them as dllexport achieves this; both +// for DLLs (that normally export symbols as part of their interface) and for +// EXEs (that normally don't export anything). +// For a build with libclang-cpp.dll, this doesn't make any difference - the +// functions would have been exported anyway. But for cases when these are +// statically linked into an EXE, it makes sure that they're exported. +#define REPL_EXTERNAL_VISIBILITY __declspec(dllexport) +#elif __has_attribute(visibility) +#if defined(LLVM_BUILD_LLVM_DYLIB) || defined(LLVM_BUILD_SHARED_LIBS) +#define REPL_EXTERNAL_VISIBILITY __attribute__((visibility("default"))) +#else +#define REPL_EXTERNAL_VISIBILITY +#endif +#else +#define REPL_EXTERNAL_VISIBILITY +#endif + +#define REPL_BUILTIN_TYPES \ + X(bool, Bool) \ + X(char, Char_S) \ + X(signed char, SChar) \ + X(unsigned char, UChar) \ + X(short, Short) \ + X(unsigned short, UShort) \ + X(int, Int) \ + X(unsigned int, UInt) \ + X(long, Long) \ + X(unsigned long, ULong) \ + X(long long, LongLong) \ + X(unsigned long long, ULongLong) \ + X(float, Float) \ + X(double, Double) \ + X(long double, LongDouble) + +class REPL_EXTERNAL_VISIBILITY Value { + union Storage { +#define X(type, name) type m_##name; + REPL_BUILTIN_TYPES +#undef X + void *m_Ptr; + }; + +public: + enum Kind { +#define X(type, name) K_##name, + REPL_BUILTIN_TYPES +#undef X + + K_Void, + K_PtrOrObj, + K_Unspecified + }; + + Value() = default; + Value(Interpreter *In, void *Ty); + Value(const Value &RHS); + Value(Value &&RHS) noexcept; + Value &operator=(const Value &RHS); + Value &operator=(Value &&RHS) noexcept; + ~Value(); + + void printType(llvm::raw_ostream &Out) const; + void printData(llvm::raw_ostream &Out) const; + void print(llvm::raw_ostream &Out) const; + void dump() const; + void clear(); + + ASTContext &getASTContext(); + const ASTContext &getASTContext() const; + Interpreter &getInterpreter(); + const Interpreter &getInterpreter() const; + QualType getType() const; + + bool isValid() const { return ValueKind != K_Unspecified; } + bool isVoid() const { return ValueKind == K_Void; } + bool hasValue() const { return isValid() && !isVoid(); } + bool isManuallyAlloc() const { return IsManuallyAlloc; } + Kind getKind() const { return ValueKind; } + void setKind(Kind K) { ValueKind = K; } + void setOpaqueType(void *Ty) { OpaqueType = Ty; } + + void *getPtr() const; + void setPtr(void *Ptr) { Data.m_Ptr = Ptr; } + +#define X(type, name) \ + void set##name(type Val) { Data.m_##name = Val; } \ + type get##name() const { return Data.m_##name; } + REPL_BUILTIN_TYPES +#undef X + + /// \brief Get the value with cast. + // + /// Get the value cast to T. This is similar to reinterpret_cast(value), + /// casting the value of builtins (except void), enums and pointers. + /// Values referencing an object are treated as pointers to the object. + template T convertTo() const { + return convertFwd::cast(*this); + } + +protected: + bool isPointerOrObjectType() const { return ValueKind == K_PtrOrObj; } + + /// \brief Get to the value with type checking casting the underlying + /// stored value to T. + template T as() const { + switch (ValueKind) { + default: + return T(); +#define X(type, name) \ + case Value::K_##name: \ + return (T)Data.m_##name; + REPL_BUILTIN_TYPES +#undef X + } + } + + // Allow convertTo to be partially specialized. + template struct convertFwd { + static T cast(const Value &V) { + if (V.isPointerOrObjectType()) + return (T)(uintptr_t)V.as(); + if (!V.isValid() || V.isVoid()) { + return T(); + } + return V.as(); + } + }; + + template struct convertFwd { + static T *cast(const Value &V) { + if (V.isPointerOrObjectType()) + return (T *)(uintptr_t)V.as(); + return nullptr; + } + }; + + Interpreter *Interp = nullptr; + void *OpaqueType = nullptr; + Storage Data; + Kind ValueKind = K_Unspecified; + bool IsManuallyAlloc = false; +}; + +template <> inline void *Value::as() const { + if (isPointerOrObjectType()) + return Data.m_Ptr; + return (void *)as(); +} + +} // namespace clang +#endif diff --git a/contrib/llvm-project/clang/include/clang/Lex/DependencyDirectivesScanner.h b/contrib/llvm-project/clang/include/clang/Lex/DependencyDirectivesScanner.h index 529b93aa0ff..0e115906fbf 100644 --- a/contrib/llvm-project/clang/include/clang/Lex/DependencyDirectivesScanner.h +++ b/contrib/llvm-project/clang/include/clang/Lex/DependencyDirectivesScanner.h @@ -68,6 +68,7 @@ enum DirectiveKind : uint8_t { pp_pragma_push_macro, pp_pragma_pop_macro, pp_pragma_include_alias, + pp_pragma_system_header, pp_include_next, pp_if, pp_ifdef, diff --git a/contrib/llvm-project/clang/include/clang/Lex/HeaderSearch.h b/contrib/llvm-project/clang/include/clang/Lex/HeaderSearch.h index 76e3e786ff0..1bd14283dc5 100644 --- a/contrib/llvm-project/clang/include/clang/Lex/HeaderSearch.h +++ b/contrib/llvm-project/clang/include/clang/Lex/HeaderSearch.h @@ -277,6 +277,9 @@ class HeaderSearch { /// Keeps track of each lookup performed by LookupFile. struct LookupFileCacheInfo { + // The requesting module for the lookup we cached. + const Module *RequestingModule = nullptr; + /// Starting search directory iterator that the cached search was performed /// from. If there is a hit and this value doesn't match the current query, /// the cache has to be ignored. @@ -292,7 +295,9 @@ class HeaderSearch { /// Default constructor -- Initialize all members with zero. LookupFileCacheInfo() = default; - void reset(ConstSearchDirIterator NewStartIt) { + void reset(const Module *NewRequestingModule, + ConstSearchDirIterator NewStartIt) { + RequestingModule = NewRequestingModule; StartIt = NewStartIt; MappedName = nullptr; } @@ -482,7 +487,7 @@ public: OptionalFileEntryRef LookupFile( StringRef Filename, SourceLocation IncludeLoc, bool isAngled, ConstSearchDirIterator FromDir, ConstSearchDirIterator *CurDir, - ArrayRef> Includers, + ArrayRef> Includers, SmallVectorImpl *SearchPath, SmallVectorImpl *RelativePath, Module *RequestingModule, ModuleMap::KnownHeader *SuggestedModule, bool *IsMapped, bool *IsFrameworkFound, bool SkipCache = false, @@ -553,10 +558,10 @@ public: /// macro. /// /// This routine does not consider the effect of \#import - bool isFileMultipleIncludeGuarded(const FileEntry *File); + bool isFileMultipleIncludeGuarded(const FileEntry *File) const; /// Determine whether the given file is known to have ever been \#imported. - bool hasFileBeenImported(const FileEntry *File) { + bool hasFileBeenImported(const FileEntry *File) const { const HeaderFileInfo *FI = getExistingFileInfo(File); return FI && FI->isImport; } @@ -637,9 +642,9 @@ public: bool AllowExtraModuleMapSearch = false); /// Try to find a module map file in the given directory, returning - /// \c nullptr if none is found. - const FileEntry *lookupModuleMapFile(const DirectoryEntry *Dir, - bool IsFramework); + /// \c nullopt if none is found. + OptionalFileEntryRef lookupModuleMapFile(DirectoryEntryRef Dir, + bool IsFramework); /// Determine whether there is a module map that may map the header /// with the given file name to a (sub)module. @@ -659,15 +664,23 @@ public: /// /// \param File The header that we wish to map to a module. /// \param AllowTextual Whether we want to find textual headers too. - ModuleMap::KnownHeader findModuleForHeader(const FileEntry *File, + ModuleMap::KnownHeader findModuleForHeader(FileEntryRef File, bool AllowTextual = false, bool AllowExcluded = false) const; /// Retrieve all the modules corresponding to the given file. /// + /// \param AllowCreation Whether to allow inference of a new submodule, or to + /// only return existing known modules. + /// /// \ref findModuleForHeader should typically be used instead of this. ArrayRef - findAllModulesForHeader(const FileEntry *File) const; + findAllModulesForHeader(FileEntryRef File) const; + + /// Like \ref findAllModulesForHeader, but do not attempt to infer module + /// ownership from umbrella headers if we've not already done so. + ArrayRef + findResolvedModulesForHeader(const FileEntry *File) const; /// Read the contents of the given module map file. /// @@ -682,8 +695,8 @@ public: /// used to resolve paths within the module (this is required when /// building the module from preprocessed source). /// \returns true if an error occurred, false otherwise. - bool loadModuleMapFile(const FileEntry *File, bool IsSystem, - FileID ID = FileID(), unsigned *Offset = nullptr, + bool loadModuleMapFile(FileEntryRef File, bool IsSystem, FileID ID = FileID(), + unsigned *Offset = nullptr, StringRef OriginalModuleMapFile = StringRef()); /// Collect the set of all known, top-level modules. @@ -752,8 +765,7 @@ private: /// /// \return \c true if the file can be used, \c false if we are not permitted to /// find this file due to requirements from \p RequestingModule. - bool findUsableModuleForHeader(const FileEntry *File, - const DirectoryEntry *Root, + bool findUsableModuleForHeader(FileEntryRef File, const DirectoryEntry *Root, Module *RequestingModule, ModuleMap::KnownHeader *SuggestedModule, bool IsSystemHeaderDir); @@ -764,7 +776,7 @@ private: /// \return \c true if the file can be used, \c false if we are not permitted to /// find this file due to requirements from \p RequestingModule. bool findUsableModuleForFrameworkHeader( - const FileEntry *File, StringRef FrameworkName, Module *RequestingModule, + FileEntryRef File, StringRef FrameworkName, Module *RequestingModule, ModuleMap::KnownHeader *SuggestedModule, bool IsSystemFramework); /// Look up the file with the specified name and determine its owning @@ -863,7 +875,7 @@ public: /// path is relative to a system header directory. std::string suggestPathToFileForDiagnostics(const FileEntry *File, llvm::StringRef MainFile, - bool *IsSystem = nullptr); + bool *IsSystem = nullptr) const; /// Suggest a path by which the specified file could be found, for use in /// diagnostics to suggest a #include. Returned path will only contain forward @@ -877,7 +889,7 @@ public: std::string suggestPathToFileForDiagnostics(llvm::StringRef File, llvm::StringRef WorkingDir, llvm::StringRef MainFile, - bool *IsSystem = nullptr); + bool *IsSystem = nullptr) const; void PrintStats(); @@ -900,8 +912,7 @@ private: LMM_InvalidModuleMap }; - LoadModuleMapResult loadModuleMapFileImpl(const FileEntry *File, - bool IsSystem, + LoadModuleMapResult loadModuleMapFileImpl(FileEntryRef File, bool IsSystem, DirectoryEntryRef Dir, FileID ID = FileID(), unsigned *Offset = nullptr); diff --git a/contrib/llvm-project/clang/include/clang/Lex/Lexer.h b/contrib/llvm-project/clang/include/clang/Lex/Lexer.h index 8c2923b0150..98d34b783f0 100644 --- a/contrib/llvm-project/clang/include/clang/Lex/Lexer.h +++ b/contrib/llvm-project/clang/include/clang/Lex/Lexer.h @@ -551,7 +551,7 @@ public: /// Finds the token that comes right after the given location. /// - /// Returns the next token, or none if the location is inside a macro. + /// Returns the next token, or std::nullopt if the location is inside a macro. static std::optional findNextToken(SourceLocation Loc, const SourceManager &SM, const LangOptions &LangOpts); diff --git a/contrib/llvm-project/clang/include/clang/Lex/LiteralSupport.h b/contrib/llvm-project/clang/include/clang/Lex/LiteralSupport.h index fd237c2c9cd..0a45f32326f 100644 --- a/contrib/llvm-project/clang/include/clang/Lex/LiteralSupport.h +++ b/contrib/llvm-project/clang/include/clang/Lex/LiteralSupport.h @@ -63,7 +63,7 @@ public: bool isUnsigned : 1; bool isLong : 1; // This is *not* set for long long. bool isLongLong : 1; - bool isSizeT : 1; // 1z, 1uz (C++2b) + bool isSizeT : 1; // 1z, 1uz (C++23) bool isHalf : 1; // 1.0h bool isFloat : 1; // 1.0f bool isImaginary : 1; // 1.0i @@ -212,6 +212,11 @@ public: } }; +enum class StringLiteralEvalMethod { + Evaluated, + Unevaluated, +}; + /// StringLiteralParser - This decodes string escape characters and performs /// wide string analysis and Translation Phase #6 (concatenation of string /// literals) (C99 5.1.1.2p1). @@ -230,20 +235,23 @@ class StringLiteralParser { SmallString<32> UDSuffixBuf; unsigned UDSuffixToken; unsigned UDSuffixOffset; + StringLiteralEvalMethod EvalMethod; + public: - StringLiteralParser(ArrayRef StringToks, - Preprocessor &PP); - StringLiteralParser(ArrayRef StringToks, - const SourceManager &sm, const LangOptions &features, - const TargetInfo &target, + StringLiteralParser(ArrayRef StringToks, Preprocessor &PP, + StringLiteralEvalMethod StringMethod = + StringLiteralEvalMethod::Evaluated); + StringLiteralParser(ArrayRef StringToks, const SourceManager &sm, + const LangOptions &features, const TargetInfo &target, DiagnosticsEngine *diags = nullptr) - : SM(sm), Features(features), Target(target), Diags(diags), - MaxTokenLength(0), SizeBound(0), CharByteWidth(0), Kind(tok::unknown), - ResultPtr(ResultBuf.data()), hadError(false), Pascal(false) { + : SM(sm), Features(features), Target(target), Diags(diags), + MaxTokenLength(0), SizeBound(0), CharByteWidth(0), Kind(tok::unknown), + ResultPtr(ResultBuf.data()), + EvalMethod(StringLiteralEvalMethod::Evaluated), hadError(false), + Pascal(false) { init(StringToks); } - bool hadError; bool Pascal; @@ -269,6 +277,9 @@ public: bool isUTF16() const { return Kind == tok::utf16_string_literal; } bool isUTF32() const { return Kind == tok::utf32_string_literal; } bool isPascal() const { return Pascal; } + bool isUnevaluated() const { + return EvalMethod == StringLiteralEvalMethod::Unevaluated; + } StringRef getUDSuffix() const { return UDSuffixBuf; } diff --git a/contrib/llvm-project/clang/include/clang/Lex/MacroInfo.h b/contrib/llvm-project/clang/include/clang/Lex/MacroInfo.h index 75c9ca70dfb..00c1c3866bb 100644 --- a/contrib/llvm-project/clang/include/clang/Lex/MacroInfo.h +++ b/contrib/llvm-project/clang/include/clang/Lex/MacroInfo.h @@ -206,7 +206,7 @@ public: void setIsGNUVarargs() { IsGNUVarargs = true; } bool isC99Varargs() const { return IsC99Varargs; } bool isGNUVarargs() const { return IsGNUVarargs; } - bool isVariadic() const { return IsC99Varargs | IsGNUVarargs; } + bool isVariadic() const { return IsC99Varargs || IsGNUVarargs; } /// Return true if this macro requires processing before expansion. /// diff --git a/contrib/llvm-project/clang/include/clang/Lex/ModuleMap.h b/contrib/llvm-project/clang/include/clang/Lex/ModuleMap.h index f9eb0be538c..8f3f234036d 100644 --- a/contrib/llvm-project/clang/include/clang/Lex/ModuleMap.h +++ b/contrib/llvm-project/clang/include/clang/Lex/ModuleMap.h @@ -67,10 +67,8 @@ public: /// Called when an umbrella header is added during module map parsing. /// - /// \param FileMgr FileManager instance /// \param Header The umbrella header to collect. - virtual void moduleMapAddUmbrellaHeader(FileManager *FileMgr, - const FileEntry *Header) {} + virtual void moduleMapAddUmbrellaHeader(FileEntryRef Header) {} }; class ModuleMap { @@ -84,7 +82,7 @@ class ModuleMap { /// The directory used for Clang-supplied, builtin include headers, /// such as "stdint.h". - const DirectoryEntry *BuiltinIncludeDir = nullptr; + OptionalDirectoryEntryRefDegradesToDirectoryEntryPtr BuiltinIncludeDir; /// Language options used to parse the module map itself. /// @@ -366,22 +364,22 @@ private: /// /// \param IntermediateDirs On success, contains the set of directories /// searched before finding \p File. - KnownHeader findHeaderInUmbrellaDirs(const FileEntry *File, - SmallVectorImpl &IntermediateDirs); + KnownHeader findHeaderInUmbrellaDirs( + FileEntryRef File, SmallVectorImpl &IntermediateDirs); /// Given that \p File is not in the Headers map, look it up within /// umbrella directories and find or create a module for it. - KnownHeader findOrCreateModuleForHeaderInUmbrellaDir(const FileEntry *File); + KnownHeader findOrCreateModuleForHeaderInUmbrellaDir(FileEntryRef File); /// A convenience method to determine if \p File is (possibly nested) /// in an umbrella directory. - bool isHeaderInUmbrellaDirs(const FileEntry *File) { - SmallVector IntermediateDirs; + bool isHeaderInUmbrellaDirs(FileEntryRef File) { + SmallVector IntermediateDirs; return static_cast(findHeaderInUmbrellaDirs(File, IntermediateDirs)); } - Module *inferFrameworkModule(const DirectoryEntry *FrameworkDir, - Attributes Attrs, Module *Parent); + Module *inferFrameworkModule(DirectoryEntryRef FrameworkDir, Attributes Attrs, + Module *Parent); public: /// Construct a new module map. @@ -407,7 +405,7 @@ public: /// Set the directory that contains Clang-supplied include /// files, such as our stdarg.h or tgmath.h. - void setBuiltinIncludeDir(const DirectoryEntry *Dir) { + void setBuiltinIncludeDir(DirectoryEntryRef Dir) { BuiltinIncludeDir = Dir; } @@ -439,8 +437,7 @@ public: /// \returns The module KnownHeader, which provides the module that owns the /// given header file. The KnownHeader is default constructed to indicate /// that no module owns this header file. - KnownHeader findModuleForHeader(const FileEntry *File, - bool AllowTextual = false, + KnownHeader findModuleForHeader(FileEntryRef File, bool AllowTextual = false, bool AllowExcluded = false); /// Retrieve all the modules that contain the given header file. Note that @@ -450,7 +447,7 @@ public: /// /// Typically, \ref findModuleForHeader should be used instead, as it picks /// the preferred module for the header. - ArrayRef findAllModulesForHeader(const FileEntry *File); + ArrayRef findAllModulesForHeader(FileEntryRef File); /// Like \ref findAllModulesForHeader, but do not attempt to infer module /// ownership from umbrella headers if we've not already done so. @@ -490,11 +487,11 @@ public: /// Determine whether the given header is part of a module /// marked 'unavailable'. - bool isHeaderInUnavailableModule(const FileEntry *Header) const; + bool isHeaderInUnavailableModule(FileEntryRef Header) const; /// Determine whether the given header is unavailable as part /// of the specified module. - bool isHeaderUnavailableInModule(const FileEntry *Header, + bool isHeaderUnavailableInModule(FileEntryRef Header, const Module *RequestingModule) const; /// Retrieve a module with the given name. @@ -553,11 +550,18 @@ public: /// parent. Module *createGlobalModuleFragmentForModuleUnit(SourceLocation Loc, Module *Parent = nullptr); + Module *createImplicitGlobalModuleFragmentForModuleUnit( + SourceLocation Loc, bool IsExported, Module *Parent = nullptr); /// Create a global module fragment for a C++ module interface unit. Module *createPrivateModuleFragmentForInterfaceUnit(Module *Parent, SourceLocation Loc); + /// Create a new C++ module with the specified kind, and reparent any pending + /// global module fragment(s) to it. + Module *createModuleUnitWithKind(SourceLocation Loc, StringRef Name, + Module::ModuleKind Kind); + /// Create a new module for a C++ module interface unit. /// The module must not already exist, and will be configured for the current /// compilation. @@ -567,14 +571,21 @@ public: /// \returns The newly-created module. Module *createModuleForInterfaceUnit(SourceLocation Loc, StringRef Name); + /// Create a new module for a C++ module implementation unit. + /// The interface module for this implementation (implicitly imported) must + /// exist and be loaded and present in the modules map. + /// + /// \returns The newly-created module. + Module *createModuleForImplementationUnit(SourceLocation Loc, StringRef Name); + /// Create a C++20 header unit. Module *createHeaderUnit(SourceLocation Loc, StringRef Name, Module::Header H); /// Infer the contents of a framework module map from the given /// framework directory. - Module *inferFrameworkModule(const DirectoryEntry *FrameworkDir, - bool IsSystem, Module *Parent); + Module *inferFrameworkModule(DirectoryEntryRef FrameworkDir, bool IsSystem, + Module *Parent); /// Create a new top-level module that is shadowed by /// \p ShadowingModule. @@ -674,17 +685,16 @@ public: /// false otherwise. bool resolveConflicts(Module *Mod, bool Complain); - /// Sets the umbrella header of the given module to the given - /// header. - void setUmbrellaHeader(Module *Mod, FileEntryRef UmbrellaHeader, - const Twine &NameAsWritten, - const Twine &PathRelativeToRootModuleDirectory); + /// Sets the umbrella header of the given module to the given header. + void + setUmbrellaHeaderAsWritten(Module *Mod, FileEntryRef UmbrellaHeader, + const Twine &NameAsWritten, + const Twine &PathRelativeToRootModuleDirectory); - /// Sets the umbrella directory of the given module to the given - /// directory. - void setUmbrellaDir(Module *Mod, const DirectoryEntry *UmbrellaDir, - const Twine &NameAsWritten, - const Twine &PathRelativeToRootModuleDirectory); + /// Sets the umbrella directory of the given module to the given directory. + void setUmbrellaDirAsWritten(Module *Mod, DirectoryEntryRef UmbrellaDir, + const Twine &NameAsWritten, + const Twine &PathRelativeToRootModuleDirectory); /// Adds this header to the given module. /// \param Role The role of the header wrt the module. @@ -712,8 +722,8 @@ public: /// /// \returns true if an error occurred, false otherwise. bool parseModuleMapFile(const FileEntry *File, bool IsSystem, - const DirectoryEntry *HomeDir, - FileID ID = FileID(), unsigned *Offset = nullptr, + DirectoryEntryRef HomeDir, FileID ID = FileID(), + unsigned *Offset = nullptr, SourceLocation ExternModuleLoc = SourceLocation()); /// Dump the contents of the module map, for debugging purposes. diff --git a/contrib/llvm-project/clang/include/clang/Lex/MultipleIncludeOpt.h b/contrib/llvm-project/clang/include/clang/Lex/MultipleIncludeOpt.h index 7ceb7e53c75..8e570226c4b 100644 --- a/contrib/llvm-project/clang/include/clang/Lex/MultipleIncludeOpt.h +++ b/contrib/llvm-project/clang/include/clang/Lex/MultipleIncludeOpt.h @@ -108,6 +108,12 @@ public: ImmediatelyAfterTopLevelIfndef = false; } + /// SetReadToken - Set whether the value of 'ReadAnyTokens'. Called to + /// override when encountering tokens outside of the include guard that have + /// no effect if the file in question is is included multiple times (e.g. the + /// null directive). + void SetReadToken(bool Value) { ReadAnyTokens = Value; } + /// ExpandedMacro - When a macro is expanded with this lexer as the current /// buffer, this method is called to disable the MIOpt if needed. void ExpandedMacro() { DidMacroExpansion = true; } diff --git a/contrib/llvm-project/clang/include/clang/Lex/Pragma.h b/contrib/llvm-project/clang/include/clang/Lex/Pragma.h index cf8cca5414e..67eca618f6c 100644 --- a/contrib/llvm-project/clang/include/clang/Lex/Pragma.h +++ b/contrib/llvm-project/clang/include/clang/Lex/Pragma.h @@ -123,6 +123,13 @@ public: PragmaNamespace *getIfNamespace() override { return this; } }; +/// Destringize a \c _Pragma("") string according to C11 6.10.9.1: +/// "The string literal is destringized by deleting any encoding prefix, +/// deleting the leading and trailing double-quotes, replacing each escape +/// sequence \" by a double-quote, and replacing each escape sequence \\ by a +/// single backslash." +void prepare_PragmaString(SmallVectorImpl &StrVal); + } // namespace clang #endif // LLVM_CLANG_LEX_PRAGMA_H diff --git a/contrib/llvm-project/clang/include/clang/Lex/Preprocessor.h b/contrib/llvm-project/clang/include/clang/Lex/Preprocessor.h index 322626802ea..9efe439bc5f 100644 --- a/contrib/llvm-project/clang/include/clang/Lex/Preprocessor.h +++ b/contrib/llvm-project/clang/include/clang/Lex/Preprocessor.h @@ -499,7 +499,7 @@ private: }; public: - ModuleDeclSeq() : State(NotAModuleDecl) {} + ModuleDeclSeq() = default; void handleExport() { if (State == NotAModuleDecl) @@ -586,7 +586,7 @@ private: } private: - ModuleDeclState State; + ModuleDeclState State = NotAModuleDecl; std::string Name; }; @@ -625,7 +625,7 @@ private: /// The directory that the main file should be considered to occupy, /// if it does not correspond to a real file (as happens when building a /// module). - const DirectoryEntry *MainFileDir = nullptr; + OptionalDirectoryEntryRef MainFileDir; /// The number of bytes that we will initially skip when entering the /// main file, along with a flag that indicates whether skipping this number @@ -729,7 +729,7 @@ private: /// Only one of CurLexer, or CurTokenLexer will be non-null. std::unique_ptr CurLexer; - /// The current top of the stack what we're lexing from + /// The current top of the stack that we're lexing from /// if not expanding a macro. /// /// This is an alias for CurLexer. @@ -1486,6 +1486,7 @@ public: /// Return true if this header has already been included. bool alreadyIncluded(const FileEntry *File) const { + HeaderInfo.getFileInfo(File); return IncludedFiles.count(File); } @@ -2012,9 +2013,7 @@ public: /// Set the directory in which the main file should be considered /// to have been found, if it is not a real file. - void setMainFileDir(const DirectoryEntry *Dir) { - MainFileDir = Dir; - } + void setMainFileDir(DirectoryEntryRef Dir) { MainFileDir = Dir; } /// Instruct the preprocessor to skip part of the main source file. /// @@ -2842,10 +2841,60 @@ public: const LangOptions &LangOpts, const TargetInfo &TI); + static void processPathToFileName(SmallVectorImpl &FileName, + const PresumedLoc &PLoc, + const LangOptions &LangOpts, + const TargetInfo &TI); + private: void emitMacroDeprecationWarning(const Token &Identifier) const; void emitRestrictExpansionWarning(const Token &Identifier) const; void emitFinalMacroWarning(const Token &Identifier, bool IsUndef) const; + + /// This boolean state keeps track if the current scanned token (by this PP) + /// is in an "-Wunsafe-buffer-usage" opt-out region. Assuming PP scans a + /// translation unit in a linear order. + bool InSafeBufferOptOutRegion = false; + + /// Hold the start location of the current "-Wunsafe-buffer-usage" opt-out + /// region if PP is currently in such a region. Hold undefined value + /// otherwise. + SourceLocation CurrentSafeBufferOptOutStart; // It is used to report the start location of an never-closed region. + + // An ordered sequence of "-Wunsafe-buffer-usage" opt-out regions in one + // translation unit. Each region is represented by a pair of start and end + // locations. A region is "open" if its' start and end locations are + // identical. + SmallVector, 8> SafeBufferOptOutMap; + +public: + /// \return true iff the given `Loc` is in a "-Wunsafe-buffer-usage" opt-out + /// region. This `Loc` must be a source location that has been pre-processed. + bool isSafeBufferOptOut(const SourceManager&SourceMgr, const SourceLocation &Loc) const; + + /// Alter the state of whether this PP currently is in a + /// "-Wunsafe-buffer-usage" opt-out region. + /// + /// \param isEnter: true if this PP is entering a region; otherwise, this PP + /// is exiting a region + /// \param Loc: the location of the entry or exit of a + /// region + /// \return true iff it is INVALID to enter or exit a region, i.e., + /// attempt to enter a region before exiting a previous region, or exiting a + /// region that PP is not currently in. + bool enterOrExitSafeBufferOptOutRegion(bool isEnter, + const SourceLocation &Loc); + + /// \return true iff this PP is currently in a "-Wunsafe-buffer-usage" + /// opt-out region + bool isPPInSafeBufferOptOutRegion(); + + /// \param StartLoc: output argument. It will be set to the start location of + /// the current "-Wunsafe-buffer-usage" opt-out region iff this function + /// returns true. + /// \return true iff this PP is currently in a "-Wunsafe-buffer-usage" + /// opt-out region + bool isPPInSafeBufferOptOutRegion(SourceLocation &StartLoc); }; /// Abstract base class that describes a handler that will receive diff --git a/contrib/llvm-project/clang/include/clang/Lex/PreprocessorOptions.h b/contrib/llvm-project/clang/include/clang/Lex/PreprocessorOptions.h index 432f5dfa9bc..058194bcde7 100644 --- a/contrib/llvm-project/clang/include/clang/Lex/PreprocessorOptions.h +++ b/contrib/llvm-project/clang/include/clang/Lex/PreprocessorOptions.h @@ -69,6 +69,9 @@ public: std::vector Includes; std::vector MacroIncludes; + /// Perform extra checks when loading PCM files for mutable file systems. + bool ModulesCheckRelocated = true; + /// Initialize the preprocessor with the compiler and target specific /// predefines. bool UsePredefines = true; diff --git a/contrib/llvm-project/clang/include/clang/Lex/Token.h b/contrib/llvm-project/clang/include/clang/Lex/Token.h index 7fd48b1b439..1409e2c58b5 100644 --- a/contrib/llvm-project/clang/include/clang/Lex/Token.h +++ b/contrib/llvm-project/clang/include/clang/Lex/Token.h @@ -117,8 +117,13 @@ public: } /// Return true if this is any of tok::annot_* kind tokens. - bool isAnnotation() const { - return tok::isAnnotation(getKind()); + bool isAnnotation() const { return tok::isAnnotation(getKind()); } + + /// Return true if the token is a keyword that is parsed in the same + /// position as a standard attribute, but that has semantic meaning + /// and so cannot be a true attribute. + bool isRegularKeywordAttribute() const { + return tok::isRegularKeywordAttribute(getKind()); } /// Return a source location identifier for the specified diff --git a/contrib/llvm-project/clang/include/clang/Parse/LoopHint.h b/contrib/llvm-project/clang/include/clang/Parse/LoopHint.h index 6e363f72b65..75705fcd4c7 100644 --- a/contrib/llvm-project/clang/include/clang/Parse/LoopHint.h +++ b/contrib/llvm-project/clang/include/clang/Parse/LoopHint.h @@ -23,20 +23,18 @@ struct LoopHint { // Identifier corresponding to the name of the pragma. "loop" for // "#pragma clang loop" directives and "unroll" for "#pragma unroll" // hints. - IdentifierLoc *PragmaNameLoc; + IdentifierLoc *PragmaNameLoc = nullptr; // Name of the loop hint. Examples: "unroll", "vectorize". In the // "#pragma unroll" and "#pragma nounroll" cases, this is identical to // PragmaNameLoc. - IdentifierLoc *OptionLoc; + IdentifierLoc *OptionLoc = nullptr; // Identifier for the hint state argument. If null, then the state is // default value such as for "#pragma unroll". - IdentifierLoc *StateLoc; + IdentifierLoc *StateLoc = nullptr; // Expression for the hint argument if it exists, null otherwise. - Expr *ValueExpr; + Expr *ValueExpr = nullptr; - LoopHint() - : PragmaNameLoc(nullptr), OptionLoc(nullptr), StateLoc(nullptr), - ValueExpr(nullptr) {} + LoopHint() = default; }; } // end namespace clang diff --git a/contrib/llvm-project/clang/include/clang/Parse/Parser.h b/contrib/llvm-project/clang/include/clang/Parse/Parser.h index 6f9581b9ea1..475dfe84552 100644 --- a/contrib/llvm-project/clang/include/clang/Parse/Parser.h +++ b/contrib/llvm-project/clang/include/clang/Parse/Parser.h @@ -18,6 +18,7 @@ #include "clang/Basic/OpenMPKinds.h" #include "clang/Basic/OperatorPrecedence.h" #include "clang/Basic/Specifiers.h" +#include "clang/Basic/TokenKinds.h" #include "clang/Lex/CodeCompletionHandler.h" #include "clang/Lex/Preprocessor.h" #include "clang/Sema/DeclSpec.h" @@ -157,7 +158,7 @@ class Parser : public CodeCompletionHandler { /// Identifiers used by the 'external_source_symbol' attribute. IdentifierInfo *Ident_language, *Ident_defined_in, - *Ident_generated_declaration; + *Ident_generated_declaration, *Ident_USR; /// C++11 contextual keywords. mutable IdentifierInfo *Ident_final; @@ -692,7 +693,8 @@ private: bool isEofOrEom() { tok::TokenKind Kind = Tok.getKind(); return Kind == tok::eof || Kind == tok::annot_module_begin || - Kind == tok::annot_module_end || Kind == tok::annot_module_include; + Kind == tok::annot_module_end || Kind == tok::annot_module_include || + Kind == tok::annot_repl_input_end; } /// Checks if the \p Level is valid for use in a fold expression. @@ -1186,7 +1188,7 @@ private: /// RAII object used to modify the scope flags for the current scope. class ParseScopeFlags { Scope *CurScope; - unsigned OldFlags; + unsigned OldFlags = 0; ParseScopeFlags(const ParseScopeFlags &) = delete; void operator=(const ParseScopeFlags &) = delete; @@ -1786,8 +1788,12 @@ public: bool IsUnevaluated); ExprResult ParseStringLiteralExpression(bool AllowUserDefinedLiteral = false); + ExprResult ParseUnevaluatedStringLiteralExpression(); private: + ExprResult ParseStringLiteralExpression(bool AllowUserDefinedLiteral, + bool Unevaluated); + ExprResult ParseExpressionWithLeadingAt(SourceLocation AtLoc); ExprResult ParseExpressionWithLeadingExtension(SourceLocation ExtLoc); @@ -2215,7 +2221,8 @@ private: DSC_objc_method_result, // ObjC method result context, enables // 'instancetype' DSC_condition, // condition declaration context - DSC_association // A _Generic selection expression's type association + DSC_association, // A _Generic selection expression's type association + DSC_new, // C++ new expression }; /// Is this a context in which we are parsing just a type-specifier (or @@ -2237,6 +2244,7 @@ private: case DeclSpecContext::DSC_trailing: case DeclSpecContext::DSC_alias_declaration: case DeclSpecContext::DSC_association: + case DeclSpecContext::DSC_new: return true; } llvm_unreachable("Missing DeclSpecContext case"); @@ -2285,6 +2293,7 @@ private: case DeclSpecContext::DSC_trailing: case DeclSpecContext::DSC_conv_operator: case DeclSpecContext::DSC_template_arg: + case DeclSpecContext::DSC_new: return AllowDefiningTypeSpec::No; } llvm_unreachable("Missing DeclSpecContext case"); @@ -2308,6 +2317,7 @@ private: case DeclSpecContext::DSC_association: case DeclSpecContext::DSC_conv_operator: case DeclSpecContext::DSC_template_arg: + case DeclSpecContext::DSC_new: return false; } @@ -2327,6 +2337,7 @@ private: case DeclSpecContext::DSC_type_specifier: case DeclSpecContext::DSC_association: case DeclSpecContext::DSC_conv_operator: + case DeclSpecContext::DSC_new: return true; case DeclSpecContext::DSC_objc_method_result: @@ -2349,6 +2360,7 @@ private: case DeclSpecContext::DSC_trailing: case DeclSpecContext::DSC_alias_declaration: case DeclSpecContext::DSC_template_param: + case DeclSpecContext::DSC_new: return ImplicitTypenameContext::Yes; case DeclSpecContext::DSC_normal: @@ -2513,17 +2525,19 @@ private: /// this is a constructor declarator. bool isConstructorDeclarator( bool Unqualified, bool DeductionGuide = false, - DeclSpec::FriendSpecified IsFriend = DeclSpec::FriendSpecified::No); + DeclSpec::FriendSpecified IsFriend = DeclSpec::FriendSpecified::No, + const ParsedTemplateInfo *TemplateInfo = nullptr); /// Specifies the context in which type-id/expression /// disambiguation will occur. enum TentativeCXXTypeIdContext { TypeIdInParens, TypeIdUnambiguous, - TypeIdAsTemplateArgument + TypeIdAsTemplateArgument, + TypeIdInTrailingReturnType, + TypeIdAsGenericSelectionArgument, }; - /// isTypeIdInParens - Assumes that a '(' was parsed and now we want to know /// whether the parens contain an expression or a type-id. /// Returns true for a type-id and false for an expression. @@ -2538,13 +2552,29 @@ private: return isTypeIdInParens(isAmbiguous); } + /// Checks whether the current tokens form a type-id or an expression for the + /// purposes of use as the initial operand to a generic selection expression. + /// This requires special handling in C++ because it accepts either a type or + /// an expression, and we need to disambiguate which is which. However, we + /// cannot use the same logic as we've used for sizeof expressions, because + /// that logic relies on the operator only accepting a single argument, + /// whereas _Generic accepts a list of arguments. + bool isTypeIdForGenericSelection() { + if (getLangOpts().CPlusPlus) { + bool isAmbiguous; + return isCXXTypeId(TypeIdAsGenericSelectionArgument, isAmbiguous); + } + return isTypeSpecifierQualifier(); + } + /// Checks if the current tokens form type-id or expression. /// It is similar to isTypeIdInParens but does not suppose that type-id /// is in parenthesis. bool isTypeIdUnambiguously() { - bool IsAmbiguous; - if (getLangOpts().CPlusPlus) - return isCXXTypeId(TypeIdUnambiguous, IsAmbiguous); + if (getLangOpts().CPlusPlus) { + bool isAmbiguous; + return isCXXTypeId(TypeIdUnambiguous, isAmbiguous); + } return isTypeSpecifierQualifier(); } @@ -2651,14 +2681,16 @@ private: TPResult TryParseProtocolQualifiers(); TPResult TryParsePtrOperatorSeq(); TPResult TryParseOperatorId(); - TPResult TryParseInitDeclaratorList(); + TPResult TryParseInitDeclaratorList(bool MayHaveTrailingReturnType = false); TPResult TryParseDeclarator(bool mayBeAbstract, bool mayHaveIdentifier = true, - bool mayHaveDirectInit = false); + bool mayHaveDirectInit = false, + bool mayHaveTrailingReturnType = false); TPResult TryParseParameterDeclarationClause( bool *InvalidAsDeclaration = nullptr, bool VersusTemplateArg = false, ImplicitTypenameContext AllowImplicitTypename = ImplicitTypenameContext::No); - TPResult TryParseFunctionDeclarator(); + TPResult TryParseFunctionDeclarator(bool MayHaveTrailingReturnType = false); + bool NameAfterArrowIsNonType(); TPResult TryParseBracketDeclarator(); TPResult TryConsumeDeclarationSpecifier(); @@ -2680,17 +2712,22 @@ public: private: void ParseBlockId(SourceLocation CaretLoc); - /// Are [[]] attributes enabled? - bool standardAttributesAllowed() const { - const LangOptions &LO = getLangOpts(); - return LO.DoubleSquareBracketAttributes; + /// Return true if the next token should be treated as a [[]] attribute, + /// or as a keyword that behaves like one. The former is only true if + /// [[]] attributes are enabled, whereas the latter is true whenever + /// such a keyword appears. The arguments are as for + /// isCXX11AttributeSpecifier. + bool isAllowedCXX11AttributeSpecifier(bool Disambiguate = false, + bool OuterMightBeMessageSend = false) { + return (Tok.isRegularKeywordAttribute() || + isCXX11AttributeSpecifier(Disambiguate, OuterMightBeMessageSend)); } // Check for the start of an attribute-specifier-seq in a context where an // attribute is not allowed. bool CheckProhibitedCXX11Attribute() { assert(Tok.is(tok::l_square)); - if (!standardAttributesAllowed() || NextToken().isNot(tok::l_square)) + if (NextToken().isNot(tok::l_square)) return false; return DiagnoseProhibitedCXX11Attribute(); } @@ -2698,9 +2735,8 @@ private: bool DiagnoseProhibitedCXX11Attribute(); void CheckMisplacedCXX11Attribute(ParsedAttributes &Attrs, SourceLocation CorrectLocation) { - if (!standardAttributesAllowed()) - return; - if ((Tok.isNot(tok::l_square) || NextToken().isNot(tok::l_square)) && + if (!Tok.isRegularKeywordAttribute() && + (Tok.isNot(tok::l_square) || NextToken().isNot(tok::l_square)) && Tok.isNot(tok::kw_alignas)) return; DiagnoseMisplacedCXX11Attribute(Attrs, CorrectLocation); @@ -2716,7 +2752,7 @@ private: SourceLocation FixItLoc = SourceLocation()) { if (Attrs.Range.isInvalid()) return; - DiagnoseProhibitedAttributes(Attrs.Range, FixItLoc); + DiagnoseProhibitedAttributes(Attrs, FixItLoc); Attrs.clear(); } @@ -2724,10 +2760,10 @@ private: SourceLocation FixItLoc = SourceLocation()) { if (Attrs.Range.isInvalid()) return; - DiagnoseProhibitedAttributes(Attrs.Range, FixItLoc); + DiagnoseProhibitedAttributes(Attrs, FixItLoc); Attrs.clearListOnly(); } - void DiagnoseProhibitedAttributes(const SourceRange &Range, + void DiagnoseProhibitedAttributes(const ParsedAttributesView &Attrs, SourceLocation FixItLoc); // Forbid C++11 and C2x attributes that appear on certain syntactic locations @@ -2736,7 +2772,8 @@ private: // For the most cases we don't want to warn on unknown type attributes, but // left them to later diagnoses. However, for a few cases like module // declarations and module import declarations, we should do it. - void ProhibitCXX11Attributes(ParsedAttributes &Attrs, unsigned DiagID, + void ProhibitCXX11Attributes(ParsedAttributes &Attrs, unsigned AttrDiagID, + unsigned KeywordDiagId, bool DiagnoseEmptyAttrs = false, bool WarnOnUnknownAttrs = false); @@ -2761,7 +2798,7 @@ private: ParseAttributeArgsCommon(IdentifierInfo *AttrName, SourceLocation AttrNameLoc, ParsedAttributes &Attrs, SourceLocation *EndLoc, IdentifierInfo *ScopeName, SourceLocation ScopeLoc, - ParsedAttr::Syntax Syntax); + ParsedAttr::Form Form); enum ParseAttrKindMask { PAKM_GNU = 1 << 0, @@ -2790,7 +2827,7 @@ private: bool MaybeParseAttributes(unsigned WhichAttrKinds, ParsedAttributes &Attrs, LateParsedAttrList *LateAttrs = nullptr) { if (Tok.isOneOf(tok::kw___attribute, tok::kw___declspec) || - (standardAttributesAllowed() && isCXX11AttributeSpecifier())) { + isAllowedCXX11AttributeSpecifier()) { ParseAttributes(WhichAttrKinds, Attrs, LateAttrs); return true; } @@ -2822,14 +2859,14 @@ private: SourceLocation AttrNameLoc, ParsedAttributes &Attrs, SourceLocation *EndLoc, IdentifierInfo *ScopeName, SourceLocation ScopeLoc, - ParsedAttr::Syntax Syntax, Declarator *D); + ParsedAttr::Form Form, Declarator *D); IdentifierLoc *ParseIdentifierLoc(); unsigned ParseClangAttributeArgs(IdentifierInfo *AttrName, SourceLocation AttrNameLoc, ParsedAttributes &Attrs, SourceLocation *EndLoc, IdentifierInfo *ScopeName, SourceLocation ScopeLoc, - ParsedAttr::Syntax Syntax); + ParsedAttr::Form Form); void ReplayOpenMPAttributeTokens(CachedTokens &OpenMPTokens) { // If parsing the attributes found an OpenMP directive, emit those tokens @@ -2842,7 +2879,7 @@ private: } } void MaybeParseCXX11Attributes(Declarator &D) { - if (standardAttributesAllowed() && isCXX11AttributeSpecifier()) { + if (isAllowedCXX11AttributeSpecifier()) { ParsedAttributes Attrs(AttrFactory); ParseCXX11Attributes(Attrs); D.takeAttributes(Attrs); @@ -2851,8 +2888,7 @@ private: bool MaybeParseCXX11Attributes(ParsedAttributes &Attrs, bool OuterMightBeMessageSend = false) { - if (standardAttributesAllowed() && - isCXX11AttributeSpecifier(false, OuterMightBeMessageSend)) { + if (isAllowedCXX11AttributeSpecifier(false, OuterMightBeMessageSend)) { ParseCXX11Attributes(Attrs); return true; } @@ -2929,6 +2965,7 @@ private: SourceLocation AttrNameLoc, ParsedAttributes &Attrs); void ParseMicrosoftTypeAttributes(ParsedAttributes &attrs); + void ParseWebAssemblyFuncrefTypeAttribute(ParsedAttributes &Attrs); void DiagnoseAndSkipExtendedMicrosoftTypeAttributes(); SourceLocation SkipExtendedMicrosoftTypeAttributes(); void ParseMicrosoftInheritanceClassAttributes(ParsedAttributes &attrs); @@ -2947,7 +2984,7 @@ private: SourceLocation *endLoc, IdentifierInfo *ScopeName, SourceLocation ScopeLoc, - ParsedAttr::Syntax Syntax); + ParsedAttr::Form Form); std::optional ParseAvailabilitySpec(); ExprResult ParseAvailabilityCheckExpr(SourceLocation StartLoc); @@ -2958,7 +2995,7 @@ private: SourceLocation *EndLoc, IdentifierInfo *ScopeName, SourceLocation ScopeLoc, - ParsedAttr::Syntax Syntax); + ParsedAttr::Form Form); void ParseObjCBridgeRelatedAttribute(IdentifierInfo &ObjCBridgeRelated, SourceLocation ObjCBridgeRelatedLoc, @@ -2966,7 +3003,7 @@ private: SourceLocation *EndLoc, IdentifierInfo *ScopeName, SourceLocation ScopeLoc, - ParsedAttr::Syntax Syntax); + ParsedAttr::Form Form); void ParseSwiftNewTypeAttribute(IdentifierInfo &AttrName, SourceLocation AttrNameLoc, @@ -2974,7 +3011,7 @@ private: SourceLocation *EndLoc, IdentifierInfo *ScopeName, SourceLocation ScopeLoc, - ParsedAttr::Syntax Syntax); + ParsedAttr::Form Form); void ParseTypeTagForDatatypeAttribute(IdentifierInfo &AttrName, SourceLocation AttrNameLoc, @@ -2982,14 +3019,14 @@ private: SourceLocation *EndLoc, IdentifierInfo *ScopeName, SourceLocation ScopeLoc, - ParsedAttr::Syntax Syntax); + ParsedAttr::Form Form); void ParseAttributeWithTypeArg(IdentifierInfo &AttrName, SourceLocation AttrNameLoc, ParsedAttributes &Attrs, IdentifierInfo *ScopeName, SourceLocation ScopeLoc, - ParsedAttr::Syntax Syntax); + ParsedAttr::Form Form); void ParseTypeofSpecifier(DeclSpec &DS); SourceLocation ParseDecltypeSpecifier(DeclSpec &DS); @@ -2998,8 +3035,9 @@ private: SourceLocation EndLoc); void ParseAtomicSpecifier(DeclSpec &DS); - ExprResult ParseAlignArgument(SourceLocation Start, - SourceLocation &EllipsisLoc); + ExprResult ParseAlignArgument(StringRef KWName, SourceLocation Start, + SourceLocation &EllipsisLoc, bool &IsType, + ParsedType &Ty); void ParseAlignmentSpecifier(ParsedAttributes &Attrs, SourceLocation *endLoc = nullptr); ExprResult ParseExtIntegerArgument(); diff --git a/contrib/llvm-project/clang/include/clang/Rewrite/Core/RewriteRope.h b/contrib/llvm-project/clang/include/clang/Rewrite/Core/RewriteRope.h index 8fa7af245eb..73e66e111f5 100644 --- a/contrib/llvm-project/clang/include/clang/Rewrite/Core/RewriteRope.h +++ b/contrib/llvm-project/clang/include/clang/Rewrite/Core/RewriteRope.h @@ -181,6 +181,10 @@ public: RewriteRope() = default; RewriteRope(const RewriteRope &RHS) : Chunks(RHS.Chunks) {} + // The copy assignment operator is defined as deleted pending further + // motivation. + RewriteRope &operator=(const RewriteRope &) = delete; + using iterator = RopePieceBTree::iterator; using const_iterator = RopePieceBTree::iterator; diff --git a/contrib/llvm-project/clang/include/clang/Sema/AnalysisBasedWarnings.h b/contrib/llvm-project/clang/include/clang/Sema/AnalysisBasedWarnings.h index 13a88bb9f89..020ddd36cf7 100644 --- a/contrib/llvm-project/clang/include/clang/Sema/AnalysisBasedWarnings.h +++ b/contrib/llvm-project/clang/include/clang/Sema/AnalysisBasedWarnings.h @@ -13,6 +13,7 @@ #ifndef LLVM_CLANG_SEMA_ANALYSISBASEDWARNINGS_H #define LLVM_CLANG_SEMA_ANALYSISBASEDWARNINGS_H +#include "clang/AST/Decl.h" #include "llvm/ADT/DenseMap.h" #include @@ -95,6 +96,9 @@ public: void IssueWarnings(Policy P, FunctionScopeInfo *fscope, const Decl *D, QualType BlockType); + // Issue warnings that require whole-translation-unit analysis. + void IssueWarnings(TranslationUnitDecl *D); + Policy getDefaultPolicy() { return DefaultPolicy; } void PrintStats() const; diff --git a/contrib/llvm-project/clang/include/clang/Sema/CodeCompleteConsumer.h b/contrib/llvm-project/clang/include/clang/Sema/CodeCompleteConsumer.h index a2d523cd3e9..bb4b6380503 100644 --- a/contrib/llvm-project/clang/include/clang/Sema/CodeCompleteConsumer.h +++ b/contrib/llvm-project/clang/include/clang/Sema/CodeCompleteConsumer.h @@ -333,7 +333,10 @@ public: /// An unknown context, in which we are recovering from a parsing /// error and don't know which completions we should give. - CCC_Recovery + CCC_Recovery, + + /// Code completion in a @class forward declaration. + CCC_ObjCClassForwardDecl }; using VisitedContextSet = llvm::SmallPtrSet; diff --git a/contrib/llvm-project/clang/include/clang/Sema/DeclSpec.h b/contrib/llvm-project/clang/include/clang/Sema/DeclSpec.h index 69fe2c54160..c63378c7329 100644 --- a/contrib/llvm-project/clang/include/clang/Sema/DeclSpec.h +++ b/contrib/llvm-project/clang/include/clang/Sema/DeclSpec.h @@ -62,9 +62,18 @@ namespace clang { /// often used as if it meant "present". /// /// The actual scope is described by getScopeRep(). +/// +/// If the kind of getScopeRep() is TypeSpec then TemplateParamLists may be empty +/// or contain the template parameter lists attached to the current declaration. +/// Consider the following example: +/// template void SomeType::some_method() {} +/// If CXXScopeSpec refers to SomeType then TemplateParamLists will contain +/// a single element referring to template . + class CXXScopeSpec { SourceRange Range; NestedNameSpecifierLocBuilder Builder; + ArrayRef TemplateParamLists; public: SourceRange getRange() const { return Range; } @@ -74,6 +83,13 @@ public: SourceLocation getBeginLoc() const { return Range.getBegin(); } SourceLocation getEndLoc() const { return Range.getEnd(); } + void setTemplateParamLists(ArrayRef L) { + TemplateParamLists = L; + } + ArrayRef getTemplateParamLists() const { + return TemplateParamLists; + } + /// Retrieve the representation of the nested-name-specifier. NestedNameSpecifier *getScopeRep() const { return Builder.getRepresentation(); @@ -1956,9 +1972,10 @@ public: InventedTemplateParameterList(nullptr) { assert(llvm::all_of(DeclarationAttrs, [](const ParsedAttr &AL) { - return AL.isStandardAttributeSyntax(); + return (AL.isStandardAttributeSyntax() || + AL.isRegularKeywordAttribute()); }) && - "DeclarationAttrs may only contain [[]] attributes"); + "DeclarationAttrs may only contain [[]] and keyword attributes"); } ~Declarator() { @@ -2603,14 +2620,6 @@ public: return false; } - /// Return a source range list of C++11 attributes associated - /// with the declarator. - void getCXX11AttributeRanges(SmallVectorImpl &Ranges) { - for (const ParsedAttr &AL : Attrs) - if (AL.isCXX11Attribute()) - Ranges.push_back(AL.getRange()); - } - void setAsmLabel(Expr *E) { AsmLabel = E; } Expr *getAsmLabel() const { return AsmLabel; } diff --git a/contrib/llvm-project/clang/include/clang/Sema/Designator.h b/contrib/llvm-project/clang/include/clang/Sema/Designator.h index 84837bfeba5..244535978d4 100644 --- a/contrib/llvm-project/clang/include/clang/Sema/Designator.h +++ b/contrib/llvm-project/clang/include/clang/Sema/Designator.h @@ -21,60 +21,108 @@ namespace clang { class Expr; class IdentifierInfo; -class Sema; /// Designator - A designator in a C99 designated initializer. /// /// This class is a discriminated union which holds the various -/// different sorts of designators possible. A Designation is an array of +/// different sorts of designators possible. A Designation is an array of /// these. An example of a designator are things like this: -/// [8] .field [47] // C99 designation: 3 designators -/// [8 ... 47] field: // GNU extensions: 2 designators +/// +/// [8] .field [47] // C99 designation: 3 designators +/// [8 ... 47] field: // GNU extensions: 2 designators +/// /// These occur in initializers, e.g.: -/// int a[10] = {2, 4, [8]=9, 10}; +/// +/// int a[10] = {2, 4, [8]=9, 10}; /// class Designator { -public: - enum DesignatorKind { - FieldDesignator, ArrayDesignator, ArrayRangeDesignator - }; -private: - Designator() {}; - - DesignatorKind Kind; - + /// A field designator, e.g., ".x = 42". struct FieldDesignatorInfo { - const IdentifierInfo *II; + /// Refers to the field being initialized. + const IdentifierInfo *FieldName; + + /// The location of the '.' in the designated initializer. SourceLocation DotLoc; - SourceLocation NameLoc; + + /// The location of the field name in the designated initializer. + SourceLocation FieldLoc; + + FieldDesignatorInfo(const IdentifierInfo *FieldName, SourceLocation DotLoc, + SourceLocation FieldLoc) + : FieldName(FieldName), DotLoc(DotLoc), FieldLoc(FieldLoc) {} }; + + /// An array designator, e.g., "[42] = 0". struct ArrayDesignatorInfo { Expr *Index; + + // The location of the '[' in the designated initializer. SourceLocation LBracketLoc; + + // The location of the ']' in the designated initializer. mutable SourceLocation RBracketLoc; + + ArrayDesignatorInfo(Expr *Index, SourceLocation LBracketLoc) + : Index(Index), LBracketLoc(LBracketLoc) {} }; + + /// An array range designator, e.g. "[42 ... 50] = 1". struct ArrayRangeDesignatorInfo { - Expr *Start, *End; - SourceLocation LBracketLoc, EllipsisLoc; + Expr *Start; + Expr *End; + + // The location of the '[' in the designated initializer. + SourceLocation LBracketLoc; + + // The location of the '...' in the designated initializer. + SourceLocation EllipsisLoc; + + // The location of the ']' in the designated initializer. mutable SourceLocation RBracketLoc; + + ArrayRangeDesignatorInfo(Expr *Start, Expr *End, SourceLocation LBracketLoc, + SourceLocation EllipsisLoc) + : Start(Start), End(End), LBracketLoc(LBracketLoc), + EllipsisLoc(EllipsisLoc) {} }; + /// The kind of designator this describes. + enum DesignatorKind { + FieldDesignator, + ArrayDesignator, + ArrayRangeDesignator + }; + + DesignatorKind Kind; + union { FieldDesignatorInfo FieldInfo; ArrayDesignatorInfo ArrayInfo; ArrayRangeDesignatorInfo ArrayRangeInfo; }; -public: + Designator(DesignatorKind Kind) : Kind(Kind) {} - DesignatorKind getKind() const { return Kind; } +public: bool isFieldDesignator() const { return Kind == FieldDesignator; } bool isArrayDesignator() const { return Kind == ArrayDesignator; } bool isArrayRangeDesignator() const { return Kind == ArrayRangeDesignator; } - const IdentifierInfo *getField() const { + //===--------------------------------------------------------------------===// + // FieldDesignatorInfo + + /// Creates a field designator. + static Designator CreateFieldDesignator(const IdentifierInfo *FieldName, + SourceLocation DotLoc, + SourceLocation FieldLoc) { + Designator D(FieldDesignator); + new (&D.FieldInfo) FieldDesignatorInfo(FieldName, DotLoc, FieldLoc); + return D; + } + + const IdentifierInfo *getFieldDecl() const { assert(isFieldDesignator() && "Invalid accessor"); - return FieldInfo.II; + return FieldInfo.FieldName; } SourceLocation getDotLoc() const { @@ -84,7 +132,18 @@ public: SourceLocation getFieldLoc() const { assert(isFieldDesignator() && "Invalid accessor"); - return FieldInfo.NameLoc; + return FieldInfo.FieldLoc; + } + + //===--------------------------------------------------------------------===// + // ArrayDesignatorInfo: + + /// Creates an array designator. + static Designator CreateArrayDesignator(Expr *Index, + SourceLocation LBracketLoc) { + Designator D(ArrayDesignator); + new (&D.ArrayInfo) ArrayDesignatorInfo(Index, LBracketLoc); + return D; } Expr *getArrayIndex() const { @@ -92,31 +151,41 @@ public: return ArrayInfo.Index; } - Expr *getArrayRangeStart() const { - assert(isArrayRangeDesignator() && "Invalid accessor"); - return ArrayRangeInfo.Start; - } - Expr *getArrayRangeEnd() const { - assert(isArrayRangeDesignator() && "Invalid accessor"); - return ArrayRangeInfo.End; - } - SourceLocation getLBracketLoc() const { assert((isArrayDesignator() || isArrayRangeDesignator()) && "Invalid accessor"); - if (isArrayDesignator()) - return ArrayInfo.LBracketLoc; - else - return ArrayRangeInfo.LBracketLoc; + return isArrayDesignator() ? ArrayInfo.LBracketLoc + : ArrayRangeInfo.LBracketLoc; } SourceLocation getRBracketLoc() const { assert((isArrayDesignator() || isArrayRangeDesignator()) && "Invalid accessor"); - if (isArrayDesignator()) - return ArrayInfo.RBracketLoc; - else - return ArrayRangeInfo.RBracketLoc; + return isArrayDesignator() ? ArrayInfo.RBracketLoc + : ArrayRangeInfo.RBracketLoc; + } + + //===--------------------------------------------------------------------===// + // ArrayRangeDesignatorInfo: + + /// Creates a GNU array-range designator. + static Designator CreateArrayRangeDesignator(Expr *Start, Expr *End, + SourceLocation LBracketLoc, + SourceLocation EllipsisLoc) { + Designator D(ArrayRangeDesignator); + new (&D.ArrayRangeInfo) + ArrayRangeDesignatorInfo(Start, End, LBracketLoc, EllipsisLoc); + return D; + } + + Expr *getArrayRangeStart() const { + assert(isArrayRangeDesignator() && "Invalid accessor"); + return ArrayRangeInfo.Start; + } + + Expr *getArrayRangeEnd() const { + assert(isArrayRangeDesignator() && "Invalid accessor"); + return ArrayRangeInfo.End; } SourceLocation getEllipsisLoc() const { @@ -124,43 +193,6 @@ public: return ArrayRangeInfo.EllipsisLoc; } - static Designator getField(const IdentifierInfo *II, SourceLocation DotLoc, - SourceLocation NameLoc) { - Designator D; - D.Kind = FieldDesignator; - new (&D.FieldInfo) FieldDesignatorInfo; - D.FieldInfo.II = II; - D.FieldInfo.DotLoc = DotLoc; - D.FieldInfo.NameLoc = NameLoc; - return D; - } - - static Designator getArray(Expr *Index, - SourceLocation LBracketLoc) { - Designator D; - D.Kind = ArrayDesignator; - new (&D.ArrayInfo) ArrayDesignatorInfo; - D.ArrayInfo.Index = Index; - D.ArrayInfo.LBracketLoc = LBracketLoc; - D.ArrayInfo.RBracketLoc = SourceLocation(); - return D; - } - - static Designator getArrayRange(Expr *Start, - Expr *End, - SourceLocation LBracketLoc, - SourceLocation EllipsisLoc) { - Designator D; - D.Kind = ArrayRangeDesignator; - new (&D.ArrayRangeInfo) ArrayRangeDesignatorInfo; - D.ArrayRangeInfo.Start = Start; - D.ArrayRangeInfo.End = End; - D.ArrayRangeInfo.LBracketLoc = LBracketLoc; - D.ArrayRangeInfo.EllipsisLoc = EllipsisLoc; - D.ArrayRangeInfo.RBracketLoc = SourceLocation(); - return D; - } - void setRBracketLoc(SourceLocation RBracketLoc) const { assert((isArrayDesignator() || isArrayRangeDesignator()) && "Invalid accessor"); @@ -169,17 +201,8 @@ public: else ArrayRangeInfo.RBracketLoc = RBracketLoc; } - - /// ClearExprs - Null out any expression references, which prevents - /// them from being 'delete'd later. - void ClearExprs(Sema &Actions) {} - - /// FreeExprs - Release any unclaimed memory for the expressions in - /// this designator. - void FreeExprs(Sema &Actions) {} }; - /// Designation - Represent a full designation, which is a sequence of /// designators. This class is mostly a helper for InitListDesignations. class Designation { @@ -188,9 +211,7 @@ class Designation { public: /// AddDesignator - Add a designator to the end of this list. - void AddDesignator(Designator D) { - Designators.push_back(D); - } + void AddDesignator(Designator D) { Designators.push_back(D); } bool empty() const { return Designators.empty(); } @@ -199,14 +220,6 @@ public: assert(Idx < Designators.size()); return Designators[Idx]; } - - /// ClearExprs - Null out any expression references, which prevents them from - /// being 'delete'd later. - void ClearExprs(Sema &Actions) {} - - /// FreeExprs - Release any unclaimed memory for the expressions in this - /// designation. - void FreeExprs(Sema &Actions) {} }; } // end namespace clang diff --git a/contrib/llvm-project/clang/include/clang/Sema/EnterExpressionEvaluationContext.h b/contrib/llvm-project/clang/include/clang/Sema/EnterExpressionEvaluationContext.h new file mode 100644 index 00000000000..5eca797b884 --- /dev/null +++ b/contrib/llvm-project/clang/include/clang/Sema/EnterExpressionEvaluationContext.h @@ -0,0 +1,69 @@ +//===--- EnterExpressionEvaluationContext.h ---------------------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CLANG_SEMA_ENTEREXPRESSIONEVALUATIONCONTEXT_H +#define LLVM_CLANG_SEMA_ENTEREXPRESSIONEVALUATIONCONTEXT_H + +#include "clang/Sema/Sema.h" + +namespace clang { + +class Decl; + +/// RAII object that enters a new expression evaluation context. +class EnterExpressionEvaluationContext { + Sema &Actions; + bool Entered = true; + +public: + EnterExpressionEvaluationContext( + Sema &Actions, Sema::ExpressionEvaluationContext NewContext, + Decl *LambdaContextDecl = nullptr, + Sema::ExpressionEvaluationContextRecord::ExpressionKind ExprContext = + Sema::ExpressionEvaluationContextRecord::EK_Other, + bool ShouldEnter = true) + : Actions(Actions), Entered(ShouldEnter) { + if (Entered) + Actions.PushExpressionEvaluationContext(NewContext, LambdaContextDecl, + ExprContext); + } + EnterExpressionEvaluationContext( + Sema &Actions, Sema::ExpressionEvaluationContext NewContext, + Sema::ReuseLambdaContextDecl_t, + Sema::ExpressionEvaluationContextRecord::ExpressionKind ExprContext = + Sema::ExpressionEvaluationContextRecord::EK_Other) + : Actions(Actions) { + Actions.PushExpressionEvaluationContext( + NewContext, Sema::ReuseLambdaContextDecl, ExprContext); + } + + enum InitListTag { InitList }; + EnterExpressionEvaluationContext(Sema &Actions, InitListTag, + bool ShouldEnter = true) + : Actions(Actions), Entered(false) { + // In C++11 onwards, narrowing checks are performed on the contents of + // braced-init-lists, even when they occur within unevaluated operands. + // Therefore we still need to instantiate constexpr functions used in such + // a context. + if (ShouldEnter && Actions.isUnevaluatedContext() && + Actions.getLangOpts().CPlusPlus11) { + Actions.PushExpressionEvaluationContext( + Sema::ExpressionEvaluationContext::UnevaluatedList); + Entered = true; + } + } + + ~EnterExpressionEvaluationContext() { + if (Entered) + Actions.PopExpressionEvaluationContext(); + } +}; + +} // namespace clang + +#endif diff --git a/contrib/llvm-project/clang/include/clang/Sema/ExternalSemaSource.h b/contrib/llvm-project/clang/include/clang/Sema/ExternalSemaSource.h index 17a7ffd3bb6..22d1ee2df11 100644 --- a/contrib/llvm-project/clang/include/clang/Sema/ExternalSemaSource.h +++ b/contrib/llvm-project/clang/include/clang/Sema/ExternalSemaSource.h @@ -230,6 +230,11 @@ public: return false; } + /// Notify the external source that a lambda was assigned a mangling number. + /// This enables the external source to track the correspondence between + /// lambdas and mangling numbers if necessary. + virtual void AssignedLambdaNumbering(const CXXRecordDecl *Lambda) {} + /// LLVM-style RTTI. /// \{ bool isA(const void *ClassID) const override { diff --git a/contrib/llvm-project/clang/include/clang/Sema/HLSLExternalSemaSource.h b/contrib/llvm-project/clang/include/clang/Sema/HLSLExternalSemaSource.h index 8531609bb9e..4b6bc96f72e 100644 --- a/contrib/llvm-project/clang/include/clang/Sema/HLSLExternalSemaSource.h +++ b/contrib/llvm-project/clang/include/clang/Sema/HLSLExternalSemaSource.h @@ -23,7 +23,7 @@ class Sema; class HLSLExternalSemaSource : public ExternalSemaSource { Sema *SemaPtr = nullptr; NamespaceDecl *HLSLNamespace = nullptr; - CXXRecordDecl *ResourceDecl; + CXXRecordDecl *ResourceDecl = nullptr; using CompletionFunction = std::function; llvm::DenseMap Completions; diff --git a/contrib/llvm-project/clang/include/clang/Sema/IdentifierResolver.h b/contrib/llvm-project/clang/include/clang/Sema/IdentifierResolver.h index 7c8dc46307d..1fbd6c48e51 100644 --- a/contrib/llvm-project/clang/include/clang/Sema/IdentifierResolver.h +++ b/contrib/llvm-project/clang/include/clang/Sema/IdentifierResolver.h @@ -134,13 +134,14 @@ public: explicit IdentifierResolver(Preprocessor &PP); ~IdentifierResolver(); - /// begin - Returns an iterator for decls with the name 'Name'. + /// Returns a range of decls with the name 'Name'. + llvm::iterator_range decls(DeclarationName Name); + + /// Returns an iterator over decls with the name 'Name'. iterator begin(DeclarationName Name); - /// end - Returns an iterator that has 'finished'. - iterator end() { - return iterator(); - } + /// Returns the end iterator. + iterator end() { return iterator(); } /// isDeclInScope - If 'Ctx' is a function/method, isDeclInScope returns true /// if 'D' is in Scope 'S', otherwise 'S' is ignored and isDeclInScope returns diff --git a/contrib/llvm-project/clang/include/clang/Sema/Initialization.h b/contrib/llvm-project/clang/include/clang/Sema/Initialization.h index e1bbea0d118..2072cd8d1c3 100644 --- a/contrib/llvm-project/clang/include/clang/Sema/Initialization.h +++ b/contrib/llvm-project/clang/include/clang/Sema/Initialization.h @@ -1121,6 +1121,9 @@ public: /// Parenthesized list initialization failed at some point. /// This is a C++20 feature. FK_ParenthesizedListInitFailed, + + // A designated initializer was provided for a non-aggregate type. + FK_DesignatedInitForNonAggregate, }; private: diff --git a/contrib/llvm-project/clang/include/clang/Sema/Lookup.h b/contrib/llvm-project/clang/include/clang/Sema/Lookup.h index 39d980a857b..351fa0c6ca0 100644 --- a/contrib/llvm-project/clang/include/clang/Sema/Lookup.h +++ b/contrib/llvm-project/clang/include/clang/Sema/Lookup.h @@ -657,6 +657,15 @@ public: F.CalledDone = true; } + // The move assignment operator is defined as deleted pending + // further motivation. + Filter &operator=(Filter &&) = delete; + + // The copy constrcutor and copy assignment operator is defined as deleted + // pending further motivation. + Filter(const Filter &) = delete; + Filter &operator=(const Filter &) = delete; + ~Filter() { assert(CalledDone && "LookupResult::Filter destroyed without done() call"); diff --git a/contrib/llvm-project/clang/include/clang/Sema/MultiplexExternalSemaSource.h b/contrib/llvm-project/clang/include/clang/Sema/MultiplexExternalSemaSource.h index b0bb15eccee..2bf91cb5212 100644 --- a/contrib/llvm-project/clang/include/clang/Sema/MultiplexExternalSemaSource.h +++ b/contrib/llvm-project/clang/include/clang/Sema/MultiplexExternalSemaSource.h @@ -360,6 +360,9 @@ public: bool MaybeDiagnoseMissingCompleteType(SourceLocation Loc, QualType T) override; + // Inform all attached sources that a mangling number was assigned. + void AssignedLambdaNumbering(const CXXRecordDecl *Lambda) override; + /// LLVM-style RTTI. /// \{ bool isA(const void *ClassID) const override { diff --git a/contrib/llvm-project/clang/include/clang/Sema/Overload.h b/contrib/llvm-project/clang/include/clang/Sema/Overload.h index 1827ea5d1e5..a97968dc7b2 100644 --- a/contrib/llvm-project/clang/include/clang/Sema/Overload.h +++ b/contrib/llvm-project/clang/include/clang/Sema/Overload.h @@ -162,6 +162,9 @@ class Sema; /// Arm SVE Vector conversions ICK_SVE_Vector_Conversion, + /// RISC-V RVV Vector conversions + ICK_RVV_Vector_Conversion, + /// A vector splat from an arithmetic type ICK_Vector_Splat, diff --git a/contrib/llvm-project/clang/include/clang/Sema/ParsedAttr.h b/contrib/llvm-project/clang/include/clang/Sema/ParsedAttr.h index f060564e671..592580bccd2 100644 --- a/contrib/llvm-project/clang/include/clang/Sema/ParsedAttr.h +++ b/contrib/llvm-project/clang/include/clang/Sema/ParsedAttr.h @@ -17,12 +17,12 @@ #include "clang/Basic/AttrSubjectMatchRules.h" #include "clang/Basic/AttributeCommonInfo.h" #include "clang/Basic/Diagnostic.h" +#include "clang/Basic/ParsedAttrInfo.h" #include "clang/Basic/SourceLocation.h" #include "clang/Sema/Ownership.h" #include "llvm/ADT/PointerUnion.h" #include "llvm/ADT/SmallVector.h" #include "llvm/Support/Allocator.h" -#include "llvm/Support/Registry.h" #include "llvm/Support/VersionTuple.h" #include #include @@ -36,124 +36,10 @@ class Decl; class Expr; class IdentifierInfo; class LangOptions; -class ParsedAttr; class Sema; class Stmt; class TargetInfo; -struct ParsedAttrInfo { - /// Corresponds to the Kind enum. - unsigned AttrKind : 16; - /// The number of required arguments of this attribute. - unsigned NumArgs : 4; - /// The number of optional arguments of this attributes. - unsigned OptArgs : 4; - /// The number of non-fake arguments specified in the attribute definition. - unsigned NumArgMembers : 4; - /// True if the parsing does not match the semantic content. - unsigned HasCustomParsing : 1; - // True if this attribute accepts expression parameter pack expansions. - unsigned AcceptsExprPack : 1; - /// True if this attribute is only available for certain targets. - unsigned IsTargetSpecific : 1; - /// True if this attribute applies to types. - unsigned IsType : 1; - /// True if this attribute applies to statements. - unsigned IsStmt : 1; - /// True if this attribute has any spellings that are known to gcc. - unsigned IsKnownToGCC : 1; - /// True if this attribute is supported by #pragma clang attribute. - unsigned IsSupportedByPragmaAttribute : 1; - /// The syntaxes supported by this attribute and how they're spelled. - struct Spelling { - AttributeCommonInfo::Syntax Syntax; - const char *NormalizedFullName; - }; - ArrayRef Spellings; - // The names of the known arguments of this attribute. - ArrayRef ArgNames; - -protected: - constexpr ParsedAttrInfo(AttributeCommonInfo::Kind AttrKind = - AttributeCommonInfo::NoSemaHandlerAttribute) - : AttrKind(AttrKind), NumArgs(0), OptArgs(0), NumArgMembers(0), - HasCustomParsing(0), AcceptsExprPack(0), IsTargetSpecific(0), IsType(0), - IsStmt(0), IsKnownToGCC(0), IsSupportedByPragmaAttribute(0) {} - - constexpr ParsedAttrInfo(AttributeCommonInfo::Kind AttrKind, unsigned NumArgs, - unsigned OptArgs, unsigned NumArgMembers, - unsigned HasCustomParsing, unsigned AcceptsExprPack, - unsigned IsTargetSpecific, unsigned IsType, - unsigned IsStmt, unsigned IsKnownToGCC, - unsigned IsSupportedByPragmaAttribute, - ArrayRef Spellings, - ArrayRef ArgNames) - : AttrKind(AttrKind), NumArgs(NumArgs), OptArgs(OptArgs), - NumArgMembers(NumArgMembers), HasCustomParsing(HasCustomParsing), - AcceptsExprPack(AcceptsExprPack), IsTargetSpecific(IsTargetSpecific), - IsType(IsType), IsStmt(IsStmt), IsKnownToGCC(IsKnownToGCC), - IsSupportedByPragmaAttribute(IsSupportedByPragmaAttribute), - Spellings(Spellings), ArgNames(ArgNames) {} - -public: - virtual ~ParsedAttrInfo() = default; - - /// Check if this attribute appertains to D, and issue a diagnostic if not. - virtual bool diagAppertainsToDecl(Sema &S, const ParsedAttr &Attr, - const Decl *D) const { - return true; - } - /// Check if this attribute appertains to St, and issue a diagnostic if not. - virtual bool diagAppertainsToStmt(Sema &S, const ParsedAttr &Attr, - const Stmt *St) const { - return true; - } - /// Check if the given attribute is mutually exclusive with other attributes - /// already applied to the given declaration. - virtual bool diagMutualExclusion(Sema &S, const ParsedAttr &A, - const Decl *D) const { - return true; - } - /// Check if this attribute is allowed by the language we are compiling. - virtual bool acceptsLangOpts(const LangOptions &LO) const { return true; } - - /// Check if this attribute is allowed when compiling for the given target. - virtual bool existsInTarget(const TargetInfo &Target) const { - return true; - } - /// Convert the spelling index of Attr to a semantic spelling enum value. - virtual unsigned - spellingIndexToSemanticSpelling(const ParsedAttr &Attr) const { - return UINT_MAX; - } - /// Returns true if the specified parameter index for this attribute in - /// Attr.td is an ExprArgument or VariadicExprArgument, or a subclass thereof; - /// returns false otherwise. - virtual bool isParamExpr(size_t N) const { return false; } - /// Populate Rules with the match rules of this attribute. - virtual void getPragmaAttributeMatchRules( - llvm::SmallVectorImpl> &Rules, - const LangOptions &LangOpts) const { - } - enum AttrHandling { - NotHandled, - AttributeApplied, - AttributeNotApplied - }; - /// If this ParsedAttrInfo knows how to handle this ParsedAttr applied to this - /// Decl then do so and return either AttributeApplied if it was applied or - /// AttributeNotApplied if it wasn't. Otherwise return NotHandled. - virtual AttrHandling handleDeclAttribute(Sema &S, Decl *D, - const ParsedAttr &Attr) const { - return NotHandled; - } - - static const ParsedAttrInfo &get(const AttributeCommonInfo &A); - static ArrayRef getAllBuiltin(); -}; - -typedef llvm::Registry ParsedAttrInfoRegistry; - /// Represents information about a change in availability for /// an entity, which is part of the encoding of the 'availability' /// attribute. @@ -318,10 +204,9 @@ private: /// Constructor for attributes with expression arguments. ParsedAttr(IdentifierInfo *attrName, SourceRange attrRange, IdentifierInfo *scopeName, SourceLocation scopeLoc, - ArgsUnion *args, unsigned numArgs, Syntax syntaxUsed, + ArgsUnion *args, unsigned numArgs, Form formUsed, SourceLocation ellipsisLoc) - : AttributeCommonInfo(attrName, scopeName, attrRange, scopeLoc, - syntaxUsed), + : AttributeCommonInfo(attrName, scopeName, attrRange, scopeLoc, formUsed), EllipsisLoc(ellipsisLoc), NumArgs(numArgs), Invalid(false), UsedAsTypeAttr(false), IsAvailability(false), IsTypeTagForDatatype(false), IsProperty(false), HasParsedType(false), @@ -337,10 +222,9 @@ private: IdentifierLoc *Parm, const AvailabilityChange &introduced, const AvailabilityChange &deprecated, const AvailabilityChange &obsoleted, SourceLocation unavailable, - const Expr *messageExpr, Syntax syntaxUsed, SourceLocation strict, + const Expr *messageExpr, Form formUsed, SourceLocation strict, const Expr *replacementExpr) - : AttributeCommonInfo(attrName, scopeName, attrRange, scopeLoc, - syntaxUsed), + : AttributeCommonInfo(attrName, scopeName, attrRange, scopeLoc, formUsed), NumArgs(1), Invalid(false), UsedAsTypeAttr(false), IsAvailability(true), IsTypeTagForDatatype(false), IsProperty(false), HasParsedType(false), HasProcessingCache(false), IsPragmaClangAttribute(false), @@ -356,9 +240,8 @@ private: ParsedAttr(IdentifierInfo *attrName, SourceRange attrRange, IdentifierInfo *scopeName, SourceLocation scopeLoc, IdentifierLoc *Parm1, IdentifierLoc *Parm2, IdentifierLoc *Parm3, - Syntax syntaxUsed) - : AttributeCommonInfo(attrName, scopeName, attrRange, scopeLoc, - syntaxUsed), + Form formUsed) + : AttributeCommonInfo(attrName, scopeName, attrRange, scopeLoc, formUsed), NumArgs(3), Invalid(false), UsedAsTypeAttr(false), IsAvailability(false), IsTypeTagForDatatype(false), IsProperty(false), HasParsedType(false), HasProcessingCache(false), @@ -373,9 +256,8 @@ private: ParsedAttr(IdentifierInfo *attrName, SourceRange attrRange, IdentifierInfo *scopeName, SourceLocation scopeLoc, IdentifierLoc *ArgKind, ParsedType matchingCType, - bool layoutCompatible, bool mustBeNull, Syntax syntaxUsed) - : AttributeCommonInfo(attrName, scopeName, attrRange, scopeLoc, - syntaxUsed), + bool layoutCompatible, bool mustBeNull, Form formUsed) + : AttributeCommonInfo(attrName, scopeName, attrRange, scopeLoc, formUsed), NumArgs(1), Invalid(false), UsedAsTypeAttr(false), IsAvailability(false), IsTypeTagForDatatype(true), IsProperty(false), HasParsedType(false), HasProcessingCache(false), @@ -391,23 +273,21 @@ private: /// Constructor for attributes with a single type argument. ParsedAttr(IdentifierInfo *attrName, SourceRange attrRange, IdentifierInfo *scopeName, SourceLocation scopeLoc, - ParsedType typeArg, Syntax syntaxUsed) - : AttributeCommonInfo(attrName, scopeName, attrRange, scopeLoc, - syntaxUsed), - NumArgs(0), Invalid(false), UsedAsTypeAttr(false), - IsAvailability(false), IsTypeTagForDatatype(false), IsProperty(false), - HasParsedType(true), HasProcessingCache(false), - IsPragmaClangAttribute(false), Info(ParsedAttrInfo::get(*this)) { + ParsedType typeArg, Form formUsed, SourceLocation ellipsisLoc) + : AttributeCommonInfo(attrName, scopeName, attrRange, scopeLoc, formUsed), + EllipsisLoc(ellipsisLoc), NumArgs(0), Invalid(false), + UsedAsTypeAttr(false), IsAvailability(false), + IsTypeTagForDatatype(false), IsProperty(false), HasParsedType(true), + HasProcessingCache(false), IsPragmaClangAttribute(false), + Info(ParsedAttrInfo::get(*this)) { new (&getTypeBuffer()) ParsedType(typeArg); } /// Constructor for microsoft __declspec(property) attribute. ParsedAttr(IdentifierInfo *attrName, SourceRange attrRange, IdentifierInfo *scopeName, SourceLocation scopeLoc, - IdentifierInfo *getterId, IdentifierInfo *setterId, - Syntax syntaxUsed) - : AttributeCommonInfo(attrName, scopeName, attrRange, scopeLoc, - syntaxUsed), + IdentifierInfo *getterId, IdentifierInfo *setterId, Form formUsed) + : AttributeCommonInfo(attrName, scopeName, attrRange, scopeLoc, formUsed), NumArgs(0), Invalid(false), UsedAsTypeAttr(false), IsAvailability(false), IsTypeTagForDatatype(false), IsProperty(true), HasParsedType(false), HasProcessingCache(false), @@ -817,12 +697,19 @@ public: AttributePool(AttributeFactory &factory) : Factory(factory) {} AttributePool(const AttributePool &) = delete; + // The copy assignment operator is defined as deleted pending further + // motivation. + AttributePool &operator=(const AttributePool &) = delete; ~AttributePool() { Factory.reclaimPool(*this); } /// Move the given pool's allocations to this pool. AttributePool(AttributePool &&pool) = default; + // The move assignment operator is defined as deleted pending further + // motivation. + AttributePool &operator=(AttributePool &&pool) = delete; + AttributeFactory &getFactory() const { return Factory; } void clear() { @@ -838,8 +725,7 @@ public: ParsedAttr *create(IdentifierInfo *attrName, SourceRange attrRange, IdentifierInfo *scopeName, SourceLocation scopeLoc, - ArgsUnion *args, unsigned numArgs, - ParsedAttr::Syntax syntax, + ArgsUnion *args, unsigned numArgs, ParsedAttr::Form form, SourceLocation ellipsisLoc = SourceLocation()) { size_t temp = ParsedAttr::totalSizeToAlloc(numArgs, 0, 0, 0, 0)); return add(new (memory) ParsedAttr(attrName, attrRange, scopeName, scopeLoc, - args, numArgs, syntax, ellipsisLoc)); + args, numArgs, form, ellipsisLoc)); } ParsedAttr *create(IdentifierInfo *attrName, SourceRange attrRange, @@ -861,24 +747,24 @@ public: const AvailabilityChange &deprecated, const AvailabilityChange &obsoleted, SourceLocation unavailable, const Expr *MessageExpr, - ParsedAttr::Syntax syntax, SourceLocation strict, + ParsedAttr::Form form, SourceLocation strict, const Expr *ReplacementExpr) { void *memory = allocate(AttributeFactory::AvailabilityAllocSize); return add(new (memory) ParsedAttr( attrName, attrRange, scopeName, scopeLoc, Param, introduced, deprecated, - obsoleted, unavailable, MessageExpr, syntax, strict, ReplacementExpr)); + obsoleted, unavailable, MessageExpr, form, strict, ReplacementExpr)); } ParsedAttr *create(IdentifierInfo *attrName, SourceRange attrRange, IdentifierInfo *scopeName, SourceLocation scopeLoc, IdentifierLoc *Param1, IdentifierLoc *Param2, - IdentifierLoc *Param3, ParsedAttr::Syntax syntax) { + IdentifierLoc *Param3, ParsedAttr::Form form) { void *memory = allocate( ParsedAttr::totalSizeToAlloc(3, 0, 0, 0, 0)); return add(new (memory) ParsedAttr(attrName, attrRange, scopeName, scopeLoc, - Param1, Param2, Param3, syntax)); + Param1, Param2, Param3, form)); } ParsedAttr * @@ -886,34 +772,35 @@ public: IdentifierInfo *scopeName, SourceLocation scopeLoc, IdentifierLoc *argumentKind, ParsedType matchingCType, bool layoutCompatible, - bool mustBeNull, ParsedAttr::Syntax syntax) { + bool mustBeNull, ParsedAttr::Form form) { void *memory = allocate(AttributeFactory::TypeTagForDatatypeAllocSize); return add(new (memory) ParsedAttr(attrName, attrRange, scopeName, scopeLoc, argumentKind, matchingCType, - layoutCompatible, mustBeNull, syntax)); + layoutCompatible, mustBeNull, form)); } ParsedAttr *createTypeAttribute(IdentifierInfo *attrName, SourceRange attrRange, IdentifierInfo *scopeName, SourceLocation scopeLoc, ParsedType typeArg, - ParsedAttr::Syntax syntaxUsed) { + ParsedAttr::Form formUsed, + SourceLocation ellipsisLoc) { void *memory = allocate( ParsedAttr::totalSizeToAlloc(0, 0, 0, 1, 0)); return add(new (memory) ParsedAttr(attrName, attrRange, scopeName, scopeLoc, - typeArg, syntaxUsed)); + typeArg, formUsed, ellipsisLoc)); } ParsedAttr * createPropertyAttribute(IdentifierInfo *attrName, SourceRange attrRange, IdentifierInfo *scopeName, SourceLocation scopeLoc, IdentifierInfo *getterId, IdentifierInfo *setterId, - ParsedAttr::Syntax syntaxUsed) { + ParsedAttr::Form formUsed) { void *memory = allocate(AttributeFactory::PropertyAllocSize); return add(new (memory) ParsedAttr(attrName, attrRange, scopeName, scopeLoc, - getterId, setterId, syntaxUsed)); + getterId, setterId, formUsed)); } }; @@ -1010,6 +897,16 @@ public: }); } + const ParsedAttr *getMSPropertyAttr() const { + auto It = llvm::find_if(AttrList, [](const ParsedAttr *AL) { + return AL->isDeclspecPropertyAttribute(); + }); + if (It != AttrList.end()) + return *It; + return nullptr; + } + bool hasMSPropertyAttr() const { return getMSPropertyAttr(); } + private: VecTy AttrList; }; @@ -1024,6 +921,7 @@ class ParsedAttributes : public ParsedAttributesView { public: ParsedAttributes(AttributeFactory &factory) : pool(factory) {} ParsedAttributes(const ParsedAttributes &) = delete; + ParsedAttributes &operator=(const ParsedAttributes &) = delete; AttributePool &getPool() const { return pool; } @@ -1053,11 +951,10 @@ public: /// Add attribute with expression arguments. ParsedAttr *addNew(IdentifierInfo *attrName, SourceRange attrRange, IdentifierInfo *scopeName, SourceLocation scopeLoc, - ArgsUnion *args, unsigned numArgs, - ParsedAttr::Syntax syntax, + ArgsUnion *args, unsigned numArgs, ParsedAttr::Form form, SourceLocation ellipsisLoc = SourceLocation()) { ParsedAttr *attr = pool.create(attrName, attrRange, scopeName, scopeLoc, - args, numArgs, syntax, ellipsisLoc); + args, numArgs, form, ellipsisLoc); addAtEnd(attr); return attr; } @@ -1069,11 +966,11 @@ public: const AvailabilityChange &deprecated, const AvailabilityChange &obsoleted, SourceLocation unavailable, const Expr *MessageExpr, - ParsedAttr::Syntax syntax, SourceLocation strict, + ParsedAttr::Form form, SourceLocation strict, const Expr *ReplacementExpr) { ParsedAttr *attr = pool.create( attrName, attrRange, scopeName, scopeLoc, Param, introduced, deprecated, - obsoleted, unavailable, MessageExpr, syntax, strict, ReplacementExpr); + obsoleted, unavailable, MessageExpr, form, strict, ReplacementExpr); addAtEnd(attr); return attr; } @@ -1082,9 +979,9 @@ public: ParsedAttr *addNew(IdentifierInfo *attrName, SourceRange attrRange, IdentifierInfo *scopeName, SourceLocation scopeLoc, IdentifierLoc *Param1, IdentifierLoc *Param2, - IdentifierLoc *Param3, ParsedAttr::Syntax syntax) { + IdentifierLoc *Param3, ParsedAttr::Form form) { ParsedAttr *attr = pool.create(attrName, attrRange, scopeName, scopeLoc, - Param1, Param2, Param3, syntax); + Param1, Param2, Param3, form); addAtEnd(attr); return attr; } @@ -1095,10 +992,10 @@ public: IdentifierInfo *scopeName, SourceLocation scopeLoc, IdentifierLoc *argumentKind, ParsedType matchingCType, bool layoutCompatible, - bool mustBeNull, ParsedAttr::Syntax syntax) { + bool mustBeNull, ParsedAttr::Form form) { ParsedAttr *attr = pool.createTypeTagForDatatype( attrName, attrRange, scopeName, scopeLoc, argumentKind, matchingCType, - layoutCompatible, mustBeNull, syntax); + layoutCompatible, mustBeNull, form); addAtEnd(attr); return attr; } @@ -1106,10 +1003,11 @@ public: /// Add an attribute with a single type argument. ParsedAttr *addNewTypeAttr(IdentifierInfo *attrName, SourceRange attrRange, IdentifierInfo *scopeName, SourceLocation scopeLoc, - ParsedType typeArg, - ParsedAttr::Syntax syntaxUsed) { - ParsedAttr *attr = pool.createTypeAttribute(attrName, attrRange, scopeName, - scopeLoc, typeArg, syntaxUsed); + ParsedType typeArg, ParsedAttr::Form formUsed, + SourceLocation ellipsisLoc = SourceLocation()) { + ParsedAttr *attr = + pool.createTypeAttribute(attrName, attrRange, scopeName, scopeLoc, + typeArg, formUsed, ellipsisLoc); addAtEnd(attr); return attr; } @@ -1119,10 +1017,9 @@ public: addNewPropertyAttr(IdentifierInfo *attrName, SourceRange attrRange, IdentifierInfo *scopeName, SourceLocation scopeLoc, IdentifierInfo *getterId, IdentifierInfo *setterId, - ParsedAttr::Syntax syntaxUsed) { - ParsedAttr *attr = - pool.createPropertyAttribute(attrName, attrRange, scopeName, scopeLoc, - getterId, setterId, syntaxUsed); + ParsedAttr::Form formUsed) { + ParsedAttr *attr = pool.createPropertyAttribute( + attrName, attrRange, scopeName, scopeLoc, getterId, setterId, formUsed); addAtEnd(attr); return attr; } diff --git a/contrib/llvm-project/clang/include/clang/Sema/RISCVIntrinsicManager.h b/contrib/llvm-project/clang/include/clang/Sema/RISCVIntrinsicManager.h index 128858bb430..2a3dd1e7c46 100644 --- a/contrib/llvm-project/clang/include/clang/Sema/RISCVIntrinsicManager.h +++ b/contrib/llvm-project/clang/include/clang/Sema/RISCVIntrinsicManager.h @@ -14,6 +14,8 @@ #ifndef LLVM_CLANG_SEMA_RISCVINTRINSICMANAGER_H #define LLVM_CLANG_SEMA_RISCVINTRINSICMANAGER_H +#include + namespace clang { class LookupResult; class IdentifierInfo; @@ -22,8 +24,12 @@ class Preprocessor; namespace sema { class RISCVIntrinsicManager { public: + enum class IntrinsicKind : uint8_t { RVV, SIFIVE_VECTOR }; + virtual ~RISCVIntrinsicManager() = default; + virtual void InitIntrinsicList() = 0; + // Create RISC-V intrinsic and insert into symbol table and return true if // found, otherwise return false. virtual bool CreateIntrinsicIfFound(LookupResult &LR, IdentifierInfo *II, diff --git a/contrib/llvm-project/clang/include/clang/Sema/Scope.h b/contrib/llvm-project/clang/include/clang/Sema/Scope.h index be5cdb62045..9e81706cd2a 100644 --- a/contrib/llvm-project/clang/include/clang/Sema/Scope.h +++ b/contrib/llvm-project/clang/include/clang/Sema/Scope.h @@ -145,6 +145,11 @@ public: /// This is a scope of some OpenMP directive with /// order clause which specifies concurrent OpenMPOrderClauseScope = 0x4000000, + /// This is the scope for a lambda, after the lambda introducer. + /// Lambdas need two FunctionPrototypeScope scopes (because there is a + /// template scope in between), the outer scope does not increase the + /// depth of recursion. + LambdaScope = 0x8000000, }; private: diff --git a/contrib/llvm-project/clang/include/clang/Sema/ScopeInfo.h b/contrib/llvm-project/clang/include/clang/Sema/ScopeInfo.h index 65fa18fbb29..26c0387dfc4 100644 --- a/contrib/llvm-project/clang/include/clang/Sema/ScopeInfo.h +++ b/contrib/llvm-project/clang/include/clang/Sema/ScopeInfo.h @@ -172,6 +172,9 @@ public: /// in the function. One of co_return, co_await, or co_yield. unsigned char FirstCoroutineStmtKind : 2; + /// Whether we found an immediate-escalating expression. + bool FoundImmediateEscalatingExpression : 1; + /// First coroutine statement in the current function. /// (ex co_return, co_await, co_yield) SourceLocation FirstCoroutineStmtLoc; @@ -388,7 +391,8 @@ public: HasPotentialAvailabilityViolations(false), ObjCShouldCallSuper(false), ObjCIsDesignatedInit(false), ObjCWarnForNoDesignatedInitChain(false), ObjCIsSecondaryInit(false), ObjCWarnForNoInitDelegation(false), - NeedsCoroutineSuspends(true), ErrorTrap(Diag) {} + NeedsCoroutineSuspends(true), FoundImmediateEscalatingExpression(false), + ErrorTrap(Diag) {} virtual ~FunctionScopeInfo(); @@ -838,6 +842,11 @@ public: /// The lambda's compiler-generated \c operator(). CXXMethodDecl *CallOperator = nullptr; + /// Indicate that we parsed the parameter list + /// at which point the mutability of the lambda + /// is known. + bool AfterParameterList = true; + /// Source range covering the lambda introducer [...]. SourceRange IntroducerRange; @@ -849,8 +858,9 @@ public: /// explicit captures. unsigned NumExplicitCaptures = 0; - /// Whether this is a mutable lambda. - bool Mutable = false; + /// Whether this is a mutable lambda. Until the mutable keyword is parsed, + /// we assume the lambda is mutable. + bool Mutable = true; /// Whether the (empty) parameter list is explicit. bool ExplicitParams = false; diff --git a/contrib/llvm-project/clang/include/clang/Sema/Sema.h b/contrib/llvm-project/clang/include/clang/Sema/Sema.h index e57955f16bd..3418a37b307 100644 --- a/contrib/llvm-project/clang/include/clang/Sema/Sema.h +++ b/contrib/llvm-project/clang/include/clang/Sema/Sema.h @@ -481,6 +481,12 @@ public: PSK_Pop_Set = PSK_Pop | PSK_Set, // #pragma (pop[, id], value) }; + struct PragmaPackInfo { + PragmaMsStackAction Action; + StringRef SlotLabel; + Token Alignment; + }; + // #pragma pack and align. class AlignPackInfo { public: @@ -704,6 +710,22 @@ public: return result; } + class FpPragmaStackSaveRAII { + public: + FpPragmaStackSaveRAII(Sema &S) : S(S), SavedStack(S.FpPragmaStack) {} + ~FpPragmaStackSaveRAII() { S.FpPragmaStack = std::move(SavedStack); } + + private: + Sema &S; + PragmaStack SavedStack; + }; + + void resetFPOptions(FPOptions FPO) { + CurFPFeatures = FPO; + FpPragmaStack.Stack.clear(); + FpPragmaStack.CurrentValue = FPO.getChangesFrom(FPOptions(LangOpts)); + } + // RAII object to push / pop sentinel slots for all MS #pragma stacks. // Actions should be performed only if we enter / exit a C++ method body. class PragmaStackSentinelRAII { @@ -786,8 +808,7 @@ public: /// we won't know until all lvalue-to-rvalue and discarded value conversions /// have been applied to all subexpressions of the enclosing full expression. /// This is cleared at the end of each full expression. - using MaybeODRUseExprSet = llvm::SetVector, - llvm::SmallPtrSet>; + using MaybeODRUseExprSet = llvm::SmallSetVector; MaybeODRUseExprSet MaybeODRUseExprs; std::unique_ptr CachedFunctionScope; @@ -800,6 +821,9 @@ public: /// context. unsigned FunctionScopesStart = 0; + /// Track the number of currently active capturing scopes. + unsigned CapturingFunctionScopes = 0; + ArrayRef getFunctionScopes() const { return llvm::ArrayRef(FunctionScopes.begin() + FunctionScopesStart, FunctionScopes.end()); @@ -834,7 +858,7 @@ public: /// FieldCollector - Collects CXXFieldDecls during parsing of C++ classes. std::unique_ptr FieldCollector; - typedef llvm::SmallSetVector NamedDeclSetType; + typedef llvm::SmallSetVector NamedDeclSetType; /// Set containing all declared private fields that are not used. NamedDeclSetType UnusedPrivateFields; @@ -929,7 +953,7 @@ public: class DelayedDiagnostics; class DelayedDiagnosticsState { - sema::DelayedDiagnosticPool *SavedPool; + sema::DelayedDiagnosticPool *SavedPool = nullptr; friend class Sema::DelayedDiagnostics; }; typedef DelayedDiagnosticsState ParsingDeclState; @@ -940,10 +964,10 @@ public: class DelayedDiagnostics { /// The current pool of diagnostics into which delayed /// diagnostics should go. - sema::DelayedDiagnosticPool *CurPool; + sema::DelayedDiagnosticPool *CurPool = nullptr; public: - DelayedDiagnostics() : CurPool(nullptr) {} + DelayedDiagnostics() = default; /// Adds a delayed diagnostic. void add(const sema::DelayedDiagnostic &diag); // in DelayedDiagnostic.h @@ -1039,7 +1063,7 @@ public: /// ExpressionEvaluationContextRecord object. bool isConstantEvaluatedOverride; - bool isConstantEvaluated() { + bool isConstantEvaluated() const { return ExprEvalContexts.back().isConstantEvaluated() || isConstantEvaluatedOverride; } @@ -1054,12 +1078,19 @@ public: public: SynthesizedFunctionScope(Sema &S, DeclContext *DC) : S(S), SavedContext(S, DC) { + auto *FD = dyn_cast(DC); S.PushFunctionScope(); S.PushExpressionEvaluationContext( - Sema::ExpressionEvaluationContext::PotentiallyEvaluated); - if (auto *FD = dyn_cast(DC)) + (FD && FD->isConsteval()) + ? ExpressionEvaluationContext::ImmediateFunctionContext + : ExpressionEvaluationContext::PotentiallyEvaluated); + if (FD) { FD->setWillHaveBody(true); - else + S.ExprEvalContexts.back().InImmediateFunctionContext = + FD->isImmediateFunction(); + S.ExprEvalContexts.back().InImmediateEscalatingFunctionContext = + S.getLangOpts().CPlusPlus20 && FD->isImmediateEscalating(); + } else assert(isa(DC)); } @@ -1078,8 +1109,10 @@ public: ~SynthesizedFunctionScope() { if (PushedCodeSynthesisContext) S.popCodeSynthesisContext(); - if (auto *FD = dyn_cast(S.CurContext)) + if (auto *FD = dyn_cast(S.CurContext)) { FD->setWillHaveBody(false); + S.CheckImmediateEscalatingFunctionDefinition(FD, S.getCurFunction()); + } S.PopExpressionEvaluationContext(); S.PopFunctionScopeInfo(); } @@ -1135,10 +1168,6 @@ public: /// standard library. LazyDeclPtr StdAlignValT; - /// The C++ "std::experimental" namespace, where the experimental parts - /// of the standard library resides. - NamespaceDecl *StdExperimentalNamespaceCache; - /// The C++ "std::initializer_list" template, which is defined in /// \. ClassTemplateDecl *StdInitializerList; @@ -1146,17 +1175,10 @@ public: /// The C++ "std::coroutine_traits" template, which is defined in /// \ ClassTemplateDecl *StdCoroutineTraitsCache; - /// The namespace where coroutine components are defined. In standard, - /// they are defined in std namespace. And in the previous implementation, - /// they are defined in std::experimental namespace. - NamespaceDecl *CoroTraitsNamespaceCache; /// The C++ "type_info" declaration, which is defined in \. RecordDecl *CXXTypeInfoDecl; - /// The MSVC "_GUID" struct, which is defined in MSVC header files. - RecordDecl *MSVCGuidDecl; - /// The C++ "std::source_location::__impl" struct, defined in /// \. RecordDecl *StdSourceLocationImplDecl; @@ -1246,7 +1268,7 @@ public: /// In addition of being constant evaluated, the current expression /// occurs in an immediate function context - either a consteval function - /// or a consteval if function. + /// or a consteval if statement. ImmediateFunctionContext, /// The current expression is potentially evaluated at run time, @@ -1327,6 +1349,7 @@ public: // an immediate function context, so they need to be tracked independently. bool InDiscardedStatement; bool InImmediateFunctionContext; + bool InImmediateEscalatingFunctionContext; bool IsCurrentlyCheckingDefaultArgumentOrInitializer = false; @@ -1355,7 +1378,8 @@ public: : Context(Context), ParentCleanup(ParentCleanup), NumCleanupObjects(NumCleanupObjects), NumTypos(0), ManglingContextDecl(ManglingContextDecl), ExprContext(ExprContext), - InDiscardedStatement(false), InImmediateFunctionContext(false) {} + InDiscardedStatement(false), InImmediateFunctionContext(false), + InImmediateEscalatingFunctionContext(false) {} bool isUnevaluated() const { return Context == ExpressionEvaluationContext::Unevaluated || @@ -1372,7 +1396,7 @@ public: return Context == ExpressionEvaluationContext::ImmediateFunctionContext || (Context == ExpressionEvaluationContext::DiscardedStatement && InImmediateFunctionContext) || - // C++2b [expr.const]p14: + // C++23 [expr.const]p14: // An expression or conversion is in an immediate function // context if it is potentially evaluated and either: // * its innermost enclosing non-block scope is a function @@ -1491,7 +1515,7 @@ public: /// Determine if VD, which must be a variable or function, is an external /// symbol that nonetheless can't be referenced from outside this translation /// unit because its type has no linkage and it's not extern "C". - bool isExternalWithNoLinkageType(ValueDecl *VD); + bool isExternalWithNoLinkageType(const ValueDecl *VD) const; /// Obtain a sorted list of functions that are undefined but ODR-used. void getUndefinedButUsed( @@ -1623,6 +1647,9 @@ public: /// Indicate RISC-V vector builtin functions enabled or not. bool DeclareRISCVVBuiltins = false; + /// Indicate RISC-V SiFive vector builtin functions enabled or not. + bool DeclareRISCVSiFiveVectorBuiltins = false; + private: std::unique_ptr RVIntrinsicManager; @@ -1780,9 +1807,15 @@ public: }; SemaDiagnosticBuilder(Kind K, SourceLocation Loc, unsigned DiagID, - FunctionDecl *Fn, Sema &S); + const FunctionDecl *Fn, Sema &S); SemaDiagnosticBuilder(SemaDiagnosticBuilder &&D); SemaDiagnosticBuilder(const SemaDiagnosticBuilder &) = default; + + // The copy and move assignment operator is defined as deleted pending + // further motivation. + SemaDiagnosticBuilder &operator=(const SemaDiagnosticBuilder &) = delete; + SemaDiagnosticBuilder &operator=(SemaDiagnosticBuilder &&) = delete; + ~SemaDiagnosticBuilder(); bool isImmediate() const { return ImmediateDiag.has_value(); } @@ -1855,7 +1888,7 @@ public: Sema &S; SourceLocation Loc; unsigned DiagID; - FunctionDecl *Fn; + const FunctionDecl *Fn; bool ShowCallStack; // Invariant: At most one of these Optionals has a value. @@ -2275,17 +2308,28 @@ private: SourceLocation BeginLoc; clang::Module *Module = nullptr; bool ModuleInterface = false; - bool IsPartition = false; - bool ImplicitGlobalModuleFragment = false; VisibleModuleSet OuterVisibleModules; }; /// The modules we're currently parsing. llvm::SmallVector ModuleScopes; - /// The global module fragment of the current translation unit. - clang::Module *GlobalModuleFragment = nullptr; - /// The modules we imported directly. - llvm::SmallPtrSet DirectModuleImports; + /// For an interface unit, this is the implicitly imported interface unit. + clang::Module *ThePrimaryInterface = nullptr; + + /// The explicit global module fragment of the current translation unit. + /// The explicit Global Module Fragment, as specified in C++ + /// [module.global.frag]. + clang::Module *TheGlobalModuleFragment = nullptr; + + /// The implicit global module fragments of the current translation unit. + /// We would only create at most two implicit global module fragments to + /// avoid performance penalties when there are many language linkage + /// exports. + /// + /// The contents in the implicit global module fragment can't be discarded + /// no matter if it is exported or not. + clang::Module *TheImplicitGlobalModuleFragment = nullptr; + clang::Module *TheExportedImplicitGlobalModuleFragment = nullptr; /// Namespace definitions that we will export when they finish. llvm::SmallPtrSet DeferredExportedNamespaces; @@ -2301,11 +2345,17 @@ private: return getCurrentModule() ? getCurrentModule()->isModulePurview() : false; } - /// Enter the scope of the global module. - Module *PushGlobalModuleFragment(SourceLocation BeginLoc, bool IsImplicit); - /// Leave the scope of the global module. + /// Enter the scope of the explicit global module fragment. + Module *PushGlobalModuleFragment(SourceLocation BeginLoc); + /// Leave the scope of the explicit global module fragment. void PopGlobalModuleFragment(); + /// Enter the scope of an implicit global module fragment. + Module *PushImplicitGlobalModuleFragment(SourceLocation BeginLoc, + bool IsExported); + /// Leave the scope of an implicit global module fragment. + void PopImplicitGlobalModuleFragment(); + VisibleModuleSet VisibleModules; /// Cache for module units which is usable for current module. @@ -2337,13 +2387,6 @@ public: return Entity->getOwningModule(); } - bool isModuleDirectlyImported(const Module *M) { - return DirectModuleImports.contains(M); - } - - // Determine whether the module M belongs to the current TU. - bool isModuleUnitOfCurrentTU(const Module *M) const; - /// Make a merged definition of an existing hidden definition \p ND /// visible at the specified location. void makeMergedDefinitionVisible(NamedDecl *ND); @@ -2392,8 +2435,8 @@ public: bool hasReachableDeclarationSlow( const NamedDecl *D, llvm::SmallVectorImpl *Modules = nullptr); - bool hasVisibleMergedDefinition(NamedDecl *Def); - bool hasMergedDefinitionInCurrentModule(NamedDecl *Def); + bool hasVisibleMergedDefinition(const NamedDecl *Def); + bool hasMergedDefinitionInCurrentModule(const NamedDecl *Def); /// Determine if \p D and \p Suggested have a structurally compatible /// layout as described in C11 6.2.7/1. @@ -2577,13 +2620,11 @@ public: // struct SkipBodyInfo { - SkipBodyInfo() - : ShouldSkip(false), CheckSameAsPrevious(false), Previous(nullptr), - New(nullptr) {} - bool ShouldSkip; - bool CheckSameAsPrevious; - NamedDecl *Previous; - NamedDecl *New; + SkipBodyInfo() = default; + bool ShouldSkip = false; + bool CheckSameAsPrevious = false; + NamedDecl *Previous = nullptr; + NamedDecl *New = nullptr; }; DeclGroupPtrTy ConvertDeclToDeclGroup(Decl *Ptr, Decl *OwnedType = nullptr); @@ -3231,9 +3272,9 @@ public: /// Diagnose that the specified declaration needs to be visible but /// isn't, and suggest a module import that would resolve the problem. - void diagnoseMissingImport(SourceLocation Loc, NamedDecl *Decl, + void diagnoseMissingImport(SourceLocation Loc, const NamedDecl *Decl, MissingImportKind MIK, bool Recover = true); - void diagnoseMissingImport(SourceLocation Loc, NamedDecl *Decl, + void diagnoseMissingImport(SourceLocation Loc, const NamedDecl *Decl, SourceLocation DeclLoc, ArrayRef Modules, MissingImportKind MIK, bool Recover); @@ -3544,13 +3585,13 @@ public: void ActOnExitFunctionContext(); /// If \p AllowLambda is true, treat lambda as function. - DeclContext *getFunctionLevelDeclContext(bool AllowLambda = false); + DeclContext *getFunctionLevelDeclContext(bool AllowLambda = false) const; /// Returns a pointer to the innermost enclosing function, or nullptr if the /// current context is not inside a function. If \p AllowLambda is true, /// this can return the call operator of an enclosing lambda, otherwise /// lambdas are skipped when looking for an enclosing function. - FunctionDecl *getCurFunctionDecl(bool AllowLambda = false); + FunctionDecl *getCurFunctionDecl(bool AllowLambda = false) const; /// getCurMethodDecl - If inside of a method body, this returns a pointer to /// the method decl for the method being parsed. If we're currently @@ -3560,7 +3601,7 @@ public: /// getCurFunctionOrMethodDecl - Return the Decl for the current ObjC method /// or C function we're in, otherwise return null. If we're currently /// in a 'block', this returns the containing context. - NamedDecl *getCurFunctionOrMethodDecl(); + NamedDecl *getCurFunctionOrMethodDecl() const; /// Add this decl to the scope shadowed decl chains. void PushOnScopeChains(NamedDecl *D, Scope *S, bool AddToContext = true); @@ -3573,7 +3614,7 @@ public: /// enclosing namespace set of the context, rather than contained /// directly within it. bool isDeclInScope(NamedDecl *D, DeclContext *Ctx, Scope *S = nullptr, - bool AllowInlineNamespace = false); + bool AllowInlineNamespace = false) const; /// Finds the scope corresponding to the given decl context, if it /// happens to be an enclosing scope. Otherwise return NULL. @@ -3851,8 +3892,17 @@ public: CCEK_TemplateArg, ///< Value of a non-type template parameter. CCEK_ArrayBound, ///< Array bound in array declarator or new-expression. CCEK_ExplicitBool, ///< Condition in an explicit(bool) specifier. - CCEK_Noexcept ///< Condition in a noexcept(bool) specifier. + CCEK_Noexcept, ///< Condition in a noexcept(bool) specifier. + CCEK_StaticAssertMessageSize, ///< Call to size() in a static assert + ///< message. + CCEK_StaticAssertMessageData, ///< Call to data() in a static assert + ///< message. }; + + ExprResult BuildConvertedConstantExpression(Expr *From, QualType T, + CCEKind CCE, + NamedDecl *Dest = nullptr); + ExprResult CheckConvertedConstantExpression(Expr *From, QualType T, llvm::APSInt &Value, CCEKind CCE); ExprResult CheckConvertedConstantExpression(Expr *From, QualType T, @@ -3976,7 +4026,8 @@ public: bool AllowExplicitConversion = false, ADLCallKind IsADLCandidate = ADLCallKind::NotADL, ConversionSequenceList EarlyConversions = std::nullopt, - OverloadCandidateParamOrder PO = {}); + OverloadCandidateParamOrder PO = {}, + bool AggregateCandidateDeduction = false); void AddFunctionCandidates(const UnresolvedSetImpl &Functions, ArrayRef Args, OverloadCandidateSet &CandidateSet, @@ -4017,7 +4068,8 @@ public: OverloadCandidateSet &CandidateSet, bool SuppressUserConversions = false, bool PartialOverloading = false, bool AllowExplicit = true, ADLCallKind IsADLCandidate = ADLCallKind::NotADL, - OverloadCandidateParamOrder PO = {}); + OverloadCandidateParamOrder PO = {}, + bool AggregateCandidateDeduction = false); bool CheckNonDependentConversions( FunctionTemplateDecl *FunctionTemplate, ArrayRef ParamTypes, ArrayRef Args, OverloadCandidateSet &CandidateSet, @@ -4065,7 +4117,7 @@ public: // Emit as a 'note' the specific overload candidate void NoteOverloadCandidate( - NamedDecl *Found, FunctionDecl *Fn, + const NamedDecl *Found, const FunctionDecl *Fn, OverloadCandidateRewriteKind RewriteKind = OverloadCandidateRewriteKind(), QualType DestType = QualType(), bool TakingAddress = false); @@ -4135,10 +4187,9 @@ public: bool resolveAndFixAddressOfSingleOverloadCandidate( ExprResult &SrcExpr, bool DoFunctionPointerConversion = false); - FunctionDecl * - ResolveSingleFunctionTemplateSpecialization(OverloadExpr *ovl, - bool Complain = false, - DeclAccessPair *Found = nullptr); + FunctionDecl *ResolveSingleFunctionTemplateSpecialization( + OverloadExpr *ovl, bool Complain = false, DeclAccessPair *Found = nullptr, + TemplateSpecCandidateSet *FailedTSC = nullptr); bool ResolveAndFixSingleFunctionTemplateSpecialization( ExprResult &SrcExpr, bool DoFunctionPointerConversion = false, @@ -4345,7 +4396,7 @@ public: ForExternalRedeclaration }; - RedeclarationKind forRedeclarationInCurContext() { + RedeclarationKind forRedeclarationInCurContext() const { // A declaration with an owning module for linkage can never link against // anything that is not visible. We don't need to check linkage here; if // the context has internal linkage, redeclaration lookup won't find things @@ -4499,7 +4550,7 @@ public: TemplateDiscarded, // Discarded due to uninstantiated templates Unknown, }; - FunctionEmissionStatus getEmissionStatus(FunctionDecl *Decl, + FunctionEmissionStatus getEmissionStatus(const FunctionDecl *Decl, bool Final = false); // Whether the callee should be ignored in CUDA/HIP/OpenMP host/device check. @@ -4711,6 +4762,11 @@ public: void CheckAlignasUnderalignment(Decl *D); + bool CheckNoInlineAttr(const Stmt *OrigSt, const Stmt *CurSt, + const AttributeCommonInfo &A); + bool CheckAlwaysInlineAttr(const Stmt *OrigSt, const Stmt *CurSt, + const AttributeCommonInfo &A); + /// Adjust the calling convention of a method to be the ABI default if it /// wasn't specified explicitly. This handles method types formed from /// function type typedefs and typename template arguments. @@ -5547,7 +5603,7 @@ public: DeclarationNameInfo &NameInfo, const TemplateArgumentListInfo *&TemplateArgs); - bool DiagnoseDependentMemberLookup(LookupResult &R); + bool DiagnoseDependentMemberLookup(const LookupResult &R); bool DiagnoseEmptyLookup(Scope *S, CXXScopeSpec &SS, LookupResult &R, @@ -5671,16 +5727,29 @@ public: ExprResult ActOnStringLiteral(ArrayRef StringToks, Scope *UDLScope = nullptr); + ExprResult ActOnUnevaluatedStringLiteral(ArrayRef StringToks); + + /// ControllingExprOrType is either an opaque pointer coming out of a + /// ParsedType or an Expr *. FIXME: it'd be better to split this interface + /// into two so we don't take a void *, but that's awkward because one of + /// the operands is either a ParsedType or an Expr *, which doesn't lend + /// itself to generic code very well. ExprResult ActOnGenericSelectionExpr(SourceLocation KeyLoc, SourceLocation DefaultLoc, SourceLocation RParenLoc, - Expr *ControllingExpr, + bool PredicateIsExpr, + void *ControllingExprOrType, ArrayRef ArgTypes, ArrayRef ArgExprs); + /// ControllingExprOrType is either a TypeSourceInfo * or an Expr *. FIXME: + /// it'd be better to split this interface into two so we don't take a + /// void *, but see the FIXME on ActOnGenericSelectionExpr as to why that + /// isn't a trivial change. ExprResult CreateGenericSelectionExpr(SourceLocation KeyLoc, SourceLocation DefaultLoc, SourceLocation RParenLoc, - Expr *ControllingExpr, + bool PredicateIsExpr, + void *ControllingExprOrType, ArrayRef Types, ArrayRef Exprs); @@ -5697,6 +5766,11 @@ public: bool CheckTypeTraitArity(unsigned Arity, SourceLocation Loc, size_t N); + bool ActOnAlignasTypeArgument(StringRef KWName, ParsedType Ty, + SourceLocation OpLoc, SourceRange R); + bool CheckAlignasTypeArgument(StringRef KWName, TypeSourceInfo *TInfo, + SourceLocation OpLoc, SourceRange R); + ExprResult CreateUnaryExprOrTypeTraitExpr(TypeSourceInfo *TInfo, SourceLocation OpLoc, UnaryExprOrTypeTrait ExprKind, @@ -5715,7 +5789,8 @@ public: bool CheckUnaryExprOrTypeTraitOperand(Expr *E, UnaryExprOrTypeTrait ExprKind); bool CheckUnaryExprOrTypeTraitOperand(QualType ExprType, SourceLocation OpLoc, SourceRange ExprRange, - UnaryExprOrTypeTrait ExprKind); + UnaryExprOrTypeTrait ExprKind, + StringRef KWName); ExprResult ActOnSizeofParameterPackExpr(Scope *S, SourceLocation OpLoc, IdentifierInfo &Name, @@ -5980,8 +6055,8 @@ public: ExprResult BuildVAArgExpr(SourceLocation BuiltinLoc, Expr *E, TypeSourceInfo *TInfo, SourceLocation RPLoc); - // __builtin_LINE(), __builtin_FUNCTION(), __builtin_FILE(), - // __builtin_COLUMN(), __builtin_source_location() + // __builtin_LINE(), __builtin_FUNCTION(), __builtin_FUNCSIG(), + // __builtin_FILE(), __builtin_COLUMN(), __builtin_source_location() ExprResult ActOnSourceLocExpr(SourceLocExpr::IdentKind Kind, SourceLocation BuiltinLoc, SourceLocation RPLoc); @@ -6089,9 +6164,6 @@ public: NamespaceDecl *getStdNamespace() const; NamespaceDecl *getOrCreateStdNamespace(); - NamespaceDecl *lookupStdExperimentalNamespace(); - NamespaceDecl *getCachedCoroNamespace() { return CoroTraitsNamespaceCache; } - CXXRecordDecl *getStdBadAlloc() const; EnumDecl *getStdAlignValT() const; @@ -6510,6 +6582,13 @@ public: /// invocation. ExprResult CheckForImmediateInvocation(ExprResult E, FunctionDecl *Decl); + bool CheckImmediateEscalatingFunctionDefinition( + FunctionDecl *FD, const sema::FunctionScopeInfo *FSI); + + void MarkExpressionAsImmediateEscalating(Expr *E); + + void DiagnoseImmediateEscalatingReason(FunctionDecl *FD); + bool CompleteConstructorCall(CXXConstructorDecl *Constructor, QualType DeclInitType, MultiExprArg ArgsPtr, SourceLocation Loc, @@ -6946,9 +7025,6 @@ public: } }; - bool isNonTypeNestedNameSpecifier(Scope *S, CXXScopeSpec &SS, - NestedNameSpecInfo &IdInfo); - bool BuildCXXNestedNameSpecifier(Scope *S, NestedNameSpecInfo &IdInfo, bool EnteringContext, @@ -7089,30 +7165,27 @@ public: unsigned LambdaDependencyKind, LambdaCaptureDefault CaptureDefault); - /// Start the definition of a lambda expression. - CXXMethodDecl * - startLambdaDefinition(CXXRecordDecl *Class, SourceRange IntroducerRange, - TypeSourceInfo *MethodType, SourceLocation EndLoc, - ArrayRef Params, - ConstexprSpecKind ConstexprKind, StorageClass SC, - Expr *TrailingRequiresClause); - /// Number lambda for linkage purposes if necessary. - void handleLambdaNumbering( - CXXRecordDecl *Class, CXXMethodDecl *Method, - std::optional> Mangling = - std::nullopt); + void handleLambdaNumbering(CXXRecordDecl *Class, CXXMethodDecl *Method, + std::optional + NumberingOverride = std::nullopt); /// Endow the lambda scope info with the relevant properties. - void buildLambdaScope(sema::LambdaScopeInfo *LSI, - CXXMethodDecl *CallOperator, + void buildLambdaScope(sema::LambdaScopeInfo *LSI, CXXMethodDecl *CallOperator, SourceRange IntroducerRange, LambdaCaptureDefault CaptureDefault, - SourceLocation CaptureDefaultLoc, - bool ExplicitParams, - bool ExplicitResultType, + SourceLocation CaptureDefaultLoc, bool ExplicitParams, bool Mutable); + CXXMethodDecl *CreateLambdaCallOperator(SourceRange IntroducerRange, + CXXRecordDecl *Class); + void CompleteLambdaCallOperator( + CXXMethodDecl *Method, SourceLocation LambdaLoc, + SourceLocation CallOperatorLoc, Expr *TrailingRequiresClause, + TypeSourceInfo *MethodTyInfo, ConstexprSpecKind ConstexprKind, + StorageClass SC, ArrayRef Params, + bool HasExplicitResultType); + /// Perform initialization analysis of the init-capture and perform /// any implicit conversions such as an lvalue-to-rvalue conversion if /// not being used to initialize a reference. @@ -7133,42 +7206,49 @@ public: /// /// CodeGen handles emission of lambda captures, ignoring these dummy /// variables appropriately. - VarDecl *createLambdaInitCaptureVarDecl(SourceLocation Loc, - QualType InitCaptureType, - SourceLocation EllipsisLoc, - IdentifierInfo *Id, - unsigned InitStyle, Expr *Init); + VarDecl *createLambdaInitCaptureVarDecl( + SourceLocation Loc, QualType InitCaptureType, SourceLocation EllipsisLoc, + IdentifierInfo *Id, unsigned InitStyle, Expr *Init, DeclContext *DeclCtx); /// Add an init-capture to a lambda scope. - void addInitCapture(sema::LambdaScopeInfo *LSI, VarDecl *Var, - bool isReferenceType); + void addInitCapture(sema::LambdaScopeInfo *LSI, VarDecl *Var, bool ByRef); /// Note that we have finished the explicit captures for the /// given lambda. void finishLambdaExplicitCaptures(sema::LambdaScopeInfo *LSI); - /// \brief This is called after parsing the explicit template parameter list + /// Deduce a block or lambda's return type based on the return + /// statements present in the body. + void deduceClosureReturnType(sema::CapturingScopeInfo &CSI); + + /// Once the Lambdas capture are known, we can start to create the closure, + /// call operator method, and keep track of the captures. + /// We do the capture lookup here, but they are not actually captured until + /// after we know what the qualifiers of the call operator are. + void ActOnLambdaExpressionAfterIntroducer(LambdaIntroducer &Intro, + Scope *CurContext); + + /// This is called after parsing the explicit template parameter list /// on a lambda (if it exists) in C++2a. - void ActOnLambdaExplicitTemplateParameterList(SourceLocation LAngleLoc, + void ActOnLambdaExplicitTemplateParameterList(LambdaIntroducer &Intro, + SourceLocation LAngleLoc, ArrayRef TParams, SourceLocation RAngleLoc, ExprResult RequiresClause); - /// Introduce the lambda parameters into scope. - void addLambdaParameters( - ArrayRef Captures, - CXXMethodDecl *CallOperator, Scope *CurScope); + void ActOnLambdaClosureQualifiers(LambdaIntroducer &Intro, + SourceLocation MutableLoc); - /// Deduce a block or lambda's return type based on the return - /// statements present in the body. - void deduceClosureReturnType(sema::CapturingScopeInfo &CSI); + void ActOnLambdaClosureParameters( + Scope *LambdaScope, + MutableArrayRef ParamInfo); /// ActOnStartOfLambdaDefinition - This is called just before we start /// parsing the body of a lambda; it analyzes the explicit captures and /// arguments, and sets up various data-structures for the body of the /// lambda. void ActOnStartOfLambdaDefinition(LambdaIntroducer &Intro, - Declarator &ParamInfo, Scope *CurScope); + Declarator &ParamInfo, const DeclSpec &DS); /// ActOnLambdaError - If there is an error parsing a lambda, this callback /// is invoked to pop the information about the lambda. @@ -7263,6 +7343,13 @@ private: LocalInstantiationScope &Scope, const MultiLevelTemplateArgumentList &TemplateArgs); + /// Introduce the instantiated captures of the lambda into the local + /// instantiation scope. + bool addInstantiatedCapturesToScope( + FunctionDecl *Function, const FunctionDecl *PatternDecl, + LocalInstantiationScope &Scope, + const MultiLevelTemplateArgumentList &TemplateArgs); + /// used by SetupConstraintCheckingTemplateArgumentsAndScope to recursively(in /// the case of lambdas) set up the LocalInstantiationScope of the current /// function. @@ -7722,15 +7809,16 @@ public: void UnmarkAsLateParsedTemplate(FunctionDecl *FD); bool IsInsideALocalClassWithinATemplateFunction(); + bool EvaluateStaticAssertMessageAsString(Expr *Message, std::string &Result, + ASTContext &Ctx, + bool ErrorOnInvalidMessage); Decl *ActOnStaticAssertDeclaration(SourceLocation StaticAssertLoc, Expr *AssertExpr, Expr *AssertMessageExpr, SourceLocation RParenLoc); Decl *BuildStaticAssertDeclaration(SourceLocation StaticAssertLoc, - Expr *AssertExpr, - StringLiteral *AssertMessageExpr, - SourceLocation RParenLoc, - bool Failed); + Expr *AssertExpr, Expr *AssertMessageExpr, + SourceLocation RParenLoc, bool Failed); void DiagnoseStaticAssertDetails(const Expr *E); FriendDecl *CheckFriendTypeDecl(SourceLocation LocStart, @@ -7750,7 +7838,7 @@ public: void CheckConversionDeclarator(Declarator &D, QualType &R, StorageClass& SC); Decl *ActOnConversionDeclarator(CXXConversionDecl *Conversion); - void CheckDeductionGuideDeclarator(Declarator &D, QualType &R, + bool CheckDeductionGuideDeclarator(Declarator &D, QualType &R, StorageClass &SC); void CheckDeductionGuideTemplate(FunctionTemplateDecl *TD); @@ -8044,7 +8132,7 @@ public: /// Determine whether a particular identifier might be the name in a C++1z /// deduction-guide declaration. bool isDeductionGuideName(Scope *S, const IdentifierInfo &Name, - SourceLocation NameLoc, + SourceLocation NameLoc, CXXScopeSpec &SS, ParsedTemplateTy *Template = nullptr); bool DiagnoseUnknownTemplateName(const IdentifierInfo &II, @@ -8074,6 +8162,8 @@ public: SourceLocation EqualLoc, ParsedType DefaultArg, bool HasTypeConstraint); + bool CheckTypeConstraint(TemplateIdAnnotation *TypeConstraint); + bool ActOnTypeConstraint(const CXXScopeSpec &SS, TemplateIdAnnotation *TypeConstraint, TemplateTypeParmDecl *ConstrainedParameter, @@ -8092,7 +8182,8 @@ public: SourceLocation EllipsisLoc); bool AttachTypeConstraint(AutoTypeLoc TL, - NonTypeTemplateParmDecl *ConstrainedParameter, + NonTypeTemplateParmDecl *NewConstrainedParm, + NonTypeTemplateParmDecl *OrigConstrainedParm, SourceLocation EllipsisLoc); bool RequireStructuralType(QualType T, SourceLocation Loc); @@ -8426,24 +8517,31 @@ public: /// template struct integer_c; /// X xic; /// \endcode - TPL_TemplateTemplateArgumentMatch + TPL_TemplateTemplateArgumentMatch, + + /// We are determining whether the template-parameters are equivalent + /// according to C++ [temp.over.link]/6. This comparison does not consider + /// constraints. + /// + /// \code + /// template void f(T); + /// template void f(T); + /// \endcode + TPL_TemplateParamsEquivalent, }; bool TemplateParameterListsAreEqual( const NamedDecl *NewInstFrom, TemplateParameterList *New, const NamedDecl *OldInstFrom, TemplateParameterList *Old, bool Complain, TemplateParameterListEqualKind Kind, - SourceLocation TemplateArgLoc = SourceLocation(), - bool PartialOrdering = false); + SourceLocation TemplateArgLoc = SourceLocation()); bool TemplateParameterListsAreEqual( TemplateParameterList *New, TemplateParameterList *Old, bool Complain, TemplateParameterListEqualKind Kind, - SourceLocation TemplateArgLoc = SourceLocation(), - bool PartialOrdering = false) { + SourceLocation TemplateArgLoc = SourceLocation()) { return TemplateParameterListsAreEqual(nullptr, New, nullptr, Old, Complain, - Kind, TemplateArgLoc, - PartialOrdering); + Kind, TemplateArgLoc); } bool CheckTemplateDeclScope(Scope *S, TemplateParameterList *TemplateParams); @@ -9049,7 +9147,7 @@ public: FunctionTemplateDecl *FunctionTemplate, TemplateArgumentListInfo *ExplicitTemplateArgs, ArrayRef Args, FunctionDecl *&Specialization, sema::TemplateDeductionInfo &Info, - bool PartialOverloading, + bool PartialOverloading, bool AggregateDeductionCandidate, llvm::function_ref)> CheckNonDependent); TemplateDeductionResult @@ -9092,23 +9190,33 @@ public: TypeSourceInfo *ReplaceAutoTypeSourceInfo(TypeSourceInfo *TypeWithAuto, QualType Replacement); - TemplateDeductionResult DeduceAutoType(TypeLoc AutoTypeLoc, Expr *Initializer, - QualType &Result, - sema::TemplateDeductionInfo &Info, - bool DependentDeduction = false, - bool IgnoreConstraints = false); + TemplateDeductionResult + DeduceAutoType(TypeLoc AutoTypeLoc, Expr *Initializer, QualType &Result, + sema::TemplateDeductionInfo &Info, + bool DependentDeduction = false, + bool IgnoreConstraints = false, + TemplateSpecCandidateSet *FailedTSC = nullptr); void DiagnoseAutoDeductionFailure(VarDecl *VDecl, Expr *Init); bool DeduceReturnType(FunctionDecl *FD, SourceLocation Loc, bool Diagnose = true); + bool CheckIfFunctionSpecializationIsImmediate(FunctionDecl *FD, + SourceLocation Loc); + /// Declare implicit deduction guides for a class template if we've /// not already done so. void DeclareImplicitDeductionGuides(TemplateDecl *Template, SourceLocation Loc); + FunctionTemplateDecl *DeclareImplicitDeductionGuideFromInitList( + TemplateDecl *Template, MutableArrayRef ParamTypes, + SourceLocation Loc); + llvm::DenseMap + AggregateDeductionCandidates; QualType DeduceTemplateSpecializationFromInitializer( TypeSourceInfo *TInfo, const InitializedEntity &Entity, - const InitializationKind &Kind, MultiExprArg Init); + const InitializationKind &Kind, MultiExprArg Init, + ParenListExpr *PL = nullptr); QualType deduceVarTypeFromInitializer(VarDecl *VDecl, DeclarationName Name, QualType Type, TypeSourceInfo *TSI, @@ -9214,6 +9322,9 @@ public: /// a TemplateDecl. DeducedTemplateArgumentSubstitution, + /// We are substituting into a lambda expression. + LambdaExpressionSubstitution, + /// We are substituting prior template arguments into a new /// template parameter. The template parameter itself is either a /// NonTypeTemplateParmDecl or a TemplateTemplateParmDecl. @@ -9285,7 +9396,10 @@ public: /// Memoization means we are _not_ instantiating a template because /// it is already instantiated (but we entered a context where we /// would have had to if it was not already instantiated). - Memoization + Memoization, + + /// We are building deduction guides for a class. + BuildingDeductionGuides, } Kind; /// Was the enclosing context a non-instantiation SFINAE context? @@ -9598,6 +9712,13 @@ public: const RequiresExpr *E, sema::TemplateDeductionInfo &DeductionInfo, SourceRange InstantiationRange); + + struct BuildingDeductionGuidesTag {}; + /// \brief Note that we are building deduction guides. + InstantiatingTemplate(Sema &SemaRef, SourceLocation PointOfInstantiation, + TemplateDecl *Entity, BuildingDeductionGuidesTag, + SourceRange InstantiationRange = SourceRange()); + /// Note that we have finished instantiating this template. void Clear(); @@ -9823,14 +9944,21 @@ public: /// eagerly. SmallVector LateParsedInstantiations; + SmallVector, 8> SavedVTableUses; + SmallVector, 8> + SavedPendingInstantiations; + class GlobalEagerInstantiationScope { public: GlobalEagerInstantiationScope(Sema &S, bool Enabled) : S(S), Enabled(Enabled) { if (!Enabled) return; - SavedPendingInstantiations.swap(S.PendingInstantiations); - SavedVTableUses.swap(S.VTableUses); + S.SavedPendingInstantiations.emplace_back(); + S.SavedPendingInstantiations.back().swap(S.PendingInstantiations); + + S.SavedVTableUses.emplace_back(); + S.SavedVTableUses.back().swap(S.VTableUses); } void perform() { @@ -9846,26 +9974,28 @@ public: // Restore the set of pending vtables. assert(S.VTableUses.empty() && "VTableUses should be empty before it is discarded."); - S.VTableUses.swap(SavedVTableUses); + S.VTableUses.swap(S.SavedVTableUses.back()); + S.SavedVTableUses.pop_back(); // Restore the set of pending implicit instantiations. if (S.TUKind != TU_Prefix || !S.LangOpts.PCHInstantiateTemplates) { assert(S.PendingInstantiations.empty() && "PendingInstantiations should be empty before it is discarded."); - S.PendingInstantiations.swap(SavedPendingInstantiations); + S.PendingInstantiations.swap(S.SavedPendingInstantiations.back()); + S.SavedPendingInstantiations.pop_back(); } else { // Template instantiations in the PCH may be delayed until the TU. - S.PendingInstantiations.swap(SavedPendingInstantiations); - S.PendingInstantiations.insert(S.PendingInstantiations.end(), - SavedPendingInstantiations.begin(), - SavedPendingInstantiations.end()); + S.PendingInstantiations.swap(S.SavedPendingInstantiations.back()); + S.PendingInstantiations.insert( + S.PendingInstantiations.end(), + S.SavedPendingInstantiations.back().begin(), + S.SavedPendingInstantiations.back().end()); + S.SavedPendingInstantiations.pop_back(); } } private: Sema &S; - SmallVector SavedVTableUses; - std::deque SavedPendingInstantiations; bool Enabled; }; @@ -10067,6 +10197,7 @@ public: const Decl *Pattern, Decl *Inst, LateInstantiatedAttrVec *LateAttrs = nullptr, LocalInstantiationScope *OuterMostScope = nullptr); + void updateAttrsForLateParsedTemplate(const Decl *Pattern, Decl *Inst); void InstantiateAttrsForDecl(const MultiLevelTemplateArgumentList &TemplateArgs, @@ -10662,6 +10793,9 @@ public: /// Called on #pragma clang __debug dump II void ActOnPragmaDump(Scope *S, SourceLocation Loc, IdentifierInfo *II); + /// Called on #pragma clang __debug dump E + void ActOnPragmaDump(Expr *E); + /// ActOnPragmaDetectMismatch - Call on well-formed \#pragma detect_mismatch void ActOnPragmaDetectMismatch(SourceLocation Loc, StringRef Name, StringRef Value); @@ -10883,7 +11017,7 @@ public: bool checkNSReturnsRetainedReturnType(SourceLocation loc, QualType type); //===--------------------------------------------------------------------===// - // C++ Coroutines TS + // C++ Coroutines // bool ActOnCoroutineBodyStart(Scope *S, SourceLocation KwLoc, StringRef Keyword); @@ -10908,8 +11042,7 @@ public: /// Lookup 'coroutine_traits' in std namespace and std::experimental /// namespace. The namespace found is recorded in Namespace. ClassTemplateDecl *lookupCoroutineTraits(SourceLocation KwLoc, - SourceLocation FuncLoc, - NamespaceDecl *&Namespace); + SourceLocation FuncLoc); /// Check that the expression co_await promise.final_suspend() shall not be /// potentially-throwing. bool checkFinalSuspendNoThrow(const Stmt *FinalSuspend); @@ -10950,10 +11083,7 @@ private: /// Initialization of data-sharing attributes stack. void InitDataSharingAttributesStack(); void DestroyDataSharingAttributesStack(); - ExprResult - VerifyPositiveIntegerConstantInClause(Expr *Op, OpenMPClauseKind CKind, - bool StrictlyPositive = true, - bool SuppressExprDiags = false); + /// Returns OpenMP nesting level for current directive. unsigned getOpenMPNestingLevel() const; @@ -11039,6 +11169,11 @@ public: return !OMPDeclareVariantScopes.empty(); } + ExprResult + VerifyPositiveIntegerConstantInClause(Expr *Op, OpenMPClauseKind CKind, + bool StrictlyPositive = true, + bool SuppressExprDiags = false); + /// Given the potential call expression \p Call, determine if there is a /// specialization via the OpenMP declare variant mechanism available. If /// there is, return the specialized call expression, otherwise return the @@ -11261,6 +11396,11 @@ public: void checkDeclIsAllowedInOpenMPTarget(Expr *E, Decl *D, SourceLocation IdLoc = SourceLocation()); + + /// Adds OMPDeclareTargetDeclAttr to referenced variables in declare target + /// directive. + void ActOnOpenMPDeclareTargetInitializer(Decl *D); + /// Finishes analysis of the deferred functions calls that may be declared as /// host/nohost during device/host compilation. void finalizeOpenMPDelayedAnalysis(const FunctionDecl *Caller, @@ -12194,6 +12334,13 @@ public: SourceLocation LParenLoc, SourceLocation EndLoc); + /// Called on well-formed 'doacross' clause. + OMPClause * + ActOnOpenMPDoacrossClause(OpenMPDoacrossClauseModifier DepType, + SourceLocation DepLoc, SourceLocation ColonLoc, + ArrayRef VarList, SourceLocation StartLoc, + SourceLocation LParenLoc, SourceLocation EndLoc); + /// The kind of conversion being performed. enum CheckedConversionKind { /// An implicit conversion. @@ -12547,6 +12694,8 @@ public: QualType CheckBitwiseOperands( // C99 6.5.[10...12] ExprResult &LHS, ExprResult &RHS, SourceLocation Loc, BinaryOperatorKind Opc); + void diagnoseLogicalInsteadOfBitwise(Expr *Op1, Expr *Op2, SourceLocation Loc, + BinaryOperatorKind Opc); QualType CheckLogicalOperands( // C99 6.5.[13,14] ExprResult &LHS, ExprResult &RHS, SourceLocation Loc, BinaryOperatorKind Opc); @@ -12630,13 +12779,13 @@ public: SourceLocation Loc, bool IsCompAssign); bool isValidSveBitcast(QualType srcType, QualType destType); + bool isValidRVVBitcast(QualType srcType, QualType destType); bool areMatrixTypesOfTheSameDimension(QualType srcTy, QualType destTy); bool areVectorTypesSameSize(QualType srcType, QualType destType); bool areLaxCompatibleVectorTypes(QualType srcType, QualType destType); bool isLaxVectorConversion(QualType srcType, QualType destType); - bool areSameVectorElemTypes(QualType srcType, QualType destType); bool anyAltivecTypes(QualType srcType, QualType destType); /// type checking declaration initializers (C99 6.7.8) @@ -12789,20 +12938,22 @@ public: Decl *ConditionVar; FullExprArg Condition; bool Invalid; - bool HasKnownValue; - bool KnownValue; + std::optional KnownValue; friend class Sema; ConditionResult(Sema &S, Decl *ConditionVar, FullExprArg Condition, bool IsConstexpr) - : ConditionVar(ConditionVar), Condition(Condition), Invalid(false), - HasKnownValue(IsConstexpr && Condition.get() && - !Condition.get()->isValueDependent()), - KnownValue(HasKnownValue && - !!Condition.get()->EvaluateKnownConstInt(S.Context)) {} + : ConditionVar(ConditionVar), Condition(Condition), Invalid(false) { + if (IsConstexpr && Condition.get()) { + if (std::optional Val = + Condition.get()->getIntegerConstantExpr(S.Context)) { + KnownValue = !!(*Val); + } + } + } explicit ConditionResult(bool Invalid) : ConditionVar(nullptr), Condition(nullptr), Invalid(Invalid), - HasKnownValue(false), KnownValue(false) {} + KnownValue(std::nullopt) {} public: ConditionResult() : ConditionResult(false) {} @@ -12811,11 +12962,7 @@ public: return std::make_pair(cast_or_null(ConditionVar), Condition.get()); } - std::optional getKnownValue() const { - if (!HasKnownValue) - return std::nullopt; - return KnownValue; - } + std::optional getKnownValue() const { return KnownValue; } }; static ConditionResult ConditionError() { return ConditionResult(true); } @@ -12872,13 +13019,6 @@ public: /// CheckCXXBooleanCondition - Returns true if conversion to bool is invalid. ExprResult CheckCXXBooleanCondition(Expr *CondExpr, bool IsConstexpr = false); - /// ConvertIntegerToTypeWarnOnOverflow - Convert the specified APInt to have - /// the specified width and sign. If an overflow occurs, detect it and emit - /// the specified diagnostic. - void ConvertIntegerToTypeWarnOnOverflow(llvm::APSInt &OldVal, - unsigned NewWidth, bool NewSign, - SourceLocation Loc, unsigned DiagID); - /// Checks that the Objective-C declaration is declared in the global scope. /// Emits an error and marks the declaration as invalid if it's not declared /// in the global scope. @@ -12945,14 +13085,14 @@ public: /// Diagnostics that are emitted only if we discover that the given function /// must be codegen'ed. Because handling these correctly adds overhead to /// compilation, this is currently only enabled for CUDA compilations. - llvm::DenseMap, + llvm::DenseMap, std::vector> DeviceDeferredDiags; /// A pair of a canonical FunctionDecl and a SourceLocation. When used as the /// key in a hashtable, both the FD and location are hashed. struct FunctionDeclAndLoc { - CanonicalDeclPtr FD; + CanonicalDeclPtr FD; SourceLocation Loc; }; @@ -12966,7 +13106,7 @@ public: /// /// Functions that we can tell a priori must be emitted aren't added to this /// map. - llvm::DenseMap, + llvm::DenseMap, /* Caller = */ FunctionDeclAndLoc> DeviceKnownEmittedFns; @@ -13011,8 +13151,9 @@ public: /// if (diagIfOpenMPDeviceCode(Loc, diag::err_vla_unsupported)) /// return ExprError(); /// // Otherwise, continue parsing as normal. - SemaDiagnosticBuilder - diagIfOpenMPDeviceCode(SourceLocation Loc, unsigned DiagID, FunctionDecl *FD); + SemaDiagnosticBuilder diagIfOpenMPDeviceCode(SourceLocation Loc, + unsigned DiagID, + const FunctionDecl *FD); /// Creates a SemaDiagnosticBuilder that emits the diagnostic if the current /// context is "used as host code". @@ -13028,13 +13169,14 @@ public: /// return ExprError(); /// // Otherwise, continue parsing as normal. SemaDiagnosticBuilder diagIfOpenMPHostCode(SourceLocation Loc, - unsigned DiagID, FunctionDecl *FD); + unsigned DiagID, + const FunctionDecl *FD); SemaDiagnosticBuilder targetDiag(SourceLocation Loc, unsigned DiagID, - FunctionDecl *FD = nullptr); + const FunctionDecl *FD = nullptr); SemaDiagnosticBuilder targetDiag(SourceLocation Loc, const PartialDiagnostic &PD, - FunctionDecl *FD = nullptr) { + const FunctionDecl *FD = nullptr) { return targetDiag(Loc, PD.getDiagID(), FD) << PD; } @@ -13349,6 +13491,7 @@ public: ArrayRef Protocols); void CodeCompleteObjCProtocolDecl(Scope *S); void CodeCompleteObjCInterfaceDecl(Scope *S); + void CodeCompleteObjCClassForwardDecl(Scope *S); void CodeCompleteObjCSuperclass(Scope *S, IdentifierInfo *ClassName, SourceLocation ClassNameLoc); @@ -13491,8 +13634,14 @@ private: bool CheckRISCVLMUL(CallExpr *TheCall, unsigned ArgNum); bool CheckRISCVBuiltinFunctionCall(const TargetInfo &TI, unsigned BuiltinID, CallExpr *TheCall); + void checkRVVTypeSupport(QualType Ty, SourceLocation Loc, ValueDecl *D); bool CheckLoongArchBuiltinFunctionCall(const TargetInfo &TI, unsigned BuiltinID, CallExpr *TheCall); + bool CheckWebAssemblyBuiltinFunctionCall(const TargetInfo &TI, + unsigned BuiltinID, + CallExpr *TheCall); + bool CheckNVPTXBuiltinFunctionCall(const TargetInfo &TI, unsigned BuiltinID, + CallExpr *TheCall); bool SemaBuiltinVAStart(unsigned BuiltinID, CallExpr *TheCall); bool SemaBuiltinVAStartARMMicrosoft(CallExpr *Call); @@ -13545,9 +13694,12 @@ private: bool CheckPPCMMAType(QualType Type, SourceLocation TypeLoc); bool SemaBuiltinElementwiseMath(CallExpr *TheCall); + bool SemaBuiltinElementwiseTernaryMath(CallExpr *TheCall); bool PrepareBuiltinElementwiseMathOneArgCall(CallExpr *TheCall); bool PrepareBuiltinReduceMathOneArgCall(CallExpr *TheCall); + bool SemaBuiltinNonDeterministicValue(CallExpr *TheCall); + // Matrix builtin handling. ExprResult SemaBuiltinMatrixTranspose(CallExpr *TheCall, ExprResult CallResult); @@ -13556,6 +13708,16 @@ private: ExprResult SemaBuiltinMatrixColumnMajorStore(CallExpr *TheCall, ExprResult CallResult); + // WebAssembly builtin handling. + bool BuiltinWasmRefNullExtern(CallExpr *TheCall); + bool BuiltinWasmRefNullFunc(CallExpr *TheCall); + bool BuiltinWasmTableGet(CallExpr *TheCall); + bool BuiltinWasmTableSet(CallExpr *TheCall); + bool BuiltinWasmTableSize(CallExpr *TheCall); + bool BuiltinWasmTableGrow(CallExpr *TheCall); + bool BuiltinWasmTableFill(CallExpr *TheCall); + bool BuiltinWasmTableCopy(CallExpr *TheCall); + public: enum FormatStringType { FST_Scanf, @@ -13618,7 +13780,7 @@ public: private: void CheckImplicitConversions(Expr *E, SourceLocation CC = SourceLocation()); void CheckBoolLikeConversion(Expr *E, SourceLocation CC); - void CheckForIntOverflow(Expr *E); + void CheckForIntOverflow(const Expr *E); void CheckUnsequencedOperations(const Expr *E); /// Perform semantic checks on a completed expression. This will either @@ -13696,7 +13858,6 @@ private: Scope *CurScope; mutable IdentifierInfo *Ident_super; - mutable IdentifierInfo *Ident___float128; /// Nullability type specifiers. IdentifierInfo *Ident__Nonnull = nullptr; @@ -13745,7 +13906,6 @@ public: } IdentifierInfo *getSuperIdentifier() const; - IdentifierInfo *getFloat128Identifier() const; ObjCContainerDecl *getObjCDeclContext() const; @@ -13888,74 +14048,11 @@ public: SemaDiagnosticBuilder SYCLDiagIfDeviceCode(SourceLocation Loc, unsigned DiagID); - /// Check whether we're allowed to call Callee from the current context. - /// - /// - If the call is never allowed in a semantically-correct program - /// emits an error and returns false. - /// - /// - If the call is allowed in semantically-correct programs, but only if - /// it's never codegen'ed, creates a deferred diagnostic to be emitted if - /// and when the caller is codegen'ed, and returns true. - /// - /// - Otherwise, returns true without emitting any diagnostics. - /// - /// Adds Callee to DeviceCallGraph if we don't know if its caller will be - /// codegen'ed yet. - bool checkSYCLDeviceFunction(SourceLocation Loc, FunctionDecl *Callee); void deepTypeCheckForSYCLDevice(SourceLocation UsedAt, llvm::DenseSet Visited, ValueDecl *DeclToCheck); }; -/// RAII object that enters a new expression evaluation context. -class EnterExpressionEvaluationContext { - Sema &Actions; - bool Entered = true; - -public: - EnterExpressionEvaluationContext( - Sema &Actions, Sema::ExpressionEvaluationContext NewContext, - Decl *LambdaContextDecl = nullptr, - Sema::ExpressionEvaluationContextRecord::ExpressionKind ExprContext = - Sema::ExpressionEvaluationContextRecord::EK_Other, - bool ShouldEnter = true) - : Actions(Actions), Entered(ShouldEnter) { - if (Entered) - Actions.PushExpressionEvaluationContext(NewContext, LambdaContextDecl, - ExprContext); - } - EnterExpressionEvaluationContext( - Sema &Actions, Sema::ExpressionEvaluationContext NewContext, - Sema::ReuseLambdaContextDecl_t, - Sema::ExpressionEvaluationContextRecord::ExpressionKind ExprContext = - Sema::ExpressionEvaluationContextRecord::EK_Other) - : Actions(Actions) { - Actions.PushExpressionEvaluationContext( - NewContext, Sema::ReuseLambdaContextDecl, ExprContext); - } - - enum InitListTag { InitList }; - EnterExpressionEvaluationContext(Sema &Actions, InitListTag, - bool ShouldEnter = true) - : Actions(Actions), Entered(false) { - // In C++11 onwards, narrowing checks are performed on the contents of - // braced-init-lists, even when they occur within unevaluated operands. - // Therefore we still need to instantiate constexpr functions used in such - // a context. - if (ShouldEnter && Actions.isUnevaluatedContext() && - Actions.getLangOpts().CPlusPlus11) { - Actions.PushExpressionEvaluationContext( - Sema::ExpressionEvaluationContext::UnevaluatedList); - Entered = true; - } - } - - ~EnterExpressionEvaluationContext() { - if (Entered) - Actions.PopExpressionEvaluationContext(); - } -}; - DeductionFailureInfo MakeDeductionFailureInfo(ASTContext &Context, Sema::TemplateDeductionResult TDK, sema::TemplateDeductionInfo &Info); @@ -13966,6 +14063,8 @@ struct LateParsedTemplate { CachedTokens Toks; /// The template function declaration to be late parsed. Decl *D; + /// Floating-point options in the point of definition. + FPOptions FPO; }; template <> @@ -13983,7 +14082,8 @@ namespace llvm { // SourceLocation. template <> struct DenseMapInfo { using FunctionDeclAndLoc = clang::Sema::FunctionDeclAndLoc; - using FDBaseInfo = DenseMapInfo>; + using FDBaseInfo = + DenseMapInfo>; static FunctionDeclAndLoc getEmptyKey() { return {FDBaseInfo::getEmptyKey(), clang::SourceLocation()}; diff --git a/contrib/llvm-project/clang/include/clang/Sema/Template.h b/contrib/llvm-project/clang/include/clang/Sema/Template.h index 90838943838..1de2cc6917b 100644 --- a/contrib/llvm-project/clang/include/clang/Sema/Template.h +++ b/contrib/llvm-project/clang/include/clang/Sema/Template.h @@ -232,9 +232,21 @@ enum class TemplateSubstitutionKind : char { /// Replaces the current 'innermost' level with the provided argument list. /// This is useful for type deduction cases where we need to get the entire /// list from the AST, but then add the deduced innermost list. - void replaceInnermostTemplateArguments(ArgList Args) { - assert(TemplateArgumentLists.size() > 0 && "Replacing in an empty list?"); - TemplateArgumentLists[0].Args = Args; + void replaceInnermostTemplateArguments(Decl *AssociatedDecl, ArgList Args) { + assert((!TemplateArgumentLists.empty() || NumRetainedOuterLevels) && + "Replacing in an empty list?"); + + if (!TemplateArgumentLists.empty()) { + assert((TemplateArgumentLists[0].AssociatedDeclAndFinal.getPointer() || + TemplateArgumentLists[0].AssociatedDeclAndFinal.getPointer() == + AssociatedDecl) && + "Trying to change incorrect declaration?"); + TemplateArgumentLists[0].Args = Args; + } else { + --NumRetainedOuterLevels; + TemplateArgumentLists.push_back( + {{AssociatedDecl, /*Final=*/false}, Args}); + } } /// Add an outermost level that we are not substituting. We have no @@ -261,6 +273,23 @@ enum class TemplateSubstitutionKind : char { } ArgListsIterator end() { return TemplateArgumentLists.end(); } ConstArgListsIterator end() const { return TemplateArgumentLists.end(); } + + LLVM_DUMP_METHOD void dump() const { + LangOptions LO; + LO.CPlusPlus = true; + LO.Bool = true; + PrintingPolicy PP(LO); + llvm::errs() << "NumRetainedOuterLevels: " << NumRetainedOuterLevels + << "\n"; + for (unsigned Depth = NumRetainedOuterLevels; Depth < getNumLevels(); + ++Depth) { + llvm::errs() << Depth << ": "; + printTemplateArgumentList( + llvm::errs(), + TemplateArgumentLists[getNumLevels() - Depth - 1].Args, PP); + llvm::errs() << "\n"; + } + } }; /// The context in which partial ordering of function templates occurs. diff --git a/contrib/llvm-project/clang/include/clang/Sema/TemplateDeduction.h b/contrib/llvm-project/clang/include/clang/Sema/TemplateDeduction.h index 9d860a8949d..85691c66a04 100644 --- a/contrib/llvm-project/clang/include/clang/Sema/TemplateDeduction.h +++ b/contrib/llvm-project/clang/include/clang/Sema/TemplateDeduction.h @@ -234,6 +234,13 @@ public: /// different argument type from its substituted parameter type. unsigned CallArgIndex = 0; + // C++20 [over.match.class.deduct]p5.2: + // During template argument deduction for the aggregate deduction + // candidate, the number of elements in a trailing parameter pack is only + // deduced from the number of remaining function arguments if it is not + // otherwise deduced. + bool AggregateDeductionCandidateHasMismatchedArity = false; + /// Information on packs that we're currently expanding. /// /// FIXME: This should be kept internal to SemaTemplateDeduction. diff --git a/contrib/llvm-project/clang/include/clang/Serialization/ASTBitCodes.h b/contrib/llvm-project/clang/include/clang/Serialization/ASTBitCodes.h index 9ba94da0372..2ae9e09998c 100644 --- a/contrib/llvm-project/clang/include/clang/Serialization/ASTBitCodes.h +++ b/contrib/llvm-project/clang/include/clang/Serialization/ASTBitCodes.h @@ -41,7 +41,7 @@ namespace serialization { /// Version 4 of AST files also requires that the version control branch and /// revision match exactly, since there is no backward compatibility of /// AST files at this time. -const unsigned VERSION_MAJOR = 25; +const unsigned VERSION_MAJOR = 27; /// AST file minor version number supported by this version of /// Clang. @@ -696,8 +696,7 @@ enum ASTRecordTypes { /// Record code for \#pragma float_control options. FLOAT_CONTROL_PRAGMA_OPTIONS = 65, - /// Record code for included files. - PP_INCLUDED_FILES = 66, + /// ID 66 used to be the list of included files. /// Record code for an unterminated \#pragma clang assume_nonnull begin /// recorded in a preamble. @@ -1096,6 +1095,11 @@ enum PredefinedTypeIDs { // \brief RISC-V V types with auto numeration #define RVV_TYPE(Name, Id, SingletonId) PREDEF_TYPE_##Id##_ID, #include "clang/Basic/RISCVVTypes.def" +// \brief WebAssembly reference types with auto numeration +#define WASM_TYPE(Name, Id, SingletonId) PREDEF_TYPE_##Id##_ID, +#include "clang/Basic/WebAssemblyReferenceTypes.def" + // Sentinel value. Considered a predefined type but not useable as one. + PREDEF_TYPE_LAST_ID }; /// The number of predefined type IDs that are reserved for @@ -1103,7 +1107,13 @@ enum PredefinedTypeIDs { /// /// Type IDs for non-predefined types will start at /// NUM_PREDEF_TYPE_IDs. -const unsigned NUM_PREDEF_TYPE_IDS = 300; +const unsigned NUM_PREDEF_TYPE_IDS = 500; + +// Ensure we do not overrun the predefined types we reserved +// in the enum PredefinedTypeIDs above. +static_assert(PREDEF_TYPE_LAST_ID < NUM_PREDEF_TYPE_IDS, + "Too many enumerators in PredefinedTypeIDs. Review the value of " + "NUM_PREDEF_TYPE_IDS"); /// Record codes for each kind of type. /// diff --git a/contrib/llvm-project/clang/include/clang/Serialization/ASTReader.h b/contrib/llvm-project/clang/include/clang/Serialization/ASTReader.h index 5cdbdfe4e38..d56e2117a53 100644 --- a/contrib/llvm-project/clang/include/clang/Serialization/ASTReader.h +++ b/contrib/llvm-project/clang/include/clang/Serialization/ASTReader.h @@ -560,6 +560,10 @@ private: llvm::DenseMap> AnonymousDeclarationsForMerging; + /// Map from numbering information for lambdas to the corresponding lambdas. + llvm::DenseMap, NamedDecl *> + LambdaDeclarationsForMerging; + /// Key used to identify LifetimeExtendedTemporaryDecl for merging, /// containing the lifetime-extending declaration and the mangling number. using LETemporaryKey = std::pair; @@ -944,8 +948,14 @@ public: private: /// A list of modules that were imported by precompiled headers or - /// any other non-module AST file. - SmallVector ImportedModules; + /// any other non-module AST file and have not yet been made visible. If a + /// module is made visible in the ASTReader, it will be transfered to + /// \c PendingImportedModulesSema. + SmallVector PendingImportedModules; + + /// A list of modules that were imported by precompiled headers or + /// any other non-module AST file and have not yet been made visible for Sema. + SmallVector PendingImportedModulesSema; //@} /// The system include root to be used when loading the @@ -1101,7 +1111,13 @@ private: /// they might contain a deduced return type that refers to a local type /// declared within the function. SmallVector, 16> - PendingFunctionTypes; + PendingDeducedFunctionTypes; + + /// The list of deduced variable types that we have not yet read, because + /// they might contain a deduced type that refers to a local type declared + /// within the variable. + SmallVector, 16> + PendingDeducedVarTypes; /// The list of redeclaration chains that still need to be /// reconstructed, and the local offset to the corresponding list @@ -1139,6 +1155,11 @@ private: 2> PendingObjCExtensionIvarRedeclarations; + /// Members that have been added to classes, for which the class has not yet + /// been notified. CXXRecordDecl::addedMember will be called for each of + /// these once recursive deserialization is complete. + SmallVector, 4> PendingAddedClassMembers; + /// The set of NamedDecls that have been loaded, but are members of a /// context that has been merged into another context where the corresponding /// declaration is either missing or has not yet been loaded. @@ -1369,9 +1390,7 @@ private: void ReadModuleOffsetMap(ModuleFile &F) const; void ParseLineTable(ModuleFile &F, const RecordData &Record); llvm::Error ReadSourceManagerBlock(ModuleFile &F); - llvm::BitstreamCursor &SLocCursorForID(int ID); SourceLocation getImportLocation(ModuleFile *F); - void readIncludedFiles(ModuleFile &F, StringRef Blob, Preprocessor &PP); ASTReadResult ReadModuleMapFileBlock(RecordData &Record, ModuleFile &F, const ModuleFile *ImportedBy, unsigned ClientLoadCapabilities); @@ -2082,6 +2101,8 @@ public: llvm::MapVector> &LPTMap) override; + void AssignedLambdaNumbering(const CXXRecordDecl *Lambda) override; + /// Load a selector from disk, registering its ID if it exists. void LoadSelector(Selector Sel); @@ -2236,7 +2257,7 @@ public: unsigned &Idx, LocSeq *Seq = nullptr); // Read a string - static std::string ReadString(const RecordData &Record, unsigned &Idx); + static std::string ReadString(const RecordDataImpl &Record, unsigned &Idx); // Skip a string static void SkipString(const RecordData &Record, unsigned &Idx) { diff --git a/contrib/llvm-project/clang/include/clang/Serialization/ASTWriter.h b/contrib/llvm-project/clang/include/clang/Serialization/ASTWriter.h index 09ee1744e89..e328dd0cd55 100644 --- a/contrib/llvm-project/clang/include/clang/Serialization/ASTWriter.h +++ b/contrib/llvm-project/clang/include/clang/Serialization/ASTWriter.h @@ -500,7 +500,6 @@ private: void WriteInputFiles(SourceManager &SourceMgr, HeaderSearchOptions &HSOpts); void WriteSourceManagerBlock(SourceManager &SourceMgr, const Preprocessor &PP); - void writeIncludedFiles(raw_ostream &Out, const Preprocessor &PP); void WritePreprocessor(const Preprocessor &PP, bool IsModule); void WriteHeaderSearch(const HeaderSearch &HS); void WritePreprocessorDetail(PreprocessingRecord &PPRec, diff --git a/contrib/llvm-project/clang/include/clang/Serialization/GlobalModuleIndex.h b/contrib/llvm-project/clang/include/clang/Serialization/GlobalModuleIndex.h index 9d6b52a97f5..d82e0dd294b 100644 --- a/contrib/llvm-project/clang/include/clang/Serialization/GlobalModuleIndex.h +++ b/contrib/llvm-project/clang/include/clang/Serialization/GlobalModuleIndex.h @@ -136,12 +136,6 @@ public: /// The caller accepts ownership of the returned object. IdentifierIterator *createIdentifierIterator() const; - /// Retrieve the set of modules that have up-to-date indexes. - /// - /// \param ModuleFiles Will be populated with the set of module files that - /// have been indexed. - void getKnownModules(llvm::SmallVectorImpl &ModuleFiles); - /// Retrieve the set of module files on which the given module file /// directly depends. void getModuleDependencies(ModuleFile *File, diff --git a/contrib/llvm-project/clang/include/clang/Serialization/ModuleFile.h b/contrib/llvm-project/clang/include/clang/Serialization/ModuleFile.h index 871fdd0a483..b632b4e3e7a 100644 --- a/contrib/llvm-project/clang/include/clang/Serialization/ModuleFile.h +++ b/contrib/llvm-project/clang/include/clang/Serialization/ModuleFile.h @@ -164,6 +164,9 @@ public: /// Whether this precompiled header is a relocatable PCH file. bool RelocatablePCH = false; + /// Whether this module file is a standard C++ module. + bool StandardCXXModule = false; + /// Whether timestamps are included in this module file. bool HasTimestamps = false; @@ -193,7 +196,7 @@ public: /// The memory buffer that stores the data associated with /// this AST file, owned by the InMemoryModuleCache. - llvm::MemoryBuffer *Buffer; + llvm::MemoryBuffer *Buffer = nullptr; /// The size of this file, in bits. uint64_t SizeInBits = 0; diff --git a/contrib/llvm-project/clang/include/clang/Serialization/PCHContainerOperations.h b/contrib/llvm-project/clang/include/clang/Serialization/PCHContainerOperations.h index 9f9700a418a..be10feb5e35 100644 --- a/contrib/llvm-project/clang/include/clang/Serialization/PCHContainerOperations.h +++ b/contrib/llvm-project/clang/include/clang/Serialization/PCHContainerOperations.h @@ -56,7 +56,7 @@ class PCHContainerReader { public: virtual ~PCHContainerReader() = 0; /// Equivalent to the format passed to -fmodule-format= - virtual llvm::StringRef getFormat() const = 0; + virtual llvm::ArrayRef getFormats() const = 0; /// Returns the serialized AST inside the PCH container Buffer. virtual llvm::StringRef ExtractPCH(llvm::MemoryBufferRef Buffer) const = 0; @@ -78,8 +78,7 @@ class RawPCHContainerWriter : public PCHContainerWriter { /// Implements read operations for a raw pass-through PCH container. class RawPCHContainerReader : public PCHContainerReader { - llvm::StringRef getFormat() const override { return "raw"; } - + llvm::ArrayRef getFormats() const override; /// Simply returns the buffer contained in Buffer. llvm::StringRef ExtractPCH(llvm::MemoryBufferRef Buffer) const override; }; @@ -87,7 +86,9 @@ class RawPCHContainerReader : public PCHContainerReader { /// A registry of PCHContainerWriter and -Reader objects for different formats. class PCHContainerOperations { llvm::StringMap> Writers; - llvm::StringMap> Readers; + llvm::StringMap Readers; + llvm::SmallVector> OwnedReaders; + public: /// Automatically registers a RawPCHContainerWriter and /// RawPCHContainerReader. @@ -96,13 +97,17 @@ public: Writers[Writer->getFormat()] = std::move(Writer); } void registerReader(std::unique_ptr Reader) { - Readers[Reader->getFormat()] = std::move(Reader); + assert(!Reader->getFormats().empty() && + "PCHContainerReader must handle >=1 format"); + for (llvm::StringRef Fmt : Reader->getFormats()) + Readers[Fmt] = Reader.get(); + OwnedReaders.push_back(std::move(Reader)); } const PCHContainerWriter *getWriterOrNull(llvm::StringRef Format) { return Writers[Format].get(); } const PCHContainerReader *getReaderOrNull(llvm::StringRef Format) { - return Readers[Format].get(); + return Readers[Format]; } const PCHContainerReader &getRawReader() { return *getReaderOrNull("raw"); diff --git a/contrib/llvm-project/clang/include/clang/StaticAnalyzer/Checkers/Checkers.td b/contrib/llvm-project/clang/include/clang/StaticAnalyzer/Checkers/Checkers.td index 094b3a69c23..885b1b68de9 100644 --- a/contrib/llvm-project/clang/include/clang/StaticAnalyzer/Checkers/Checkers.td +++ b/contrib/llvm-project/clang/include/clang/StaticAnalyzer/Checkers/Checkers.td @@ -359,29 +359,6 @@ def ErrnoModeling : Checker<"Errno">, HelpText<"Make the special value 'errno' available to other checkers.">, Documentation; -def StdCLibraryFunctionsChecker : Checker<"StdCLibraryFunctions">, - HelpText<"Improve modeling of the C standard library functions">, - // Uninitialized value check is a mandatory dependency. This Checker asserts - // that arguments are always initialized. - Dependencies<[CallAndMessageModeling]>, - CheckerOptions<[ - CmdLineOption, - CmdLineOption - ]>, - Documentation, - Hidden; - def TrustNonnullChecker : Checker<"TrustNonnull">, HelpText<"Trust that returns from framework methods annotated with _Nonnull " "are not null">, @@ -486,12 +463,12 @@ def CStringNotNullTerm : Checker<"NotNullTerminated">, HelpText<"Check for arguments which are not null-terminating strings">, Dependencies<[CStringModeling]>, Documentation; - + def CStringUninitializedRead : Checker<"UninitializedRead">, HelpText<"Checks if the string manipulation function would read uninitialized bytes">, Dependencies<[CStringModeling]>, Documentation; - + } // end "alpha.unix.cstring" let ParentPackage = Unix in { @@ -573,6 +550,7 @@ def PthreadLockChecker : Checker<"PthreadLock">, def StreamChecker : Checker<"Stream">, HelpText<"Check stream handling functions">, + WeakDependencies<[NonNullParamChecker]>, Documentation; def SimpleStreamChecker : Checker<"SimpleStream">, @@ -583,12 +561,25 @@ def BlockInCriticalSectionChecker : Checker<"BlockInCriticalSection">, HelpText<"Check for calls to blocking functions inside a critical section">, Documentation; -def StdCLibraryFunctionArgsChecker : Checker<"StdCLibraryFunctionArgs">, - HelpText<"Check constraints of arguments of C standard library functions, " - "such as whether the parameter of isalpha is in the range [0, 255] " - "or is EOF.">, - Dependencies<[StdCLibraryFunctionsChecker]>, - WeakDependencies<[CallAndMessageChecker, NonNullParamChecker]>, +def StdCLibraryFunctionsChecker : Checker<"StdCLibraryFunctions">, + HelpText<"Check for invalid arguments of C standard library functions, " + "and apply relations between arguments and return value">, + CheckerOptions<[ + CmdLineOption, + CmdLineOption + ]>, + WeakDependencies<[CallAndMessageChecker, NonNullParamChecker, StreamChecker]>, Documentation; } // end "alpha.unix" @@ -1618,7 +1609,6 @@ def DebugIteratorModeling : Checker<"DebugIteratorModeling">, def StdCLibraryFunctionsTesterChecker : Checker<"StdCLibraryFunctionsTester">, HelpText<"Add test functions to the summary map, so testing of individual " "summary constituents becomes possible.">, - Dependencies<[StdCLibraryFunctionsChecker]>, Documentation; } // end "debug" diff --git a/contrib/llvm-project/clang/include/clang/StaticAnalyzer/Checkers/Taint.h b/contrib/llvm-project/clang/include/clang/StaticAnalyzer/Checkers/Taint.h index df863a24954..3ec8dbfb09e 100644 --- a/contrib/llvm-project/clang/include/clang/StaticAnalyzer/Checkers/Taint.h +++ b/contrib/llvm-project/clang/include/clang/StaticAnalyzer/Checkers/Taint.h @@ -79,26 +79,48 @@ bool isTainted(ProgramStateRef State, SymbolRef Sym, bool isTainted(ProgramStateRef State, const MemRegion *Reg, TaintTagType Kind = TaintTagGeneric); +/// Returns the tainted Symbols for a given Statement and state. +std::vector getTaintedSymbols(ProgramStateRef State, const Stmt *S, + const LocationContext *LCtx, + TaintTagType Kind = TaintTagGeneric); + +/// Returns the tainted Symbols for a given SVal and state. +std::vector getTaintedSymbols(ProgramStateRef State, SVal V, + TaintTagType Kind = TaintTagGeneric); + +/// Returns the tainted Symbols for a SymbolRef and state. +std::vector getTaintedSymbols(ProgramStateRef State, SymbolRef Sym, + TaintTagType Kind = TaintTagGeneric); + +/// Returns the tainted (index, super/sub region, symbolic region) symbols +/// for a given memory region. +std::vector getTaintedSymbols(ProgramStateRef State, + const MemRegion *Reg, + TaintTagType Kind = TaintTagGeneric); + +std::vector getTaintedSymbolsImpl(ProgramStateRef State, + const Stmt *S, + const LocationContext *LCtx, + TaintTagType Kind, + bool returnFirstOnly); + +std::vector getTaintedSymbolsImpl(ProgramStateRef State, SVal V, + TaintTagType Kind, + bool returnFirstOnly); + +std::vector getTaintedSymbolsImpl(ProgramStateRef State, + SymbolRef Sym, TaintTagType Kind, + bool returnFirstOnly); + +std::vector getTaintedSymbolsImpl(ProgramStateRef State, + const MemRegion *Reg, + TaintTagType Kind, + bool returnFirstOnly); + void printTaint(ProgramStateRef State, raw_ostream &Out, const char *nl = "\n", const char *sep = ""); LLVM_DUMP_METHOD void dumpTaint(ProgramStateRef State); - -/// The bug visitor prints a diagnostic message at the location where a given -/// variable was tainted. -class TaintBugVisitor final : public BugReporterVisitor { -private: - const SVal V; - -public: - TaintBugVisitor(const SVal V) : V(V) {} - void Profile(llvm::FoldingSetNodeID &ID) const override { ID.Add(V); } - - PathDiagnosticPieceRef VisitNode(const ExplodedNode *N, - BugReporterContext &BRC, - PathSensitiveBugReport &BR) override; -}; - } // namespace taint } // namespace ento } // namespace clang diff --git a/contrib/llvm-project/clang/include/clang/StaticAnalyzer/Core/AnalyzerOptions.def b/contrib/llvm-project/clang/include/clang/StaticAnalyzer/Core/AnalyzerOptions.def index acfbcf67b1b..2fc825c2af9 100644 --- a/contrib/llvm-project/clang/include/clang/StaticAnalyzer/Core/AnalyzerOptions.def +++ b/contrib/llvm-project/clang/include/clang/StaticAnalyzer/Core/AnalyzerOptions.def @@ -326,15 +326,6 @@ ANALYZER_OPTION(bool, ShouldSupportSymbolicIntegerCasts, "Produce cast symbols for integral types.", false) -ANALYZER_OPTION( - bool, ShouldConsiderSingleElementArraysAsFlexibleArrayMembers, - "consider-single-element-arrays-as-flexible-array-members", - "Consider single element arrays as flexible array member candidates. " - "This will prevent the analyzer from assuming that a single element array " - "holds a single element. [DEPRECATED, removing in clang-17; " - "use '-fstrict-flex-arrays=' instead]", - true) - ANALYZER_OPTION( bool, ShouldAssumeControlledEnvironment, "assume-controlled-environment", "Whether the analyzed application runs in a controlled environment. " diff --git a/contrib/llvm-project/clang/include/clang/StaticAnalyzer/Core/AnalyzerOptions.h b/contrib/llvm-project/clang/include/clang/StaticAnalyzer/Core/AnalyzerOptions.h index e81d7bbb882..a947bd08670 100644 --- a/contrib/llvm-project/clang/include/clang/StaticAnalyzer/Core/AnalyzerOptions.h +++ b/contrib/llvm-project/clang/include/clang/StaticAnalyzer/Core/AnalyzerOptions.h @@ -260,9 +260,10 @@ public: #undef ANALYZER_OPTION #undef ANALYZER_OPTION_DEPENDS_ON_USER_MODE - // Create an array of all -analyzer-config command line options. Sort it in - // the constructor. - std::vector AnalyzerConfigCmdFlags = { + bool isUnknownAnalyzerConfig(llvm::StringRef Name) { + static std::vector AnalyzerConfigCmdFlags = []() { + // Create an array of all -analyzer-config command line options. + std::vector AnalyzerConfigCmdFlags = { #define ANALYZER_OPTION_DEPENDS_ON_USER_MODE(TYPE, NAME, CMDFLAG, DESC, \ SHALLOW_VAL, DEEP_VAL) \ ANALYZER_OPTION(TYPE, NAME, CMDFLAG, DESC, SHALLOW_VAL) @@ -273,10 +274,11 @@ public: #include "clang/StaticAnalyzer/Core/AnalyzerOptions.def" #undef ANALYZER_OPTION #undef ANALYZER_OPTION_DEPENDS_ON_USER_MODE - }; - - bool isUnknownAnalyzerConfig(StringRef Name) const { - assert(llvm::is_sorted(AnalyzerConfigCmdFlags)); + }; + // FIXME: Sort this at compile-time when we get constexpr sort (C++20). + llvm::sort(AnalyzerConfigCmdFlags); + return AnalyzerConfigCmdFlags; + }(); return !std::binary_search(AnalyzerConfigCmdFlags.begin(), AnalyzerConfigCmdFlags.end(), Name); @@ -292,9 +294,7 @@ public: AnalyzerDisplayProgress(false), eagerlyAssumeBinOpBifurcation(false), TrimGraph(false), visualizeExplodedGraphWithGraphViz(false), UnoptimizedCFG(false), PrintStats(false), NoRetryExhausted(false), - AnalyzerWerror(false) { - llvm::sort(AnalyzerConfigCmdFlags); - } + AnalyzerWerror(false) {} /// Interprets an option's string value as a boolean. The "true" string is /// interpreted as true and the "false" string is interpreted as false. diff --git a/contrib/llvm-project/clang/include/clang/StaticAnalyzer/Core/BugReporter/BugReporter.h b/contrib/llvm-project/clang/include/clang/StaticAnalyzer/Core/BugReporter/BugReporter.h index e5ebb04d67b..826370c2648 100644 --- a/contrib/llvm-project/clang/include/clang/StaticAnalyzer/Core/BugReporter/BugReporter.h +++ b/contrib/llvm-project/clang/include/clang/StaticAnalyzer/Core/BugReporter/BugReporter.h @@ -608,8 +608,9 @@ public: /// Iterator over the set of BugReports tracked by the BugReporter. using EQClasses_iterator = llvm::FoldingSet::iterator; - EQClasses_iterator EQClasses_begin() { return EQClasses.begin(); } - EQClasses_iterator EQClasses_end() { return EQClasses.end(); } + llvm::iterator_range equivalenceClasses() { + return EQClasses; + } ASTContext &getContext() { return D.getASTContext(); } diff --git a/contrib/llvm-project/clang/include/clang/StaticAnalyzer/Core/BugReporter/BugReporterVisitors.h b/contrib/llvm-project/clang/include/clang/StaticAnalyzer/Core/BugReporter/BugReporterVisitors.h index c479daea678..d9b3d9352d3 100644 --- a/contrib/llvm-project/clang/include/clang/StaticAnalyzer/Core/BugReporter/BugReporterVisitors.h +++ b/contrib/llvm-project/clang/include/clang/StaticAnalyzer/Core/BugReporter/BugReporterVisitors.h @@ -51,6 +51,12 @@ public: BugReporterVisitor() = default; BugReporterVisitor(const BugReporterVisitor &) = default; BugReporterVisitor(BugReporterVisitor &&) {} + + // The copy and move assignment operator is defined as deleted pending further + // motivation. + BugReporterVisitor &operator=(const BugReporterVisitor &) = delete; + BugReporterVisitor &operator=(BugReporterVisitor &&) = delete; + virtual ~BugReporterVisitor(); /// Return a diagnostic piece which should be associated with the @@ -386,19 +392,19 @@ const Expr *getDerefExpr(const Stmt *S); } // namespace bugreporter class TrackConstraintBRVisitor final : public BugReporterVisitor { - DefinedSVal Constraint; - bool Assumption; + const SmallString<64> Message; + const DefinedSVal Constraint; + const bool Assumption; bool IsSatisfied = false; - bool IsZeroCheck; /// We should start tracking from the last node along the path in which the /// value is constrained. bool IsTrackingTurnedOn = false; public: - TrackConstraintBRVisitor(DefinedSVal constraint, bool assumption) - : Constraint(constraint), Assumption(assumption), - IsZeroCheck(!Assumption && isa(Constraint)) {} + TrackConstraintBRVisitor(DefinedSVal constraint, bool assumption, + StringRef Message) + : Message(Message), Constraint(constraint), Assumption(assumption) {} void Profile(llvm::FoldingSetNodeID &ID) const override; @@ -411,6 +417,9 @@ public: PathSensitiveBugReport &BR) override; private: + /// Checks if the constraint refers to a null-location. + bool isZeroCheck() const; + /// Checks if the constraint is valid in the current state. bool isUnderconstrained(const ExplodedNode *N) const; }; diff --git a/contrib/llvm-project/clang/include/clang/StaticAnalyzer/Core/BugReporter/CommonBugCategories.h b/contrib/llvm-project/clang/include/clang/StaticAnalyzer/Core/BugReporter/CommonBugCategories.h index 392bc484bf6..5d2c96e5bc9 100644 --- a/contrib/llvm-project/clang/include/clang/StaticAnalyzer/Core/BugReporter/CommonBugCategories.h +++ b/contrib/llvm-project/clang/include/clang/StaticAnalyzer/Core/BugReporter/CommonBugCategories.h @@ -22,6 +22,7 @@ extern const char *const CXXObjectLifecycle; extern const char *const CXXMoveSemantics; extern const char *const SecurityError; extern const char *const UnusedCode; +extern const char *const TaintedData; } // namespace categories } // namespace ento } // namespace clang diff --git a/contrib/llvm-project/clang/include/clang/StaticAnalyzer/Core/Checker.h b/contrib/llvm-project/clang/include/clang/StaticAnalyzer/Core/Checker.h index 36a8bcb26bd..b92f0e1e9f0 100644 --- a/contrib/llvm-project/clang/include/clang/StaticAnalyzer/Core/Checker.h +++ b/contrib/llvm-project/clang/include/clang/StaticAnalyzer/Core/Checker.h @@ -370,13 +370,12 @@ class PointerEscape { Kind); InvalidatedSymbols RegularEscape; - for (InvalidatedSymbols::const_iterator I = Escaped.begin(), - E = Escaped.end(); I != E; ++I) - if (!ETraits->hasTrait(*I, - RegionAndSymbolInvalidationTraits::TK_PreserveContents) && - !ETraits->hasTrait(*I, - RegionAndSymbolInvalidationTraits::TK_SuppressEscape)) - RegularEscape.insert(*I); + for (SymbolRef Sym : Escaped) + if (!ETraits->hasTrait( + Sym, RegionAndSymbolInvalidationTraits::TK_PreserveContents) && + !ETraits->hasTrait( + Sym, RegionAndSymbolInvalidationTraits::TK_SuppressEscape)) + RegularEscape.insert(Sym); if (RegularEscape.empty()) return State; @@ -410,13 +409,13 @@ class ConstPointerEscape { return State; InvalidatedSymbols ConstEscape; - for (InvalidatedSymbols::const_iterator I = Escaped.begin(), - E = Escaped.end(); I != E; ++I) - if (ETraits->hasTrait(*I, - RegionAndSymbolInvalidationTraits::TK_PreserveContents) && - !ETraits->hasTrait(*I, - RegionAndSymbolInvalidationTraits::TK_SuppressEscape)) - ConstEscape.insert(*I); + for (SymbolRef Sym : Escaped) { + if (ETraits->hasTrait( + Sym, RegionAndSymbolInvalidationTraits::TK_PreserveContents) && + !ETraits->hasTrait( + Sym, RegionAndSymbolInvalidationTraits::TK_SuppressEscape)) + ConstEscape.insert(Sym); + } if (ConstEscape.empty()) return State; diff --git a/contrib/llvm-project/clang/include/clang/StaticAnalyzer/Core/PathSensitive/CallEvent.h b/contrib/llvm-project/clang/include/clang/StaticAnalyzer/Core/PathSensitive/CallEvent.h index 710bc8c3384..8129ebc8fdc 100644 --- a/contrib/llvm-project/clang/include/clang/StaticAnalyzer/Core/PathSensitive/CallEvent.h +++ b/contrib/llvm-project/clang/include/clang/StaticAnalyzer/Core/PathSensitive/CallEvent.h @@ -84,6 +84,10 @@ public: CallEventRef(const T *Call) : IntrusiveRefCntPtr(Call) {} CallEventRef(const CallEventRef &Orig) : IntrusiveRefCntPtr(Orig) {} + // The copy assignment operator is defined as deleted pending further + // motivation. + CallEventRef &operator=(const CallEventRef &) = delete; + CallEventRef cloneWithState(ProgramStateRef State) const { return this->get()->template cloneWithState(State); } @@ -154,6 +158,7 @@ private: ProgramStateRef State; const LocationContext *LCtx; llvm::PointerUnion Origin; + CFGBlock::ConstCFGElementRef ElemRef = {nullptr, 0}; mutable std::optional Foreign; // Set by CTU analysis. protected: @@ -176,16 +181,19 @@ private: protected: friend class CallEventManager; - CallEvent(const Expr *E, ProgramStateRef state, const LocationContext *lctx) - : State(std::move(state)), LCtx(lctx), Origin(E) {} + CallEvent(const Expr *E, ProgramStateRef state, const LocationContext *lctx, + CFGBlock::ConstCFGElementRef ElemRef) + : State(std::move(state)), LCtx(lctx), Origin(E), ElemRef(ElemRef) {} - CallEvent(const Decl *D, ProgramStateRef state, const LocationContext *lctx) - : State(std::move(state)), LCtx(lctx), Origin(D) {} + CallEvent(const Decl *D, ProgramStateRef state, const LocationContext *lctx, + CFGBlock::ConstCFGElementRef ElemRef) + : State(std::move(state)), LCtx(lctx), Origin(D), ElemRef(ElemRef) {} // DO NOT MAKE PUBLIC CallEvent(const CallEvent &Original) : State(Original.State), LCtx(Original.LCtx), Origin(Original.Origin), - Data(Original.Data), Location(Original.Location) {} + ElemRef(Original.ElemRef), Data(Original.Data), + Location(Original.Location) {} /// Copies this CallEvent, with vtable intact, into a new block of memory. virtual void cloneTo(void *Dest) const = 0; @@ -232,6 +240,10 @@ public: return LCtx; } + const CFGBlock::ConstCFGElementRef &getCFGElementRef() const { + return ElemRef; + } + /// Returns the definition of the function or method that will be /// called. virtual RuntimeDefinition getRuntimeDefinition() const = 0; @@ -484,11 +496,13 @@ public: class AnyFunctionCall : public CallEvent { protected: AnyFunctionCall(const Expr *E, ProgramStateRef St, - const LocationContext *LCtx) - : CallEvent(E, St, LCtx) {} + const LocationContext *LCtx, + CFGBlock::ConstCFGElementRef ElemRef) + : CallEvent(E, St, LCtx, ElemRef) {} AnyFunctionCall(const Decl *D, ProgramStateRef St, - const LocationContext *LCtx) - : CallEvent(D, St, LCtx) {} + const LocationContext *LCtx, + CFGBlock::ConstCFGElementRef ElemRef) + : CallEvent(D, St, LCtx, ElemRef) {} AnyFunctionCall(const AnyFunctionCall &Other) = default; public: @@ -521,8 +535,9 @@ class SimpleFunctionCall : public AnyFunctionCall { protected: SimpleFunctionCall(const CallExpr *CE, ProgramStateRef St, - const LocationContext *LCtx) - : AnyFunctionCall(CE, St, LCtx) {} + const LocationContext *LCtx, + CFGBlock::ConstCFGElementRef ElemRef) + : AnyFunctionCall(CE, St, LCtx, ElemRef) {} SimpleFunctionCall(const SimpleFunctionCall &Other) = default; void cloneTo(void *Dest) const override { @@ -557,9 +572,9 @@ class BlockCall : public CallEvent { friend class CallEventManager; protected: - BlockCall(const CallExpr *CE, ProgramStateRef St, - const LocationContext *LCtx) - : CallEvent(CE, St, LCtx) {} + BlockCall(const CallExpr *CE, ProgramStateRef St, const LocationContext *LCtx, + CFGBlock::ConstCFGElementRef ElemRef) + : CallEvent(CE, St, LCtx, ElemRef) {} BlockCall(const BlockCall &Other) = default; void cloneTo(void *Dest) const override { new (Dest) BlockCall(*this); } @@ -605,10 +620,9 @@ public: const BlockDataRegion *BR = getBlockRegion(); assert(BR && "Block converted from lambda must have a block region"); - auto I = BR->referenced_vars_begin(); - assert(I != BR->referenced_vars_end()); - - return I.getCapturedRegion(); + auto ReferencedVars = BR->referenced_vars(); + assert(!ReferencedVars.empty()); + return ReferencedVars.begin().getCapturedRegion(); } RuntimeDefinition getRuntimeDefinition() const override { @@ -661,11 +675,13 @@ public: class CXXInstanceCall : public AnyFunctionCall { protected: CXXInstanceCall(const CallExpr *CE, ProgramStateRef St, - const LocationContext *LCtx) - : AnyFunctionCall(CE, St, LCtx) {} + const LocationContext *LCtx, + CFGBlock::ConstCFGElementRef ElemRef) + : AnyFunctionCall(CE, St, LCtx, ElemRef) {} CXXInstanceCall(const FunctionDecl *D, ProgramStateRef St, - const LocationContext *LCtx) - : AnyFunctionCall(D, St, LCtx) {} + const LocationContext *LCtx, + CFGBlock::ConstCFGElementRef ElemRef) + : AnyFunctionCall(D, St, LCtx, ElemRef) {} CXXInstanceCall(const CXXInstanceCall &Other) = default; void getExtraInvalidatedValues(ValueList &Values, @@ -699,8 +715,9 @@ class CXXMemberCall : public CXXInstanceCall { protected: CXXMemberCall(const CXXMemberCallExpr *CE, ProgramStateRef St, - const LocationContext *LCtx) - : CXXInstanceCall(CE, St, LCtx) {} + const LocationContext *LCtx, + CFGBlock::ConstCFGElementRef ElemRef) + : CXXInstanceCall(CE, St, LCtx, ElemRef) {} CXXMemberCall(const CXXMemberCall &Other) = default; void cloneTo(void *Dest) const override { new (Dest) CXXMemberCall(*this); } @@ -741,8 +758,9 @@ class CXXMemberOperatorCall : public CXXInstanceCall { protected: CXXMemberOperatorCall(const CXXOperatorCallExpr *CE, ProgramStateRef St, - const LocationContext *LCtx) - : CXXInstanceCall(CE, St, LCtx) {} + const LocationContext *LCtx, + CFGBlock::ConstCFGElementRef ElemRef) + : CXXInstanceCall(CE, St, LCtx, ElemRef) {} CXXMemberOperatorCall(const CXXMemberOperatorCall &Other) = default; void cloneTo(void *Dest) const override { @@ -808,10 +826,17 @@ protected: /// \param Target The object region to be destructed. /// \param St The path-sensitive state at this point in the program. /// \param LCtx The location context at this point in the program. + /// \param ElemRef The reference to this destructor in the CFG. + /// + /// FIXME: Eventually we want to drop \param Target and deduce it from + /// \param ElemRef. To do that we need to migrate the logic for target + /// region lookup from ExprEngine::ProcessImplicitDtor() and make it + /// independent from ExprEngine. CXXDestructorCall(const CXXDestructorDecl *DD, const Stmt *Trigger, const MemRegion *Target, bool IsBaseDestructor, - ProgramStateRef St, const LocationContext *LCtx) - : CXXInstanceCall(DD, St, LCtx) { + ProgramStateRef St, const LocationContext *LCtx, + CFGBlock::ConstCFGElementRef ElemRef) + : CXXInstanceCall(DD, St, LCtx, ElemRef) { Data = DtorDataTy(Target, IsBaseDestructor).getOpaqueValue(); Location = Trigger->getEndLoc(); } @@ -847,8 +872,9 @@ public: class AnyCXXConstructorCall : public AnyFunctionCall { protected: AnyCXXConstructorCall(const Expr *E, const MemRegion *Target, - ProgramStateRef St, const LocationContext *LCtx) - : AnyFunctionCall(E, St, LCtx) { + ProgramStateRef St, const LocationContext *LCtx, + CFGBlock::ConstCFGElementRef ElemRef) + : AnyFunctionCall(E, St, LCtx, ElemRef) { assert(E && (isa(E) || isa(E))); // Target may be null when the region is unknown. Data = Target; @@ -884,9 +910,14 @@ protected: /// a new symbolic region will be used. /// \param St The path-sensitive state at this point in the program. /// \param LCtx The location context at this point in the program. + /// \param ElemRef The reference to this constructor in the CFG. + /// + /// FIXME: Eventually we want to drop \param Target and deduce it from + /// \param ElemRef. CXXConstructorCall(const CXXConstructExpr *CE, const MemRegion *Target, - ProgramStateRef St, const LocationContext *LCtx) - : AnyCXXConstructorCall(CE, Target, St, LCtx) {} + ProgramStateRef St, const LocationContext *LCtx, + CFGBlock::ConstCFGElementRef ElemRef) + : AnyCXXConstructorCall(CE, Target, St, LCtx, ElemRef) {} CXXConstructorCall(const CXXConstructorCall &Other) = default; @@ -941,8 +972,9 @@ class CXXInheritedConstructorCall : public AnyCXXConstructorCall { protected: CXXInheritedConstructorCall(const CXXInheritedCtorInitExpr *CE, const MemRegion *Target, ProgramStateRef St, - const LocationContext *LCtx) - : AnyCXXConstructorCall(CE, Target, St, LCtx) {} + const LocationContext *LCtx, + CFGBlock::ConstCFGElementRef ElemRef) + : AnyCXXConstructorCall(CE, Target, St, LCtx, ElemRef) {} CXXInheritedConstructorCall(const CXXInheritedConstructorCall &Other) = default; @@ -1003,8 +1035,9 @@ class CXXAllocatorCall : public AnyFunctionCall { protected: CXXAllocatorCall(const CXXNewExpr *E, ProgramStateRef St, - const LocationContext *LCtx) - : AnyFunctionCall(E, St, LCtx) {} + const LocationContext *LCtx, + CFGBlock::ConstCFGElementRef ElemRef) + : AnyFunctionCall(E, St, LCtx, ElemRef) {} CXXAllocatorCall(const CXXAllocatorCall &Other) = default; void cloneTo(void *Dest) const override { new (Dest) CXXAllocatorCall(*this); } @@ -1084,8 +1117,9 @@ class CXXDeallocatorCall : public AnyFunctionCall { protected: CXXDeallocatorCall(const CXXDeleteExpr *E, ProgramStateRef St, - const LocationContext *LCtx) - : AnyFunctionCall(E, St, LCtx) {} + const LocationContext *LCtx, + CFGBlock::ConstCFGElementRef ElemRef) + : AnyFunctionCall(E, St, LCtx, ElemRef) {} CXXDeallocatorCall(const CXXDeallocatorCall &Other) = default; void cloneTo(void *Dest) const override { @@ -1136,8 +1170,9 @@ class ObjCMethodCall : public CallEvent { protected: ObjCMethodCall(const ObjCMessageExpr *Msg, ProgramStateRef St, - const LocationContext *LCtx) - : CallEvent(Msg, St, LCtx) { + const LocationContext *LCtx, + CFGBlock::ConstCFGElementRef ElemRef) + : CallEvent(Msg, St, LCtx, ElemRef) { Data = nullptr; } @@ -1265,34 +1300,36 @@ class CallEventManager { } template - T *create(Arg A, ProgramStateRef St, const LocationContext *LCtx) { + T *create(Arg A, ProgramStateRef St, const LocationContext *LCtx, + CFGBlock::ConstCFGElementRef ElemRef) { static_assert(sizeof(T) == sizeof(CallEventTemplateTy), "CallEvent subclasses are not all the same size"); - return new (allocate()) T(A, St, LCtx); + return new (allocate()) T(A, St, LCtx, ElemRef); } template - T *create(Arg1 A1, Arg2 A2, ProgramStateRef St, const LocationContext *LCtx) { + T *create(Arg1 A1, Arg2 A2, ProgramStateRef St, const LocationContext *LCtx, + CFGBlock::ConstCFGElementRef ElemRef) { static_assert(sizeof(T) == sizeof(CallEventTemplateTy), "CallEvent subclasses are not all the same size"); - return new (allocate()) T(A1, A2, St, LCtx); + return new (allocate()) T(A1, A2, St, LCtx, ElemRef); } template T *create(Arg1 A1, Arg2 A2, Arg3 A3, ProgramStateRef St, - const LocationContext *LCtx) { + const LocationContext *LCtx, CFGBlock::ConstCFGElementRef ElemRef) { static_assert(sizeof(T) == sizeof(CallEventTemplateTy), "CallEvent subclasses are not all the same size"); - return new (allocate()) T(A1, A2, A3, St, LCtx); + return new (allocate()) T(A1, A2, A3, St, LCtx, ElemRef); } template T *create(Arg1 A1, Arg2 A2, Arg3 A3, Arg4 A4, ProgramStateRef St, - const LocationContext *LCtx) { + const LocationContext *LCtx, CFGBlock::ConstCFGElementRef ElemRef) { static_assert(sizeof(T) == sizeof(CallEventTemplateTy), "CallEvent subclasses are not all the same size"); - return new (allocate()) T(A1, A2, A3, A4, St, LCtx); + return new (allocate()) T(A1, A2, A3, A4, St, LCtx, ElemRef); } public: @@ -1304,50 +1341,57 @@ public: /// Gets a call event for a function call, Objective-C method call, /// a 'new', or a 'delete' call. - CallEventRef<> - getCall(const Stmt *S, ProgramStateRef State, - const LocationContext *LC); + CallEventRef<> getCall(const Stmt *S, ProgramStateRef State, + const LocationContext *LC, + CFGBlock::ConstCFGElementRef ElemRef); - CallEventRef<> - getSimpleCall(const CallExpr *E, ProgramStateRef State, - const LocationContext *LCtx); + CallEventRef<> getSimpleCall(const CallExpr *E, ProgramStateRef State, + const LocationContext *LCtx, + CFGBlock::ConstCFGElementRef ElemRef); CallEventRef getObjCMethodCall(const ObjCMessageExpr *E, ProgramStateRef State, - const LocationContext *LCtx) { - return create(E, State, LCtx); + const LocationContext *LCtx, + CFGBlock::ConstCFGElementRef ElemRef) { + return create(E, State, LCtx, ElemRef); } CallEventRef getCXXConstructorCall(const CXXConstructExpr *E, const MemRegion *Target, - ProgramStateRef State, const LocationContext *LCtx) { - return create(E, Target, State, LCtx); + ProgramStateRef State, const LocationContext *LCtx, + CFGBlock::ConstCFGElementRef ElemRef) { + return create(E, Target, State, LCtx, ElemRef); } CallEventRef getCXXInheritedConstructorCall(const CXXInheritedCtorInitExpr *E, const MemRegion *Target, ProgramStateRef State, - const LocationContext *LCtx) { - return create(E, Target, State, LCtx); + const LocationContext *LCtx, + CFGBlock::ConstCFGElementRef ElemRef) { + return create(E, Target, State, LCtx, ElemRef); } CallEventRef getCXXDestructorCall(const CXXDestructorDecl *DD, const Stmt *Trigger, const MemRegion *Target, bool IsBase, - ProgramStateRef State, const LocationContext *LCtx) { - return create(DD, Trigger, Target, IsBase, State, LCtx); + ProgramStateRef State, const LocationContext *LCtx, + CFGBlock::ConstCFGElementRef ElemRef) { + return create(DD, Trigger, Target, IsBase, State, LCtx, + ElemRef); } CallEventRef getCXXAllocatorCall(const CXXNewExpr *E, ProgramStateRef State, - const LocationContext *LCtx) { - return create(E, State, LCtx); + const LocationContext *LCtx, + CFGBlock::ConstCFGElementRef ElemRef) { + return create(E, State, LCtx, ElemRef); } CallEventRef getCXXDeallocatorCall(const CXXDeleteExpr *E, ProgramStateRef State, - const LocationContext *LCtx) { - return create(E, State, LCtx); + const LocationContext *LCtx, + CFGBlock::ConstCFGElementRef ElemRef) { + return create(E, State, LCtx, ElemRef); } }; diff --git a/contrib/llvm-project/clang/include/clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h b/contrib/llvm-project/clang/include/clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h index 9bd5a802d5d..9923c41e6ad 100644 --- a/contrib/llvm-project/clang/include/clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h +++ b/contrib/llvm-project/clang/include/clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h @@ -316,8 +316,8 @@ public: /// bug path significantly shorter. const NoteTag *getNoteTag(StringRef Note, bool IsPrunable = false) { return getNoteTag( - [Note](BugReporterContext &, - PathSensitiveBugReport &) { return std::string(Note); }, + [Note = std::string(Note)](BugReporterContext &, + PathSensitiveBugReport &) { return Note; }, IsPrunable); } diff --git a/contrib/llvm-project/clang/include/clang/StaticAnalyzer/Core/PathSensitive/CoreEngine.h b/contrib/llvm-project/clang/include/clang/StaticAnalyzer/Core/PathSensitive/CoreEngine.h index a595d517cd2..8dbe767cef9 100644 --- a/contrib/llvm-project/clang/include/clang/StaticAnalyzer/Core/PathSensitive/CoreEngine.h +++ b/contrib/llvm-project/clang/include/clang/StaticAnalyzer/Core/PathSensitive/CoreEngine.h @@ -25,6 +25,7 @@ #include "clang/StaticAnalyzer/Core/PathSensitive/ProgramState_Fwd.h" #include "clang/StaticAnalyzer/Core/PathSensitive/WorkList.h" #include "llvm/ADT/SmallVector.h" +#include "llvm/ADT/iterator_range.h" #include "llvm/Support/Casting.h" #include #include @@ -175,21 +176,11 @@ public: WorkList *getWorkList() const { return WList.get(); } WorkList *getCTUWorkList() const { return CTUWList.get(); } - BlocksExhausted::const_iterator blocks_exhausted_begin() const { - return blocksExhausted.begin(); + auto exhausted_blocks() const { + return llvm::iterator_range(blocksExhausted); } - BlocksExhausted::const_iterator blocks_exhausted_end() const { - return blocksExhausted.end(); - } - - BlocksAborted::const_iterator blocks_aborted_begin() const { - return blocksAborted.begin(); - } - - BlocksAborted::const_iterator blocks_aborted_end() const { - return blocksAborted.end(); - } + auto aborted_blocks() const { return llvm::iterator_range(blocksAborted); } /// Enqueue the given set of nodes onto the work list. void enqueue(ExplodedNodeSet &Set); @@ -507,6 +498,11 @@ public: iterator(CFGBlock::const_succ_iterator i) : I(i) {} public: + // This isn't really a conventional iterator. + // We just implement the deref as a no-op for now to make range-based for + // loops work. + const iterator &operator*() const { return *this; } + iterator &operator++() { ++I; return *this; } bool operator!=(const iterator &X) const { return I != X.I; } diff --git a/contrib/llvm-project/clang/include/clang/StaticAnalyzer/Core/PathSensitive/ExplodedGraph.h b/contrib/llvm-project/clang/include/clang/StaticAnalyzer/Core/PathSensitive/ExplodedGraph.h index cb424ba5f3e..2fb05ac46e8 100644 --- a/contrib/llvm-project/clang/include/clang/StaticAnalyzer/Core/PathSensitive/ExplodedGraph.h +++ b/contrib/llvm-project/clang/include/clang/StaticAnalyzer/Core/PathSensitive/ExplodedGraph.h @@ -32,6 +32,7 @@ #include "llvm/ADT/GraphTraits.h" #include "llvm/ADT/STLExtras.h" #include "llvm/ADT/SetVector.h" +#include "llvm/ADT/iterator_range.h" #include "llvm/Support/Allocator.h" #include "llvm/Support/Compiler.h" #include @@ -395,13 +396,9 @@ public: using node_iterator = AllNodesTy::iterator; using const_node_iterator = AllNodesTy::const_iterator; - node_iterator nodes_begin() { return Nodes.begin(); } + llvm::iterator_range nodes() { return Nodes; } - node_iterator nodes_end() { return Nodes.end(); } - - const_node_iterator nodes_begin() const { return Nodes.begin(); } - - const_node_iterator nodes_end() const { return Nodes.end(); } + llvm::iterator_range nodes() const { return Nodes; } roots_iterator roots_begin() { return Roots.begin(); } diff --git a/contrib/llvm-project/clang/include/clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h b/contrib/llvm-project/clang/include/clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h index d7366154553..ed5c4adb5e3 100644 --- a/contrib/llvm-project/clang/include/clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h +++ b/contrib/llvm-project/clang/include/clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h @@ -234,10 +234,10 @@ public: return (*G.roots_begin())->getLocation().getLocationContext(); } - void GenerateAutoTransition(ExplodedNode *N); - void enqueueEndOfPath(ExplodedNodeSet &S); - void GenerateCallExitNode(ExplodedNode *N); - + CFGBlock::ConstCFGElementRef getCFGElementRef() const { + const CFGBlock *blockPtr = currBldrCtx ? currBldrCtx->getBlock() : nullptr; + return {blockPtr, currStmtIdx}; + } /// Dump graph to the specified filename. /// If filename is empty, generate a temporary one. @@ -602,14 +602,7 @@ public: StmtNodeBuilder &Bldr, ExplodedNode *Pred); - ProgramStateRef handleLVectorSplat(ProgramStateRef state, - const LocationContext *LCtx, - const CastExpr *CastE, - StmtNodeBuilder &Bldr, - ExplodedNode *Pred); - - void handleUOExtension(ExplodedNodeSet::iterator I, - const UnaryOperator* U, + void handleUOExtension(ExplodedNode *N, const UnaryOperator *U, StmtNodeBuilder &Bldr); public: @@ -768,15 +761,6 @@ private: void finishArgumentConstruction(ExplodedNodeSet &Dst, ExplodedNode *Pred, const CallEvent &Call); - void evalLoadCommon(ExplodedNodeSet &Dst, - const Expr *NodeEx, /* Eventually will be a CFGStmt */ - const Expr *BoundEx, - ExplodedNode *Pred, - ProgramStateRef St, - SVal location, - const ProgramPointTag *tag, - QualType LoadTy); - void evalLocation(ExplodedNodeSet &Dst, const Stmt *NodeEx, /* This will eventually be a CFGStmt */ const Stmt *BoundEx, @@ -911,13 +895,6 @@ private: static SVal makeElementRegion(ProgramStateRef State, SVal LValue, QualType &Ty, bool &IsArray, unsigned Idx = 0); - /// For a DeclStmt or CXXInitCtorInitializer, walk backward in the current CFG - /// block to find the constructor expression that directly constructed into - /// the storage for this statement. Returns null if the constructor for this - /// statement created a temporary object region rather than directly - /// constructing into an existing region. - const CXXConstructExpr *findDirectConstructorForCurrentCFGElement(); - /// Common code that handles either a CXXConstructExpr or a /// CXXInheritedCtorInitExpr. void handleConstructor(const Expr *E, ExplodedNode *Pred, diff --git a/contrib/llvm-project/clang/include/clang/StaticAnalyzer/Core/PathSensitive/MemRegion.h b/contrib/llvm-project/clang/include/clang/StaticAnalyzer/Core/PathSensitive/MemRegion.h index e982384b3fb..151d3e57c1c 100644 --- a/contrib/llvm-project/clang/include/clang/StaticAnalyzer/Core/PathSensitive/MemRegion.h +++ b/contrib/llvm-project/clang/include/clang/StaticAnalyzer/Core/PathSensitive/MemRegion.h @@ -31,6 +31,7 @@ #include "llvm/ADT/DenseMap.h" #include "llvm/ADT/FoldingSet.h" #include "llvm/ADT/PointerIntPair.h" +#include "llvm/ADT/iterator_range.h" #include "llvm/Support/Allocator.h" #include "llvm/Support/Casting.h" #include @@ -136,8 +137,6 @@ public: /// It might return null. const SymbolicRegion *getSymbolicBase() const; - bool hasGlobalsOrParametersStorage() const; - bool hasStackStorage() const; bool hasStackNonParametersStorage() const; @@ -739,6 +738,11 @@ public: ++OriginalR; return *this; } + + // This isn't really a conventional iterator. + // We just implement the deref as a no-op for now to make range-based for + // loops work. + const referenced_vars_iterator &operator*() const { return *this; } }; /// Return the original region for a captured region, if @@ -747,6 +751,7 @@ public: referenced_vars_iterator referenced_vars_begin() const; referenced_vars_iterator referenced_vars_end() const; + llvm::iterator_range referenced_vars() const; void dumpToStream(raw_ostream &os) const override; @@ -1233,8 +1238,7 @@ class CXXTempObjectRegion : public TypedValueRegion { CXXTempObjectRegion(Expr const *E, MemSpaceRegion const *sReg) : TypedValueRegion(sReg, CXXTempObjectRegionKind), Ex(E) { assert(E); - assert(isa(sReg) || - isa(sReg)); + assert(isa(sReg)); } static void ProfileRegion(llvm::FoldingSetNodeID &ID, @@ -1244,6 +1248,9 @@ public: LLVM_ATTRIBUTE_RETURNS_NONNULL const Expr *getExpr() const { return Ex; } + LLVM_ATTRIBUTE_RETURNS_NONNULL + const StackFrameContext *getStackFrame() const; + QualType getValueType() const override { return Ex->getType(); } void dumpToStream(raw_ostream &os) const override; @@ -1255,6 +1262,45 @@ public: } }; +// C++ temporary object that have lifetime extended to lifetime of the +// variable. Usually they represent temporary bounds to reference variables. +class CXXLifetimeExtendedObjectRegion : public TypedValueRegion { + friend class MemRegionManager; + + Expr const *Ex; + ValueDecl const *ExD; + + CXXLifetimeExtendedObjectRegion(Expr const *E, ValueDecl const *D, + MemSpaceRegion const *sReg) + : TypedValueRegion(sReg, CXXLifetimeExtendedObjectRegionKind), Ex(E), + ExD(D) { + assert(E); + assert(D); + assert((isa(sReg))); + } + + static void ProfileRegion(llvm::FoldingSetNodeID &ID, Expr const *E, + ValueDecl const *D, const MemRegion *sReg); + +public: + LLVM_ATTRIBUTE_RETURNS_NONNULL + const Expr *getExpr() const { return Ex; } + LLVM_ATTRIBUTE_RETURNS_NONNULL + const ValueDecl *getExtendingDecl() const { return ExD; } + /// It might return null. + const StackFrameContext *getStackFrame() const; + + QualType getValueType() const override { return Ex->getType(); } + + void dumpToStream(raw_ostream &os) const override; + + void Profile(llvm::FoldingSetNodeID &ID) const override; + + static bool classof(const MemRegion *R) { + return R->getKind() == CXXLifetimeExtendedObjectRegionKind; + } +}; + // CXXBaseObjectRegion represents a base object within a C++ object. It is // identified by the base class declaration and the region of its parent object. class CXXBaseObjectRegion : public TypedValueRegion { @@ -1487,6 +1533,19 @@ public: const CXXTempObjectRegion *getCXXTempObjectRegion(Expr const *Ex, LocationContext const *LC); + /// Create a CXXLifetimeExtendedObjectRegion for temporaries which are + /// lifetime-extended by local references. + const CXXLifetimeExtendedObjectRegion * + getCXXLifetimeExtendedObjectRegion(Expr const *Ex, ValueDecl const *VD, + LocationContext const *LC); + + /// Create a CXXLifetimeExtendedObjectRegion for temporaries which are + /// lifetime-extended by *static* references. + /// This differs from \ref getCXXLifetimeExtendedObjectRegion(Expr const *, + /// ValueDecl const *, LocationContext const *) in the super-region used. + const CXXLifetimeExtendedObjectRegion * + getCXXStaticLifetimeExtendedObjectRegion(const Expr *Ex, ValueDecl const *VD); + /// Create a CXXBaseObjectRegion with the given base class for region /// \p Super. /// @@ -1525,11 +1584,6 @@ public: const LocationContext *lc, unsigned blockCount); - /// Create a CXXTempObjectRegion for temporaries which are lifetime-extended - /// by static references. This differs from getCXXTempObjectRegion in the - /// super-region used. - const CXXTempObjectRegion *getCXXStaticTempObjectRegion(const Expr *Ex); - private: template diff --git a/contrib/llvm-project/clang/include/clang/StaticAnalyzer/Core/PathSensitive/Regions.def b/contrib/llvm-project/clang/include/clang/StaticAnalyzer/Core/PathSensitive/Regions.def index 44ab31fc9f2..245828a2fcc 100644 --- a/contrib/llvm-project/clang/include/clang/StaticAnalyzer/Core/PathSensitive/Regions.def +++ b/contrib/llvm-project/clang/include/clang/StaticAnalyzer/Core/PathSensitive/Regions.def @@ -69,6 +69,7 @@ ABSTRACT_REGION(SubRegion, MemRegion) REGION(CXXBaseObjectRegion, TypedValueRegion) REGION(CXXDerivedObjectRegion, TypedValueRegion) REGION(CXXTempObjectRegion, TypedValueRegion) + REGION(CXXLifetimeExtendedObjectRegion, TypedValueRegion) REGION(CXXThisRegion, TypedValueRegion) ABSTRACT_REGION(DeclRegion, TypedValueRegion) REGION(FieldRegion, DeclRegion) diff --git a/contrib/llvm-project/clang/include/clang/StaticAnalyzer/Core/PathSensitive/SMTConstraintManager.h b/contrib/llvm-project/clang/include/clang/StaticAnalyzer/Core/PathSensitive/SMTConstraintManager.h index d5c2dc61724..5116a4c0685 100644 --- a/contrib/llvm-project/clang/include/clang/StaticAnalyzer/Core/PathSensitive/SMTConstraintManager.h +++ b/contrib/llvm-project/clang/include/clang/StaticAnalyzer/Core/PathSensitive/SMTConstraintManager.h @@ -203,9 +203,9 @@ public: auto CZ = State->get(); auto &CZFactory = State->get_context(); - for (auto I = CZ.begin(), E = CZ.end(); I != E; ++I) { - if (SymReaper.isDead(I->first)) - CZ = CZFactory.remove(CZ, *I); + for (const auto &Entry : CZ) { + if (SymReaper.isDead(Entry.first)) + CZ = CZFactory.remove(CZ, Entry); } return State->set(CZ); diff --git a/contrib/llvm-project/clang/include/clang/StaticAnalyzer/Core/PathSensitive/SVals.h b/contrib/llvm-project/clang/include/clang/StaticAnalyzer/Core/PathSensitive/SVals.h index 32a1125ce4d..00cce21151a 100644 --- a/contrib/llvm-project/clang/include/clang/StaticAnalyzer/Core/PathSensitive/SVals.h +++ b/contrib/llvm-project/clang/include/clang/StaticAnalyzer/Core/PathSensitive/SVals.h @@ -21,6 +21,7 @@ #include "llvm/ADT/FoldingSet.h" #include "llvm/ADT/ImmutableList.h" #include "llvm/ADT/PointerUnion.h" +#include "llvm/ADT/iterator_range.h" #include "llvm/Support/Casting.h" #include #include @@ -180,16 +181,11 @@ public: void dumpToStream(raw_ostream &OS) const; void dump() const; - SymExpr::symbol_iterator symbol_begin() const { - const SymExpr *SE = getAsSymbol(/*IncludeBaseRegions=*/true); - if (SE) - return SE->symbol_begin(); - else - return SymExpr::symbol_iterator(); - } - - SymExpr::symbol_iterator symbol_end() const { - return SymExpr::symbol_end(); + llvm::iterator_range symbols() const { + if (const SymExpr *SE = getAsSymbol(/*IncludeBaseRegions=*/true)) + return SE->symbols(); + SymExpr::symbol_iterator end{}; + return llvm::make_range(end, end); } /// Try to get a reasonable type for the given value. diff --git a/contrib/llvm-project/clang/include/clang/StaticAnalyzer/Core/PathSensitive/SymExpr.h b/contrib/llvm-project/clang/include/clang/StaticAnalyzer/Core/PathSensitive/SymExpr.h index abd05fe34f5..862a30c0e73 100644 --- a/contrib/llvm-project/clang/include/clang/StaticAnalyzer/Core/PathSensitive/SymExpr.h +++ b/contrib/llvm-project/clang/include/clang/StaticAnalyzer/Core/PathSensitive/SymExpr.h @@ -17,6 +17,7 @@ #include "clang/Basic/LLVM.h" #include "llvm/ADT/FoldingSet.h" #include "llvm/ADT/SmallVector.h" +#include "llvm/ADT/iterator_range.h" #include namespace clang { @@ -83,8 +84,9 @@ public: bool operator!=(const symbol_iterator &X) const; }; - symbol_iterator symbol_begin() const { return symbol_iterator(this); } - static symbol_iterator symbol_end() { return symbol_iterator(); } + llvm::iterator_range symbols() const { + return llvm::make_range(symbol_iterator(this), symbol_iterator()); + } virtual unsigned computeComplexity() const = 0; diff --git a/contrib/llvm-project/clang/include/clang/StaticAnalyzer/Core/PathSensitive/SymbolManager.h b/contrib/llvm-project/clang/include/clang/StaticAnalyzer/Core/PathSensitive/SymbolManager.h index b7ce6ebe987..3b64d38ee2b 100644 --- a/contrib/llvm-project/clang/include/clang/StaticAnalyzer/Core/PathSensitive/SymbolManager.h +++ b/contrib/llvm-project/clang/include/clang/StaticAnalyzer/Core/PathSensitive/SymbolManager.h @@ -24,6 +24,7 @@ #include "llvm/ADT/DenseMap.h" #include "llvm/ADT/DenseSet.h" #include "llvm/ADT/FoldingSet.h" +#include "llvm/ADT/iterator_range.h" #include "llvm/Support/Allocator.h" #include @@ -631,10 +632,9 @@ public: /// symbol marking has occurred, i.e. in the MarkLiveSymbols callback. void markInUse(SymbolRef sym); - using region_iterator = RegionSetTy::const_iterator; - - region_iterator region_begin() const { return LiveRegionRoots.begin(); } - region_iterator region_end() const { return LiveRegionRoots.end(); } + llvm::iterator_range regions() const { + return LiveRegionRoots; + } /// Returns whether or not a symbol has been confirmed dead. /// @@ -672,6 +672,11 @@ public: SymbolVisitor(const SymbolVisitor &) = default; SymbolVisitor(SymbolVisitor &&) {} + // The copy and move assignment operator is defined as deleted pending further + // motivation. + SymbolVisitor &operator=(const SymbolVisitor &) = delete; + SymbolVisitor &operator=(SymbolVisitor &&) = delete; + /// A visitor method invoked by ProgramStateManager::scanReachableSymbols. /// /// The method returns \c true if symbols should continue be scanned and \c diff --git a/contrib/llvm-project/clang/include/clang/Support/RISCVVIntrinsicUtils.h b/contrib/llvm-project/clang/include/clang/Support/RISCVVIntrinsicUtils.h index bf31dced98b..804b1518c06 100644 --- a/contrib/llvm-project/clang/include/clang/Support/RISCVVIntrinsicUtils.h +++ b/contrib/llvm-project/clang/include/clang/Support/RISCVVIntrinsicUtils.h @@ -58,6 +58,13 @@ enum class VectorTypeModifier : uint8_t { SFixedLog2LMUL1, SFixedLog2LMUL2, SFixedLog2LMUL3, + Tuple2, + Tuple3, + Tuple4, + Tuple5, + Tuple6, + Tuple7, + Tuple8, }; // Similar to basic type but used to describe what's kind of type related to @@ -243,6 +250,8 @@ class RVVType { unsigned ElementBitwidth = 0; VScaleVal Scale = 0; bool Valid; + bool IsTuple = false; + unsigned NF = 0; std::string BuiltinStr; std::string ClangBuiltinStr; @@ -293,10 +302,15 @@ public: } bool isConstant() const { return IsConstant; } bool isPointer() const { return IsPointer; } + bool isTuple() const { return IsTuple; } unsigned getElementBitwidth() const { return ElementBitwidth; } ScalarTypeKind getScalarType() const { return ScalarType; } VScaleVal getScale() const { return Scale; } + unsigned getNF() const { + assert(NF > 1 && NF <= 8 && "Only legal NF should be fetched"); + return NF; + } private: // Verify RVV vector type and set Valid. @@ -383,7 +397,7 @@ public: const RVVTypes &Types, const std::vector &IntrinsicTypes, const std::vector &RequiredFeatures, - unsigned NF, Policy PolicyAttrs); + unsigned NF, Policy PolicyAttrs, bool HasFRMRoundModeOp); ~RVVIntrinsic() = default; RVVTypePtr getOutputType() const { return OutputType; } @@ -444,7 +458,7 @@ public: computeBuiltinTypes(llvm::ArrayRef Prototype, bool IsMasked, bool HasMaskedOffOperand, bool HasVL, unsigned NF, PolicyScheme DefaultScheme, - Policy PolicyAttrs); + Policy PolicyAttrs, bool IsTuple); static llvm::SmallVector getSupportedUnMaskedPolicies(); static llvm::SmallVector @@ -453,7 +467,7 @@ public: static void updateNamesAndPolicy(bool IsMasked, bool HasPolicy, std::string &Name, std::string &BuiltinName, std::string &OverloadedName, - Policy &PolicyAttrs); + Policy &PolicyAttrs, bool HasFRMRoundModeOp); }; // RVVRequire should be sync'ed with target features, but only @@ -461,9 +475,9 @@ public: enum RVVRequire : uint8_t { RVV_REQ_None = 0, RVV_REQ_RV64 = 1 << 0, - RVV_REQ_FullMultiply = 1 << 1, + RVV_REQ_Xsfvcp = 1 << 1, - LLVM_MARK_AS_BITMASK_ENUM(RVV_REQ_FullMultiply) + LLVM_MARK_AS_BITMASK_ENUM(RVV_REQ_Xsfvcp) }; // Raw RVV intrinsic info, used to expand later. @@ -511,6 +525,8 @@ struct RVVIntrinsicRecord { bool HasMaskedOffOperand : 1; bool HasTailPolicy : 1; bool HasMaskPolicy : 1; + bool HasFRMRoundModeOp : 1; + bool IsTuple : 1; uint8_t UnMaskedPolicyScheme : 2; uint8_t MaskedPolicyScheme : 2; }; diff --git a/contrib/llvm-project/clang/include/clang/Testing/CommandLineArgs.h b/contrib/llvm-project/clang/include/clang/Testing/CommandLineArgs.h index e668781ee2c..4dd28718dfa 100644 --- a/contrib/llvm-project/clang/include/clang/Testing/CommandLineArgs.h +++ b/contrib/llvm-project/clang/include/clang/Testing/CommandLineArgs.h @@ -38,6 +38,11 @@ std::vector getCC1ArgsForTesting(TestLanguage Lang); StringRef getFilenameForTesting(TestLanguage Lang); +/// Find a target name such that looking for it in TargetRegistry by that name +/// returns the same target. We expect that there is at least one target +/// configured with this property. +std::string getAnyTargetForTesting(); + } // end namespace clang #endif diff --git a/contrib/llvm-project/clang/include/clang/Testing/TestAST.h b/contrib/llvm-project/clang/include/clang/Testing/TestAST.h index 7ba2ca882b9..845e31f6543 100644 --- a/contrib/llvm-project/clang/include/clang/Testing/TestAST.h +++ b/contrib/llvm-project/clang/include/clang/Testing/TestAST.h @@ -49,6 +49,9 @@ struct TestInputs { /// Keys are plain filenames ("foo.h"), values are file content. llvm::StringMap ExtraFiles = {}; + /// Filename to use for translation unit. A default will be used when empty. + std::string FileName; + /// By default, error diagnostics during parsing are reported as gtest errors. /// To suppress this, set ErrorOK or include "error-ok" in a comment in Code. /// In either case, all diagnostics appear in TestAST::diagnostics(). diff --git a/contrib/llvm-project/clang/include/clang/Tooling/DependencyScanning/DependencyScanningTool.h b/contrib/llvm-project/clang/include/clang/Tooling/DependencyScanning/DependencyScanningTool.h index b1a4df141ed..87a4299c7f1 100644 --- a/contrib/llvm-project/clang/include/clang/Tooling/DependencyScanning/DependencyScanningTool.h +++ b/contrib/llvm-project/clang/include/clang/Tooling/DependencyScanning/DependencyScanningTool.h @@ -28,8 +28,14 @@ namespace dependencies { using LookupModuleOutputCallback = llvm::function_ref; +/// Graph of modular dependencies. +using ModuleDepsGraph = std::vector; + /// The full dependencies and module graph for a specific input. -struct FullDependencies { +struct TranslationUnitDeps { + /// The graph of direct and transitive modular dependencies. + ModuleDepsGraph ModuleGraph; + /// The identifier of the C++20 module this translation unit exports. /// /// If the translation unit is not a module then \c ID.ModuleName is empty. @@ -62,11 +68,6 @@ struct FullDependencies { std::vector DriverCommandLine; }; -struct FullDependenciesResult { - FullDependencies FullDeps; - std::vector DiscoveredModules; -}; - struct P1689Rule { std::string PrimaryOutput; std::optional Provides; @@ -84,14 +85,12 @@ public: /// Print out the dependency information into a string using the dependency /// file format that is specified in the options (-MD is the default) and - /// return it. If \p ModuleName isn't empty, this function returns the - /// dependency information of module \p ModuleName. + /// return it. /// /// \returns A \c StringError with the diagnostic output if clang errors /// occurred, dependency file contents otherwise. llvm::Expected - getDependencyFile(const std::vector &CommandLine, StringRef CWD, - std::optional ModuleName = std::nullopt); + getDependencyFile(const std::vector &CommandLine, StringRef CWD); /// Collect the module dependency in P1689 format for C++20 named modules. /// @@ -105,9 +104,9 @@ public: /// \returns A \c StringError with the diagnostic output if clang errors /// occurred, P1689 dependency format rules otherwise. llvm::Expected - getP1689ModuleDependencyFile( - const clang::tooling::CompileCommand &Command, StringRef CWD, - std::string &MakeformatOutput, std::string &MakeformatOutputPath); + getP1689ModuleDependencyFile(const clang::tooling::CompileCommand &Command, + StringRef CWD, std::string &MakeformatOutput, + std::string &MakeformatOutputPath); /// Given a Clang driver command-line for a translation unit, gather the /// modular dependencies and return the information needed for explicit build. @@ -122,18 +121,21 @@ public: /// arguments for dependencies. /// /// \returns a \c StringError with the diagnostic output if clang errors - /// occurred, \c FullDependencies otherwise. - llvm::Expected - getFullDependencies(const std::vector &CommandLine, - StringRef CWD, const llvm::StringSet<> &AlreadySeen, - LookupModuleOutputCallback LookupModuleOutput, - std::optional ModuleName = std::nullopt); + /// occurred, \c TranslationUnitDeps otherwise. + llvm::Expected + getTranslationUnitDependencies(const std::vector &CommandLine, + StringRef CWD, + const llvm::StringSet<> &AlreadySeen, + LookupModuleOutputCallback LookupModuleOutput); - llvm::Expected getFullDependenciesLegacyDriverCommand( - const std::vector &CommandLine, StringRef CWD, - const llvm::StringSet<> &AlreadySeen, - LookupModuleOutputCallback LookupModuleOutput, - std::optional ModuleName = std::nullopt); + /// Given a compilation context specified via the Clang driver command-line, + /// gather modular dependencies of module with the given name, and return the + /// information needed for explicit build. + llvm::Expected + getModuleDependencies(StringRef ModuleName, + const std::vector &CommandLine, + StringRef CWD, const llvm::StringSet<> &AlreadySeen, + LookupModuleOutputCallback LookupModuleOutput); private: DependencyScanningWorker Worker; @@ -141,11 +143,8 @@ private: class FullDependencyConsumer : public DependencyConsumer { public: - FullDependencyConsumer(const llvm::StringSet<> &AlreadySeen, - LookupModuleOutputCallback LookupModuleOutput, - bool EagerLoadModules) - : AlreadySeen(AlreadySeen), LookupModuleOutput(LookupModuleOutput), - EagerLoadModules(EagerLoadModules) {} + FullDependencyConsumer(const llvm::StringSet<> &AlreadySeen) + : AlreadySeen(AlreadySeen) {} void handleBuildCommand(Command Cmd) override { Commands.push_back(std::move(Cmd)); @@ -169,15 +168,8 @@ public: ContextHash = std::move(Hash); } - std::string lookupModuleOutput(const ModuleID &ID, - ModuleOutputKind Kind) override { - return LookupModuleOutput(ID, Kind); - } - - FullDependenciesResult getFullDependenciesLegacyDriverCommand( - const std::vector &OriginalCommandLine) const; - - FullDependenciesResult takeFullDependencies(); + TranslationUnitDeps takeTranslationUnitDeps(); + ModuleDepsGraph takeModuleGraphDeps(); private: std::vector Dependencies; @@ -188,8 +180,31 @@ private: std::string ContextHash; std::vector OutputPaths; const llvm::StringSet<> &AlreadySeen; +}; + +/// A simple dependency action controller that uses a callback. If no callback +/// is provided, it is assumed that looking up module outputs is unreachable. +class CallbackActionController : public DependencyActionController { +public: + virtual ~CallbackActionController(); + + CallbackActionController(LookupModuleOutputCallback LMO) + : LookupModuleOutput(std::move(LMO)) { + if (!LookupModuleOutput) { + LookupModuleOutput = [](const ModuleID &, + ModuleOutputKind) -> std::string { + llvm::report_fatal_error("unexpected call to lookupModuleOutput"); + }; + } + } + + std::string lookupModuleOutput(const ModuleID &ID, + ModuleOutputKind Kind) override { + return LookupModuleOutput(ID, Kind); + } + +private: LookupModuleOutputCallback LookupModuleOutput; - bool EagerLoadModules; }; } // end namespace dependencies diff --git a/contrib/llvm-project/clang/include/clang/Tooling/DependencyScanning/DependencyScanningWorker.h b/contrib/llvm-project/clang/include/clang/Tooling/DependencyScanning/DependencyScanningWorker.h index 6edf2cbe6b5..350acb8f8a7 100644 --- a/contrib/llvm-project/clang/include/clang/Tooling/DependencyScanning/DependencyScanningWorker.h +++ b/contrib/llvm-project/clang/include/clang/Tooling/DependencyScanning/DependencyScanningWorker.h @@ -31,7 +31,7 @@ class DependencyScanningWorkerFilesystem; /// A command-line tool invocation that is part of building a TU. /// -/// \see FullDependencies::Commands. +/// \see TranslationUnitDeps::Commands. struct Command { std::string Executable; std::vector Arguments; @@ -57,6 +57,13 @@ public: virtual void handleModuleDependency(ModuleDeps MD) = 0; virtual void handleContextHash(std::string Hash) = 0; +}; + +/// Dependency scanner callbacks that are used during scanning to influence the +/// behaviour of the scan - for example, to customize the scanned invocations. +class DependencyActionController { +public: + virtual ~DependencyActionController(); virtual std::string lookupModuleOutput(const ModuleID &ID, ModuleOutputKind Kind) = 0; @@ -83,15 +90,15 @@ public: bool computeDependencies(StringRef WorkingDirectory, const std::vector &CommandLine, DependencyConsumer &DepConsumer, + DependencyActionController &Controller, DiagnosticConsumer &DiagConsumer, std::optional ModuleName = std::nullopt); /// \returns A \c StringError with the diagnostic output if clang errors /// occurred, success otherwise. - llvm::Error - computeDependencies(StringRef WorkingDirectory, - const std::vector &CommandLine, - DependencyConsumer &Consumer, - std::optional ModuleName = std::nullopt); + llvm::Error computeDependencies( + StringRef WorkingDirectory, const std::vector &CommandLine, + DependencyConsumer &Consumer, DependencyActionController &Controller, + std::optional ModuleName = std::nullopt); bool shouldEagerLoadModules() const { return EagerLoadModules; } diff --git a/contrib/llvm-project/clang/include/clang/Tooling/DependencyScanning/ModuleDepCollector.h b/contrib/llvm-project/clang/include/clang/Tooling/DependencyScanning/ModuleDepCollector.h index bce3e066372..0a5cbc4f046 100644 --- a/contrib/llvm-project/clang/include/clang/Tooling/DependencyScanning/ModuleDepCollector.h +++ b/contrib/llvm-project/clang/include/clang/Tooling/DependencyScanning/ModuleDepCollector.h @@ -27,6 +27,7 @@ namespace clang { namespace tooling { namespace dependencies { +class DependencyActionController; class DependencyConsumer; /// Modular dependency that has already been built prior to the dependency scan. @@ -58,7 +59,13 @@ struct ModuleID { std::string ContextHash; bool operator==(const ModuleID &Other) const { - return ModuleName == Other.ModuleName && ContextHash == Other.ContextHash; + return std::tie(ModuleName, ContextHash) == + std::tie(Other.ModuleName, Other.ContextHash); + } + + bool operator<(const ModuleID& Other) const { + return std::tie(ModuleName, ContextHash) < + std::tie(Other.ModuleName, Other.ContextHash); } }; @@ -147,9 +154,9 @@ class ModuleDepCollectorPP final : public PPCallbacks { public: ModuleDepCollectorPP(ModuleDepCollector &MDC) : MDC(MDC) {} - void FileChanged(SourceLocation Loc, FileChangeReason Reason, - SrcMgr::CharacteristicKind FileType, - FileID PrevFID) override; + void LexedFileChanged(FileID FID, LexedFileChangeReason Reason, + SrcMgr::CharacteristicKind FileType, FileID PrevFID, + SourceLocation Loc) override; void InclusionDirective(SourceLocation HashLoc, const Token &IncludeTok, StringRef FileName, bool IsAngled, CharSourceRange FilenameRange, @@ -201,6 +208,7 @@ class ModuleDepCollector final : public DependencyCollector { public: ModuleDepCollector(std::unique_ptr Opts, CompilerInstance &ScanInstance, DependencyConsumer &C, + DependencyActionController &Controller, CompilerInvocation OriginalCI, bool OptimizeArgs, bool EagerLoadModules, bool IsStdModuleP1689Format); @@ -218,6 +226,8 @@ private: CompilerInstance &ScanInstance; /// The consumer of collected dependency information. DependencyConsumer &Consumer; + /// Callbacks for computing dependency information. + DependencyActionController &Controller; /// Path to the main source file. std::string MainFile; /// Hash identifying the compilation conditions of the current TU. diff --git a/contrib/llvm-project/clang/include/clang/Tooling/Inclusions/HeaderAnalysis.h b/contrib/llvm-project/clang/include/clang/Tooling/Inclusions/HeaderAnalysis.h index 760b8dd0879..84d90c44de0 100644 --- a/contrib/llvm-project/clang/include/clang/Tooling/Inclusions/HeaderAnalysis.h +++ b/contrib/llvm-project/clang/include/clang/Tooling/Inclusions/HeaderAnalysis.h @@ -28,7 +28,7 @@ namespace tooling { /// This function can be expensive as it may scan the source code to find out /// dont-include-me pattern heuristically. bool isSelfContainedHeader(const FileEntry *FE, const SourceManager &SM, - HeaderSearch &HeaderInfo); + const HeaderSearch &HeaderInfo); /// This scans the given source code to see if it contains #import(s). bool codeContainsImports(llvm::StringRef Code); diff --git a/contrib/llvm-project/clang/include/clang/Tooling/Inclusions/HeaderIncludes.h b/contrib/llvm-project/clang/include/clang/Tooling/Inclusions/HeaderIncludes.h index 9e08046d2e3..d5439dd2c84 100644 --- a/contrib/llvm-project/clang/include/clang/Tooling/Inclusions/HeaderIncludes.h +++ b/contrib/llvm-project/clang/include/clang/Tooling/Inclusions/HeaderIncludes.h @@ -128,6 +128,8 @@ private: // inserting new #includes into the actual code section (e.g. after a // declaration). unsigned MaxInsertOffset; + // True if we find the main-file header in the Code. + bool MainIncludeFound; IncludeCategoryManager Categories; // Record the offset of the end of the last include in each category. std::unordered_map CategoryEndOffsets; diff --git a/contrib/llvm-project/clang/include/clang/Tooling/Inclusions/StandardLibrary.h b/contrib/llvm-project/clang/include/clang/Tooling/Inclusions/StandardLibrary.h index beb2f496f51..a39ceb520dc 100644 --- a/contrib/llvm-project/clang/include/clang/Tooling/Inclusions/StandardLibrary.h +++ b/contrib/llvm-project/clang/include/clang/Tooling/Inclusions/StandardLibrary.h @@ -30,6 +30,7 @@ namespace tooling { namespace stdlib { class Symbol; +enum class Lang { C = 0, CXX, LastValue = CXX }; // A standard library header, such as // Lightweight class, in fact just an index into a table. @@ -37,8 +38,10 @@ class Symbol; // "" and "" (and their symbols) are treated differently. class Header { public: + static std::vector
all(Lang L = Lang::CXX); // Name should contain the angle brackets, e.g. "". - static std::optional
named(llvm::StringRef Name); + static std::optional
named(llvm::StringRef Name, + Lang Language = Lang::CXX); friend llvm::raw_ostream &operator<<(llvm::raw_ostream &OS, const Header &H) { return OS << H.name(); @@ -46,8 +49,10 @@ public: llvm::StringRef name() const; private: - Header(unsigned ID) : ID(ID) {} + Header(unsigned ID, Lang Language) : ID(ID), Language(Language) {} unsigned ID; + Lang Language; + friend Symbol; friend llvm::DenseMapInfo
; friend bool operator==(const Header &L, const Header &R) { @@ -63,24 +68,28 @@ private: // for them. class Symbol { public: + static std::vector all(Lang L = Lang::CXX); /// \p Scope should have the trailing "::", for example: /// named("std::chrono::", "system_clock") - static std::optional named(llvm::StringRef Scope, - llvm::StringRef Name); + static std::optional + named(llvm::StringRef Scope, llvm::StringRef Name, Lang Language = Lang::CXX); friend llvm::raw_ostream &operator<<(llvm::raw_ostream &OS, const Symbol &S) { - return OS << S.scope() << S.name(); + return OS << S.qualifiedName(); } llvm::StringRef scope() const; llvm::StringRef name() const; + llvm::StringRef qualifiedName() const; // The preferred header for this symbol (e.g. the suggested insertion). - Header header() const; + std::optional
header() const; // Some symbols may be provided by multiple headers. llvm::SmallVector
headers() const; private: - Symbol(unsigned ID) : ID(ID) {} + Symbol(unsigned ID, Lang Language) : ID(ID), Language(Language) {} unsigned ID; + Lang Language; + friend class Recognizer; friend llvm::DenseMapInfo; friend bool operator==(const Symbol &L, const Symbol &R) { @@ -99,7 +108,7 @@ public: private: using NSSymbolMap = llvm::DenseMap; - NSSymbolMap *namespaceSymbols(const NamespaceDecl *D); + NSSymbolMap *namespaceSymbols(const DeclContext *DC, Lang L); llvm::DenseMap NamespaceCache; }; @@ -111,10 +120,12 @@ namespace llvm { template <> struct DenseMapInfo { static inline clang::tooling::stdlib::Header getEmptyKey() { - return clang::tooling::stdlib::Header(-1); + return clang::tooling::stdlib::Header(-1, + clang::tooling::stdlib::Lang::CXX); } static inline clang::tooling::stdlib::Header getTombstoneKey() { - return clang::tooling::stdlib::Header(-2); + return clang::tooling::stdlib::Header(-2, + clang::tooling::stdlib::Lang::CXX); } static unsigned getHashValue(const clang::tooling::stdlib::Header &H) { return hash_value(H.ID); @@ -127,10 +138,12 @@ template <> struct DenseMapInfo { template <> struct DenseMapInfo { static inline clang::tooling::stdlib::Symbol getEmptyKey() { - return clang::tooling::stdlib::Symbol(-1); + return clang::tooling::stdlib::Symbol(-1, + clang::tooling::stdlib::Lang::CXX); } static inline clang::tooling::stdlib::Symbol getTombstoneKey() { - return clang::tooling::stdlib::Symbol(-2); + return clang::tooling::stdlib::Symbol(-2, + clang::tooling::stdlib::Lang::CXX); } static unsigned getHashValue(const clang::tooling::stdlib::Symbol &S) { return hash_value(S.ID); diff --git a/contrib/llvm-project/clang/include/clang/Tooling/Inclusions/StdSymbolMap.inc b/contrib/llvm-project/clang/include/clang/Tooling/Inclusions/StdSymbolMap.inc deleted file mode 100644 index e5e9065731e..00000000000 --- a/contrib/llvm-project/clang/include/clang/Tooling/Inclusions/StdSymbolMap.inc +++ /dev/null @@ -1,1538 +0,0 @@ -//===-- gen_std.py generated file -------------------------------*- C++ -*-===// -// -// Used to build a lookup table (qualified names => include headers) for CPP -// Standard Library symbols. -// -// This file was generated automatically by -// clang/tools/include-mapping/gen_std.py, DO NOT EDIT! -// -// Generated from cppreference offline HTML book (modified on 2018-10-28). -//===----------------------------------------------------------------------===// - -SYMBOL(Assignable, std::, ) -SYMBOL(Boolean, std::, ) -SYMBOL(Common, std::, ) -SYMBOL(CommonReference, std::, ) -SYMBOL(Constructible, std::, ) -SYMBOL(ConvertibleTo, std::, ) -SYMBOL(CopyConstructible, std::, ) -SYMBOL(Copyable, std::, ) -SYMBOL(DefaultConstructible, std::, ) -SYMBOL(DerivedFrom, std::, ) -SYMBOL(Destructible, std::, ) -SYMBOL(EqualityComparable, std::, ) -SYMBOL(EqualityComparableWith, std::, ) -SYMBOL(FILE, std::, ) -SYMBOL(Integral, std::, ) -SYMBOL(Invocable, std::, ) -SYMBOL(Movable, std::, ) -SYMBOL(MoveConstructible, std::, ) -SYMBOL(Predicate, std::, ) -SYMBOL(Regular, std::, ) -SYMBOL(RegularInvocable, std::, ) -SYMBOL(Relation, std::, ) -SYMBOL(Same, std::, ) -SYMBOL(Semiregular, std::, ) -SYMBOL(SignedIntegral, std::, ) -SYMBOL(StrictTotallyOrdered, std::, ) -SYMBOL(StrictTotallyOrderedWith, std::, ) -SYMBOL(StrictWeakOrder, std::, ) -SYMBOL(Swappable, std::, ) -SYMBOL(SwappableWith, std::, ) -SYMBOL(UniformRandomBitGenerator, std::, ) -SYMBOL(UnsignedIntegral, std::, ) -SYMBOL(_Exit, std::, ) -SYMBOL(accumulate, std::, ) -SYMBOL(acos, std::, ) -SYMBOL(acosh, std::, ) -SYMBOL(add_const, std::, ) -SYMBOL(add_const_t, std::, ) -SYMBOL(add_cv, std::, ) -SYMBOL(add_cv_t, std::, ) -SYMBOL(add_lvalue_reference, std::, ) -SYMBOL(add_lvalue_reference_t, std::, ) -SYMBOL(add_pointer, std::, ) -SYMBOL(add_pointer_t, std::, ) -SYMBOL(add_rvalue_reference, std::, ) -SYMBOL(add_rvalue_reference_t, std::, ) -SYMBOL(add_volatile, std::, ) -SYMBOL(add_volatile_t, std::, ) -SYMBOL(addressof, std::, ) -SYMBOL(adjacent_difference, std::, ) -SYMBOL(adjacent_find, std::, ) -SYMBOL(adopt_lock, std::, ) -SYMBOL(adopt_lock_t, std::, ) -SYMBOL(advance, std::, ) -SYMBOL(align, std::, ) -SYMBOL(align_val_t, std::, ) -SYMBOL(aligned_alloc, std::, ) -SYMBOL(aligned_storage, std::, ) -SYMBOL(aligned_storage_t, std::, ) -SYMBOL(aligned_union, std::, ) -SYMBOL(aligned_union_t, std::, ) -SYMBOL(alignment_of, std::, ) -SYMBOL(alignment_of_v, std::, ) -SYMBOL(all_of, std::, ) -SYMBOL(allocate_shared, std::, ) -SYMBOL(allocator, std::, ) -SYMBOL(allocator_arg, std::, ) -SYMBOL(allocator_arg_t, std::, ) -SYMBOL(allocator_traits, std::, ) -SYMBOL(any, std::, ) -SYMBOL(any_of, std::, ) -SYMBOL(apply, std::, ) -SYMBOL(arg, std::, ) -SYMBOL(array, std::, ) -SYMBOL(as_const, std::, ) -SYMBOL(asctime, std::, ) -SYMBOL(asin, std::, ) -SYMBOL(asinh, std::, ) -SYMBOL(async, std::, ) -SYMBOL(at_quick_exit, std::, ) -SYMBOL(atan, std::, ) -SYMBOL(atan2, std::, ) -SYMBOL(atanh, std::, ) -SYMBOL(atexit, std::, ) -SYMBOL(atof, std::, ) -SYMBOL(atoi, std::, ) -SYMBOL(atol, std::, ) -SYMBOL(atoll, std::, ) -SYMBOL(atomic_compare_exchange_strong, std::, ) -SYMBOL(atomic_compare_exchange_strong_explicit, std::, ) -SYMBOL(atomic_compare_exchange_weak, std::, ) -SYMBOL(atomic_compare_exchange_weak_explicit, std::, ) -SYMBOL(atomic_exchange, std::, ) -SYMBOL(atomic_exchange_explicit, std::, ) -SYMBOL(atomic_fetch_add, std::, ) -SYMBOL(atomic_fetch_add_explicit, std::, ) -SYMBOL(atomic_fetch_and, std::, ) -SYMBOL(atomic_fetch_and_explicit, std::, ) -SYMBOL(atomic_fetch_or, std::, ) -SYMBOL(atomic_fetch_or_explicit, std::, ) -SYMBOL(atomic_fetch_sub, std::, ) -SYMBOL(atomic_fetch_sub_explicit, std::, ) -SYMBOL(atomic_fetch_xor, std::, ) -SYMBOL(atomic_fetch_xor_explicit, std::, ) -SYMBOL(atomic_flag, std::, ) -SYMBOL(atomic_flag_clear, std::, ) -SYMBOL(atomic_flag_clear_explicit, std::, ) -SYMBOL(atomic_flag_test_and_set, std::, ) -SYMBOL(atomic_flag_test_and_set_explicit, std::, ) -SYMBOL(atomic_init, std::, ) -SYMBOL(atomic_is_lockfree, std::, ) -SYMBOL(atomic_load, std::, ) -SYMBOL(atomic_load_explicit, std::, ) -SYMBOL(atomic_ref, std::, ) -SYMBOL(atomic_signal_fence, std::, ) -SYMBOL(atomic_store, std::, ) -SYMBOL(atomic_store_explicit, std::, ) -SYMBOL(atomic_thread_fence, std::, ) -SYMBOL(atto, std::, ) -SYMBOL(auto_ptr, std::, ) -SYMBOL(back_insert_iterator, std::, ) -SYMBOL(back_inserter, std::, ) -SYMBOL(bad_alloc, std::, ) -SYMBOL(bad_any_cast, std::, ) -SYMBOL(bad_array_new_length, std::, ) -SYMBOL(bad_cast, std::, ) -SYMBOL(bad_exception, std::, ) -SYMBOL(bad_function_call, std::, ) -SYMBOL(bad_optional_access, std::, ) -SYMBOL(bad_typeid, std::, ) -SYMBOL(bad_variant_access, std::, ) -SYMBOL(bad_weak_ptr, std::, ) -SYMBOL(basic_common_reference, std::, ) -SYMBOL(basic_filebuf, std::, ) -SYMBOL(basic_fstream, std::, ) -SYMBOL(basic_ifstream, std::, ) -SYMBOL(basic_ios, std::, ) -SYMBOL(basic_iostream, std::, ) -SYMBOL(basic_istream, std::, ) -SYMBOL(basic_istringstream, std::, ) -SYMBOL(basic_ofstream, std::, ) -SYMBOL(basic_ostream, std::, ) -SYMBOL(basic_ostringstream, std::, ) -SYMBOL(basic_osyncstream, std::, ) -SYMBOL(basic_regex, std::, ) -SYMBOL(basic_streambuf, std::, ) -SYMBOL(basic_string, std::, ) -SYMBOL(basic_string_view, std::, ) -SYMBOL(basic_stringbuf, std::, ) -SYMBOL(basic_stringstream, std::, ) -SYMBOL(basic_syncbuf, std::, ) -SYMBOL(begin, std::, ) -SYMBOL(bernoulli_distribution, std::, ) -SYMBOL(bidirectional_iterator_tag, std::, ) -SYMBOL(binary_search, std::, ) -SYMBOL(bind, std::, ) -SYMBOL(binomial_distribution, std::, ) -SYMBOL(bit_and, std::, ) -SYMBOL(bit_cast, std::, ) -SYMBOL(bit_not, std::, ) -SYMBOL(bit_or, std::, ) -SYMBOL(bit_xor, std::, ) -SYMBOL(bitset, std::, ) -SYMBOL(bool_constant, std::, ) -SYMBOL(boolalpha, std::, ) -SYMBOL(boyer_moore_horspool_searcher, std::, ) -SYMBOL(boyer_moore_searcher, std::, ) -SYMBOL(bsearch, std::, ) -SYMBOL(btowc, std::, ) -SYMBOL(byte, std::, ) -SYMBOL(c16rtomb, std::, ) -SYMBOL(c32rtomb, std::, ) -SYMBOL(call_once, std::, ) -SYMBOL(calloc, std::, ) -SYMBOL(cauchy_distribution, std::, ) -SYMBOL(cbegin, std::, ) -SYMBOL(cbrt, std::, ) -SYMBOL(ceil, std::, ) -SYMBOL(ceil2, std::, ) -SYMBOL(cend, std::, ) -SYMBOL(centi, std::, ) -SYMBOL(cerr, std::, ) -SYMBOL(char_traits, std::, ) -SYMBOL(chars_format, std::, ) -SYMBOL(chi_squared_distribution, std::, ) -SYMBOL(cin, std::, ) -SYMBOL(clamp, std::, ) -SYMBOL(clearerr, std::, ) -SYMBOL(clock, std::, ) -SYMBOL(clock_t, std::, ) -SYMBOL(clog, std::, ) -SYMBOL(cmatch, std::, ) -SYMBOL(codecvt, std::, ) -SYMBOL(codecvt_base, std::, ) -SYMBOL(codecvt_byname, std::, ) -SYMBOL(codecvt_mode, std::, ) -SYMBOL(codecvt_utf16, std::, ) -SYMBOL(codecvt_utf8, std::, ) -SYMBOL(codecvt_utf8_utf16, std::, ) -SYMBOL(collate, std::, ) -SYMBOL(collate_byname, std::, ) -SYMBOL(common_comparison_category, std::, ) -SYMBOL(common_comparison_category_t, std::, ) -SYMBOL(common_reference, std::, ) -SYMBOL(common_reference_t, std::, ) -SYMBOL(common_type, std::, ) -SYMBOL(common_type_t, std::, ) -SYMBOL(compare_3way, std::, ) -SYMBOL(complex, std::, ) -SYMBOL(condition_variable, std::, ) -SYMBOL(condition_variable_any, std::, ) -SYMBOL(conditional, std::, ) -SYMBOL(conditional_t, std::, ) -SYMBOL(conj, std::, ) -SYMBOL(conjunction, std::, ) -SYMBOL(conjunction_v, std::, ) -SYMBOL(const_pointer_cast, std::, ) -SYMBOL(contract_violation, std::, ) -SYMBOL(copy, std::, ) -SYMBOL(copy_backward, std::, ) -SYMBOL(copy_if, std::, ) -SYMBOL(copy_n, std::, ) -SYMBOL(copysign, std::, ) -SYMBOL(cos, std::, ) -SYMBOL(cosh, std::, ) -SYMBOL(count, std::, ) -SYMBOL(count_if, std::, ) -SYMBOL(cout, std::, ) -SYMBOL(crbegin, std::, ) -SYMBOL(cref, std::, ) -SYMBOL(cregex_iterator, std::, ) -SYMBOL(cregex_token_iterator, std::, ) -SYMBOL(crend, std::, ) -SYMBOL(csub_match, std::, ) -SYMBOL(ctime, std::, ) -SYMBOL(ctype, std::, ) -SYMBOL(ctype_base, std::, ) -SYMBOL(ctype_byname, std::, ) -SYMBOL(current_exception, std::, ) -SYMBOL(cv_status, std::, ) -SYMBOL(data, std::, ) -SYMBOL(dec, std::, ) -SYMBOL(deca, std::, ) -SYMBOL(decay, std::, ) -SYMBOL(decay_t, std::, ) -SYMBOL(deci, std::, ) -SYMBOL(declare_no_pointers, std::, ) -SYMBOL(declare_reachable, std::, ) -SYMBOL(declval, std::, ) -SYMBOL(default_delete, std::, ) -SYMBOL(default_random_engine, std::, ) -SYMBOL(default_searcher, std::, ) -SYMBOL(defaultfloat, std::, ) -SYMBOL(defer_lock, std::, ) -SYMBOL(defer_lock_t, std::, ) -SYMBOL(denorm_absent, std::, ) -SYMBOL(denorm_indeterminate, std::, ) -SYMBOL(denorm_present, std::, ) -SYMBOL(deque, std::, ) -SYMBOL(destroy, std::, ) -SYMBOL(destroy_at, std::, ) -SYMBOL(destroy_n, std::, ) -SYMBOL(destroying_delete, std::, ) -SYMBOL(destroying_delete_t, std::, ) -SYMBOL(difftime, std::, ) -SYMBOL(discard_block_engine, std::, ) -SYMBOL(discrete_distribution, std::, ) -SYMBOL(disjunction, std::, ) -SYMBOL(disjunction_v, std::, ) -SYMBOL(distance, std::, ) -SYMBOL(div_t, std::, ) -SYMBOL(divides, std::, ) -SYMBOL(domain_error, std::, ) -SYMBOL(double_t, std::, ) -SYMBOL(dynamic_extent, std::, ) -SYMBOL(dynamic_pointer_cast, std::, ) -SYMBOL(emit_on_flush, std::, ) -SYMBOL(empty, std::, ) -SYMBOL(enable_if, std::, ) -SYMBOL(enable_if_t, std::, ) -SYMBOL(enable_shared_from_this, std::, ) -SYMBOL(end, std::, ) -SYMBOL(endian, std::, ) -SYMBOL(endl, std::, ) -SYMBOL(ends, std::, ) -SYMBOL(equal, std::, ) -SYMBOL(equal_range, std::, ) -SYMBOL(equal_to, std::, ) -SYMBOL(erf, std::, ) -SYMBOL(erfc, std::, ) -SYMBOL(errc, std::, ) -SYMBOL(error_category, std::, ) -SYMBOL(error_code, std::, ) -SYMBOL(error_condition, std::, ) -SYMBOL(exa, std::, ) -SYMBOL(exception, std::, ) -SYMBOL(exception_ptr, std::, ) -SYMBOL(exchange, std::, ) -SYMBOL(exclusive_scan, std::, ) -SYMBOL(exit, std::, ) -SYMBOL(exp, std::, ) -SYMBOL(exp2, std::, ) -SYMBOL(expm1, std::, ) -SYMBOL(exponential_distribution, std::, ) -SYMBOL(extent, std::, ) -SYMBOL(extent_v, std::, ) -SYMBOL(extreme_value_distribution, std::, ) -SYMBOL(false_type, std::, ) -SYMBOL(fclose, std::, ) -SYMBOL(fdim, std::, ) -SYMBOL(feclearexcept, std::, ) -SYMBOL(fegetenv, std::, ) -SYMBOL(fegetexceptflag, std::, ) -SYMBOL(fegetround, std::, ) -SYMBOL(feholdexcept, std::, ) -SYMBOL(femto, std::, ) -SYMBOL(fenv_t, std::, ) -SYMBOL(feof, std::, ) -SYMBOL(feraiseexcept, std::, ) -SYMBOL(ferror, std::, ) -SYMBOL(fesetenv, std::, ) -SYMBOL(fesetexceptflag, std::, ) -SYMBOL(fesetround, std::, ) -SYMBOL(fetestexcept, std::, ) -SYMBOL(feupdateenv, std::, ) -SYMBOL(fexcept_t, std::, ) -SYMBOL(fflush, std::, ) -SYMBOL(fgetc, std::, ) -SYMBOL(fgetpos, std::, ) -SYMBOL(fgets, std::, ) -SYMBOL(fgetwc, std::, ) -SYMBOL(fgetws, std::, ) -SYMBOL(filebuf, std::, ) -SYMBOL(fill, std::, ) -SYMBOL(fill_n, std::, ) -SYMBOL(find, std::, ) -SYMBOL(find_end, std::, ) -SYMBOL(find_first_of, std::, ) -SYMBOL(find_if, std::, ) -SYMBOL(find_if_not, std::, ) -SYMBOL(fisher_f_distribution, std::, ) -SYMBOL(fixed, std::, ) -SYMBOL(float_denorm_style, std::, ) -SYMBOL(float_round_style, std::, ) -SYMBOL(float_t, std::, ) -SYMBOL(floor, std::, ) -SYMBOL(floor2, std::, ) -SYMBOL(flush, std::, ) -SYMBOL(flush_emit, std::, ) -SYMBOL(fma, std::, ) -SYMBOL(fmax, std::, ) -SYMBOL(fmin, std::, ) -SYMBOL(fmod, std::, ) -SYMBOL(fopen, std::, ) -SYMBOL(for_each, std::, ) -SYMBOL(for_each_n, std::, ) -SYMBOL(forward, std::, ) -SYMBOL(forward_as_tuple, std::, ) -SYMBOL(forward_iterator_tag, std::, ) -SYMBOL(forward_list, std::, ) -SYMBOL(fpclassify, std::, ) -SYMBOL(fpos, std::, ) -SYMBOL(fpos_t, std::, ) -SYMBOL(fprintf, std::, ) -SYMBOL(fputc, std::, ) -SYMBOL(fputs, std::, ) -SYMBOL(fputwc, std::, ) -SYMBOL(fputws, std::, ) -SYMBOL(fread, std::, ) -SYMBOL(free, std::, ) -SYMBOL(freopen, std::, ) -SYMBOL(frexp, std::, ) -SYMBOL(from_chars, std::, ) -SYMBOL(front_insert_iterator, std::, ) -SYMBOL(front_inserter, std::, ) -SYMBOL(fscanf, std::, ) -SYMBOL(fseek, std::, ) -SYMBOL(fsetpos, std::, ) -SYMBOL(fstream, std::, ) -SYMBOL(ftell, std::, ) -SYMBOL(function, std::, ) -SYMBOL(future, std::, ) -SYMBOL(future_category, std::, ) -SYMBOL(future_errc, std::, ) -SYMBOL(future_error, std::, ) -SYMBOL(future_status, std::, ) -SYMBOL(fwide, std::, ) -SYMBOL(fwprintf, std::, ) -SYMBOL(fwrite, std::, ) -SYMBOL(fwscanf, std::, ) -SYMBOL(gamma_distribution, std::, ) -SYMBOL(gcd, std::, ) -SYMBOL(generate, std::, ) -SYMBOL(generate_canonical, std::, ) -SYMBOL(generate_n, std::, ) -SYMBOL(generic_category, std::, ) -SYMBOL(geometric_distribution, std::, ) -SYMBOL(get_if, std::, ) -SYMBOL(get_money, std::, ) -SYMBOL(get_new_handler, std::, ) -SYMBOL(get_pointer_safety, std::, ) -SYMBOL(get_terminate, std::, ) -SYMBOL(get_time, std::, ) -SYMBOL(getc, std::, ) -SYMBOL(getchar, std::, ) -SYMBOL(getenv, std::, ) -SYMBOL(gets, std::, ) -SYMBOL(getwc, std::, ) -SYMBOL(getwchar, std::, ) -SYMBOL(giga, std::, ) -SYMBOL(gmtime, std::, ) -SYMBOL(greater, std::, ) -SYMBOL(greater_equal, std::, ) -SYMBOL(gslice, std::, ) -SYMBOL(gslice_array, std::, ) -SYMBOL(hardware_constructive_interference_size, std::, ) -SYMBOL(hardware_destructive_interference_size, std::, ) -SYMBOL(has_facet, std::, ) -SYMBOL(has_unique_object_representations, std::, ) -SYMBOL(has_unique_object_representations_v, std::, ) -SYMBOL(has_virtual_destructor, std::, ) -SYMBOL(has_virtual_destructor_v, std::, ) -SYMBOL(hash, std::, ) -SYMBOL(hecto, std::, ) -SYMBOL(hex, std::, ) -SYMBOL(hexfloat, std::, ) -SYMBOL(holds_alternative, std::, ) -SYMBOL(hypot, std::, ) -SYMBOL(identity, std::, ) -SYMBOL(ifstream, std::, ) -SYMBOL(ignore, std::, ) -SYMBOL(ilogb, std::, ) -SYMBOL(imag, std::, ) -SYMBOL(imaxabs, std::, ) -SYMBOL(imaxdiv, std::, ) -SYMBOL(imaxdiv_t, std::, ) -SYMBOL(in_place, std::, ) -SYMBOL(in_place_index, std::, ) -SYMBOL(in_place_index_t, std::, ) -SYMBOL(in_place_t, std::, ) -SYMBOL(in_place_type, std::, ) -SYMBOL(in_place_type_t, std::, ) -SYMBOL(includes, std::, ) -SYMBOL(inclusive_scan, std::, ) -SYMBOL(independent_bits_engine, std::, ) -SYMBOL(indirect_array, std::, ) -SYMBOL(initializer_list, std::, ) -SYMBOL(inner_product, std::, ) -SYMBOL(inplace_merge, std::, ) -SYMBOL(input_iterator_tag, std::, ) -SYMBOL(insert_iterator, std::, ) -SYMBOL(inserter, std::, ) -SYMBOL(int16_t, std::, ) -SYMBOL(int32_t, std::, ) -SYMBOL(int64_t, std::, ) -SYMBOL(int8_t, std::, ) -SYMBOL(int_fast16_t, std::, ) -SYMBOL(int_fast32_t, std::, ) -SYMBOL(int_fast64_t, std::, ) -SYMBOL(int_fast8_t, std::, ) -SYMBOL(int_least16_t, std::, ) -SYMBOL(int_least32_t, std::, ) -SYMBOL(int_least64_t, std::, ) -SYMBOL(int_least8_t, std::, ) -SYMBOL(integer_sequence, std::, ) -SYMBOL(integral_constant, std::, ) -SYMBOL(internal, std::, ) -SYMBOL(intmax_t, std::, ) -SYMBOL(intptr_t, std::, ) -SYMBOL(invalid_argument, std::, ) -SYMBOL(invoke, std::, ) -SYMBOL(invoke_result, std::, ) -SYMBOL(invoke_result_t, std::, ) -SYMBOL(io_errc, std::, ) -SYMBOL(ios, std::, ) -SYMBOL(ios_base, std::, ) -SYMBOL(iostream, std::, ) -SYMBOL(iostream_category, std::, ) -SYMBOL(iota, std::, ) -SYMBOL(is_abstract, std::, ) -SYMBOL(is_abstract_v, std::, ) -SYMBOL(is_aggregate, std::, ) -SYMBOL(is_aggregate_v, std::, ) -SYMBOL(is_arithmetic, std::, ) -SYMBOL(is_arithmetic_v, std::, ) -SYMBOL(is_array, std::, ) -SYMBOL(is_array_v, std::, ) -SYMBOL(is_assignable, std::, ) -SYMBOL(is_assignable_v, std::, ) -SYMBOL(is_base_of, std::, ) -SYMBOL(is_base_of_v, std::, ) -SYMBOL(is_bind_expression, std::, ) -SYMBOL(is_bind_expression_v, std::, ) -SYMBOL(is_class, std::, ) -SYMBOL(is_class_v, std::, ) -SYMBOL(is_compound, std::, ) -SYMBOL(is_compound_v, std::, ) -SYMBOL(is_const, std::, ) -SYMBOL(is_const_v, std::, ) -SYMBOL(is_constructible, std::, ) -SYMBOL(is_constructible_v, std::, ) -SYMBOL(is_convertible, std::, ) -SYMBOL(is_convertible_v, std::, ) -SYMBOL(is_copy_assignable, std::, ) -SYMBOL(is_copy_assignable_v, std::, ) -SYMBOL(is_copy_constructible, std::, ) -SYMBOL(is_copy_constructible_v, std::, ) -SYMBOL(is_default_constructible, std::, ) -SYMBOL(is_default_constructible_v, std::, ) -SYMBOL(is_destructible, std::, ) -SYMBOL(is_destructible_v, std::, ) -SYMBOL(is_empty, std::, ) -SYMBOL(is_empty_v, std::, ) -SYMBOL(is_enum, std::, ) -SYMBOL(is_enum_v, std::, ) -SYMBOL(is_eq, std::, ) -SYMBOL(is_error_code_enum, std::, ) -SYMBOL(is_error_condition_enum, std::, ) -SYMBOL(is_error_condition_enum_v, std::, ) -SYMBOL(is_execution_policy, std::, ) -SYMBOL(is_execution_policy_v, std::, ) -SYMBOL(is_final, std::, ) -SYMBOL(is_final_v, std::, ) -SYMBOL(is_floating_point, std::, ) -SYMBOL(is_floating_point_v, std::, ) -SYMBOL(is_function, std::, ) -SYMBOL(is_function_v, std::, ) -SYMBOL(is_fundamental, std::, ) -SYMBOL(is_fundamental_v, std::, ) -SYMBOL(is_gt, std::, ) -SYMBOL(is_gteq, std::, ) -SYMBOL(is_heap, std::, ) -SYMBOL(is_heap_until, std::, ) -SYMBOL(is_integral, std::, ) -SYMBOL(is_integral_v, std::, ) -SYMBOL(is_invocable, std::, ) -SYMBOL(is_invocable_r, std::, ) -SYMBOL(is_invocable_r_v, std::, ) -SYMBOL(is_invocable_v, std::, ) -SYMBOL(is_lt, std::, ) -SYMBOL(is_lteq, std::, ) -SYMBOL(is_lvalue_reference, std::, ) -SYMBOL(is_lvalue_reference_v, std::, ) -SYMBOL(is_member_function_pointer, std::, ) -SYMBOL(is_member_function_pointer_v, std::, ) -SYMBOL(is_member_object_pointer, std::, ) -SYMBOL(is_member_object_pointer_v, std::, ) -SYMBOL(is_member_pointer, std::, ) -SYMBOL(is_member_pointer_v, std::, ) -SYMBOL(is_move_assignable, std::, ) -SYMBOL(is_move_assignable_v, std::, ) -SYMBOL(is_move_constructible, std::, ) -SYMBOL(is_move_constructible_v, std::, ) -SYMBOL(is_neq, std::, ) -SYMBOL(is_nothrow_assignable, std::, ) -SYMBOL(is_nothrow_assignable_v, std::, ) -SYMBOL(is_nothrow_constructible, std::, ) -SYMBOL(is_nothrow_constructible_v, std::, ) -SYMBOL(is_nothrow_copy_assignable, std::, ) -SYMBOL(is_nothrow_copy_assignable_v, std::, ) -SYMBOL(is_nothrow_copy_constructible, std::, ) -SYMBOL(is_nothrow_copy_constructible_v, std::, ) -SYMBOL(is_nothrow_default_constructible, std::, ) -SYMBOL(is_nothrow_default_constructible_v, std::, ) -SYMBOL(is_nothrow_destructible, std::, ) -SYMBOL(is_nothrow_destructible_v, std::, ) -SYMBOL(is_nothrow_invocable, std::, ) -SYMBOL(is_nothrow_invocable_r, std::, ) -SYMBOL(is_nothrow_invocable_r_v, std::, ) -SYMBOL(is_nothrow_invocable_v, std::, ) -SYMBOL(is_nothrow_move_assignable, std::, ) -SYMBOL(is_nothrow_move_assignable_v, std::, ) -SYMBOL(is_nothrow_move_constructible, std::, ) -SYMBOL(is_nothrow_move_constructible_v, std::, ) -SYMBOL(is_nothrow_swappable, std::, ) -SYMBOL(is_nothrow_swappable_v, std::, ) -SYMBOL(is_nothrow_swappable_with, std::, ) -SYMBOL(is_nothrow_swappable_with_v, std::, ) -SYMBOL(is_null_pointer, std::, ) -SYMBOL(is_null_pointer_v, std::, ) -SYMBOL(is_object, std::, ) -SYMBOL(is_object_v, std::, ) -SYMBOL(is_partitioned, std::, ) -SYMBOL(is_permutation, std::, ) -SYMBOL(is_placeholder, std::, ) -SYMBOL(is_placeholder_v, std::, ) -SYMBOL(is_pod, std::, ) -SYMBOL(is_pod_v, std::, ) -SYMBOL(is_pointer, std::, ) -SYMBOL(is_pointer_v, std::, ) -SYMBOL(is_polymorphic, std::, ) -SYMBOL(is_polymorphic_v, std::, ) -SYMBOL(is_reference, std::, ) -SYMBOL(is_reference_v, std::, ) -SYMBOL(is_rvalue_reference, std::, ) -SYMBOL(is_rvalue_reference_v, std::, ) -SYMBOL(is_same, std::, ) -SYMBOL(is_same_v, std::, ) -SYMBOL(is_scalar, std::, ) -SYMBOL(is_scalar_v, std::, ) -SYMBOL(is_signed, std::, ) -SYMBOL(is_signed_v, std::, ) -SYMBOL(is_sorted, std::, ) -SYMBOL(is_sorted_until, std::, ) -SYMBOL(is_standard_layout, std::, ) -SYMBOL(is_standard_layout_v, std::, ) -SYMBOL(is_swappable, std::, ) -SYMBOL(is_swappable_v, std::, ) -SYMBOL(is_swappable_with, std::, ) -SYMBOL(is_swappable_with_v, std::, ) -SYMBOL(is_trivial, std::, ) -SYMBOL(is_trivial_v, std::, ) -SYMBOL(is_trivially_assignable, std::, ) -SYMBOL(is_trivially_assignable_v, std::, ) -SYMBOL(is_trivially_constructible, std::, ) -SYMBOL(is_trivially_constructible_v, std::, ) -SYMBOL(is_trivially_copy_assignable, std::, ) -SYMBOL(is_trivially_copy_assignable_v, std::, ) -SYMBOL(is_trivially_copy_constructible, std::, ) -SYMBOL(is_trivially_copy_constructible_v, std::, ) -SYMBOL(is_trivially_copyable, std::, ) -SYMBOL(is_trivially_copyable_v, std::, ) -SYMBOL(is_trivially_default_constructible, std::, ) -SYMBOL(is_trivially_default_constructible_v, std::, ) -SYMBOL(is_trivially_destructible, std::, ) -SYMBOL(is_trivially_destructible_v, std::, ) -SYMBOL(is_trivially_move_assignable, std::, ) -SYMBOL(is_trivially_move_assignable_v, std::, ) -SYMBOL(is_trivially_move_constructible, std::, ) -SYMBOL(is_trivially_move_constructible_v, std::, ) -SYMBOL(is_union, std::, ) -SYMBOL(is_union_v, std::, ) -SYMBOL(is_unsigned, std::, ) -SYMBOL(is_unsigned_v, std::, ) -SYMBOL(is_void, std::, ) -SYMBOL(is_void_v, std::, ) -SYMBOL(is_volatile, std::, ) -SYMBOL(is_volatile_v, std::, ) -SYMBOL(isalnum, std::, ) -SYMBOL(isalpha, std::, ) -SYMBOL(isblank, std::, ) -SYMBOL(iscntrl, std::, ) -SYMBOL(isdigit, std::, ) -SYMBOL(isfinite, std::, ) -SYMBOL(isgraph, std::, ) -SYMBOL(isgreater, std::, ) -SYMBOL(isgreaterequal, std::, ) -SYMBOL(isinf, std::, ) -SYMBOL(isless, std::, ) -SYMBOL(islessequal, std::, ) -SYMBOL(islessgreater, std::, ) -SYMBOL(islower, std::, ) -SYMBOL(isnan, std::, ) -SYMBOL(isnormal, std::, ) -SYMBOL(ispow2, std::, ) -SYMBOL(isprint, std::, ) -SYMBOL(ispunct, std::, ) -SYMBOL(isspace, std::, ) -SYMBOL(istream, std::, ) -SYMBOL(istream_iterator, std::, ) -SYMBOL(istreambuf_iterator, std::, ) -SYMBOL(istringstream, std::, ) -SYMBOL(isunordered, std::, ) -SYMBOL(isupper, std::, ) -SYMBOL(iswalnum, std::, ) -SYMBOL(iswalpha, std::, ) -SYMBOL(iswblank, std::, ) -SYMBOL(iswcntrl, std::, ) -SYMBOL(iswctype, std::, ) -SYMBOL(iswdigit, std::, ) -SYMBOL(iswgraph, std::, ) -SYMBOL(iswlower, std::, ) -SYMBOL(iswprint, std::, ) -SYMBOL(iswpunct, std::, ) -SYMBOL(iswspace, std::, ) -SYMBOL(iswupper, std::, ) -SYMBOL(iswxdigit, std::, ) -SYMBOL(isxdigit, std::, ) -SYMBOL(iter_swap, std::, ) -SYMBOL(iterator, std::, ) -SYMBOL(iterator_traits, std::, ) -SYMBOL(jmp_buf, std::, ) -SYMBOL(kill_dependency, std::, ) -SYMBOL(kilo, std::, ) -SYMBOL(knuth_b, std::, ) -SYMBOL(labs, std::, ) -SYMBOL(launch, std::, ) -SYMBOL(launder, std::, ) -SYMBOL(lcm, std::, ) -SYMBOL(lconv, std::, ) -SYMBOL(ldexp, std::, ) -SYMBOL(ldiv, std::, ) -SYMBOL(ldiv_t, std::, ) -SYMBOL(left, std::, ) -SYMBOL(length_error, std::, ) -SYMBOL(less, std::, ) -SYMBOL(less_equal, std::, ) -SYMBOL(lexicographical_compare, std::, ) -SYMBOL(lexicographical_compare_3way, std::, ) -SYMBOL(lgamma, std::, ) -SYMBOL(linear_congruential_engine, std::, ) -SYMBOL(list, std::, ) -SYMBOL(llabs, std::, ) -SYMBOL(lldiv, std::, ) -SYMBOL(lldiv_t, std::, ) -SYMBOL(llrint, std::, ) -SYMBOL(llround, std::, ) -SYMBOL(locale, std::, ) -SYMBOL(localeconv, std::, ) -SYMBOL(localtime, std::, ) -SYMBOL(lock, std::, ) -SYMBOL(lock_guard, std::, ) -SYMBOL(log, std::, ) -SYMBOL(log10, std::, ) -SYMBOL(log1p, std::, ) -SYMBOL(log2, std::, ) -SYMBOL(log2p1, std::, ) -SYMBOL(logb, std::, ) -SYMBOL(logic_error, std::, ) -SYMBOL(logical_and, std::, ) -SYMBOL(logical_not, std::, ) -SYMBOL(logical_or, std::, ) -SYMBOL(lognormal_distribution, std::, ) -SYMBOL(longjmp, std::, ) -SYMBOL(lower_bound, std::, ) -SYMBOL(lrint, std::, ) -SYMBOL(lround, std::, ) -SYMBOL(make_exception_ptr, std::, ) -SYMBOL(make_from_tuple, std::, ) -SYMBOL(make_heap, std::, ) -SYMBOL(make_move_iterator, std::, ) -SYMBOL(make_optional, std::, ) -SYMBOL(make_pair, std::, ) -SYMBOL(make_reverse_iterator, std::, ) -SYMBOL(make_shared, std::, ) -SYMBOL(make_signed, std::, ) -SYMBOL(make_signed_t, std::, ) -SYMBOL(make_tuple, std::, ) -SYMBOL(make_unique, std::, ) -SYMBOL(make_unsigned, std::, ) -SYMBOL(make_unsigned_t, std::, ) -SYMBOL(malloc, std::, ) -SYMBOL(map, std::, ) -SYMBOL(mask_array, std::, ) -SYMBOL(match_results, std::, ) -SYMBOL(max, std::, ) -SYMBOL(max_align_t, std::, ) -SYMBOL(max_element, std::, ) -SYMBOL(mblen, std::, ) -SYMBOL(mbrlen, std::, ) -SYMBOL(mbrtoc16, std::, ) -SYMBOL(mbrtoc32, std::, ) -SYMBOL(mbrtowc, std::, ) -SYMBOL(mbsinit, std::, ) -SYMBOL(mbsrtowcs, std::, ) -SYMBOL(mbstowcs, std::, ) -SYMBOL(mbtowc, std::, ) -SYMBOL(mega, std::, ) -SYMBOL(mem_fn, std::, ) -SYMBOL(memchr, std::, ) -SYMBOL(memcmp, std::, ) -SYMBOL(memcpy, std::, ) -SYMBOL(memmove, std::, ) -SYMBOL(memory_order, std::, ) -SYMBOL(memory_order_acq_rel, std::, ) -SYMBOL(memory_order_acquire, std::, ) -SYMBOL(memory_order_consume, std::, ) -SYMBOL(memory_order_relaxed, std::, ) -SYMBOL(memory_order_release, std::, ) -SYMBOL(memory_order_seq_cst, std::, ) -SYMBOL(memset, std::, ) -SYMBOL(merge, std::, ) -SYMBOL(mersenne_twister_engine, std::, ) -SYMBOL(messages, std::, ) -SYMBOL(messages_base, std::, ) -SYMBOL(messages_byname, std::, ) -SYMBOL(micro, std::, ) -SYMBOL(milli, std::, ) -SYMBOL(min, std::, ) -SYMBOL(min_element, std::, ) -SYMBOL(minmax, std::, ) -SYMBOL(minmax_element, std::, ) -SYMBOL(minstd_rand, std::, ) -SYMBOL(minstd_rand0, std::, ) -SYMBOL(minus, std::, ) -SYMBOL(mismatch, std::, ) -SYMBOL(mktime, std::, ) -SYMBOL(modf, std::, ) -SYMBOL(modulus, std::, ) -SYMBOL(money_base, std::, ) -SYMBOL(money_get, std::, ) -SYMBOL(money_put, std::, ) -SYMBOL(moneypunct, std::, ) -SYMBOL(moneypunct_byname, std::, ) -SYMBOL(monostate, std::, ) -SYMBOL(move_backward, std::, ) -SYMBOL(move_if_noexcept, std::, ) -SYMBOL(move_iterator, std::, ) -SYMBOL(mt19937, std::, ) -SYMBOL(mt19937_64, std::, ) -SYMBOL(multimap, std::, ) -SYMBOL(multiplies, std::, ) -SYMBOL(multiset, std::, ) -SYMBOL(mutex, std::, ) -SYMBOL(nan, std::, ) -SYMBOL(nanf, std::, ) -SYMBOL(nanl, std::, ) -SYMBOL(nano, std::, ) -SYMBOL(nearbyint, std::, ) -SYMBOL(negate, std::, ) -SYMBOL(negation, std::, ) -SYMBOL(negation_v, std::, ) -SYMBOL(negative_binomial_distribution, std::, ) -SYMBOL(nested_exception, std::, ) -SYMBOL(new_handler, std::, ) -SYMBOL(next, std::, ) -SYMBOL(next_permutation, std::, ) -SYMBOL(nextafter, std::, ) -SYMBOL(nexttoward, std::, ) -SYMBOL(no_emit_on_flush, std::, ) -SYMBOL(noboolalpha, std::, ) -SYMBOL(none_of, std::, ) -SYMBOL(norm, std::, ) -SYMBOL(normal_distribution, std::, ) -SYMBOL(noshowbase, std::, ) -SYMBOL(noshowpoint, std::, ) -SYMBOL(noshowpos, std::, ) -SYMBOL(noskipws, std::, ) -SYMBOL(not_equal_to, std::, ) -SYMBOL(not_fn, std::, ) -SYMBOL(nothrow, std::, ) -SYMBOL(nothrow_t, std::, ) -SYMBOL(notify_all_at_thread_exit, std::, ) -SYMBOL(nounitbuf, std::, ) -SYMBOL(nouppercase, std::, ) -SYMBOL(nth_element, std::, ) -SYMBOL(nullopt, std::, ) -SYMBOL(nullopt_t, std::, ) -SYMBOL(nullptr_t, std::, ) -SYMBOL(num_get, std::, ) -SYMBOL(num_put, std::, ) -SYMBOL(numeric_limits, std::, ) -SYMBOL(numpunct, std::, ) -SYMBOL(numpunct_byname, std::, ) -SYMBOL(oct, std::, ) -SYMBOL(ofstream, std::, ) -SYMBOL(once_flag, std::, ) -SYMBOL(optional, std::, ) -SYMBOL(ostream, std::, ) -SYMBOL(ostream_iterator, std::, ) -SYMBOL(ostreambuf_iterator, std::, ) -SYMBOL(ostringstream, std::, ) -SYMBOL(osyncstream, std::, ) -SYMBOL(out_of_range, std::, ) -SYMBOL(output_iterator_tag, std::, ) -SYMBOL(overflow_error, std::, ) -SYMBOL(owner_less, std::, ) -SYMBOL(packaged_task, std::, ) -SYMBOL(pair, std::, ) -SYMBOL(partial_order, std::, ) -SYMBOL(partial_ordering, std::, ) -SYMBOL(partial_sort, std::, ) -SYMBOL(partial_sort_copy, std::, ) -SYMBOL(partial_sum, std::, ) -SYMBOL(partition, std::, ) -SYMBOL(partition_copy, std::, ) -SYMBOL(partition_point, std::, ) -SYMBOL(perror, std::, ) -SYMBOL(peta, std::, ) -SYMBOL(pico, std::, ) -SYMBOL(piecewise_constant_distribution, std::, ) -SYMBOL(piecewise_construct_t, std::, ) -SYMBOL(piecewise_linear_distribution, std::, ) -SYMBOL(plus, std::, ) -SYMBOL(pointer_safety, std::, ) -SYMBOL(pointer_traits, std::, ) -SYMBOL(poisson_distribution, std::, ) -SYMBOL(polar, std::, ) -SYMBOL(polymorphic_allocator, std::, ) -SYMBOL(pop_heap, std::, ) -SYMBOL(pow, std::, ) -SYMBOL(prev, std::, ) -SYMBOL(prev_permutation, std::, ) -SYMBOL(printf, std::, ) -SYMBOL(priority_queue, std::, ) -SYMBOL(proj, std::, ) -SYMBOL(promise, std::, ) -SYMBOL(ptrdiff_t, std::, ) -SYMBOL(push_heap, std::, ) -SYMBOL(put_money, std::, ) -SYMBOL(put_time, std::, ) -SYMBOL(putc, std::, ) -SYMBOL(putchar, std::, ) -SYMBOL(puts, std::, ) -SYMBOL(putwc, std::, ) -SYMBOL(putwchar, std::, ) -SYMBOL(qsort, std::, ) -SYMBOL(queue, std::, ) -SYMBOL(quick_exit, std::, ) -SYMBOL(quoted, std::, ) -SYMBOL(raise, std::, ) -SYMBOL(rand, std::, ) -SYMBOL(random_access_iterator_tag, std::, ) -SYMBOL(random_device, std::, ) -SYMBOL(random_shuffle, std::, ) -SYMBOL(range_error, std::, ) -SYMBOL(rank, std::, ) -SYMBOL(rank_v, std::, ) -SYMBOL(ranlux24, std::, ) -SYMBOL(ranlux24_base, std::, ) -SYMBOL(ranlux48, std::, ) -SYMBOL(ranlux48_base, std::, ) -SYMBOL(ratio, std::, ) -SYMBOL(ratio_add, std::, ) -SYMBOL(ratio_divide, std::, ) -SYMBOL(ratio_equal, std::, ) -SYMBOL(ratio_equal_v, std::, ) -SYMBOL(ratio_greater, std::, ) -SYMBOL(ratio_greater_equal, std::, ) -SYMBOL(ratio_greater_equal_v, std::, ) -SYMBOL(ratio_greater_v, std::, ) -SYMBOL(ratio_less, std::, ) -SYMBOL(ratio_less_equal, std::, ) -SYMBOL(ratio_less_equal_v, std::, ) -SYMBOL(ratio_less_v, std::, ) -SYMBOL(ratio_multiply, std::, ) -SYMBOL(ratio_not_equal, std::, ) -SYMBOL(ratio_not_equal_v, std::, ) -SYMBOL(ratio_subtract, std::, ) -SYMBOL(rbegin, std::, ) -SYMBOL(real, std::, ) -SYMBOL(realloc, std::, ) -SYMBOL(recursive_mutex, std::, ) -SYMBOL(recursive_timed_mutex, std::, ) -SYMBOL(reduce, std::, ) -SYMBOL(ref, std::, ) -SYMBOL(reference_wrapper, std::, ) -SYMBOL(regex, std::, ) -SYMBOL(regex_error, std::, ) -SYMBOL(regex_iterator, std::, ) -SYMBOL(regex_match, std::, ) -SYMBOL(regex_replace, std::, ) -SYMBOL(regex_search, std::, ) -SYMBOL(regex_token_iterator, std::, ) -SYMBOL(regex_traits, std::, ) -SYMBOL(reinterpret_pointer_cast, std::, ) -SYMBOL(remainder, std::, ) -SYMBOL(remove_all_extents, std::, ) -SYMBOL(remove_all_extents_t, std::, ) -SYMBOL(remove_const, std::, ) -SYMBOL(remove_const_t, std::, ) -SYMBOL(remove_copy, std::, ) -SYMBOL(remove_copy_if, std::, ) -SYMBOL(remove_cv, std::, ) -SYMBOL(remove_cv_t, std::, ) -SYMBOL(remove_cvref, std::, ) -SYMBOL(remove_cvref_t, std::, ) -SYMBOL(remove_extent, std::, ) -SYMBOL(remove_extent_t, std::, ) -SYMBOL(remove_pointer, std::, ) -SYMBOL(remove_pointer_t, std::, ) -SYMBOL(remove_reference, std::, ) -SYMBOL(remove_reference_t, std::, ) -SYMBOL(remove_volatile, std::, ) -SYMBOL(remove_volatile_t, std::, ) -SYMBOL(remquo, std::, ) -SYMBOL(rename, std::, ) -SYMBOL(rend, std::, ) -SYMBOL(replace, std::, ) -SYMBOL(replace_copy, std::, ) -SYMBOL(replace_copy_if, std::, ) -SYMBOL(replace_if, std::, ) -SYMBOL(resetiosflags, std::, ) -SYMBOL(result_of, std::, ) -SYMBOL(result_of_t, std::, ) -SYMBOL(rethrow_exception, std::, ) -SYMBOL(rethrow_if_nested, std::, ) -SYMBOL(reverse, std::, ) -SYMBOL(reverse_copy, std::, ) -SYMBOL(reverse_iterator, std::, ) -SYMBOL(rewind, std::, ) -SYMBOL(right, std::, ) -SYMBOL(rint, std::, ) -SYMBOL(rotate, std::, ) -SYMBOL(rotate_copy, std::, ) -SYMBOL(round, std::, ) -SYMBOL(round_indeterminate, std::, ) -SYMBOL(round_to_nearest, std::, ) -SYMBOL(round_toward_infinity, std::, ) -SYMBOL(round_toward_neg_infinity, std::, ) -SYMBOL(round_toward_zero, std::, ) -SYMBOL(runtime_error, std::, ) -SYMBOL(sample, std::, ) -SYMBOL(scalbln, std::, ) -SYMBOL(scalbn, std::, ) -SYMBOL(scanf, std::, ) -SYMBOL(scientific, std::, ) -SYMBOL(scoped_allocator_adaptor, std::, ) -SYMBOL(search, std::, ) -SYMBOL(search_n, std::, ) -SYMBOL(seed_seq, std::, ) -SYMBOL(set, std::, ) -SYMBOL(set_difference, std::, ) -SYMBOL(set_intersection, std::, ) -SYMBOL(set_new_handler, std::, ) -SYMBOL(set_symmetric_difference, std::, ) -SYMBOL(set_terminate, std::, ) -SYMBOL(set_union, std::, ) -SYMBOL(setbase, std::, ) -SYMBOL(setbuf, std::, ) -SYMBOL(setfill, std::, ) -SYMBOL(setiosflags, std::, ) -SYMBOL(setlocale, std::, ) -SYMBOL(setprecision, std::, ) -SYMBOL(setvbuf, std::, ) -SYMBOL(setw, std::, ) -SYMBOL(shared_future, std::, ) -SYMBOL(shared_lock, std::, ) -SYMBOL(shared_mutex, std::, ) -SYMBOL(shared_ptr, std::, ) -SYMBOL(shared_timed_mutex, std::, ) -SYMBOL(shift_left, std::, ) -SYMBOL(shift_right, std::, ) -SYMBOL(showbase, std::, ) -SYMBOL(showpoint, std::, ) -SYMBOL(showpos, std::, ) -SYMBOL(shuffle, std::, ) -SYMBOL(shuffle_order_engine, std::, ) -SYMBOL(sig_atomic_t, std::, ) -SYMBOL(signal, std::, ) -SYMBOL(signbit, std::, ) -SYMBOL(sin, std::, ) -SYMBOL(sinh, std::, ) -SYMBOL(size, std::, ) -SYMBOL(skipws, std::, ) -SYMBOL(slice, std::, ) -SYMBOL(slice_array, std::, ) -SYMBOL(smatch, std::, ) -SYMBOL(snprintf, std::, ) -SYMBOL(sort, std::, ) -SYMBOL(sort_heap, std::, ) -SYMBOL(span, std::, ) -SYMBOL(sprintf, std::, ) -SYMBOL(sqrt, std::, ) -SYMBOL(srand, std::, ) -SYMBOL(sregex_iterator, std::, ) -SYMBOL(sregex_token_iterator, std::, ) -SYMBOL(sscanf, std::, ) -SYMBOL(ssub_match, std::, ) -SYMBOL(stable_partition, std::, ) -SYMBOL(stable_sort, std::, ) -SYMBOL(stack, std::, ) -SYMBOL(static_pointer_cast, std::, ) -SYMBOL(strcat, std::, ) -SYMBOL(strchr, std::, ) -SYMBOL(strcmp, std::, ) -SYMBOL(strcoll, std::, ) -SYMBOL(strcpy, std::, ) -SYMBOL(strcspn, std::, ) -SYMBOL(streambuf, std::, ) -SYMBOL(streamoff, std::, ) -SYMBOL(streampos, std::, ) -SYMBOL(streamsize, std::, ) -SYMBOL(strerror, std::, ) -SYMBOL(strftime, std::, ) -SYMBOL(string, std::, ) -SYMBOL(string_view, std::, ) -SYMBOL(stringbuf, std::, ) -SYMBOL(stringstream, std::, ) -SYMBOL(strlen, std::, ) -SYMBOL(strncat, std::, ) -SYMBOL(strncmp, std::, ) -SYMBOL(strncpy, std::, ) -SYMBOL(strong_equal, std::, ) -SYMBOL(strong_equality, std::, ) -SYMBOL(strong_order, std::, ) -SYMBOL(strong_ordering, std::, ) -SYMBOL(strpbrk, std::, ) -SYMBOL(strrchr, std::, ) -SYMBOL(strspn, std::, ) -SYMBOL(strstr, std::, ) -SYMBOL(strtod, std::, ) -SYMBOL(strtof, std::, ) -SYMBOL(strtoimax, std::, ) -SYMBOL(strtok, std::, ) -SYMBOL(strtol, std::, ) -SYMBOL(strtold, std::, ) -SYMBOL(strtoll, std::, ) -SYMBOL(strtoul, std::, ) -SYMBOL(strtoull, std::, ) -SYMBOL(strtoumax, std::, ) -SYMBOL(strxfrm, std::, ) -SYMBOL(student_t_distribution, std::, ) -SYMBOL(sub_match, std::, ) -SYMBOL(subtract_with_carry_engine, std::, ) -SYMBOL(swap_ranges, std::, ) -SYMBOL(swprintf, std::, ) -SYMBOL(swscanf, std::, ) -SYMBOL(syncbuf, std::, ) -SYMBOL(system, std::, ) -SYMBOL(system_category, std::, ) -SYMBOL(system_error, std::, ) -SYMBOL(tan, std::, ) -SYMBOL(tanh, std::, ) -SYMBOL(tera, std::, ) -SYMBOL(terminate, std::, ) -SYMBOL(terminate_handler, std::, ) -SYMBOL(tgamma, std::, ) -SYMBOL(thread, std::, ) -SYMBOL(throw_with_nested, std::, ) -SYMBOL(tie, std::, ) -SYMBOL(time, std::, ) -SYMBOL(time_base, std::, ) -SYMBOL(time_get, std::, ) -SYMBOL(time_get_byname, std::, ) -SYMBOL(time_put, std::, ) -SYMBOL(time_put_byname, std::, ) -SYMBOL(time_t, std::, ) -SYMBOL(timed_mutex, std::, ) -SYMBOL(timespec, std::, ) -SYMBOL(timespec_get, std::, ) -SYMBOL(tm, std::, ) -SYMBOL(tmpfile, std::, ) -SYMBOL(tmpnam, std::, ) -SYMBOL(to_address, std::, ) -SYMBOL(to_chars, std::, ) -SYMBOL(to_integer, std::, ) -SYMBOL(to_string, std::, ) -SYMBOL(tolower, std::, ) -SYMBOL(toupper, std::, ) -SYMBOL(towctrans, std::, ) -SYMBOL(towlower, std::, ) -SYMBOL(towupper, std::, ) -SYMBOL(transform, std::, ) -SYMBOL(transform_exclusive_scan, std::, ) -SYMBOL(transform_inclusive_scan, std::, ) -SYMBOL(transform_reduce, std::, ) -SYMBOL(true_type, std::, ) -SYMBOL(trunc, std::, ) -SYMBOL(try_lock, std::, ) -SYMBOL(try_to_lock, std::, ) -SYMBOL(try_to_lock_t, std::, ) -SYMBOL(tuple, std::, ) -SYMBOL(tuple_cat, std::, ) -SYMBOL(type_identity, std::, ) -SYMBOL(type_identity_t, std::, ) -SYMBOL(type_index, std::, ) -SYMBOL(type_info, std::, ) -SYMBOL(u16streampos, std::, ) -SYMBOL(u16string, std::, ) -SYMBOL(u16string_view, std::, ) -SYMBOL(u32streampos, std::, ) -SYMBOL(u32string, std::, ) -SYMBOL(u32string_view, std::, ) -SYMBOL(uint16_t, std::, ) -SYMBOL(uint32_t, std::, ) -SYMBOL(uint64_t, std::, ) -SYMBOL(uint8_t, std::, ) -SYMBOL(uint_fast16_t, std::, ) -SYMBOL(uint_fast32_t, std::, ) -SYMBOL(uint_fast64_t, std::, ) -SYMBOL(uint_fast8_t, std::, ) -SYMBOL(uint_least16_t, std::, ) -SYMBOL(uint_least32_t, std::, ) -SYMBOL(uint_least64_t, std::, ) -SYMBOL(uint_least8_t, std::, ) -SYMBOL(uintmax_t, std::, ) -SYMBOL(uintptr_t, std::, ) -SYMBOL(uncaught_exceptions, std::, ) -SYMBOL(undeclare_no_pointers, std::, ) -SYMBOL(undeclare_reachable, std::, ) -SYMBOL(underflow_error, std::, ) -SYMBOL(underlying_type, std::, ) -SYMBOL(underlying_type_t, std::, ) -SYMBOL(ungetc, std::, ) -SYMBOL(ungetwc, std::, ) -SYMBOL(uniform_int_distribution, std::, ) -SYMBOL(uniform_real_distribution, std::, ) -SYMBOL(uninitialized_copy, std::, ) -SYMBOL(uninitialized_copy_n, std::, ) -SYMBOL(uninitialized_default_construct, std::, ) -SYMBOL(uninitialized_default_construct_n, std::, ) -SYMBOL(uninitialized_fill, std::, ) -SYMBOL(uninitialized_fill_n, std::, ) -SYMBOL(uninitialized_move, std::, ) -SYMBOL(uninitialized_move_n, std::, ) -SYMBOL(uninitialized_value_construct, std::, ) -SYMBOL(uninitialized_value_construct_n, std::, ) -SYMBOL(unique, std::, ) -SYMBOL(unique_copy, std::, ) -SYMBOL(unique_lock, std::, ) -SYMBOL(unique_ptr, std::, ) -SYMBOL(unitbuf, std::, ) -SYMBOL(unordered_map, std::, ) -SYMBOL(unordered_multimap, std::, ) -SYMBOL(unordered_multiset, std::, ) -SYMBOL(unordered_set, std::, ) -SYMBOL(upper_bound, std::, ) -SYMBOL(uppercase, std::, ) -SYMBOL(use_facet, std::, ) -SYMBOL(uses_allocator, std::, ) -SYMBOL(uses_allocator_v, std::, ) -SYMBOL(va_list, std::, ) -SYMBOL(valarray, std::, ) -SYMBOL(variant, std::, ) -SYMBOL(variant_alternative, std::, ) -SYMBOL(variant_alternative_t, std::, ) -SYMBOL(variant_npos, std::, ) -SYMBOL(variant_size, std::, ) -SYMBOL(variant_size_v, std::, ) -SYMBOL(vector, std::, ) -SYMBOL(vfprintf, std::, ) -SYMBOL(vfscanf, std::, ) -SYMBOL(vfwprintf, std::, ) -SYMBOL(vfwscanf, std::, ) -SYMBOL(visit, std::, ) -SYMBOL(void_t, std::, ) -SYMBOL(vprintf, std::, ) -SYMBOL(vscanf, std::, ) -SYMBOL(vsnprintf, std::, ) -SYMBOL(vsprintf, std::, ) -SYMBOL(vsscanf, std::, ) -SYMBOL(vswprintf, std::, ) -SYMBOL(vswscanf, std::, ) -SYMBOL(vwprintf, std::, ) -SYMBOL(vwscanf, std::, ) -SYMBOL(wbuffer_convert, std::, ) -SYMBOL(wcerr, std::, ) -SYMBOL(wcin, std::, ) -SYMBOL(wclog, std::, ) -SYMBOL(wcmatch, std::, ) -SYMBOL(wcout, std::, ) -SYMBOL(wcregex_iterator, std::, ) -SYMBOL(wcregex_token_iterator, std::, ) -SYMBOL(wcrtomb, std::, ) -SYMBOL(wcscat, std::, ) -SYMBOL(wcschr, std::, ) -SYMBOL(wcscmp, std::, ) -SYMBOL(wcscoll, std::, ) -SYMBOL(wcscpy, std::, ) -SYMBOL(wcscspn, std::, ) -SYMBOL(wcsftime, std::, ) -SYMBOL(wcslen, std::, ) -SYMBOL(wcsncat, std::, ) -SYMBOL(wcsncmp, std::, ) -SYMBOL(wcsncpy, std::, ) -SYMBOL(wcspbrk, std::, ) -SYMBOL(wcsrchr, std::, ) -SYMBOL(wcsrtombs, std::, ) -SYMBOL(wcsspn, std::, ) -SYMBOL(wcsstr, std::, ) -SYMBOL(wcstod, std::, ) -SYMBOL(wcstof, std::, ) -SYMBOL(wcstoimax, std::, ) -SYMBOL(wcstok, std::, ) -SYMBOL(wcstol, std::, ) -SYMBOL(wcstold, std::, ) -SYMBOL(wcstoll, std::, ) -SYMBOL(wcstombs, std::, ) -SYMBOL(wcstoul, std::, ) -SYMBOL(wcstoull, std::, ) -SYMBOL(wcstoumax, std::, ) -SYMBOL(wcsub_match, std::, ) -SYMBOL(wcsxfrm, std::, ) -SYMBOL(wctob, std::, ) -SYMBOL(wctomb, std::, ) -SYMBOL(wctrans, std::, ) -SYMBOL(wctrans_t, std::, ) -SYMBOL(wctype, std::, ) -SYMBOL(wctype_t, std::, ) -SYMBOL(weak_equal, std::, ) -SYMBOL(weak_equality, std::, ) -SYMBOL(weak_order, std::, ) -SYMBOL(weak_ordering, std::, ) -SYMBOL(weak_ptr, std::, ) -SYMBOL(weibull_distribution, std::, ) -SYMBOL(wfilebuf, std::, ) -SYMBOL(wfstream, std::, ) -SYMBOL(wifstream, std::, ) -SYMBOL(wios, std::, ) -SYMBOL(wiostream, std::, ) -SYMBOL(wistream, std::, ) -SYMBOL(wistringstream, std::, ) -SYMBOL(wmemchr, std::, ) -SYMBOL(wmemcmp, std::, ) -SYMBOL(wmemcpy, std::, ) -SYMBOL(wmemmove, std::, ) -SYMBOL(wmemset, std::, ) -SYMBOL(wofstream, std::, ) -SYMBOL(wostream, std::, ) -SYMBOL(wostringstream, std::, ) -SYMBOL(wosyncstream, std::, ) -SYMBOL(wprintf, std::, ) -SYMBOL(wregex, std::, ) -SYMBOL(ws, std::, ) -SYMBOL(wscanf, std::, ) -SYMBOL(wsmatch, std::, ) -SYMBOL(wsregex_iterator, std::, ) -SYMBOL(wsregex_token_iterator, std::, ) -SYMBOL(wssub_match, std::, ) -SYMBOL(wstreambuf, std::, ) -SYMBOL(wstreampos, std::, ) -SYMBOL(wstring, std::, ) -SYMBOL(wstring_convert, std::, ) -SYMBOL(wstring_view, std::, ) -SYMBOL(wstringbuf, std::, ) -SYMBOL(wstringstream, std::, ) -SYMBOL(wsyncbuf, std::, ) -SYMBOL(yocto, std::, ) -SYMBOL(yotta, std::, ) -SYMBOL(zepto, std::, ) -SYMBOL(zetta, std::, ) -SYMBOL(April, std::chrono::, ) -SYMBOL(August, std::chrono::, ) -SYMBOL(December, std::chrono::, ) -SYMBOL(February, std::chrono::, ) -SYMBOL(Friday, std::chrono::, ) -SYMBOL(January, std::chrono::, ) -SYMBOL(July, std::chrono::, ) -SYMBOL(June, std::chrono::, ) -SYMBOL(March, std::chrono::, ) -SYMBOL(May, std::chrono::, ) -SYMBOL(Monday, std::chrono::, ) -SYMBOL(November, std::chrono::, ) -SYMBOL(October, std::chrono::, ) -SYMBOL(Saturday, std::chrono::, ) -SYMBOL(September, std::chrono::, ) -SYMBOL(Sunday, std::chrono::, ) -SYMBOL(Thursday, std::chrono::, ) -SYMBOL(Tuesday, std::chrono::, ) -SYMBOL(Wednesday, std::chrono::, ) -SYMBOL(abs, std::chrono::, ) -SYMBOL(ambiguous_local_time, std::chrono::, ) -SYMBOL(ceil, std::chrono::, ) -SYMBOL(choose, std::chrono::, ) -SYMBOL(clock_cast, std::chrono::, ) -SYMBOL(clock_time_conversion, std::chrono::, ) -SYMBOL(current_zone, std::chrono::, ) -SYMBOL(day, std::chrono::, ) -SYMBOL(duration, std::chrono::, ) -SYMBOL(duration_values, std::chrono::, ) -SYMBOL(file_clock, std::chrono::, ) -SYMBOL(file_seconds, std::chrono::, ) -SYMBOL(file_time, std::chrono::, ) -SYMBOL(floor, std::chrono::, ) -SYMBOL(gps_clock, std::chrono::, ) -SYMBOL(gps_seconds, std::chrono::, ) -SYMBOL(gps_time, std::chrono::, ) -SYMBOL(high_resolution_clock, std::chrono::, ) -SYMBOL(hours, std::chrono::, ) -SYMBOL(is_clock, std::chrono::, ) -SYMBOL(is_clock_v, std::chrono::, ) -SYMBOL(last, std::chrono::, ) -SYMBOL(last_spec, std::chrono::, ) -SYMBOL(leap, std::chrono::, ) -SYMBOL(link, std::chrono::, ) -SYMBOL(local_info, std::chrono::, ) -SYMBOL(local_seconds, std::chrono::, ) -SYMBOL(local_t, std::chrono::, ) -SYMBOL(local_time, std::chrono::, ) -SYMBOL(locate_zone, std::chrono::, ) -SYMBOL(microseconds, std::chrono::, ) -SYMBOL(milliseconds, std::chrono::, ) -SYMBOL(minutes, std::chrono::, ) -SYMBOL(month, std::chrono::, ) -SYMBOL(month_day, std::chrono::, ) -SYMBOL(month_day_last, std::chrono::, ) -SYMBOL(month_weekday, std::chrono::, ) -SYMBOL(month_weekday_last, std::chrono::, ) -SYMBOL(nanoseconds, std::chrono::, ) -SYMBOL(nonexistent_local_time, std::chrono::, ) -SYMBOL(round, std::chrono::, ) -SYMBOL(seconds, std::chrono::, ) -SYMBOL(steady_clock, std::chrono::, ) -SYMBOL(sys_days, std::chrono::, ) -SYMBOL(sys_info, std::chrono::, ) -SYMBOL(sys_seconds, std::chrono::, ) -SYMBOL(sys_time, std::chrono::, ) -SYMBOL(system_clock, std::chrono::, ) -SYMBOL(tai_clock, std::chrono::, ) -SYMBOL(tai_seconds, std::chrono::, ) -SYMBOL(tai_time, std::chrono::, ) -SYMBOL(time_of_day, std::chrono::, ) -SYMBOL(time_point, std::chrono::, ) -SYMBOL(time_zone, std::chrono::, ) -SYMBOL(treat_as_floating_point, std::chrono::, ) -SYMBOL(treat_as_floating_point_v, std::chrono::, ) -SYMBOL(tzdb, std::chrono::, ) -SYMBOL(tzdb_list, std::chrono::, ) -SYMBOL(utc_clock, std::chrono::, ) -SYMBOL(utc_seconds, std::chrono::, ) -SYMBOL(utc_time, std::chrono::, ) -SYMBOL(weekday, std::chrono::, ) -SYMBOL(weekday_indexed, std::chrono::, ) -SYMBOL(weekday_last, std::chrono::, ) -SYMBOL(year, std::chrono::, ) -SYMBOL(year_month, std::chrono::, ) -SYMBOL(year_month_day, std::chrono::, ) -SYMBOL(year_month_day_last, std::chrono::, ) -SYMBOL(year_month_weekday, std::chrono::, ) -SYMBOL(year_month_weekday_last, std::chrono::, ) -SYMBOL(zoned_time, std::chrono::, ) -SYMBOL(zoned_traits, std::chrono::, ) -SYMBOL(absolute, std::filesystem::, ) -SYMBOL(canonical, std::filesystem::, ) -SYMBOL(copy, std::filesystem::, ) -SYMBOL(copy_file, std::filesystem::, ) -SYMBOL(copy_options, std::filesystem::, ) -SYMBOL(copy_symlink, std::filesystem::, ) -SYMBOL(create_directories, std::filesystem::, ) -SYMBOL(create_directory, std::filesystem::, ) -SYMBOL(create_directory_symlink, std::filesystem::, ) -SYMBOL(create_hard_link, std::filesystem::, ) -SYMBOL(create_symlink, std::filesystem::, ) -SYMBOL(current_path, std::filesystem::, ) -SYMBOL(directory_entry, std::filesystem::, ) -SYMBOL(directory_iterator, std::filesystem::, ) -SYMBOL(directory_options, std::filesystem::, ) -SYMBOL(equivalent, std::filesystem::, ) -SYMBOL(exists, std::filesystem::, ) -SYMBOL(file_size, std::filesystem::, ) -SYMBOL(file_status, std::filesystem::, ) -SYMBOL(file_time_type, std::filesystem::, ) -SYMBOL(file_type, std::filesystem::, ) -SYMBOL(filesystem_error, std::filesystem::, ) -SYMBOL(hard_link_count, std::filesystem::, ) -SYMBOL(is_block_file, std::filesystem::, ) -SYMBOL(is_character_file, std::filesystem::, ) -SYMBOL(is_directory, std::filesystem::, ) -SYMBOL(is_empty, std::filesystem::, ) -SYMBOL(is_fifo, std::filesystem::, ) -SYMBOL(is_other, std::filesystem::, ) -SYMBOL(is_regular_file, std::filesystem::, ) -SYMBOL(is_socket, std::filesystem::, ) -SYMBOL(is_symlink, std::filesystem::, ) -SYMBOL(last_write_time, std::filesystem::, ) -SYMBOL(path, std::filesystem::, ) -SYMBOL(perm_options, std::filesystem::, ) -SYMBOL(permissions, std::filesystem::, ) -SYMBOL(perms, std::filesystem::, ) -SYMBOL(proximate, std::filesystem::, ) -SYMBOL(read_symlink, std::filesystem::, ) -SYMBOL(recursive_directory_iterator, std::filesystem::, ) -SYMBOL(relative, std::filesystem::, ) -SYMBOL(remove, std::filesystem::, ) -SYMBOL(remove_all, std::filesystem::, ) -SYMBOL(rename, std::filesystem::, ) -SYMBOL(resize_file, std::filesystem::, ) -SYMBOL(space, std::filesystem::, ) -SYMBOL(space_info, std::filesystem::, ) -SYMBOL(status, std::filesystem::, ) -SYMBOL(status_known, std::filesystem::, ) -SYMBOL(symlink_status, std::filesystem::, ) -SYMBOL(temp_directory_path, std::filesystem::, ) -SYMBOL(u8path, std::filesystem::, ) -SYMBOL(weakly_canonical, std::filesystem::, ) -SYMBOL(basic_string, std::pmr::, ) -SYMBOL(deque, std::pmr::, ) -SYMBOL(forward_list, std::pmr::, ) -SYMBOL(get_default_resource, std::pmr::, ) -SYMBOL(list, std::pmr::, ) -SYMBOL(map, std::pmr::, ) -SYMBOL(memory_resource, std::pmr::, ) -SYMBOL(monotonic_buffer_resource, std::pmr::, ) -SYMBOL(multimap, std::pmr::, ) -SYMBOL(multiset, std::pmr::, ) -SYMBOL(new_delete_resource, std::pmr::, ) -SYMBOL(null_memory_resource, std::pmr::, ) -SYMBOL(polymorphic_allocator, std::pmr::, ) -SYMBOL(pool_options, std::pmr::, ) -SYMBOL(set, std::pmr::, ) -SYMBOL(set_default_resource, std::pmr::, ) -SYMBOL(string, std::pmr::, ) -SYMBOL(synchronized_pool_resource, std::pmr::, ) -SYMBOL(u16string, std::pmr::, ) -SYMBOL(u32string, std::pmr::, ) -SYMBOL(unordered_map, std::pmr::, ) -SYMBOL(unordered_multimap, std::pmr::, ) -SYMBOL(unordered_multiset, std::pmr::, ) -SYMBOL(unordered_set, std::pmr::, ) -SYMBOL(unsynchronized_pool_resource, std::pmr::, ) -SYMBOL(vector, std::pmr::, ) -SYMBOL(wstring, std::pmr::, ) -SYMBOL(ECMAScript, std::regex_constants::, ) -SYMBOL(awk, std::regex_constants::, ) -SYMBOL(basic, std::regex_constants::, ) -SYMBOL(collate, std::regex_constants::, ) -SYMBOL(egrep, std::regex_constants::, ) -SYMBOL(error_backref, std::regex_constants::, ) -SYMBOL(error_badbrace, std::regex_constants::, ) -SYMBOL(error_badrepeat, std::regex_constants::, ) -SYMBOL(error_brace, std::regex_constants::, ) -SYMBOL(error_brack, std::regex_constants::, ) -SYMBOL(error_collate, std::regex_constants::, ) -SYMBOL(error_complexity, std::regex_constants::, ) -SYMBOL(error_ctype, std::regex_constants::, ) -SYMBOL(error_escape, std::regex_constants::, ) -SYMBOL(error_paren, std::regex_constants::, ) -SYMBOL(error_range, std::regex_constants::, ) -SYMBOL(error_space, std::regex_constants::, ) -SYMBOL(error_stack, std::regex_constants::, ) -SYMBOL(error_type, std::regex_constants::, ) -SYMBOL(extended, std::regex_constants::, ) -SYMBOL(format_default, std::regex_constants::, ) -SYMBOL(format_first_only, std::regex_constants::, ) -SYMBOL(format_no_copy, std::regex_constants::, ) -SYMBOL(format_sed, std::regex_constants::, ) -SYMBOL(grep, std::regex_constants::, ) -SYMBOL(icase, std::regex_constants::, ) -SYMBOL(match_any, std::regex_constants::, ) -SYMBOL(match_continuous, std::regex_constants::, ) -SYMBOL(match_default, std::regex_constants::, ) -SYMBOL(match_flag_type, std::regex_constants::, ) -SYMBOL(match_not_bol, std::regex_constants::, ) -SYMBOL(match_not_bow, std::regex_constants::, ) -SYMBOL(match_not_eol, std::regex_constants::, ) -SYMBOL(match_not_eow, std::regex_constants::, ) -SYMBOL(match_not_null, std::regex_constants::, ) -SYMBOL(match_prev_avail, std::regex_constants::, ) -SYMBOL(multiline, std::regex_constants::, ) -SYMBOL(nosubs, std::regex_constants::, ) -SYMBOL(optimize, std::regex_constants::, ) -SYMBOL(syntax_option_type, std::regex_constants::, ) -SYMBOL(get_id, std::this_thread::, ) -SYMBOL(sleep_for, std::this_thread::, ) -SYMBOL(sleep_until, std::this_thread::, ) -SYMBOL(yield, std::this_thread::, ) diff --git a/contrib/llvm-project/clang/include/clang/Tooling/Refactoring/RecursiveSymbolVisitor.h b/contrib/llvm-project/clang/include/clang/Tooling/Refactoring/RecursiveSymbolVisitor.h index 6fb2decf861..015dbba26f6 100644 --- a/contrib/llvm-project/clang/include/clang/Tooling/Refactoring/RecursiveSymbolVisitor.h +++ b/contrib/llvm-project/clang/include/clang/Tooling/Refactoring/RecursiveSymbolVisitor.h @@ -124,10 +124,11 @@ public: bool VisitDesignatedInitExpr(const DesignatedInitExpr *E) { for (const DesignatedInitExpr::Designator &D : E->designators()) { - if (D.isFieldDesignator() && D.getField()) { - const FieldDecl *Decl = D.getField(); - if (!visit(Decl, D.getFieldLoc(), D.getFieldLoc())) - return false; + if (D.isFieldDesignator()) { + if (const FieldDecl *Decl = D.getFieldDecl()) { + if (!visit(Decl, D.getFieldLoc(), D.getFieldLoc())) + return false; + } } } return true; diff --git a/contrib/llvm-project/clang/include/clang/Tooling/Tooling.h b/contrib/llvm-project/clang/include/clang/Tooling/Tooling.h index 52a81cd9e77..13c1b51bf85 100644 --- a/contrib/llvm-project/clang/include/clang/Tooling/Tooling.h +++ b/contrib/llvm-project/clang/include/clang/Tooling/Tooling.h @@ -361,11 +361,6 @@ public: /// append them to ASTs. int buildASTs(std::vector> &ASTs); - /// Sets whether working directory should be restored after calling run(). By - /// default, working directory is restored. However, it could be useful to - /// turn this off when running on multiple threads to avoid the raciness. - void setRestoreWorkingDir(bool RestoreCWD); - /// Sets whether an error message should be printed out if an action fails. By /// default, if an action fails, a message is printed out to stderr. void setPrintErrorMessage(bool PrintErrorMessage); @@ -395,7 +390,6 @@ private: DiagnosticConsumer *DiagConsumer = nullptr; - bool RestoreCWD = true; bool PrintErrorMessage = true; }; @@ -506,6 +500,12 @@ llvm::Expected getAbsolutePath(llvm::vfs::FileSystem &FS, void addTargetAndModeForProgramName(std::vector &CommandLine, StringRef InvokedAs); +/// Helper function that expands response files in command line. +void addExpandedResponseFiles(std::vector &CommandLine, + llvm::StringRef WorkingDir, + llvm::cl::TokenizerCallback Tokenizer, + llvm::vfs::FileSystem &FS); + /// Creates a \c CompilerInvocation. CompilerInvocation *newInvocation(DiagnosticsEngine *Diagnostics, ArrayRef CC1Args, diff --git a/contrib/llvm-project/clang/include/clang/module.modulemap b/contrib/llvm-project/clang/include/clang/module.modulemap deleted file mode 100644 index 57a9b480312..00000000000 --- a/contrib/llvm-project/clang/include/clang/module.modulemap +++ /dev/null @@ -1,199 +0,0 @@ -module Clang_Analysis { - requires cplusplus - umbrella "Analysis" - - textual header "Analysis/Analyses/ThreadSafetyOps.def" - - module * { export * } - - // FIXME: Exclude these headers to avoid pulling all of the AST matchers - // library into clang. Due to inline key functions in the headers, - // importing the AST matchers library gives a link dependency on the AST - // matchers (and thus the AST), which clang-format should not have. - exclude header "Analysis/Analyses/ExprMutationAnalyzer.h" -} - -module Clang_AST { - requires cplusplus - umbrella "AST" - - textual header "AST/BuiltinTypes.def" - textual header "AST/CXXRecordDeclDefinitionBits.def" - textual header "AST/OperationKinds.def" - textual header "AST/TypeLocNodes.def" - - module * { export * } -} - -module Clang_ASTMatchers { requires cplusplus umbrella "ASTMatchers" module * { export * } } - -module Clang_Basic { - requires cplusplus - umbrella "Basic" - - textual header "Basic/AArch64SVEACLETypes.def" - textual header "Basic/BuiltinsAArch64.def" - textual header "Basic/BuiltinsAMDGPU.def" - textual header "Basic/BuiltinsAArch64NeonSVEBridge.def" - textual header "Basic/BuiltinsAArch64NeonSVEBridge_cg.def" - textual header "Basic/BuiltinsARM.def" - textual header "Basic/BuiltinsBPF.def" - textual header "Basic/Builtins.def" - textual header "Basic/BuiltinHeaders.def" - textual header "Basic/BuiltinsHexagon.def" - textual header "Basic/BuiltinsHexagonDep.def" - textual header "Basic/BuiltinsHexagonMapCustomDep.def" - textual header "Basic/BuiltinsLoongArch.def" - textual header "Basic/BuiltinsMips.def" - textual header "Basic/BuiltinsNEON.def" - textual header "Basic/BuiltinsNVPTX.def" - textual header "Basic/BuiltinsPPC.def" - textual header "Basic/BuiltinsRISCV.def" - textual header "Basic/BuiltinsRISCVVector.def" - textual header "Basic/BuiltinsSVE.def" - textual header "Basic/BuiltinsSystemZ.def" - textual header "Basic/BuiltinsVE.def" - textual header "Basic/BuiltinsVEVL.gen.def" - textual header "Basic/BuiltinsWebAssembly.def" - textual header "Basic/BuiltinsX86.def" - textual header "Basic/BuiltinsX86_64.def" - textual header "Basic/BuiltinsXCore.def" - textual header "Basic/CodeGenOptions.def" - textual header "Basic/DiagnosticOptions.def" - textual header "Basic/Features.def" - textual header "Basic/FPOptions.def" - textual header "Basic/MSP430Target.def" - textual header "Basic/LangOptions.def" - textual header "Basic/OpenCLExtensions.def" - textual header "Basic/OpenCLImageTypes.def" - textual header "Basic/OpenCLExtensionTypes.def" - textual header "Basic/OpenMPKinds.def" - textual header "Basic/OperatorKinds.def" - textual header "Basic/PPCTypes.def" - textual header "Basic/RISCVVTypes.def" - textual header "Basic/Sanitizers.def" - textual header "Basic/TargetCXXABI.def" - textual header "Basic/TransformTypeTraits.def" - - module * { export * } -} -module Clang_Basic_TokenKinds { - requires cplusplus - - header "Basic/TokenKinds.h" - textual header "Basic/TokenKinds.def" - - export * -} - -module Clang_CodeGen { requires cplusplus umbrella "CodeGen" module * { export * } } -module Clang_Config { requires cplusplus umbrella "Config" module * { export * } } - -// Files for diagnostic groups are spread all over the include/clang/ tree, but -// logically form a single module. -module Clang_Diagnostics { - requires cplusplus - - module All { header "Basic/AllDiagnostics.h" export * } - module Analysis { textual header "Analysis/Analyses/UnsafeBufferUsageGadgets.def" } - module AST { header "AST/ASTDiagnostic.h" export * } - module Comment { header "AST/CommentDiagnostic.h" export * } - module Driver { header "Driver/DriverDiagnostic.h" export * } - module Frontend { header "Frontend/FrontendDiagnostic.h" export * } - module Lex { header "Lex/LexDiagnostic.h" export * } - module Parse { header "Parse/ParseDiagnostic.h" export * } - module Sema { header "Sema/SemaDiagnostic.h" export * } - module Serialization { header "Serialization/SerializationDiagnostic.h" export * } - module Refactoring { header "Tooling/Refactoring/RefactoringDiagnostic.h" export * } -} - -module Clang_Driver { - requires cplusplus - umbrella "Driver" - - textual header "Driver/Types.def" - - module * { export * } -} - -module Clang_Edit { requires cplusplus umbrella "Edit" module * { export * } } -module Clang_Format { requires cplusplus umbrella "Format" module * { export * } } - -module Clang_Frontend { - requires cplusplus - umbrella "Frontend" - - textual header "Basic/LangStandards.def" - - module * { export * } -} - -module Clang_FrontendTool { requires cplusplus umbrella "FrontendTool" module * { export * } } -module Clang_Index { requires cplusplus umbrella "Index" module * { export * } } -module Clang_Lex { requires cplusplus umbrella "Lex" module * { export * } } -module Clang_Parse { requires cplusplus umbrella "Parse" module * { export * } } -module Clang_Rewrite { requires cplusplus umbrella "Rewrite/Core" module * { export * } } -module Clang_RewriteFrontend { requires cplusplus umbrella "Rewrite/Frontend" module * { export * } } -module Clang_Sema { requires cplusplus umbrella "Sema" module * { export * } } - -module Clang_Serialization { - requires cplusplus - umbrella "Serialization" - - textual header "Serialization/TypeBitCodes.def" - - module * { export * } -} - -module Clang_StaticAnalyzer_Core { - requires cplusplus - umbrella "StaticAnalyzer/Core" - - textual header "StaticAnalyzer/Core/Analyses.def" - textual header "StaticAnalyzer/Core/AnalyzerOptions.def" - textual header "StaticAnalyzer/Core/PathSensitive/SVals.def" - textual header "StaticAnalyzer/Core/PathSensitive/Symbols.def" - textual header "StaticAnalyzer/Core/PathSensitive/Regions.def" - - module * { export * } -} - -module Clang_StaticAnalyzer_Checkers { - requires cplusplus - umbrella "StaticAnalyzer/Checkers" - module * { export * } -} - -module Clang_StaticAnalyzer_Frontend { - requires cplusplus - umbrella "StaticAnalyzer/Frontend" - module * { export * } -} - -module Clang_Testing { - requires cplusplus - umbrella "Testing" - module * { export * } -} - -module Clang_Tooling { - requires cplusplus umbrella "Tooling" module * { export * } - // FIXME: Exclude these headers to avoid pulling all of the AST matchers - // library into clang-format. Due to inline key functions in the headers, - // importing the AST matchers library gives a link dependency on the AST - // matchers (and thus the AST), which clang-format should not have. - exclude header "Tooling/RefactoringCallbacks.h" -} - -module Clang_ToolingCore { - requires cplusplus - umbrella "Tooling/Core" module * { export * } -} - -module Clang_ToolingInclusions { - requires cplusplus - umbrella "Tooling/Inclusions" - textual header "Tooling/Inclusions/CSymbolMap.inc" - textual header "Tooling/Inclusions/StdSymbolMap.inc" - module * { export * } -} diff --git a/contrib/llvm-project/clang/include/module.modulemap b/contrib/llvm-project/clang/include/module.modulemap new file mode 100644 index 00000000000..6ea613c7030 --- /dev/null +++ b/contrib/llvm-project/clang/include/module.modulemap @@ -0,0 +1,205 @@ +module Clang_C { + umbrella "clang-c" + module * { export * } +} + +module Clang_Analysis { + requires cplusplus + umbrella "clang/Analysis" + + textual header "clang/Analysis/Analyses/ThreadSafetyOps.def" + + module * { export * } + + // FIXME: Exclude these headers to avoid pulling all of the AST matchers + // library into clang. Due to inline key functions in the headers, + // importing the AST matchers library gives a link dependency on the AST + // matchers (and thus the AST), which clang-format should not have. + exclude header "clang/Analysis/Analyses/ExprMutationAnalyzer.h" +} + +module Clang_AST { + requires cplusplus + umbrella "clang/AST" + + textual header "clang/AST/BuiltinTypes.def" + textual header "clang/AST/CXXRecordDeclDefinitionBits.def" + textual header "clang/AST/OperationKinds.def" + textual header "clang/AST/TypeLocNodes.def" + + module * { export * } +} + +module Clang_ASTMatchers { requires cplusplus umbrella "clang/ASTMatchers" module * { export * } } + +module Clang_Basic { + requires cplusplus + umbrella "clang/Basic" + + textual header "clang/Basic/AArch64SVEACLETypes.def" + textual header "clang/Basic/BuiltinsAArch64.def" + textual header "clang/Basic/BuiltinsAMDGPU.def" + textual header "clang/Basic/BuiltinsAArch64NeonSVEBridge.def" + textual header "clang/Basic/BuiltinsAArch64NeonSVEBridge_cg.def" + textual header "clang/Basic/BuiltinsARM.def" + textual header "clang/Basic/BuiltinsBPF.def" + textual header "clang/Basic/Builtins.def" + textual header "clang/Basic/BuiltinHeaders.def" + textual header "clang/Basic/BuiltinsHexagon.def" + textual header "clang/Basic/BuiltinsHexagonDep.def" + textual header "clang/Basic/BuiltinsHexagonMapCustomDep.def" + textual header "clang/Basic/BuiltinsLoongArch.def" + textual header "clang/Basic/BuiltinsMips.def" + textual header "clang/Basic/BuiltinsNEON.def" + textual header "clang/Basic/BuiltinsNVPTX.def" + textual header "clang/Basic/BuiltinsPPC.def" + textual header "clang/Basic/BuiltinsRISCV.def" + textual header "clang/Basic/BuiltinsRISCVVector.def" + textual header "clang/Basic/BuiltinsSME.def" + textual header "clang/Basic/BuiltinsSVE.def" + textual header "clang/Basic/BuiltinsSystemZ.def" + textual header "clang/Basic/BuiltinsVE.def" + textual header "clang/Basic/BuiltinsVEVL.gen.def" + textual header "clang/Basic/BuiltinsWebAssembly.def" + textual header "clang/Basic/BuiltinsX86.def" + textual header "clang/Basic/BuiltinsX86_64.def" + textual header "clang/Basic/BuiltinsXCore.def" + textual header "clang/Basic/CodeGenOptions.def" + textual header "clang/Basic/DiagnosticOptions.def" + textual header "clang/Basic/Features.def" + textual header "clang/Basic/FPOptions.def" + textual header "clang/Basic/MSP430Target.def" + textual header "clang/Basic/LangOptions.def" + textual header "clang/Basic/OpenCLExtensions.def" + textual header "clang/Basic/OpenCLImageTypes.def" + textual header "clang/Basic/OpenCLExtensionTypes.def" + textual header "clang/Basic/OpenMPKinds.def" + textual header "clang/Basic/OperatorKinds.def" + textual header "clang/Basic/PPCTypes.def" + textual header "clang/Basic/RISCVVTypes.def" + textual header "clang/Basic/Sanitizers.def" + textual header "clang/Basic/TargetCXXABI.def" + textual header "clang/Basic/TransformTypeTraits.def" + textual header "clang/Basic/TokenKinds.def" + textual header "clang/Basic/WebAssemblyReferenceTypes.def" + + module * { export * } +} +module Clang_Basic_TokenKinds { + requires cplusplus + + header "clang/Basic/TokenKinds.h" + textual header "clang/Basic/TokenKinds.def" + + export * +} + +module Clang_CodeGen { requires cplusplus umbrella "clang/CodeGen" module * { export * } } +module Clang_Config { requires cplusplus umbrella "clang/Config" module * { export * } } + +// Files for diagnostic groups are spread all over the include/clang/ tree, but +// logically form a single module. +module Clang_Diagnostics { + requires cplusplus + + module All { header "clang/Basic/AllDiagnostics.h" export * } + module Analysis { textual header "clang/Analysis/Analyses/UnsafeBufferUsageGadgets.def" } + module AST { header "clang/AST/ASTDiagnostic.h" export * } + module Comment { header "clang/AST/CommentDiagnostic.h" export * } + module Driver { header "clang/Driver/DriverDiagnostic.h" export * } + module Frontend { header "clang/Frontend/FrontendDiagnostic.h" export * } + module Lex { header "clang/Lex/LexDiagnostic.h" export * } + module Parse { header "clang/Parse/ParseDiagnostic.h" export * } + module Sema { header "clang/Sema/SemaDiagnostic.h" export * } + module Serialization { header "clang/Serialization/SerializationDiagnostic.h" export * } + module Refactoring { header "clang/Tooling/Refactoring/RefactoringDiagnostic.h" export * } +} + +module Clang_Driver { + requires cplusplus + umbrella "clang/Driver" + + textual header "clang/Driver/Types.def" + + module * { export * } +} + +module Clang_Edit { requires cplusplus umbrella "clang/Edit" module * { export * } } +module Clang_Format { requires cplusplus umbrella "clang/Format" module * { export * } } + +module Clang_Frontend { + requires cplusplus + umbrella "clang/Frontend" + + textual header "clang/Basic/LangStandards.def" + + module * { export * } +} + +module Clang_FrontendTool { requires cplusplus umbrella "clang/FrontendTool" module * { export * } } +module Clang_Index { requires cplusplus umbrella "clang/Index" module * { export * } } +module Clang_Lex { requires cplusplus umbrella "clang/Lex" module * { export * } } +module Clang_Parse { requires cplusplus umbrella "clang/Parse" module * { export * } } +module Clang_Rewrite { requires cplusplus umbrella "clang/Rewrite/Core" module * { export * } } +module Clang_RewriteFrontend { requires cplusplus umbrella "clang/Rewrite/Frontend" module * { export * } } +module Clang_Sema { requires cplusplus umbrella "clang/Sema" module * { export * } } + +module Clang_Serialization { + requires cplusplus + umbrella "clang/Serialization" + + textual header "clang/Serialization/TypeBitCodes.def" + + module * { export * } +} + +module Clang_StaticAnalyzer_Core { + requires cplusplus + umbrella "clang/StaticAnalyzer/Core" + + textual header "clang/StaticAnalyzer/Core/Analyses.def" + textual header "clang/StaticAnalyzer/Core/AnalyzerOptions.def" + textual header "clang/StaticAnalyzer/Core/PathSensitive/SVals.def" + textual header "clang/StaticAnalyzer/Core/PathSensitive/Symbols.def" + textual header "clang/StaticAnalyzer/Core/PathSensitive/Regions.def" + + module * { export * } +} + +module Clang_StaticAnalyzer_Checkers { + requires cplusplus + umbrella "clang/StaticAnalyzer/Checkers" + module * { export * } +} + +module Clang_StaticAnalyzer_Frontend { + requires cplusplus + umbrella "clang/StaticAnalyzer/Frontend" + module * { export * } +} + +module Clang_Testing { + requires cplusplus + umbrella "clang/Testing" + module * { export * } +} + +module Clang_Tooling { + requires cplusplus umbrella "clang/Tooling" module * { export * } + // FIXME: Exclude these headers to avoid pulling all of the AST matchers + // library into clang-format. Due to inline key functions in the headers, + // importing the AST matchers library gives a link dependency on the AST + // matchers (and thus the AST), which clang-format should not have. + exclude header "clang/Tooling/RefactoringCallbacks.h" +} + +module Clang_ToolingCore { + requires cplusplus + umbrella "clang/Tooling/Core" module * { export * } +} + +module Clang_ToolingInclusions { + requires cplusplus + umbrella "clang/Tooling/Inclusions" + module * { export * } +} diff --git a/contrib/llvm-project/clang/lib/APINotes/APINotesFormat.h b/contrib/llvm-project/clang/lib/APINotes/APINotesFormat.h index 6b76ecfc256..a0a5efe8f9b 100644 --- a/contrib/llvm-project/clang/lib/APINotes/APINotesFormat.h +++ b/contrib/llvm-project/clang/lib/APINotes/APINotesFormat.h @@ -220,7 +220,7 @@ using TagDataLayout = // below) llvm::BCBlob // map from name to tag information >; -}; // namespace tag_block +} // namespace tag_block namespace typedef_block { enum { TYPEDEF_DATA = 1 }; @@ -231,7 +231,7 @@ using TypedefDataLayout = // below) llvm::BCBlob // map from name to typedef information >; -}; // namespace typedef_block +} // namespace typedef_block namespace enum_constant_block { enum { ENUM_CONSTANT_DATA = 1 }; diff --git a/contrib/llvm-project/clang/lib/ARCMigrate/ARCMT.cpp b/contrib/llvm-project/clang/lib/ARCMigrate/ARCMT.cpp index 68ee7c59270..ac79f3f03e6 100644 --- a/contrib/llvm-project/clang/lib/ARCMigrate/ARCMT.cpp +++ b/contrib/llvm-project/clang/lib/ARCMigrate/ARCMT.cpp @@ -6,8 +6,8 @@ // //===----------------------------------------------------------------------===// -#include "Internals.h" #include "clang/ARCMigrate/ARCMT.h" +#include "Internals.h" #include "clang/AST/ASTConsumer.h" #include "clang/Basic/DiagnosticCategories.h" #include "clang/Frontend/ASTUnit.h" @@ -20,8 +20,8 @@ #include "clang/Rewrite/Core/Rewriter.h" #include "clang/Sema/SemaDiagnostic.h" #include "clang/Serialization/ASTReader.h" -#include "llvm/ADT/Triple.h" #include "llvm/Support/MemoryBuffer.h" +#include "llvm/TargetParser/Triple.h" #include using namespace clang; using namespace arcmt; diff --git a/contrib/llvm-project/clang/lib/ARCMigrate/FileRemapper.cpp b/contrib/llvm-project/clang/lib/ARCMigrate/FileRemapper.cpp index 92027fe4f1f..7e56e0683c1 100644 --- a/contrib/llvm-project/clang/lib/ARCMigrate/FileRemapper.cpp +++ b/contrib/llvm-project/clang/lib/ARCMigrate/FileRemapper.cpp @@ -251,8 +251,7 @@ const FileEntry *FileRemapper::getOriginalFile(StringRef filePath) { I = ToFromMappings.find(file); if (I != ToFromMappings.end()) { file = I->second; - assert(FromToMappings.find(file) != FromToMappings.end() && - "Original file not in mappings!"); + assert(FromToMappings.contains(file) && "Original file not in mappings!"); } return file; } diff --git a/contrib/llvm-project/clang/lib/ARCMigrate/ObjCMT.cpp b/contrib/llvm-project/clang/lib/ARCMigrate/ObjCMT.cpp index ce1decd3ba3..c76efd78976 100644 --- a/contrib/llvm-project/clang/lib/ARCMigrate/ObjCMT.cpp +++ b/contrib/llvm-project/clang/lib/ARCMigrate/ObjCMT.cpp @@ -153,8 +153,7 @@ protected: bool canModifyFile(StringRef Path) { if (AllowListFilenames.empty()) return true; - return AllowListFilenames.find(llvm::sys::path::filename(Path)) != - AllowListFilenames.end(); + return AllowListFilenames.contains(llvm::sys::path::filename(Path)); } bool canModifyFile(OptionalFileEntryRef FE) { if (!FE) diff --git a/contrib/llvm-project/clang/lib/ARCMigrate/TransProperties.cpp b/contrib/llvm-project/clang/lib/ARCMigrate/TransProperties.cpp index e5ccf1cf79b..6d1d950821a 100644 --- a/contrib/llvm-project/clang/lib/ARCMigrate/TransProperties.cpp +++ b/contrib/llvm-project/clang/lib/ARCMigrate/TransProperties.cpp @@ -45,7 +45,7 @@ namespace { class PropertiesRewriter { MigrationContext &MigrateCtx; MigrationPass &Pass; - ObjCImplementationDecl *CurImplD; + ObjCImplementationDecl *CurImplD = nullptr; enum PropActionKind { PropAction_None, diff --git a/contrib/llvm-project/clang/lib/AST/ASTContext.cpp b/contrib/llvm-project/clang/lib/AST/ASTContext.cpp index 8054eb2e12d..7acacd7bf4f 100644 --- a/contrib/llvm-project/clang/lib/AST/ASTContext.cpp +++ b/contrib/llvm-project/clang/lib/AST/ASTContext.cpp @@ -77,7 +77,7 @@ #include "llvm/ADT/SmallVector.h" #include "llvm/ADT/StringExtras.h" #include "llvm/ADT/StringRef.h" -#include "llvm/ADT/Triple.h" +#include "llvm/Frontend/OpenMP/OMPIRBuilder.h" #include "llvm/Support/Capacity.h" #include "llvm/Support/Casting.h" #include "llvm/Support/Compiler.h" @@ -85,6 +85,7 @@ #include "llvm/Support/MD5.h" #include "llvm/Support/MathExtras.h" #include "llvm/Support/raw_ostream.h" +#include "llvm/TargetParser/Triple.h" #include #include #include @@ -181,22 +182,96 @@ static SourceLocation getDeclLocForCommentSearch(const Decl *D, const SourceLocation DeclLoc = D->getLocation(); if (DeclLoc.isMacroID()) { - if (isa(D)) { - // If location of the typedef name is in a macro, it is because being - // declared via a macro. Try using declaration's starting location as - // the "declaration location". - return D->getBeginLoc(); - } + // There are (at least) three types of macros we care about here. + // + // 1. Macros that are used in the definition of a type outside the macro, + // with a comment attached at the macro call site. + // ``` + // #define MAKE_NAME(Foo) Name##Foo + // + // /// Comment is here, where we use the macro. + // struct MAKE_NAME(Foo) { + // int a; + // int b; + // }; + // ``` + // 2. Macros that define whole things along with the comment. + // ``` + // #define MAKE_METHOD(name) \ + // /** Comment is here, inside the macro. */ \ + // void name() {} + // + // struct S { + // MAKE_METHOD(f) + // } + // ``` + // 3. Macros that both declare a type and name a decl outside the macro. + // ``` + // /// Comment is here, where we use the macro. + // typedef NS_ENUM(NSInteger, Size) { + // SizeWidth, + // SizeHeight + // }; + // ``` + // In this case NS_ENUM declares am enum type, and uses the same name for + // the typedef declaration that appears outside the macro. The comment + // here should be applied to both declarations inside and outside the + // macro. + // + // We have found a Decl name that comes from inside a macro, but + // Decl::getLocation() returns the place where the macro is being called. + // If the declaration (and not just the name) resides inside the macro, + // then we want to map Decl::getLocation() into the macro to where the + // declaration and its attached comment (if any) were written. + // + // This mapping into the macro is done by mapping the location to its + // spelling location, however even if the declaration is inside a macro, + // the name's spelling can come from a macro argument (case 2 above). In + // this case mapping the location to the spelling location finds the + // argument's position (at `f` in MAKE_METHOD(`f`) above), which is not + // where the declaration and its comment are located. + // + // To avoid this issue, we make use of Decl::getBeginLocation() instead. + // While the declaration's position is where the name is written, the + // comment is always attached to the begining of the declaration, not to + // the name. + // + // In the first case, the begin location of the decl is outside the macro, + // at the location of `typedef`. This is where the comment is found as + // well. The begin location is not inside a macro, so it's spelling + // location is the same. + // + // In the second case, the begin location of the decl is the call to the + // macro, at `MAKE_METHOD`. However its spelling location is inside the + // the macro at the location of `void`. This is where the comment is found + // again. + // + // In the third case, there's no correct single behaviour. We want to use + // the comment outside the macro for the definition that's inside the macro. + // There is also a definition outside the macro, and we want the comment to + // apply to both. The cases we care about here is NS_ENUM() and + // NS_OPTIONS(). In general, if an enum is defined inside a macro, we should + // try to find the comment there. - if (const auto *TD = dyn_cast(D)) { - // If location of the tag decl is inside a macro, but the spelling of - // the tag name comes from a macro argument, it looks like a special - // macro like NS_ENUM is being used to define the tag decl. In that - // case, adjust the source location to the expansion loc so that we can - // attach the comment to the tag decl. - if (SourceMgr.isMacroArgExpansion(DeclLoc) && TD->isCompleteDefinition()) - return SourceMgr.getExpansionLoc(DeclLoc); + // This is handling case 3 for NS_ENUM() and NS_OPTIONS(), which define + // enum types inside the macro. + if (isa(D)) { + SourceLocation MacroCallLoc = SourceMgr.getExpansionLoc(DeclLoc); + if (auto BufferRef = + SourceMgr.getBufferOrNone(SourceMgr.getFileID(MacroCallLoc)); + BufferRef.has_value()) { + llvm::StringRef buffer = BufferRef->getBuffer().substr( + SourceMgr.getFileOffset(MacroCallLoc)); + if (buffer.starts_with("NS_ENUM(") || + buffer.starts_with("NS_OPTIONS(")) { + // We want to use the comment on the call to NS_ENUM and NS_OPTIONS + // macros for the types defined inside the macros, which is at the + // expansion location. + return MacroCallLoc; + } + } } + return SourceMgr.getSpellingLoc(D->getBeginLoc()); } return DeclLoc; @@ -274,7 +349,7 @@ RawComment *ASTContext::getRawCommentForDeclNoCacheImpl( // There should be no other declarations or preprocessor directives between // comment and declaration. - if (Text.find_first_of(";{}#@") != StringRef::npos) + if (Text.find_last_of(";{}#@") != StringRef::npos) return nullptr; return CommentBeforeDecl; @@ -424,10 +499,7 @@ const RawComment *ASTContext::getRawCommentForAnyRedecl( // Any redeclarations of D that we haven't checked for comments yet? // We can't use DenseMap::iterator directly since it'd get invalid. auto LastCheckedRedecl = [this, CanonicalD]() -> const Decl * { - auto LookupRes = CommentlessRedeclChains.find(CanonicalD); - if (LookupRes != CommentlessRedeclChains.end()) - return LookupRes->second; - return nullptr; + return CommentlessRedeclChains.lookup(CanonicalD); }(); for (const auto Redecl : D->redecls()) { @@ -679,11 +751,6 @@ ASTContext::CanonicalTemplateTemplateParm::Profile(llvm::FoldingSetNodeID &ID, if (const auto *TTP = dyn_cast(*P)) { ID.AddInteger(0); ID.AddBoolean(TTP->isParameterPack()); - const TypeConstraint *TC = TTP->getTypeConstraint(); - ID.AddBoolean(TC != nullptr); - if (TC) - TC->getImmediatelyDeclaredConstraint()->Profile(ID, C, - /*Canonical=*/true); if (TTP->isExpandedParameterPack()) { ID.AddBoolean(true); ID.AddInteger(TTP->getNumExpansionParameters()); @@ -695,11 +762,8 @@ ASTContext::CanonicalTemplateTemplateParm::Profile(llvm::FoldingSetNodeID &ID, if (const auto *NTTP = dyn_cast(*P)) { ID.AddInteger(1); ID.AddBoolean(NTTP->isParameterPack()); - const Expr *TC = NTTP->getPlaceholderTypeConstraint(); - ID.AddBoolean(TC != nullptr); - ID.AddPointer(NTTP->getType().getCanonicalType().getAsOpaquePtr()); - if (TC) - TC->Profile(ID, C, /*Canonical=*/true); + ID.AddPointer(C.getUnconstrainedType(C.getCanonicalType(NTTP->getType())) + .getAsOpaquePtr()); if (NTTP->isExpandedParameterPack()) { ID.AddBoolean(true); ID.AddInteger(NTTP->getNumExpansionTypes()); @@ -716,65 +780,6 @@ ASTContext::CanonicalTemplateTemplateParm::Profile(llvm::FoldingSetNodeID &ID, ID.AddInteger(2); Profile(ID, C, TTP); } - Expr *RequiresClause = Parm->getTemplateParameters()->getRequiresClause(); - ID.AddBoolean(RequiresClause != nullptr); - if (RequiresClause) - RequiresClause->Profile(ID, C, /*Canonical=*/true); -} - -static Expr * -canonicalizeImmediatelyDeclaredConstraint(const ASTContext &C, Expr *IDC, - QualType ConstrainedType) { - // This is a bit ugly - we need to form a new immediately-declared - // constraint that references the new parameter; this would ideally - // require semantic analysis (e.g. template struct S {}; - the - // converted arguments of C could be an argument pack if C is - // declared as template concept C = ...). - // We don't have semantic analysis here so we dig deep into the - // ready-made constraint expr and change the thing manually. - ConceptSpecializationExpr *CSE; - if (const auto *Fold = dyn_cast(IDC)) - CSE = cast(Fold->getLHS()); - else - CSE = cast(IDC); - ArrayRef OldConverted = CSE->getTemplateArguments(); - SmallVector NewConverted; - NewConverted.reserve(OldConverted.size()); - if (OldConverted.front().getKind() == TemplateArgument::Pack) { - // The case: - // template concept C = true; - // template T> struct S; -> constraint is C<{T, int}> - NewConverted.push_back(ConstrainedType); - llvm::append_range(NewConverted, - OldConverted.front().pack_elements().drop_front(1)); - TemplateArgument NewPack(NewConverted); - - NewConverted.clear(); - NewConverted.push_back(NewPack); - assert(OldConverted.size() == 1 && - "Template parameter pack should be the last parameter"); - } else { - assert(OldConverted.front().getKind() == TemplateArgument::Type && - "Unexpected first argument kind for immediately-declared " - "constraint"); - NewConverted.push_back(ConstrainedType); - llvm::append_range(NewConverted, OldConverted.drop_front(1)); - } - auto *CSD = ImplicitConceptSpecializationDecl::Create( - C, CSE->getNamedConcept()->getDeclContext(), - CSE->getNamedConcept()->getLocation(), NewConverted); - - Expr *NewIDC = ConceptSpecializationExpr::Create( - C, CSE->getNamedConcept(), CSE->getTemplateArgsAsWritten(), CSD, - /*Satisfaction=*/nullptr, CSE->isInstantiationDependent(), - CSE->containsUnexpandedParameterPack()); - - if (auto *OrigFold = dyn_cast(IDC)) - NewIDC = new (C) CXXFoldExpr( - OrigFold->getType(), /*Callee*/ nullptr, SourceLocation(), NewIDC, - BinaryOperatorKind::BO_LAnd, SourceLocation(), /*RHS=*/nullptr, - SourceLocation(), /*NumExpansions=*/std::nullopt); - return NewIDC; } TemplateTemplateParmDecl * @@ -796,30 +801,19 @@ ASTContext::getCanonicalTemplateTemplateParmDecl( for (TemplateParameterList::const_iterator P = Params->begin(), PEnd = Params->end(); P != PEnd; ++P) { + // Note that, per C++20 [temp.over.link]/6, when determining whether + // template-parameters are equivalent, constraints are ignored. if (const auto *TTP = dyn_cast(*P)) { TemplateTypeParmDecl *NewTTP = TemplateTypeParmDecl::Create( *this, getTranslationUnitDecl(), SourceLocation(), SourceLocation(), TTP->getDepth(), TTP->getIndex(), nullptr, false, - TTP->isParameterPack(), TTP->hasTypeConstraint(), + TTP->isParameterPack(), /*HasTypeConstraint=*/false, TTP->isExpandedParameterPack() ? std::optional(TTP->getNumExpansionParameters()) : std::nullopt); - if (const auto *TC = TTP->getTypeConstraint()) { - QualType ParamAsArgument(NewTTP->getTypeForDecl(), 0); - Expr *NewIDC = canonicalizeImmediatelyDeclaredConstraint( - *this, TC->getImmediatelyDeclaredConstraint(), - ParamAsArgument); - NewTTP->setTypeConstraint( - NestedNameSpecifierLoc(), - DeclarationNameInfo(TC->getNamedConcept()->getDeclName(), - SourceLocation()), /*FoundDecl=*/nullptr, - // Actually canonicalizing a TemplateArgumentLoc is difficult so we - // simply omit the ArgsAsWritten - TC->getNamedConcept(), /*ArgsAsWritten=*/nullptr, NewIDC); - } CanonParams.push_back(NewTTP); } else if (const auto *NTTP = dyn_cast(*P)) { - QualType T = getCanonicalType(NTTP->getType()); + QualType T = getUnconstrainedType(getCanonicalType(NTTP->getType())); TypeSourceInfo *TInfo = getTrivialTypeSourceInfo(T); NonTypeTemplateParmDecl *Param; if (NTTP->isExpandedParameterPack()) { @@ -850,35 +844,18 @@ ASTContext::getCanonicalTemplateTemplateParmDecl( NTTP->isParameterPack(), TInfo); } - if (AutoType *AT = T->getContainedAutoType()) { - if (AT->isConstrained()) { - Param->setPlaceholderTypeConstraint( - canonicalizeImmediatelyDeclaredConstraint( - *this, NTTP->getPlaceholderTypeConstraint(), T)); - } - } CanonParams.push_back(Param); - } else CanonParams.push_back(getCanonicalTemplateTemplateParmDecl( cast(*P))); } - Expr *CanonRequiresClause = nullptr; - if (Expr *RequiresClause = TTP->getTemplateParameters()->getRequiresClause()) - CanonRequiresClause = RequiresClause; - - TemplateTemplateParmDecl *CanonTTP - = TemplateTemplateParmDecl::Create(*this, getTranslationUnitDecl(), - SourceLocation(), TTP->getDepth(), - TTP->getPosition(), - TTP->isParameterPack(), - nullptr, - TemplateParameterList::Create(*this, SourceLocation(), - SourceLocation(), - CanonParams, - SourceLocation(), - CanonRequiresClause)); + TemplateTemplateParmDecl *CanonTTP = TemplateTemplateParmDecl::Create( + *this, getTranslationUnitDecl(), SourceLocation(), TTP->getDepth(), + TTP->getPosition(), TTP->isParameterPack(), nullptr, + TemplateParameterList::Create(*this, SourceLocation(), SourceLocation(), + CanonParams, SourceLocation(), + /*RequiresClause=*/nullptr)); // Get the new insert position for the node we care about. Canonical = CanonTemplateTemplateParms.FindNodeOrInsertPos(ID, InsertPos); @@ -1172,6 +1149,13 @@ ArrayRef ASTContext::getModuleInitializers(Module *M) { return Inits->Initializers; } +void ASTContext::setCurrentNamedModule(Module *M) { + assert(M->isModulePurview()); + assert(!CurrentCXXNamedModule && + "We should set named module for ASTContext for only once"); + CurrentCXXNamedModule = M; +} + ExternCContextDecl *ASTContext::getExternCContextDecl() const { if (!ExternCContext) ExternCContext = ExternCContextDecl::Create(*this, getTranslationUnitDecl()); @@ -1433,6 +1417,12 @@ void ASTContext::InitBuiltinTypes(const TargetInfo &Target, #include "clang/Basic/RISCVVTypes.def" } + if (Target.getTriple().isWasm() && Target.hasFeature("reference-types")) { +#define WASM_TYPE(Name, Id, SingletonId) \ + InitBuiltinType(SingletonId, BuiltinType::Id); +#include "clang/Basic/WebAssemblyReferenceTypes.def" + } + // Builtin type for __objc_yes and __objc_no ObjCBuiltinBoolTy = (Target.useSignedCharForObjCBool() ? SignedCharTy : BoolTy); @@ -1530,11 +1520,7 @@ ASTContext::setTemplateOrSpecializationInfo(VarDecl *Inst, NamedDecl * ASTContext::getInstantiatedFromUsingDecl(NamedDecl *UUD) { - auto Pos = InstantiatedFromUsingDecl.find(UUD); - if (Pos == InstantiatedFromUsingDecl.end()) - return nullptr; - - return Pos->second; + return InstantiatedFromUsingDecl.lookup(UUD); } void @@ -1553,11 +1539,7 @@ ASTContext::setInstantiatedFromUsingDecl(NamedDecl *Inst, NamedDecl *Pattern) { UsingEnumDecl * ASTContext::getInstantiatedFromUsingEnumDecl(UsingEnumDecl *UUD) { - auto Pos = InstantiatedFromUsingEnumDecl.find(UUD); - if (Pos == InstantiatedFromUsingEnumDecl.end()) - return nullptr; - - return Pos->second; + return InstantiatedFromUsingEnumDecl.lookup(UUD); } void ASTContext::setInstantiatedFromUsingEnumDecl(UsingEnumDecl *Inst, @@ -1568,12 +1550,7 @@ void ASTContext::setInstantiatedFromUsingEnumDecl(UsingEnumDecl *Inst, UsingShadowDecl * ASTContext::getInstantiatedFromUsingShadowDecl(UsingShadowDecl *Inst) { - llvm::DenseMap::const_iterator Pos - = InstantiatedFromUsingShadowDecl.find(Inst); - if (Pos == InstantiatedFromUsingShadowDecl.end()) - return nullptr; - - return Pos->second; + return InstantiatedFromUsingShadowDecl.lookup(Inst); } void @@ -1584,12 +1561,7 @@ ASTContext::setInstantiatedFromUsingShadowDecl(UsingShadowDecl *Inst, } FieldDecl *ASTContext::getInstantiatedFromUnnamedFieldDecl(FieldDecl *Field) { - llvm::DenseMap::iterator Pos - = InstantiatedFromUnnamedFieldDecl.find(Field); - if (Pos == InstantiatedFromUnnamedFieldDecl.end()) - return nullptr; - - return Pos->second; + return InstantiatedFromUnnamedFieldDecl.lookup(Field); } void ASTContext::setInstantiatedFromUnnamedFieldDecl(FieldDecl *Inst, @@ -1696,11 +1668,11 @@ const llvm::fltSemantics &ASTContext::getFloatTypeSemantics(QualType T) const { case BuiltinType::Ibm128: return Target->getIbm128Format(); case BuiltinType::LongDouble: - if (getLangOpts().OpenMP && getLangOpts().OpenMPIsDevice) + if (getLangOpts().OpenMP && getLangOpts().OpenMPIsTargetDevice) return AuxTarget->getLongDoubleFormat(); return Target->getLongDoubleFormat(); case BuiltinType::Float128: - if (getLangOpts().OpenMP && getLangOpts().OpenMPIsDevice) + if (getLangOpts().OpenMP && getLangOpts().OpenMPIsTargetDevice) return AuxTarget->getFloat128Format(); return Target->getFloat128Format(); } @@ -2003,13 +1975,14 @@ TypeInfo ASTContext::getTypeInfoImpl(const Type *T) const { TypeInfo EltInfo = getTypeInfo(VT->getElementType()); Width = VT->isExtVectorBoolType() ? VT->getNumElements() : EltInfo.Width * VT->getNumElements(); - // Enforce at least byte alignment. + // Enforce at least byte size and alignment. + Width = std::max(8, Width); Align = std::max(8, Width); // If the alignment is not a power of 2, round up to the next power of 2. // This happens for non-power-of-2 length vectors. if (Align & (Align-1)) { - Align = llvm::NextPowerOf2(Align); + Align = llvm::bit_ceil(Align); Width = llvm::alignTo(Width, Align); } // Adjust the alignment based on the target max. @@ -2023,6 +1996,9 @@ TypeInfo ASTContext::getTypeInfoImpl(const Type *T) const { else if (VT->getVectorKind() == VectorType::SveFixedLengthPredicateVector) // Adjust the alignment for fixed-length SVE predicates. Align = 16; + else if (VT->getVectorKind() == VectorType::RVVFixedLengthDataVector) + // Adjust the alignment for fixed-length RVV vectors. + Align = std::min(64, Width); break; } @@ -2141,16 +2117,22 @@ TypeInfo ASTContext::getTypeInfoImpl(const Type *T) const { if (Target->hasBFloat16Type()) { Width = Target->getBFloat16Width(); Align = Target->getBFloat16Align(); + } else if ((getLangOpts().SYCLIsDevice || + (getLangOpts().OpenMP && + getLangOpts().OpenMPIsTargetDevice)) && + AuxTarget->hasBFloat16Type()) { + Width = AuxTarget->getBFloat16Width(); + Align = AuxTarget->getBFloat16Align(); } break; case BuiltinType::Float16: case BuiltinType::Half: if (Target->hasFloat16Type() || !getLangOpts().OpenMP || - !getLangOpts().OpenMPIsDevice) { + !getLangOpts().OpenMPIsTargetDevice) { Width = Target->getHalfWidth(); Align = Target->getHalfAlign(); } else { - assert(getLangOpts().OpenMP && getLangOpts().OpenMPIsDevice && + assert(getLangOpts().OpenMP && getLangOpts().OpenMPIsTargetDevice && "Expected OpenMP device compilation."); Width = AuxTarget->getHalfWidth(); Align = AuxTarget->getHalfAlign(); @@ -2169,7 +2151,7 @@ TypeInfo ASTContext::getTypeInfoImpl(const Type *T) const { Align = Target->getIbm128Align(); break; case BuiltinType::LongDouble: - if (getLangOpts().OpenMP && getLangOpts().OpenMPIsDevice && + if (getLangOpts().OpenMP && getLangOpts().OpenMPIsTargetDevice && (Target->getLongDoubleWidth() != AuxTarget->getLongDoubleWidth() || Target->getLongDoubleAlign() != AuxTarget->getLongDoubleAlign())) { Width = AuxTarget->getLongDoubleWidth(); @@ -2181,11 +2163,11 @@ TypeInfo ASTContext::getTypeInfoImpl(const Type *T) const { break; case BuiltinType::Float128: if (Target->hasFloat128Type() || !getLangOpts().OpenMP || - !getLangOpts().OpenMPIsDevice) { + !getLangOpts().OpenMPIsTargetDevice) { Width = Target->getFloat128Width(); Align = Target->getFloat128Align(); } else { - assert(getLangOpts().OpenMP && getLangOpts().OpenMPIsDevice && + assert(getLangOpts().OpenMP && getLangOpts().OpenMPIsTargetDevice && "Expected OpenMP device compilation."); Width = AuxTarget->getFloat128Width(); Align = AuxTarget->getFloat128Align(); @@ -2236,6 +2218,11 @@ TypeInfo ASTContext::getTypeInfoImpl(const Type *T) const { Width = 0; \ Align = 16; \ break; +#define SVE_OPAQUE_TYPE(Name, MangledName, Id, SingletonId) \ + case BuiltinType::Id: \ + Width = 0; \ + Align = 16; \ + break; #include "clang/Basic/AArch64SVEACLETypes.def" #define PPC_VECTOR_TYPE(Name, Id, Size) \ case BuiltinType::Id: \ @@ -2255,6 +2242,12 @@ TypeInfo ASTContext::getTypeInfoImpl(const Type *T) const { Align = 8; \ break; #include "clang/Basic/RISCVVTypes.def" +#define WASM_TYPE(Name, Id, SingletonId) \ + case BuiltinType::Id: \ + Width = 0; \ + Align = 8; \ + break; +#include "clang/Basic/WebAssemblyReferenceTypes.def" } break; case Type::ObjCObjectPointer: @@ -2313,10 +2306,8 @@ TypeInfo ASTContext::getTypeInfoImpl(const Type *T) const { } case Type::BitInt: { const auto *EIT = cast(T); - Align = - std::min(static_cast(std::max( - getCharWidth(), llvm::PowerOf2Ceil(EIT->getNumBits()))), - Target->getLongLongAlign()); + Align = std::clamp(llvm::PowerOf2Ceil(EIT->getNumBits()), + getCharWidth(), Target->getLongLongAlign()); Width = llvm::alignTo(EIT->getNumBits(), Align); break; } @@ -2422,8 +2413,7 @@ TypeInfo ASTContext::getTypeInfoImpl(const Type *T) const { // favorable to atomic operations: // Round the size up to a power of 2. - if (!llvm::isPowerOf2_64(Width)) - Width = llvm::NextPowerOf2(Width); + Width = llvm::bit_ceil(Width); // Set the alignment equal to the size. Align = static_cast(Width); @@ -2463,7 +2453,8 @@ unsigned ASTContext::getTypeUnadjustedAlign(const Type *T) const { } unsigned ASTContext::getOpenMPDefaultSimdAlign(QualType T) const { - unsigned SimdAlign = getTargetInfo().getSimdDefaultAlign(); + unsigned SimdAlign = llvm::OpenMPIRBuilder::getOpenMPDefaultSimdAlign( + getTargetInfo().getTriple(), Target->getTargetOpts().FeatureMap); return SimdAlign; } @@ -2667,12 +2658,14 @@ void ASTContext::CollectInheritedProtocols(const Decl *CDecl, } static bool unionHasUniqueObjectRepresentations(const ASTContext &Context, - const RecordDecl *RD) { + const RecordDecl *RD, + bool CheckIfTriviallyCopyable) { assert(RD->isUnion() && "Must be union type"); CharUnits UnionSize = Context.getTypeSizeInChars(RD->getTypeForDecl()); for (const auto *Field : RD->fields()) { - if (!Context.hasUniqueObjectRepresentations(Field->getType())) + if (!Context.hasUniqueObjectRepresentations(Field->getType(), + CheckIfTriviallyCopyable)) return false; CharUnits FieldSize = Context.getTypeSizeInChars(Field->getType()); if (FieldSize != UnionSize) @@ -2695,26 +2688,35 @@ static int64_t getSubobjectOffset(const CXXRecordDecl *RD, static std::optional structHasUniqueObjectRepresentations(const ASTContext &Context, - const RecordDecl *RD); + const RecordDecl *RD, + bool CheckIfTriviallyCopyable); static std::optional -getSubobjectSizeInBits(const FieldDecl *Field, const ASTContext &Context) { +getSubobjectSizeInBits(const FieldDecl *Field, const ASTContext &Context, + bool CheckIfTriviallyCopyable) { if (Field->getType()->isRecordType()) { const RecordDecl *RD = Field->getType()->getAsRecordDecl(); if (!RD->isUnion()) - return structHasUniqueObjectRepresentations(Context, RD); + return structHasUniqueObjectRepresentations(Context, RD, + CheckIfTriviallyCopyable); } // A _BitInt type may not be unique if it has padding bits // but if it is a bitfield the padding bits are not used. bool IsBitIntType = Field->getType()->isBitIntType(); if (!Field->getType()->isReferenceType() && !IsBitIntType && - !Context.hasUniqueObjectRepresentations(Field->getType())) + !Context.hasUniqueObjectRepresentations(Field->getType(), + CheckIfTriviallyCopyable)) return std::nullopt; int64_t FieldSizeInBits = Context.toBits(Context.getTypeSizeInChars(Field->getType())); if (Field->isBitField()) { + // If we have explicit padding bits, they don't contribute bits + // to the actual object representation, so return 0. + if (Field->isUnnamedBitfield()) + return 0; + int64_t BitfieldSize = Field->getBitWidthValue(Context); if (IsBitIntType) { if ((unsigned)BitfieldSize > @@ -2724,25 +2726,28 @@ getSubobjectSizeInBits(const FieldDecl *Field, const ASTContext &Context) { return std::nullopt; } FieldSizeInBits = BitfieldSize; - } else if (IsBitIntType && - !Context.hasUniqueObjectRepresentations(Field->getType())) { + } else if (IsBitIntType && !Context.hasUniqueObjectRepresentations( + Field->getType(), CheckIfTriviallyCopyable)) { return std::nullopt; } return FieldSizeInBits; } static std::optional -getSubobjectSizeInBits(const CXXRecordDecl *RD, const ASTContext &Context) { - return structHasUniqueObjectRepresentations(Context, RD); +getSubobjectSizeInBits(const CXXRecordDecl *RD, const ASTContext &Context, + bool CheckIfTriviallyCopyable) { + return structHasUniqueObjectRepresentations(Context, RD, + CheckIfTriviallyCopyable); } template static std::optional structSubobjectsHaveUniqueObjectRepresentations( const RangeT &Subobjects, int64_t CurOffsetInBits, - const ASTContext &Context, const clang::ASTRecordLayout &Layout) { + const ASTContext &Context, const clang::ASTRecordLayout &Layout, + bool CheckIfTriviallyCopyable) { for (const auto *Subobject : Subobjects) { std::optional SizeInBits = - getSubobjectSizeInBits(Subobject, Context); + getSubobjectSizeInBits(Subobject, Context, CheckIfTriviallyCopyable); if (!SizeInBits) return std::nullopt; if (*SizeInBits != 0) { @@ -2757,7 +2762,8 @@ static std::optional structSubobjectsHaveUniqueObjectRepresentations( static std::optional structHasUniqueObjectRepresentations(const ASTContext &Context, - const RecordDecl *RD) { + const RecordDecl *RD, + bool CheckIfTriviallyCopyable) { assert(!RD->isUnion() && "Must be struct/class type"); const auto &Layout = Context.getASTRecordLayout(RD); @@ -2778,8 +2784,8 @@ structHasUniqueObjectRepresentations(const ASTContext &Context, }); std::optional OffsetAfterBases = - structSubobjectsHaveUniqueObjectRepresentations(Bases, CurOffsetInBits, - Context, Layout); + structSubobjectsHaveUniqueObjectRepresentations( + Bases, CurOffsetInBits, Context, Layout, CheckIfTriviallyCopyable); if (!OffsetAfterBases) return std::nullopt; CurOffsetInBits = *OffsetAfterBases; @@ -2787,7 +2793,8 @@ structHasUniqueObjectRepresentations(const ASTContext &Context, std::optional OffsetAfterFields = structSubobjectsHaveUniqueObjectRepresentations( - RD->fields(), CurOffsetInBits, Context, Layout); + RD->fields(), CurOffsetInBits, Context, Layout, + CheckIfTriviallyCopyable); if (!OffsetAfterFields) return std::nullopt; CurOffsetInBits = *OffsetAfterFields; @@ -2795,7 +2802,8 @@ structHasUniqueObjectRepresentations(const ASTContext &Context, return CurOffsetInBits; } -bool ASTContext::hasUniqueObjectRepresentations(QualType Ty) const { +bool ASTContext::hasUniqueObjectRepresentations( + QualType Ty, bool CheckIfTriviallyCopyable) const { // C++17 [meta.unary.prop]: // The predicate condition for a template specialization // has_unique_object_representations shall be @@ -2817,16 +2825,17 @@ bool ASTContext::hasUniqueObjectRepresentations(QualType Ty) const { // Arrays are unique only if their element type is unique. if (Ty->isArrayType()) - return hasUniqueObjectRepresentations(getBaseElementType(Ty)); + return hasUniqueObjectRepresentations(getBaseElementType(Ty), + CheckIfTriviallyCopyable); // (9.1) - T is trivially copyable... - if (!Ty.isTriviallyCopyableType(*this)) + if (CheckIfTriviallyCopyable && !Ty.isTriviallyCopyableType(*this)) return false; // All integrals and enums are unique. if (Ty->isIntegralOrEnumerationType()) { // Except _BitInt types that have padding bits. - if (const auto *BIT = dyn_cast(Ty)) + if (const auto *BIT = Ty->getAs()) return getTypeSize(BIT) == BIT->getNumBits(); return true; @@ -2836,10 +2845,8 @@ bool ASTContext::hasUniqueObjectRepresentations(QualType Ty) const { if (Ty->isPointerType()) return true; - if (Ty->isMemberPointerType()) { - const auto *MPT = Ty->getAs(); + if (const auto *MPT = Ty->getAs()) return !ABI->getMemberPointerInfo(MPT).HasPadding; - } if (Ty->isRecordType()) { const RecordDecl *Record = Ty->castAs()->getDecl(); @@ -2848,10 +2855,11 @@ bool ASTContext::hasUniqueObjectRepresentations(QualType Ty) const { return false; if (Record->isUnion()) - return unionHasUniqueObjectRepresentations(*this, Record); + return unionHasUniqueObjectRepresentations(*this, Record, + CheckIfTriviallyCopyable); - std::optional StructSize = - structHasUniqueObjectRepresentations(*this, Record); + std::optional StructSize = structHasUniqueObjectRepresentations( + *this, Record, CheckIfTriviallyCopyable); return StructSize && *StructSize == static_cast(getTypeSize(Ty)); } @@ -2990,7 +2998,7 @@ TypeSourceInfo *ASTContext::CreateTypeSourceInfo(QualType T, auto *TInfo = (TypeSourceInfo*)BumpAlloc.Allocate(sizeof(TypeSourceInfo) + DataSize, 8); - new (TInfo) TypeSourceInfo(T); + new (TInfo) TypeSourceInfo(T, DataSize); return TInfo; } @@ -3946,6 +3954,10 @@ ASTContext::getBuiltinVectorTypeInfo(const BuiltinType *Ty) const { return SVE_INT_ELTTY(64, 2, false, 4); case BuiltinType::SveBool: return SVE_ELTTY(BoolTy, 16, 1); + case BuiltinType::SveBoolx2: + return SVE_ELTTY(BoolTy, 16, 2); + case BuiltinType::SveBoolx4: + return SVE_ELTTY(BoolTy, 16, 4); case BuiltinType::SveFloat16: return SVE_ELTTY(HalfTy, 8, 1); case BuiltinType::SveFloat16x2: @@ -3994,11 +4006,24 @@ ASTContext::getBuiltinVectorTypeInfo(const BuiltinType *Ty) const { } } +/// getExternrefType - Return a WebAssembly externref type, which represents an +/// opaque reference to a host value. +QualType ASTContext::getWebAssemblyExternrefType() const { + if (Target->getTriple().isWasm() && Target->hasFeature("reference-types")) { +#define WASM_REF_TYPE(Name, MangledName, Id, SingletonId, AS) \ + if (BuiltinType::Id == BuiltinType::WasmExternRef) \ + return SingletonId; +#include "clang/Basic/WebAssemblyReferenceTypes.def" + } + llvm_unreachable( + "shouldn't try to generate type externref outside WebAssembly target"); +} + /// getScalableVectorType - Return the unique reference to a scalable vector /// type of the specified element type and size. VectorType must be a built-in /// type. -QualType ASTContext::getScalableVectorType(QualType EltTy, - unsigned NumElts) const { +QualType ASTContext::getScalableVectorType(QualType EltTy, unsigned NumElts, + unsigned NumFields) const { if (Target->hasAArch64SVETypes()) { uint64_t EltTySize = getTypeSize(EltTy); #define SVE_VECTOR_TYPE(Name, MangledName, Id, SingletonId, NumEls, ElBits, \ @@ -4016,20 +4041,21 @@ QualType ASTContext::getScalableVectorType(QualType EltTy, #define SVE_PREDICATE_TYPE(Name, MangledName, Id, SingletonId, NumEls) \ if (EltTy->isBooleanType() && NumElts == NumEls) \ return SingletonId; +#define SVE_OPAQUE_TYPE(Name, MangledName, Id, SingleTonId) #include "clang/Basic/AArch64SVEACLETypes.def" } else if (Target->hasRISCVVTypes()) { uint64_t EltTySize = getTypeSize(EltTy); #define RVV_VECTOR_TYPE(Name, Id, SingletonId, NumEls, ElBits, NF, IsSigned, \ IsFP) \ - if (!EltTy->isBooleanType() && \ - ((EltTy->hasIntegerRepresentation() && \ - EltTy->hasSignedIntegerRepresentation() == IsSigned) || \ - (EltTy->hasFloatingRepresentation() && IsFP)) && \ - EltTySize == ElBits && NumElts == NumEls) \ - return SingletonId; + if (!EltTy->isBooleanType() && \ + ((EltTy->hasIntegerRepresentation() && \ + EltTy->hasSignedIntegerRepresentation() == IsSigned) || \ + (EltTy->hasFloatingRepresentation() && IsFP)) && \ + EltTySize == ElBits && NumElts == NumEls && NumFields == NF) \ + return SingletonId; #define RVV_PREDICATE_TYPE(Name, Id, SingletonId, NumEls) \ - if (EltTy->isBooleanType() && NumElts == NumEls) \ - return SingletonId; + if (EltTy->isBooleanType() && NumElts == NumEls) \ + return SingletonId; #include "clang/Basic/RISCVVTypes.def" } return QualType(); @@ -4116,8 +4142,8 @@ QualType ASTContext::getExtVectorType(QualType vecType, assert(vecType->isBuiltinType() || vecType->isDependentType() || (vecType->isBitIntType() && // Only support _BitInt elements with byte-sized power of 2 NumBits. - llvm::isPowerOf2_32(vecType->getAs()->getNumBits()) && - vecType->getAs()->getNumBits() >= 8)); + llvm::isPowerOf2_32(vecType->castAs()->getNumBits()) && + vecType->castAs()->getNumBits() >= 8)); // Check if we've already instantiated a vector of this type. llvm::FoldingSetNodeID ID; @@ -5775,12 +5801,19 @@ QualType ASTContext::getAutoTypeInternal( if (!DeducedType.isNull()) { Canon = DeducedType.getCanonicalType(); } else if (TypeConstraintConcept) { - Canon = getAutoTypeInternal(QualType(), Keyword, IsDependent, IsPack, - nullptr, {}, true); - // Find the insert position again. - [[maybe_unused]] auto *Nothing = - AutoTypes.FindNodeOrInsertPos(ID, InsertPos); - assert(!Nothing && "canonical type broken"); + bool AnyNonCanonArgs = false; + ConceptDecl *CanonicalConcept = TypeConstraintConcept->getCanonicalDecl(); + auto CanonicalConceptArgs = ::getCanonicalTemplateArguments( + *this, TypeConstraintArgs, AnyNonCanonArgs); + if (CanonicalConcept != TypeConstraintConcept || AnyNonCanonArgs) { + Canon = + getAutoTypeInternal(QualType(), Keyword, IsDependent, IsPack, + CanonicalConcept, CanonicalConceptArgs, true); + // Find the insert position again. + [[maybe_unused]] auto *Nothing = + AutoTypes.FindNodeOrInsertPos(ID, InsertPos); + assert(!Nothing && "canonical type broken"); + } } } @@ -5813,6 +5846,26 @@ ASTContext::getAutoType(QualType DeducedType, AutoTypeKeyword Keyword, TypeConstraintConcept, TypeConstraintArgs); } +QualType ASTContext::getUnconstrainedType(QualType T) const { + QualType CanonT = T.getCanonicalType(); + + // Remove a type-constraint from a top-level auto or decltype(auto). + if (auto *AT = CanonT->getAs()) { + if (!AT->isConstrained()) + return T; + return getQualifiedType(getAutoType(QualType(), AT->getKeyword(), false, + AT->containsUnexpandedParameterPack()), + T.getQualifiers()); + } + + // FIXME: We only support constrained auto at the top level in the type of a + // non-type template parameter at the moment. Once we lift that restriction, + // we'll need to recursively build types containing auto here. + assert(!CanonT->getContainedAutoType() || + !CanonT->getContainedAutoType()->isConstrained()); + return T; +} + /// Return the uniqued reference to the deduced template specialization type /// which has been deduced to the given type, or to the canonical undeduced /// such type, or the canonical deduced-but-dependent such type. @@ -6275,8 +6328,8 @@ bool ASTContext::isSameConstraintExpr(const Expr *XCE, const Expr *YCE) const { return true; llvm::FoldingSetNodeID XCEID, YCEID; - XCE->Profile(XCEID, *this, /*Canonical=*/true); - YCE->Profile(YCEID, *this, /*Canonical=*/true); + XCE->Profile(XCEID, *this, /*Canonical=*/true, /*ProfileLambdaExpr=*/true); + YCE->Profile(YCEID, *this, /*Canonical=*/true, /*ProfileLambdaExpr=*/true); return XCEID == YCEID; } @@ -6479,32 +6532,11 @@ static bool hasSameOverloadableAttrs(const FunctionDecl *A, return true; } -bool ASTContext::FriendsDifferByConstraints(const FunctionDecl *X, - const FunctionDecl *Y) const { - // If these aren't friends, then they aren't friends that differ by - // constraints. - if (!X->getFriendObjectKind() || !Y->getFriendObjectKind()) - return false; - - // If the two functions share lexical declaration context, they are not in - // separate instantations, and thus in the same scope. - if (X->getLexicalDeclContext() == Y->getLexicalDeclContext()) - return false; - - if (!X->getDescribedFunctionTemplate()) { - assert(!Y->getDescribedFunctionTemplate() && - "How would these be the same if they aren't both templates?"); - - // If these friends don't have constraints, they aren't constrained, and - // thus don't fall under temp.friend p9. Else the simple presence of a - // constraint makes them unique. - return X->getTrailingRequiresClause(); - } - - return X->FriendConstraintRefersToEnclosingTemplate(); -} - bool ASTContext::isSameEntity(const NamedDecl *X, const NamedDecl *Y) const { + // Caution: this function is called by the AST reader during deserialization, + // so it cannot rely on AST invariants being met. Non-trivial accessors + // should be avoided, along with any traversal of redeclaration chains. + if (X == Y) return true; @@ -6580,14 +6612,19 @@ bool ASTContext::isSameEntity(const NamedDecl *X, const NamedDecl *Y) const { return false; } + // Per C++20 [temp.over.link]/4, friends in different classes are sometimes + // not the same entity if they are constrained. + if ((FuncX->isMemberLikeConstrainedFriend() || + FuncY->isMemberLikeConstrainedFriend()) && + !FuncX->getLexicalDeclContext()->Equals( + FuncY->getLexicalDeclContext())) { + return false; + } + if (!isSameConstraintExpr(FuncX->getTrailingRequiresClause(), FuncY->getTrailingRequiresClause())) return false; - // Constrained friends are different in certain cases, see: [temp.friend]p9. - if (FriendsDifferByConstraints(FuncX, FuncY)) - return false; - auto GetTypeAsWritten = [](const FunctionDecl *FD) { // Map to the first declaration that we've already merged into this one. // The TSI of redeclarations might not match (due to calling conventions @@ -6620,6 +6657,11 @@ bool ASTContext::isSameEntity(const NamedDecl *X, const NamedDecl *Y) const { if (const auto *VarX = dyn_cast(X)) { const auto *VarY = cast(Y); if (VarX->getLinkageInternal() == VarY->getLinkageInternal()) { + // During deserialization, we might compare variables before we load + // their types. Assume the types will end up being the same. + if (VarX->getType().isNull() || VarY->getType().isNull()) + return true; + if (hasSameType(VarX->getType(), VarY->getType())) return true; @@ -6652,13 +6694,8 @@ bool ASTContext::isSameEntity(const NamedDecl *X, const NamedDecl *Y) const { // ConceptDecl wouldn't be the same if their constraint expression differs. if (const auto *ConceptX = dyn_cast(X)) { const auto *ConceptY = cast(Y); - const Expr *XCE = ConceptX->getConstraintExpr(); - const Expr *YCE = ConceptY->getConstraintExpr(); - assert(XCE && YCE && "ConceptDecl without constraint expression?"); - llvm::FoldingSetNodeID XID, YID; - XCE->Profile(XID, *this, /*Canonical=*/true); - YCE->Profile(YID, *this, /*Canonical=*/true); - if (XID != YID) + if (!isSameConstraintExpr(ConceptX->getConstraintExpr(), + ConceptY->getConstraintExpr())) return false; } @@ -6740,26 +6777,29 @@ ASTContext::getCanonicalTemplateArgument(const TemplateArgument &Arg) const { case TemplateArgument::Declaration: { auto *D = cast(Arg.getAsDecl()->getCanonicalDecl()); - return TemplateArgument(D, getCanonicalType(Arg.getParamTypeForDecl())); + return TemplateArgument(D, getCanonicalType(Arg.getParamTypeForDecl()), + Arg.getIsDefaulted()); } case TemplateArgument::NullPtr: return TemplateArgument(getCanonicalType(Arg.getNullPtrType()), - /*isNullPtr*/true); + /*isNullPtr*/ true, Arg.getIsDefaulted()); case TemplateArgument::Template: - return TemplateArgument(getCanonicalTemplateName(Arg.getAsTemplate())); + return TemplateArgument(getCanonicalTemplateName(Arg.getAsTemplate()), + Arg.getIsDefaulted()); case TemplateArgument::TemplateExpansion: - return TemplateArgument(getCanonicalTemplateName( - Arg.getAsTemplateOrTemplatePattern()), - Arg.getNumTemplateExpansions()); + return TemplateArgument( + getCanonicalTemplateName(Arg.getAsTemplateOrTemplatePattern()), + Arg.getNumTemplateExpansions(), Arg.getIsDefaulted()); case TemplateArgument::Integral: return TemplateArgument(Arg, getCanonicalType(Arg.getIntegralType())); case TemplateArgument::Type: - return TemplateArgument(getCanonicalType(Arg.getAsType())); + return TemplateArgument(getCanonicalType(Arg.getAsType()), + /*isNullPtr*/ false, Arg.getIsDefaulted()); case TemplateArgument::Pack: { bool AnyNonCanonArgs = false; @@ -8030,6 +8070,8 @@ static char getObjCEncodingForPrimitiveType(const ASTContext *C, #include "clang/Basic/AArch64SVEACLETypes.def" #define RVV_TYPE(Name, Id, SingletonId) case BuiltinType::Id: #include "clang/Basic/RISCVVTypes.def" +#define WASM_TYPE(Name, Id, SingletonId) case BuiltinType::Id: +#include "clang/Basic/WebAssemblyReferenceTypes.def" { DiagnosticsEngine &Diags = C->getDiagnostics(); unsigned DiagID = Diags.getCustomDiagID(DiagnosticsEngine::Error, @@ -8144,7 +8186,7 @@ static bool hasTemplateSpecializationInEncodedString(const Type *T, if (!CXXRD->hasDefinition() || !VisitBasesAndFields) return false; - for (auto B : CXXRD->bases()) + for (const auto &B : CXXRD->bases()) if (hasTemplateSpecializationInEncodedString(B.getType().getTypePtr(), true)) return true; @@ -9409,7 +9451,9 @@ bool ASTContext::areCompatibleVectorTypes(QualType FirstVec, First->getVectorKind() != VectorType::SveFixedLengthDataVector && First->getVectorKind() != VectorType::SveFixedLengthPredicateVector && Second->getVectorKind() != VectorType::SveFixedLengthDataVector && - Second->getVectorKind() != VectorType::SveFixedLengthPredicateVector) + Second->getVectorKind() != VectorType::SveFixedLengthPredicateVector && + First->getVectorKind() != VectorType::RVVFixedLengthDataVector && + Second->getVectorKind() != VectorType::RVVFixedLengthDataVector) return true; return false; @@ -9418,16 +9462,18 @@ bool ASTContext::areCompatibleVectorTypes(QualType FirstVec, /// getSVETypeSize - Return SVE vector or predicate register size. static uint64_t getSVETypeSize(ASTContext &Context, const BuiltinType *Ty) { assert(Ty->isVLSTBuiltinType() && "Invalid SVE Type"); - return Ty->getKind() == BuiltinType::SveBool - ? (Context.getLangOpts().VScaleMin * 128) / Context.getCharWidth() - : Context.getLangOpts().VScaleMin * 128; + if (Ty->getKind() == BuiltinType::SveBool || + Ty->getKind() == BuiltinType::SveCount) + return (Context.getLangOpts().VScaleMin * 128) / Context.getCharWidth(); + return Context.getLangOpts().VScaleMin * 128; } bool ASTContext::areCompatibleSveTypes(QualType FirstType, QualType SecondType) { - assert(((FirstType->isSizelessBuiltinType() && SecondType->isVectorType()) || - (FirstType->isVectorType() && SecondType->isSizelessBuiltinType())) && - "Expected SVE builtin type and vector type!"); + assert( + ((FirstType->isSVESizelessBuiltinType() && SecondType->isVectorType()) || + (FirstType->isVectorType() && SecondType->isSVESizelessBuiltinType())) && + "Expected SVE builtin type and vector type!"); auto IsValidCast = [this](QualType FirstType, QualType SecondType) { if (const auto *BT = FirstType->getAs()) { @@ -9454,9 +9500,10 @@ bool ASTContext::areCompatibleSveTypes(QualType FirstType, bool ASTContext::areLaxCompatibleSveTypes(QualType FirstType, QualType SecondType) { - assert(((FirstType->isSizelessBuiltinType() && SecondType->isVectorType()) || - (FirstType->isVectorType() && SecondType->isSizelessBuiltinType())) && - "Expected SVE builtin type and vector type!"); + assert( + ((FirstType->isSVESizelessBuiltinType() && SecondType->isVectorType()) || + (FirstType->isVectorType() && SecondType->isSVESizelessBuiltinType())) && + "Expected SVE builtin type and vector type!"); auto IsLaxCompatible = [this](QualType FirstType, QualType SecondType) { const auto *BT = FirstType->getAs(); @@ -9504,6 +9551,91 @@ bool ASTContext::areLaxCompatibleSveTypes(QualType FirstType, IsLaxCompatible(SecondType, FirstType); } +/// getRVVTypeSize - Return RVV vector register size. +static uint64_t getRVVTypeSize(ASTContext &Context, const BuiltinType *Ty) { + assert(Ty->isRVVVLSBuiltinType() && "Invalid RVV Type"); + auto VScale = Context.getTargetInfo().getVScaleRange(Context.getLangOpts()); + if (!VScale) + return 0; + + ASTContext::BuiltinVectorTypeInfo Info = Context.getBuiltinVectorTypeInfo(Ty); + + uint64_t EltSize = Context.getTypeSize(Info.ElementType); + uint64_t MinElts = Info.EC.getKnownMinValue(); + return VScale->first * MinElts * EltSize; +} + +bool ASTContext::areCompatibleRVVTypes(QualType FirstType, + QualType SecondType) { + assert( + ((FirstType->isRVVSizelessBuiltinType() && SecondType->isVectorType()) || + (FirstType->isVectorType() && SecondType->isRVVSizelessBuiltinType())) && + "Expected RVV builtin type and vector type!"); + + auto IsValidCast = [this](QualType FirstType, QualType SecondType) { + if (const auto *BT = FirstType->getAs()) { + if (const auto *VT = SecondType->getAs()) { + if (VT->getVectorKind() == VectorType::RVVFixedLengthDataVector || + VT->getVectorKind() == VectorType::GenericVector) + return FirstType->isRVVVLSBuiltinType() && + getTypeSize(SecondType) == getRVVTypeSize(*this, BT) && + hasSameType(VT->getElementType(), + getBuiltinVectorTypeInfo(BT).ElementType); + } + } + return false; + }; + + return IsValidCast(FirstType, SecondType) || + IsValidCast(SecondType, FirstType); +} + +bool ASTContext::areLaxCompatibleRVVTypes(QualType FirstType, + QualType SecondType) { + assert( + ((FirstType->isRVVSizelessBuiltinType() && SecondType->isVectorType()) || + (FirstType->isVectorType() && SecondType->isRVVSizelessBuiltinType())) && + "Expected RVV builtin type and vector type!"); + + auto IsLaxCompatible = [this](QualType FirstType, QualType SecondType) { + const auto *BT = FirstType->getAs(); + if (!BT) + return false; + + if (!BT->isRVVVLSBuiltinType()) + return false; + + const auto *VecTy = SecondType->getAs(); + if (VecTy && + (VecTy->getVectorKind() == VectorType::RVVFixedLengthDataVector || + VecTy->getVectorKind() == VectorType::GenericVector)) { + const LangOptions::LaxVectorConversionKind LVCKind = + getLangOpts().getLaxVectorConversions(); + + // If __riscv_v_fixed_vlen != N do not allow GNU vector lax conversion. + if (VecTy->getVectorKind() == VectorType::GenericVector && + getTypeSize(SecondType) != getRVVTypeSize(*this, BT)) + return false; + + // If -flax-vector-conversions=all is specified, the types are + // certainly compatible. + if (LVCKind == LangOptions::LaxVectorConversionKind::All) + return true; + + // If -flax-vector-conversions=integer is specified, the types are + // compatible if the elements are integer types. + if (LVCKind == LangOptions::LaxVectorConversionKind::Integer) + return VecTy->getElementType().getCanonicalType()->isIntegerType() && + FirstType->getRVVEltType(*this)->isIntegerType(); + } + + return false; + }; + + return IsLaxCompatible(FirstType, SecondType) || + IsLaxCompatible(SecondType, FirstType); +} + bool ASTContext::hasDirectOwnershipQualifier(QualType Ty) const { while (true) { // __strong id @@ -9894,6 +10026,9 @@ static bool sameObjCTypeArgs(ASTContext &ctx, return false; ObjCTypeParamList *typeParams = iface->getTypeParamList(); + if (!typeParams) + return false; + for (unsigned i = 0, n = lhsArgs.size(); i != n; ++i) { if (ctx.hasSameType(lhsArgs[i], rhsArgs[i])) continue; @@ -11295,6 +11430,17 @@ static QualType DecodeTypeFromStr(const char *&Str, const ASTContext &Context, Type = Context.getScalableVectorType(ElementType, NumElements); break; } + case 'Q': { + switch (*Str++) { + case 'a': { + Type = Context.SveCountTy; + break; + } + default: + llvm_unreachable("Unexpected target builtin type"); + } + break; + } case 'V': { char *End; unsigned NumElements = strtoul(Str, &End, 10); @@ -11492,9 +11638,8 @@ static GVALinkage basicGVALinkageForFunction(const ASTContext &Context, // Non-user-provided functions get emitted as weak definitions with every // use, no matter whether they've been explicitly instantiated etc. - if (const auto *MD = dyn_cast(FD)) - if (!MD->isUserProvided()) - return GVA_DiscardableODR; + if (!FD->isUserProvided()) + return GVA_DiscardableODR; GVALinkage External; switch (FD->getTemplateSpecializationKind()) { @@ -11683,7 +11828,7 @@ static GVALinkage basicGVALinkageForVariable(const ASTContext &Context, llvm_unreachable("Invalid Linkage!"); } -GVALinkage ASTContext::GetGVALinkageForVariable(const VarDecl *VD) { +GVALinkage ASTContext::GetGVALinkageForVariable(const VarDecl *VD) const { return adjustGVALinkageForExternalDefinitionKind(*this, VD, adjustGVALinkageForAttributes(*this, VD, basicGVALinkageForVariable(*this, VD))); @@ -11775,6 +11920,10 @@ bool ASTContext::DeclMustBeEmitted(const Decl *D) { !isMSStaticDataMemberInlineDefinition(VD)) return false; + // Variables in other module units shouldn't be forced to be emitted. + if (VD->isInAnotherModuleUnit()) + return false; + // Variables that can be needed in other TUs are required. auto Linkage = GetGVALinkageForVariable(VD); if (!isDiscardableGVALinkage(Linkage)) @@ -11818,7 +11967,7 @@ void ASTContext::forEachMultiversionedFunctionVersion( FD->getDeclContext()->getRedeclContext()->lookup(FD->getDeclName())) { FunctionDecl *CurFD = CurDecl->getAsFunction()->getMostRecentDecl(); if (CurFD && hasSameType(CurFD->getType(), FD->getType()) && - !llvm::is_contained(SeenDecls, CurFD)) { + !SeenDecls.contains(CurFD)) { SeenDecls.insert(CurFD); Pred(CurFD); } @@ -12921,8 +13070,10 @@ static QualType getCommonSugarTypeNode(ASTContext &Ctx, const Type *X, SmallVector As; if (CD && getCommonTemplateArguments(Ctx, As, AX->getTypeConstraintArguments(), - AY->getTypeConstraintArguments())) + AY->getTypeConstraintArguments())) { CD = nullptr; // The arguments differ, so make it unconstrained. + As.clear(); + } // Both auto types can't be dependent, otherwise they wouldn't have been // sugar. This implies they can't contain unexpanded packs either. @@ -13035,7 +13186,7 @@ static QualType getCommonSugarTypeNode(ASTContext &Ctx, const Type *X, static auto unwrapSugar(SplitQualType &T, Qualifiers &QTotal) { SmallVector R; while (true) { - QTotal += T.Quals; + QTotal.addConsistentQualifiers(T.Quals); QualType NT = T.Ty->getLocallyUnqualifiedSingleStepDesugaredType(); if (NT == QualType(T.Ty, 0)) break; @@ -13317,6 +13468,7 @@ std::vector ASTContext::filterFunctionTargetVersionAttrs( TV->getFeatures(Feats); for (auto &Feature : Feats) if (Target->validateCpuSupports(Feature.str())) + // Use '?' to mark features that came from TargetVersion. ResFeats.push_back("?" + Feature.str()); return ResFeats; } @@ -13386,6 +13538,7 @@ void ASTContext::getFunctionFeatureMap(llvm::StringMap &FeatureMap, VersionStr.split(VersionFeatures, "+"); for (auto &VFeature : VersionFeatures) { VFeature = VFeature.trim(); + // Use '?' to mark features that came from AArch64 TargetClones. Features.push_back((StringRef{"?"} + VFeature).str()); } } @@ -13424,16 +13577,17 @@ operator<<(const StreamingDiagnostic &DB, } bool ASTContext::mayExternalize(const Decl *D) const { - bool IsStaticVar = - isa(D) && cast(D)->getStorageClass() == SC_Static; + bool IsInternalVar = + isa(D) && + basicGVALinkageForVariable(*this, cast(D)) == GVA_Internal; bool IsExplicitDeviceVar = (D->hasAttr() && !D->getAttr()->isImplicit()) || (D->hasAttr() && !D->getAttr()->isImplicit()); - // CUDA/HIP: static managed variables need to be externalized since it is + // CUDA/HIP: managed variables need to be externalized since it is // a declaration in IR, therefore cannot have internal linkage. Kernels in // anonymous name space needs to be externalized to avoid duplicate symbols. - return (IsStaticVar && + return (IsInternalVar && (D->hasAttr() || IsExplicitDeviceVar)) || (D->hasAttr() && basicGVALinkageForFunction(*this, cast(D)) == diff --git a/contrib/llvm-project/clang/lib/AST/ASTDiagnostic.cpp b/contrib/llvm-project/clang/lib/AST/ASTDiagnostic.cpp index 08877aa12c0..f96a4fa3c35 100644 --- a/contrib/llvm-project/clang/lib/AST/ASTDiagnostic.cpp +++ b/contrib/llvm-project/clang/lib/AST/ASTDiagnostic.cpp @@ -25,7 +25,8 @@ using namespace clang; // Returns a desugared version of the QualType, and marks ShouldAKA as true -// whenever we remove significant sugar from the type. +// whenever we remove significant sugar from the type. Make sure ShouldAKA +// is initialized before passing it in. QualType clang::desugarForDiagnostic(ASTContext &Context, QualType QT, bool &ShouldAKA) { QualifierCollector QC; diff --git a/contrib/llvm-project/clang/lib/AST/ASTImporter.cpp b/contrib/llvm-project/clang/lib/AST/ASTImporter.cpp index 6f367ef053d..39c7a8fa397 100644 --- a/contrib/llvm-project/clang/lib/AST/ASTImporter.cpp +++ b/contrib/llvm-project/clang/lib/AST/ASTImporter.cpp @@ -433,6 +433,7 @@ namespace clang { Decl *From, DeclContext *&ToDC, DeclContext *&ToLexicalDC); Error ImportImplicitMethods(const CXXRecordDecl *From, CXXRecordDecl *To); + Error ImportFieldDeclDefinition(const FieldDecl *From, const FieldDecl *To); Expected ImportCastPath(CastExpr *E); Expected ImportAPValue(const APValue &FromValue); @@ -640,6 +641,7 @@ namespace clang { ExpectedStmt VisitBinaryOperator(BinaryOperator *E); ExpectedStmt VisitConditionalOperator(ConditionalOperator *E); ExpectedStmt VisitBinaryConditionalOperator(BinaryConditionalOperator *E); + ExpectedStmt VisitCXXRewrittenBinaryOperator(CXXRewrittenBinaryOperator *E); ExpectedStmt VisitOpaqueValueExpr(OpaqueValueExpr *E); ExpectedStmt VisitArrayTypeTraitExpr(ArrayTypeTraitExpr *E); ExpectedStmt VisitExpressionTraitExpr(ExpressionTraitExpr *E); @@ -836,7 +838,8 @@ ASTNodeImporter::import(const TemplateArgument &From) { ExpectedType ToTypeOrErr = import(From.getAsType()); if (!ToTypeOrErr) return ToTypeOrErr.takeError(); - return TemplateArgument(*ToTypeOrErr); + return TemplateArgument(*ToTypeOrErr, /*isNullPtr*/ false, + From.getIsDefaulted()); } case TemplateArgument::Integral: { @@ -853,14 +856,15 @@ ASTNodeImporter::import(const TemplateArgument &From) { ExpectedType ToTypeOrErr = import(From.getParamTypeForDecl()); if (!ToTypeOrErr) return ToTypeOrErr.takeError(); - return TemplateArgument(*ToOrErr, *ToTypeOrErr); + return TemplateArgument(*ToOrErr, *ToTypeOrErr, From.getIsDefaulted()); } case TemplateArgument::NullPtr: { ExpectedType ToTypeOrErr = import(From.getNullPtrType()); if (!ToTypeOrErr) return ToTypeOrErr.takeError(); - return TemplateArgument(*ToTypeOrErr, /*isNullPtr*/true); + return TemplateArgument(*ToTypeOrErr, /*isNullPtr*/ true, + From.getIsDefaulted()); } case TemplateArgument::Template: { @@ -868,7 +872,7 @@ ASTNodeImporter::import(const TemplateArgument &From) { if (!ToTemplateOrErr) return ToTemplateOrErr.takeError(); - return TemplateArgument(*ToTemplateOrErr); + return TemplateArgument(*ToTemplateOrErr, From.getIsDefaulted()); } case TemplateArgument::TemplateExpansion: { @@ -877,13 +881,13 @@ ASTNodeImporter::import(const TemplateArgument &From) { if (!ToTemplateOrErr) return ToTemplateOrErr.takeError(); - return TemplateArgument( - *ToTemplateOrErr, From.getNumTemplateExpansions()); + return TemplateArgument(*ToTemplateOrErr, From.getNumTemplateExpansions(), + From.getIsDefaulted()); } case TemplateArgument::Expression: if (ExpectedExpr ToExpr = import(From.getAsExpr())) - return TemplateArgument(*ToExpr); + return TemplateArgument(*ToExpr, From.getIsDefaulted()); else return ToExpr.takeError(); @@ -974,7 +978,8 @@ ASTNodeImporter::import(const Designator &D) { if (!ToFieldLocOrErr) return ToFieldLocOrErr.takeError(); - return Designator(ToFieldName, *ToDotLocOrErr, *ToFieldLocOrErr); + return DesignatedInitExpr::Designator::CreateFieldDesignator( + ToFieldName, *ToDotLocOrErr, *ToFieldLocOrErr); } ExpectedSLoc ToLBracketLocOrErr = import(D.getLBracketLoc()); @@ -986,16 +991,17 @@ ASTNodeImporter::import(const Designator &D) { return ToRBracketLocOrErr.takeError(); if (D.isArrayDesignator()) - return Designator(D.getFirstExprIndex(), - *ToLBracketLocOrErr, *ToRBracketLocOrErr); + return Designator::CreateArrayDesignator(D.getArrayIndex(), + *ToLBracketLocOrErr, + *ToRBracketLocOrErr); ExpectedSLoc ToEllipsisLocOrErr = import(D.getEllipsisLoc()); if (!ToEllipsisLocOrErr) return ToEllipsisLocOrErr.takeError(); assert(D.isArrayRangeDesignator()); - return Designator( - D.getFirstExprIndex(), *ToLBracketLocOrErr, *ToEllipsisLocOrErr, + return Designator::CreateArrayRangeDesignator( + D.getArrayIndex(), *ToLBracketLocOrErr, *ToEllipsisLocOrErr, *ToRBracketLocOrErr); } @@ -1094,6 +1100,10 @@ ExpectedType ASTNodeImporter::VisitBuiltinType(const BuiltinType *T) { case BuiltinType::Id: \ return Importer.getToContext().SingletonId; #include "clang/Basic/RISCVVTypes.def" +#define WASM_TYPE(Name, Id, SingletonId) \ + case BuiltinType::Id: \ + return Importer.getToContext().SingletonId; +#include "clang/Basic/WebAssemblyReferenceTypes.def" #define SHARED_SINGLETON_TYPE(Expansion) #define BUILTIN_TYPE(Id, SingletonId) \ case BuiltinType::Id: return Importer.getToContext().SingletonId; @@ -1357,12 +1367,16 @@ ExpectedType ASTNodeImporter::VisitTypedefType(const TypedefType *T) { Expected ToDeclOrErr = import(T->getDecl()); if (!ToDeclOrErr) return ToDeclOrErr.takeError(); + + TypedefNameDecl *ToDecl = *ToDeclOrErr; + if (ToDecl->getTypeForDecl()) + return QualType(ToDecl->getTypeForDecl(), 0); + ExpectedType ToUnderlyingTypeOrErr = import(T->desugar()); if (!ToUnderlyingTypeOrErr) return ToUnderlyingTypeOrErr.takeError(); - return Importer.getToContext().getTypedefType(*ToDeclOrErr, - *ToUnderlyingTypeOrErr); + return Importer.getToContext().getTypedefType(ToDecl, *ToUnderlyingTypeOrErr); } ExpectedType ASTNodeImporter::VisitTypeOfExprType(const TypeOfExprType *T) { @@ -1460,20 +1474,11 @@ ExpectedType ASTNodeImporter::VisitInjectedClassNameType( if (!ToDeclOrErr) return ToDeclOrErr.takeError(); - ExpectedType ToInjTypeOrErr = import(T->getInjectedSpecializationType()); - if (!ToInjTypeOrErr) - return ToInjTypeOrErr.takeError(); - - // FIXME: ASTContext::getInjectedClassNameType is not suitable for AST reading - // See comments in InjectedClassNameType definition for details - // return Importer.getToContext().getInjectedClassNameType(D, InjType); - enum { - TypeAlignmentInBits = 4, - TypeAlignment = 1 << TypeAlignmentInBits - }; - - return QualType(new (Importer.getToContext(), TypeAlignment) - InjectedClassNameType(*ToDeclOrErr, *ToInjTypeOrErr), 0); + // The InjectedClassNameType is created in VisitRecordDecl when the + // T->getDecl() is imported. Here we can return the existing type. + const Type *Ty = (*ToDeclOrErr)->getTypeForDecl(); + assert(Ty && isa(Ty)); + return QualType(Ty, 0); } ExpectedType ASTNodeImporter::VisitRecordType(const RecordType *T) { @@ -1846,52 +1851,33 @@ ASTNodeImporter::ImportDeclContext(DeclContext *FromDC, bool ForceImport) { // different values in two distinct translation units. ChildErrorHandlingStrategy HandleChildErrors(FromDC); + auto MightNeedReordering = [](const Decl *D) { + return isa(D) || isa(D) || isa(D); + }; + + // Import everything that might need reordering first. Error ChildErrors = Error::success(); for (auto *From : FromDC->decls()) { + if (!MightNeedReordering(From)) + continue; + ExpectedDecl ImportedOrErr = import(From); // If we are in the process of ImportDefinition(...) for a RecordDecl we // want to make sure that we are also completing each FieldDecl. There // are currently cases where this does not happen and this is correctness // fix since operations such as code generation will expect this to be so. - if (ImportedOrErr) { - FieldDecl *FieldFrom = dyn_cast_or_null(From); - Decl *ImportedDecl = *ImportedOrErr; - FieldDecl *FieldTo = dyn_cast_or_null(ImportedDecl); - if (FieldFrom && FieldTo) { - RecordDecl *FromRecordDecl = nullptr; - RecordDecl *ToRecordDecl = nullptr; - // If we have a field that is an ArrayType we need to check if the array - // element is a RecordDecl and if so we need to import the definition. - if (FieldFrom->getType()->isArrayType()) { - // getBaseElementTypeUnsafe(...) handles multi-dimensonal arrays for us. - FromRecordDecl = FieldFrom->getType()->getBaseElementTypeUnsafe()->getAsRecordDecl(); - ToRecordDecl = FieldTo->getType()->getBaseElementTypeUnsafe()->getAsRecordDecl(); - } - - if (!FromRecordDecl || !ToRecordDecl) { - const RecordType *RecordFrom = - FieldFrom->getType()->getAs(); - const RecordType *RecordTo = FieldTo->getType()->getAs(); - - if (RecordFrom && RecordTo) { - FromRecordDecl = RecordFrom->getDecl(); - ToRecordDecl = RecordTo->getDecl(); - } - } - - if (FromRecordDecl && ToRecordDecl) { - if (FromRecordDecl->isCompleteDefinition() && - !ToRecordDecl->isCompleteDefinition()) { - Error Err = ImportDefinition(FromRecordDecl, ToRecordDecl); - HandleChildErrors.handleChildImportResult(ChildErrors, - std::move(Err)); - } - } - } - } else { + if (!ImportedOrErr) { HandleChildErrors.handleChildImportResult(ChildErrors, ImportedOrErr.takeError()); + continue; + } + FieldDecl *FieldFrom = dyn_cast_or_null(From); + Decl *ImportedDecl = *ImportedOrErr; + FieldDecl *FieldTo = dyn_cast_or_null(ImportedDecl); + if (FieldFrom && FieldTo) { + Error Err = ImportFieldDeclDefinition(FieldFrom, FieldTo); + HandleChildErrors.handleChildImportResult(ChildErrors, std::move(Err)); } } @@ -1906,7 +1892,7 @@ ASTNodeImporter::ImportDeclContext(DeclContext *FromDC, bool ForceImport) { // During the import of `a` we import first the dependencies in sequence, // thus the order would be `c`, `b`, `a`. We will get the normal order by // first removing the already imported members and then adding them in the - // order as they apper in the "from" context. + // order as they appear in the "from" context. // // Keeping field order is vital because it determines structure layout. // @@ -1918,9 +1904,6 @@ ASTNodeImporter::ImportDeclContext(DeclContext *FromDC, bool ForceImport) { // interface in LLDB is implemented by the means of the ASTImporter. However, // calling an import at this point would result in an uncontrolled import, we // must avoid that. - const auto *FromRD = dyn_cast(FromDC); - if (!FromRD) - return ChildErrors; auto ToDCOrErr = Importer.ImportContext(FromDC); if (!ToDCOrErr) { @@ -1931,26 +1914,70 @@ ASTNodeImporter::ImportDeclContext(DeclContext *FromDC, bool ForceImport) { DeclContext *ToDC = *ToDCOrErr; // Remove all declarations, which may be in wrong order in the // lexical DeclContext and then add them in the proper order. - for (auto *D : FromRD->decls()) { - if (isa(D) || isa(D) || isa(D)) { - assert(D && "DC contains a null decl"); - Decl *ToD = Importer.GetAlreadyImportedOrNull(D); + for (auto *D : FromDC->decls()) { + if (!MightNeedReordering(D)) + continue; + + assert(D && "DC contains a null decl"); + if (Decl *ToD = Importer.GetAlreadyImportedOrNull(D)) { // Remove only the decls which we successfully imported. - if (ToD) { - assert(ToDC == ToD->getLexicalDeclContext() && ToDC->containsDecl(ToD)); - // Remove the decl from its wrong place in the linked list. - ToDC->removeDecl(ToD); - // Add the decl to the end of the linked list. - // This time it will be at the proper place because the enclosing for - // loop iterates in the original (good) order of the decls. - ToDC->addDeclInternal(ToD); - } + assert(ToDC == ToD->getLexicalDeclContext() && ToDC->containsDecl(ToD)); + // Remove the decl from its wrong place in the linked list. + ToDC->removeDecl(ToD); + // Add the decl to the end of the linked list. + // This time it will be at the proper place because the enclosing for + // loop iterates in the original (good) order of the decls. + ToDC->addDeclInternal(ToD); } } + // Import everything else. + for (auto *From : FromDC->decls()) { + if (MightNeedReordering(From)) + continue; + + ExpectedDecl ImportedOrErr = import(From); + if (!ImportedOrErr) + HandleChildErrors.handleChildImportResult(ChildErrors, + ImportedOrErr.takeError()); + } + return ChildErrors; } +Error ASTNodeImporter::ImportFieldDeclDefinition(const FieldDecl *From, + const FieldDecl *To) { + RecordDecl *FromRecordDecl = nullptr; + RecordDecl *ToRecordDecl = nullptr; + // If we have a field that is an ArrayType we need to check if the array + // element is a RecordDecl and if so we need to import the definition. + QualType FromType = From->getType(); + QualType ToType = To->getType(); + if (FromType->isArrayType()) { + // getBaseElementTypeUnsafe(...) handles multi-dimensonal arrays for us. + FromRecordDecl = FromType->getBaseElementTypeUnsafe()->getAsRecordDecl(); + ToRecordDecl = ToType->getBaseElementTypeUnsafe()->getAsRecordDecl(); + } + + if (!FromRecordDecl || !ToRecordDecl) { + const RecordType *RecordFrom = FromType->getAs(); + const RecordType *RecordTo = ToType->getAs(); + + if (RecordFrom && RecordTo) { + FromRecordDecl = RecordFrom->getDecl(); + ToRecordDecl = RecordTo->getDecl(); + } + } + + if (FromRecordDecl && ToRecordDecl) { + if (FromRecordDecl->isCompleteDefinition() && + !ToRecordDecl->isCompleteDefinition()) + return ImportDefinition(FromRecordDecl, ToRecordDecl); + } + + return Error::success(); +} + Error ASTNodeImporter::ImportDeclContext( Decl *FromD, DeclContext *&ToDC, DeclContext *&ToLexicalDC) { auto ToDCOrErr = Importer.ImportContext(FromD->getDeclContext()); @@ -2512,6 +2539,22 @@ ASTNodeImporter::VisitTypedefNameDecl(TypedefNameDecl *D, bool IsAlias) { QualType FromUT = D->getUnderlyingType(); QualType FoundUT = FoundTypedef->getUnderlyingType(); if (Importer.IsStructurallyEquivalent(FromUT, FoundUT)) { + // If the underlying declarations are unnamed records these can be + // imported as different types. We should create a distinct typedef + // node in this case. + // If we found an existing underlying type with a record in a + // different context (than the imported), this is already reason for + // having distinct typedef nodes for these. + // Again this can create situation like + // 'typedef int T; typedef int T;' but this is hard to avoid without + // a rename strategy at import. + if (!FromUT.isNull() && !FoundUT.isNull()) { + RecordDecl *FromR = FromUT->getAsRecordDecl(); + RecordDecl *FoundR = FoundUT->getAsRecordDecl(); + if (FromR && FoundR && + !hasSameVisibilityContextAndLinkage(FoundR, FromR)) + continue; + } // If the "From" context has a complete underlying type but we // already have a complete underlying type then return with that. if (!FromUT->isIncompleteType() && !FoundUT->isIncompleteType()) @@ -2906,13 +2949,12 @@ ExpectedDecl ASTNodeImporter::VisitRecordDecl(RecordDecl *D) { DC, *TInfoOrErr, Loc, DCXX->getLambdaDependencyKind(), DCXX->isGenericLambda(), DCXX->getLambdaCaptureDefault())) return D2CXX; - ExpectedDecl CDeclOrErr = import(DCXX->getLambdaContextDecl()); + CXXRecordDecl::LambdaNumbering Numbering = DCXX->getLambdaNumbering(); + ExpectedDecl CDeclOrErr = import(Numbering.ContextDecl); if (!CDeclOrErr) return CDeclOrErr.takeError(); - D2CXX->setLambdaMangling(DCXX->getLambdaManglingNumber(), *CDeclOrErr, - DCXX->hasKnownLambdaInternalLinkage()); - D2CXX->setDeviceLambdaManglingNumber( - DCXX->getDeviceLambdaManglingNumber()); + Numbering.ContextDecl = *CDeclOrErr; + D2CXX->setLambdaNumbering(Numbering); } else if (DCXX->isInjectedClassName()) { // We have to be careful to do a similar dance to the one in // Sema::ActOnStartCXXMemberDeclarations @@ -2948,8 +2990,6 @@ ExpectedDecl ASTNodeImporter::VisitRecordDecl(RecordDecl *D) { // InjectedClassNameType (see Sema::CheckClassTemplate). Update the // previously set type to the correct value here (ToDescribed is not // available at record create). - // FIXME: The previous type is cleared but not removed from - // ASTContext's internal storage. CXXRecordDecl *Injected = nullptr; for (NamedDecl *Found : D2CXX->noload_lookup(Name)) { auto *Record = dyn_cast(Found); @@ -2959,20 +2999,34 @@ ExpectedDecl ASTNodeImporter::VisitRecordDecl(RecordDecl *D) { } } // Create an injected type for the whole redecl chain. + // The chain may contain an already existing injected type at the start, + // if yes this should be reused. We must ensure that only one type + // object exists for the injected type (including the injected record + // declaration), ASTContext does not check it. SmallVector Redecls = getCanonicalForwardRedeclChain(D2CXX); + const Type *FrontTy = + cast(Redecls.front())->getTypeForDecl(); + QualType InjSpec; + if (auto *InjTy = FrontTy->getAs()) + InjSpec = InjTy->getInjectedSpecializationType(); + else + InjSpec = ToDescribed->getInjectedClassNameSpecialization(); for (auto *R : Redecls) { auto *RI = cast(R); - RI->setTypeForDecl(nullptr); - // Below we create a new injected type and assign that to the - // canonical decl, subsequent declarations in the chain will reuse - // that type. - Importer.getToContext().getInjectedClassNameType( - RI, ToDescribed->getInjectedClassNameSpecialization()); + if (R != Redecls.front() || + !isa(RI->getTypeForDecl())) + RI->setTypeForDecl(nullptr); + // This function tries to get the injected type from getTypeForDecl, + // then from the previous declaration if possible. If not, it creates + // a new type. + Importer.getToContext().getInjectedClassNameType(RI, InjSpec); } - // Set the new type for the previous injected decl too. + // Set the new type for the injected decl too. if (Injected) { Injected->setTypeForDecl(nullptr); + // This function will copy the injected type from D2CXX into Injected. + // The injected decl does not have a previous decl to copy from. Importer.getToContext().getTypeDeclType(Injected, D2CXX); } } @@ -3668,7 +3722,7 @@ ExpectedDecl ASTNodeImporter::VisitFunctionDecl(FunctionDecl *D) { NameInfo, T, TInfo, ToEndLoc, Ctor)) return ToFunction; cast(ToFunction) - ->setIsCopyDeductionCandidate(Guide->isCopyDeductionCandidate()); + ->setDeductionCandidateKind(Guide->getDeductionCandidateKind()); } else { if (GetImportedOrCreateDecl( ToFunction, D, Importer.getToContext(), DC, ToInnerLocStart, @@ -3751,6 +3805,11 @@ ExpectedDecl ASTNodeImporter::VisitFunctionDecl(FunctionDecl *D) { if (Error Err = ImportTemplateInformation(D, ToFunction)) return std::move(Err); + if (auto *FromCXXMethod = dyn_cast(D)) + if (Error Err = ImportOverriddenMethods(cast(ToFunction), + FromCXXMethod)) + return std::move(Err); + if (D->doesThisDeclarationHaveABody()) { Error Err = ImportFunctionDeclBody(D, ToFunction); @@ -3774,11 +3833,6 @@ ExpectedDecl ASTNodeImporter::VisitFunctionDecl(FunctionDecl *D) { addDeclToContexts(D, ToFunction); - if (auto *FromCXXMethod = dyn_cast(D)) - if (Error Err = ImportOverriddenMethods(cast(ToFunction), - FromCXXMethod)) - return std::move(Err); - // Import the rest of the chain. I.e. import all subsequent declarations. for (++RedeclIt; RedeclIt != Redecls.end(); ++RedeclIt) { ExpectedDecl ToRedeclOrErr = import(*RedeclIt); @@ -3886,6 +3940,12 @@ ExpectedDecl ASTNodeImporter::VisitFieldDecl(FieldDecl *D) { D->getInClassInitStyle())) return ToField; + // We need [[no_unqiue_address]] attributes to be added to FieldDecl, before + // we add fields in CXXRecordDecl::addedMember, otherwise record will be + // marked as having non-zero size. + Err = Importer.ImportAttrs(ToField, D); + if (Err) + return std::move(Err); ToField->setAccess(D->getAccess()); ToField->setLexicalDeclContext(LexicalDC); if (ToInitializer) @@ -6762,8 +6822,8 @@ ExpectedStmt ASTNodeImporter::VisitCXXTryStmt(CXXTryStmt *S) { return ToHandlerOrErr.takeError(); } - return CXXTryStmt::Create( - Importer.getToContext(), *ToTryLocOrErr,*ToTryBlockOrErr, ToHandlers); + return CXXTryStmt::Create(Importer.getToContext(), *ToTryLocOrErr, + cast(*ToTryBlockOrErr), ToHandlers); } ExpectedStmt ASTNodeImporter::VisitCXXForRangeStmt(CXXForRangeStmt *S) { @@ -6992,7 +7052,14 @@ ExpectedStmt ASTNodeImporter::VisitGenericSelectionExpr(GenericSelectionExpr *E) { Error Err = Error::success(); auto ToGenericLoc = importChecked(Err, E->getGenericLoc()); - auto *ToControllingExpr = importChecked(Err, E->getControllingExpr()); + Expr *ToControllingExpr = nullptr; + TypeSourceInfo *ToControllingType = nullptr; + if (E->isExprPredicate()) + ToControllingExpr = importChecked(Err, E->getControllingExpr()); + else + ToControllingType = importChecked(Err, E->getControllingType()); + assert((ToControllingExpr || ToControllingType) && + "Either the controlling expr or type must be nonnull"); auto ToDefaultLoc = importChecked(Err, E->getDefaultLoc()); auto ToRParenLoc = importChecked(Err, E->getRParenLoc()); if (Err) @@ -7010,14 +7077,26 @@ ASTNodeImporter::VisitGenericSelectionExpr(GenericSelectionExpr *E) { const ASTContext &ToCtx = Importer.getToContext(); if (E->isResultDependent()) { + if (ToControllingExpr) { + return GenericSelectionExpr::Create( + ToCtx, ToGenericLoc, ToControllingExpr, llvm::ArrayRef(ToAssocTypes), + llvm::ArrayRef(ToAssocExprs), ToDefaultLoc, ToRParenLoc, + E->containsUnexpandedParameterPack()); + } return GenericSelectionExpr::Create( - ToCtx, ToGenericLoc, ToControllingExpr, llvm::ArrayRef(ToAssocTypes), + ToCtx, ToGenericLoc, ToControllingType, llvm::ArrayRef(ToAssocTypes), llvm::ArrayRef(ToAssocExprs), ToDefaultLoc, ToRParenLoc, E->containsUnexpandedParameterPack()); } + if (ToControllingExpr) { + return GenericSelectionExpr::Create( + ToCtx, ToGenericLoc, ToControllingExpr, llvm::ArrayRef(ToAssocTypes), + llvm::ArrayRef(ToAssocExprs), ToDefaultLoc, ToRParenLoc, + E->containsUnexpandedParameterPack(), E->getResultIndex()); + } return GenericSelectionExpr::Create( - ToCtx, ToGenericLoc, ToControllingExpr, llvm::ArrayRef(ToAssocTypes), + ToCtx, ToGenericLoc, ToControllingType, llvm::ArrayRef(ToAssocTypes), llvm::ArrayRef(ToAssocExprs), ToDefaultLoc, ToRParenLoc, E->containsUnexpandedParameterPack(), E->getResultIndex()); } @@ -7032,7 +7111,8 @@ ExpectedStmt ASTNodeImporter::VisitPredefinedExpr(PredefinedExpr *E) { return std::move(Err); return PredefinedExpr::Create(Importer.getToContext(), ToBeginLoc, ToType, - E->getIdentKind(), ToFunctionName); + E->getIdentKind(), E->isTransparent(), + ToFunctionName); } ExpectedStmt ASTNodeImporter::VisitDeclRefExpr(DeclRefExpr *E) { @@ -7070,6 +7150,7 @@ ExpectedStmt ASTNodeImporter::VisitDeclRefExpr(DeclRefExpr *E) { E->getValueKind(), ToFoundD, ToResInfo, E->isNonOdrUse()); if (E->hadMultipleCandidates()) ToE->setHadMultipleCandidates(true); + ToE->setIsImmediateEscalating(E->isImmediateEscalating()); return ToE; } @@ -7399,6 +7480,17 @@ ASTNodeImporter::VisitBinaryConditionalOperator(BinaryConditionalOperator *E) { E->getObjectKind()); } +ExpectedStmt ASTNodeImporter::VisitCXXRewrittenBinaryOperator( + CXXRewrittenBinaryOperator *E) { + Error Err = Error::success(); + auto ToSemanticForm = importChecked(Err, E->getSemanticForm()); + if (Err) + return std::move(Err); + + return new (Importer.getToContext()) + CXXRewrittenBinaryOperator(ToSemanticForm, E->isReversed()); +} + ExpectedStmt ASTNodeImporter::VisitArrayTypeTraitExpr(ArrayTypeTraitExpr *E) { Error Err = Error::success(); auto ToBeginLoc = importChecked(Err, E->getBeginLoc()); @@ -7887,12 +7979,14 @@ ExpectedStmt ASTNodeImporter::VisitCXXConstructExpr(CXXConstructExpr *E) { if (Error Err = ImportContainerChecked(E->arguments(), ToArgs)) return std::move(Err); - return CXXConstructExpr::Create( + CXXConstructExpr *ToE = CXXConstructExpr::Create( Importer.getToContext(), ToType, ToLocation, ToConstructor, E->isElidable(), ToArgs, E->hadMultipleCandidates(), E->isListInitialization(), E->isStdInitListInitialization(), E->requiresZeroInitialization(), E->getConstructionKind(), ToParenOrBraceRange); + ToE->setIsImmediateEscalating(E->isImmediateEscalating()); + return ToE; } ExpectedStmt ASTNodeImporter::VisitExprWithCleanups(ExprWithCleanups *E) { @@ -8111,7 +8205,7 @@ ExpectedStmt ASTNodeImporter::VisitCXXUnresolvedConstructExpr( return CXXUnresolvedConstructExpr::Create( Importer.getToContext(), ToType, ToTypeSourceInfo, ToLParenLoc, - llvm::ArrayRef(ToArgs), ToRParenLoc); + llvm::ArrayRef(ToArgs), ToRParenLoc, E->isListInitialization()); } ExpectedStmt @@ -8779,8 +8873,7 @@ public: return; AttributeCommonInfo ToI(ToAttrName, ToScopeName, ToAttrRange, ToScopeLoc, - FromAttr->getParsedKind(), FromAttr->getSyntax(), - FromAttr->getAttributeSpellingListIndex()); + FromAttr->getParsedKind(), FromAttr->getForm()); // The "SemanticSpelling" is not needed to be passed to the constructor. // That value is recalculated from the SpellingListIndex if needed. ToAttr = T::Create(Importer.getToContext(), @@ -8958,11 +9051,7 @@ Expected ASTImporter::Import(const Attr *FromAttr) { } Decl *ASTImporter::GetAlreadyImportedOrNull(const Decl *FromD) const { - auto Pos = ImportedDecls.find(FromD); - if (Pos != ImportedDecls.end()) - return Pos->second; - else - return nullptr; + return ImportedDecls.lookup(FromD); } TranslationUnitDecl *ASTImporter::GetFromTU(Decl *ToD) { @@ -8972,6 +9061,19 @@ TranslationUnitDecl *ASTImporter::GetFromTU(Decl *ToD) { return FromDPos->second->getTranslationUnitDecl(); } +Error ASTImporter::ImportAttrs(Decl *ToD, Decl *FromD) { + if (!FromD->hasAttrs() || ToD->hasAttrs()) + return Error::success(); + for (const Attr *FromAttr : FromD->getAttrs()) { + auto ToAttrOrErr = Import(FromAttr); + if (ToAttrOrErr) + ToD->addAttr(*ToAttrOrErr); + else + return ToAttrOrErr.takeError(); + } + return Error::success(); +} + Expected ASTImporter::Import(Decl *FromD) { if (!FromD) return nullptr; @@ -9106,15 +9208,8 @@ Expected ASTImporter::Import(Decl *FromD) { // Make sure that ImportImpl registered the imported decl. assert(ImportedDecls.count(FromD) != 0 && "Missing call to MapImported?"); - - if (FromD->hasAttrs()) - for (const Attr *FromAttr : FromD->getAttrs()) { - auto ToAttrOrErr = Import(FromAttr); - if (ToAttrOrErr) - ToD->addAttr(*ToAttrOrErr); - else - return ToAttrOrErr.takeError(); - } + if (auto Error = ImportAttrs(ToD, FromD)) + return std::move(Error); // Notify subclasses. Imported(FromD, ToD); @@ -9376,7 +9471,7 @@ Expected ASTImporter::Import(TemplateName From) { switch (From.getKind()) { case TemplateName::Template: if (ExpectedDecl ToTemplateOrErr = Import(From.getAsTemplateDecl())) - return TemplateName(cast(*ToTemplateOrErr)); + return TemplateName(cast((*ToTemplateOrErr)->getCanonicalDecl())); else return ToTemplateOrErr.takeError(); diff --git a/contrib/llvm-project/clang/lib/AST/ASTImporterLookupTable.cpp b/contrib/llvm-project/clang/lib/AST/ASTImporterLookupTable.cpp index b7d17a5e92d..07d39dcee25 100644 --- a/contrib/llvm-project/clang/lib/AST/ASTImporterLookupTable.cpp +++ b/contrib/llvm-project/clang/lib/AST/ASTImporterLookupTable.cpp @@ -67,6 +67,8 @@ struct Builder : RecursiveASTVisitor { } else if (isa(Ty)) { // We do not put friend typedefs to the lookup table because // ASTImporter does not organize typedefs into redecl chains. + } else if (isa(Ty)) { + // Similar to TypedefType, not putting into lookup table. } else { llvm_unreachable("Unhandled type of friend class"); } @@ -85,6 +87,18 @@ struct Builder : RecursiveASTVisitor { ASTImporterLookupTable::ASTImporterLookupTable(TranslationUnitDecl &TU) { Builder B(*this); B.TraverseDecl(&TU); + // The VaList declaration may be created on demand only or not traversed. + // To ensure it is present and found during import, add it to the table now. + if (auto *D = + dyn_cast_or_null(TU.getASTContext().getVaListTagDecl())) { + // On some platforms (AArch64) the VaList declaration can be inside a 'std' + // namespace. This is handled specially and not visible by AST traversal. + // ASTImporter must be able to find this namespace to import the VaList + // declaration (and the namespace) correctly. + if (auto *Ns = dyn_cast(D->getDeclContext())) + add(&TU, Ns); + add(D->getDeclContext(), D); + } } void ASTImporterLookupTable::add(DeclContext *DC, NamedDecl *ND) { diff --git a/contrib/llvm-project/clang/lib/AST/ASTStructuralEquivalence.cpp b/contrib/llvm-project/clang/lib/AST/ASTStructuralEquivalence.cpp index ba7dfc35edf..f867b6bf84b 100644 --- a/contrib/llvm-project/clang/lib/AST/ASTStructuralEquivalence.cpp +++ b/contrib/llvm-project/clang/lib/AST/ASTStructuralEquivalence.cpp @@ -1453,19 +1453,23 @@ static bool IsRecordContextStructurallyEquivalent(RecordDecl *D1, return true; } +static bool NameIsStructurallyEquivalent(const TagDecl &D1, const TagDecl &D2) { + auto GetName = [](const TagDecl &D) -> const IdentifierInfo * { + if (const IdentifierInfo *Name = D.getIdentifier()) + return Name; + if (const TypedefNameDecl *TypedefName = D.getTypedefNameForAnonDecl()) + return TypedefName->getIdentifier(); + return nullptr; + }; + return IsStructurallyEquivalent(GetName(D1), GetName(D2)); +} + /// Determine structural equivalence of two records. static bool IsStructurallyEquivalent(StructuralEquivalenceContext &Context, RecordDecl *D1, RecordDecl *D2) { - - // Check for equivalent structure names. - IdentifierInfo *Name1 = D1->getIdentifier(); - if (!Name1 && D1->getTypedefNameForAnonDecl()) - Name1 = D1->getTypedefNameForAnonDecl()->getIdentifier(); - IdentifierInfo *Name2 = D2->getIdentifier(); - if (!Name2 && D2->getTypedefNameForAnonDecl()) - Name2 = D2->getTypedefNameForAnonDecl()->getIdentifier(); - if (!IsStructurallyEquivalent(Name1, Name2)) + if (!NameIsStructurallyEquivalent(*D1, *D2)) { return false; + } if (D1->isUnion() != D2->isUnion()) { if (Context.Complain) { @@ -1727,16 +1731,9 @@ static bool IsStructurallyEquivalent(StructuralEquivalenceContext &Context, /// Determine structural equivalence of two enums. static bool IsStructurallyEquivalent(StructuralEquivalenceContext &Context, EnumDecl *D1, EnumDecl *D2) { - - // Check for equivalent enum names. - IdentifierInfo *Name1 = D1->getIdentifier(); - if (!Name1 && D1->getTypedefNameForAnonDecl()) - Name1 = D1->getTypedefNameForAnonDecl()->getIdentifier(); - IdentifierInfo *Name2 = D2->getIdentifier(); - if (!Name2 && D2->getTypedefNameForAnonDecl()) - Name2 = D2->getTypedefNameForAnonDecl()->getIdentifier(); - if (!IsStructurallyEquivalent(Name1, Name2)) + if (!NameIsStructurallyEquivalent(*D1, *D2)) { return false; + } // Compare the definitions of these two enums. If either or both are // incomplete (i.e. forward declared), we assume that they are equivalent. @@ -2060,8 +2057,13 @@ static bool IsStructurallyEquivalent(StructuralEquivalenceContext &Context, if (!IsStructurallyEquivalent(D1->getIdentifier(), D2->getIdentifier())) return false; - if (!IsStructurallyEquivalent(D1->getClassInterface()->getIdentifier(), - D2->getClassInterface()->getIdentifier())) + const ObjCInterfaceDecl *Intf1 = D1->getClassInterface(), + *Intf2 = D2->getClassInterface(); + if ((!Intf1 || !Intf2) && (Intf1 != Intf2)) + return false; + + if (Intf1 && + !IsStructurallyEquivalent(Intf1->getIdentifier(), Intf2->getIdentifier())) return false; // Compare protocols. @@ -2080,7 +2082,8 @@ static bool IsStructurallyEquivalent(StructuralEquivalenceContext &Context, return false; // Compare ivars. - QualType D2Type = Context.ToCtx.getObjCInterfaceType(D2->getClassInterface()); + QualType D2Type = + Intf2 ? Context.ToCtx.getObjCInterfaceType(Intf2) : QualType(); ObjCCategoryDecl::ivar_iterator Ivar2 = D2->ivar_begin(), Ivar2End = D2->ivar_end(); for (ObjCCategoryDecl::ivar_iterator Ivar1 = D1->ivar_begin(), diff --git a/contrib/llvm-project/clang/lib/AST/ASTTypeTraits.cpp b/contrib/llvm-project/clang/lib/AST/ASTTypeTraits.cpp index 64823f77e58..fb9fe39e777 100644 --- a/contrib/llvm-project/clang/lib/AST/ASTTypeTraits.cpp +++ b/contrib/llvm-project/clang/lib/AST/ASTTypeTraits.cpp @@ -56,10 +56,23 @@ const ASTNodeKind::KindInfo ASTNodeKind::AllKindInfo[] = { {NKI_None, "ObjCProtocolLoc"}, }; +bool ASTNodeKind::isBaseOf(ASTNodeKind Other) const { + return isBaseOf(KindId, Other.KindId); +} + bool ASTNodeKind::isBaseOf(ASTNodeKind Other, unsigned *Distance) const { return isBaseOf(KindId, Other.KindId, Distance); } +bool ASTNodeKind::isBaseOf(NodeKindId Base, NodeKindId Derived) { + if (Base == NKI_None || Derived == NKI_None) + return false; + while (Derived != Base && Derived != NKI_None) { + Derived = AllKindInfo[Derived].ParentId; + } + return Derived == Base; +} + bool ASTNodeKind::isBaseOf(NodeKindId Base, NodeKindId Derived, unsigned *Distance) { if (Base == NKI_None || Derived == NKI_None) return false; @@ -96,7 +109,7 @@ ASTNodeKind ASTNodeKind::getMostDerivedType(ASTNodeKind Kind1, ASTNodeKind ASTNodeKind::getMostDerivedCommonAncestor(ASTNodeKind Kind1, ASTNodeKind Kind2) { NodeKindId Parent = Kind1.KindId; - while (!isBaseOf(Parent, Kind2.KindId, nullptr) && Parent != NKI_None) { + while (!isBaseOf(Parent, Kind2.KindId) && Parent != NKI_None) { Parent = AllKindInfo[Parent].ParentId; } return ASTNodeKind(Parent); diff --git a/contrib/llvm-project/clang/lib/AST/AttrImpl.cpp b/contrib/llvm-project/clang/lib/AST/AttrImpl.cpp index 0adcca7731d..f198a9acf84 100644 --- a/contrib/llvm-project/clang/lib/AST/AttrImpl.cpp +++ b/contrib/llvm-project/clang/lib/AST/AttrImpl.cpp @@ -151,14 +151,16 @@ void OMPDeclareTargetDeclAttr::printPrettyPragma( std::optional OMPDeclareTargetDeclAttr::getActiveAttr(const ValueDecl *VD) { - if (!VD->hasAttrs()) + if (llvm::all_of(VD->redecls(), [](const Decl *D) { return !D->hasAttrs(); })) return std::nullopt; unsigned Level = 0; OMPDeclareTargetDeclAttr *FoundAttr = nullptr; - for (auto *Attr : VD->specific_attrs()) { - if (Level <= Attr->getLevel()) { - Level = Attr->getLevel(); - FoundAttr = Attr; + for (const Decl *D : VD->redecls()) { + for (auto *Attr : D->specific_attrs()) { + if (Level <= Attr->getLevel()) { + Level = Attr->getLevel(); + FoundAttr = Attr; + } } } if (FoundAttr) @@ -239,4 +241,33 @@ void OMPDeclareVariantAttr::printPrettyPragma( } } +unsigned AlignedAttr::getAlignment(ASTContext &Ctx) const { + assert(!isAlignmentDependent()); + if (getCachedAlignmentValue()) + return *getCachedAlignmentValue(); + + // Handle alignmentType case. + if (!isAlignmentExpr()) { + QualType T = getAlignmentType()->getType(); + + // C++ [expr.alignof]p3: + // When alignof is applied to a reference type, the result is the + // alignment of the referenced type. + T = T.getNonReferenceType(); + + if (T.getQualifiers().hasUnaligned()) + return Ctx.getCharWidth(); + + return Ctx.getTypeAlignInChars(T.getTypePtr()).getQuantity() * + Ctx.getCharWidth(); + } + + // Handle alignmentExpr case. + if (alignmentExpr) + return alignmentExpr->EvaluateKnownConstInt(Ctx).getZExtValue() * + Ctx.getCharWidth(); + + return Ctx.getTargetDefaultAlignForAttributeAligned(); +} + #include "clang/AST/AttrImpl.inc" diff --git a/contrib/llvm-project/clang/lib/AST/CXXInheritance.cpp b/contrib/llvm-project/clang/lib/AST/CXXInheritance.cpp index 1abbe8139ae..25de2a20a7f 100644 --- a/contrib/llvm-project/clang/lib/AST/CXXInheritance.cpp +++ b/contrib/llvm-project/clang/lib/AST/CXXInheritance.cpp @@ -80,7 +80,8 @@ bool CXXRecordDecl::isDerivedFrom(const CXXRecordDecl *Base, const CXXRecordDecl *BaseDecl = Base->getCanonicalDecl(); return lookupInBases( [BaseDecl](const CXXBaseSpecifier *Specifier, CXXBasePath &Path) { - return FindBaseClass(Specifier, Path, BaseDecl); + return Specifier->getType()->getAsRecordDecl() && + FindBaseClass(Specifier, Path, BaseDecl); }, Paths); } diff --git a/contrib/llvm-project/clang/lib/AST/ComputeDependence.cpp b/contrib/llvm-project/clang/lib/AST/ComputeDependence.cpp index b5c783b07d9..09df5401d66 100644 --- a/contrib/llvm-project/clang/lib/AST/ComputeDependence.cpp +++ b/contrib/llvm-project/clang/lib/AST/ComputeDependence.cpp @@ -227,7 +227,7 @@ ExprDependence clang::computeDependence(VAArgExpr *E) { auto D = toExprDependenceAsWritten( E->getWrittenTypeInfo()->getType()->getDependence()) | (E->getSubExpr()->getDependence() & ~ExprDependence::Type); - return D & ~ExprDependence::Value; + return D; } ExprDependence clang::computeDependence(NoInitExpr *E) { @@ -611,9 +611,24 @@ ExprDependence clang::computeDependence(OffsetOfExpr *E) { return D; } +static inline ExprDependence getDependenceInExpr(DeclarationNameInfo Name) { + auto D = ExprDependence::None; + if (Name.isInstantiationDependent()) + D |= ExprDependence::Instantiation; + if (Name.containsUnexpandedParameterPack()) + D |= ExprDependence::UnexpandedPack; + return D; +} + ExprDependence clang::computeDependence(MemberExpr *E) { - auto *MemberDecl = E->getMemberDecl(); auto D = E->getBase()->getDependence(); + D |= getDependenceInExpr(E->getMemberNameInfo()); + + if (auto *NNS = E->getQualifier()) + D |= toExprDependence(NNS->getDependence() & + ~NestedNameSpecifierDependence::Dependent); + + auto *MemberDecl = E->getMemberDecl(); if (FieldDecl *FD = dyn_cast(MemberDecl)) { DeclContext *DC = MemberDecl->getDeclContext(); // dyn_cast_or_null is used to handle objC variables which do not @@ -653,7 +668,12 @@ ExprDependence clang::computeDependence(GenericSelectionExpr *E, : ExprDependence::None; for (auto *AE : E->getAssocExprs()) D |= AE->getDependence() & ExprDependence::Error; - D |= E->getControllingExpr()->getDependence() & ExprDependence::Error; + + if (E->isExprPredicate()) + D |= E->getControllingExpr()->getDependence() & ExprDependence::Error; + else + D |= toExprDependenceAsWritten( + E->getControllingType()->getType()->getDependence()); if (E->isResultDependent()) return D | ExprDependence::TypeValueInstantiation; @@ -663,7 +683,7 @@ ExprDependence clang::computeDependence(GenericSelectionExpr *E, ExprDependence clang::computeDependence(DesignatedInitExpr *E) { auto Deps = E->getInit()->getDependence(); - for (auto D : E->designators()) { + for (const auto &D : E->designators()) { auto DesignatorDeps = ExprDependence::None; if (D.isArrayDesignator()) DesignatorDeps |= E->getArrayIndex(D)->getDependence(); @@ -718,15 +738,6 @@ ExprDependence clang::computeDependence(CXXPseudoDestructorExpr *E) { return D; } -static inline ExprDependence getDependenceInExpr(DeclarationNameInfo Name) { - auto D = ExprDependence::None; - if (Name.isInstantiationDependent()) - D |= ExprDependence::Instantiation; - if (Name.containsUnexpandedParameterPack()) - D |= ExprDependence::UnexpandedPack; - return D; -} - ExprDependence clang::computeDependence(OverloadExpr *E, bool KnownDependent, bool KnownInstantiationDependent, @@ -750,7 +761,7 @@ clang::computeDependence(OverloadExpr *E, bool KnownDependent, // If we have explicit template arguments, check for dependent // template arguments and whether they contain any unexpanded pack // expansions. - for (auto A : E->template_arguments()) + for (const auto &A : E->template_arguments()) Deps |= toExprDependence(A.getArgument().getDependence()); return Deps; } @@ -760,7 +771,7 @@ ExprDependence clang::computeDependence(DependentScopeDeclRefExpr *E) { D |= getDependenceInExpr(E->getNameInfo()); if (auto *Q = E->getQualifier()) D |= toExprDependence(Q->getDependence()); - for (auto A : E->template_arguments()) + for (const auto &A : E->template_arguments()) D |= toExprDependence(A.getArgument().getDependence()); return D; } @@ -813,7 +824,7 @@ ExprDependence clang::computeDependence(CXXDependentScopeMemberExpr *E) { if (auto *Q = E->getQualifier()) D |= toExprDependence(Q->getDependence()); D |= getDependenceInExpr(E->getMemberNameInfo()); - for (auto A : E->template_arguments()) + for (const auto &A : E->template_arguments()) D |= toExprDependence(A.getArgument().getDependence()); return D; } diff --git a/contrib/llvm-project/clang/lib/AST/Decl.cpp b/contrib/llvm-project/clang/lib/AST/Decl.cpp index 6f4c5192b7b..fbc45fb6397 100644 --- a/contrib/llvm-project/clang/lib/AST/Decl.cpp +++ b/contrib/llvm-project/clang/lib/AST/Decl.cpp @@ -58,10 +58,10 @@ #include "llvm/ADT/SmallVector.h" #include "llvm/ADT/StringRef.h" #include "llvm/ADT/StringSwitch.h" -#include "llvm/ADT/Triple.h" #include "llvm/Support/Casting.h" #include "llvm/Support/ErrorHandling.h" #include "llvm/Support/raw_ostream.h" +#include "llvm/TargetParser/Triple.h" #include #include #include @@ -600,33 +600,13 @@ static bool isExportedFromModuleInterfaceUnit(const NamedDecl *D) { llvm_unreachable("unexpected module ownership kind"); } -static LinkageInfo getInternalLinkageFor(const NamedDecl *D) { - // (for the modules ts) Internal linkage declarations within a module - // interface unit are modeled as "module-internal linkage", which means that - // they have internal linkage formally but can be indirectly accessed from - // outside the module via inline functions and templates defined within the - // module. - if (isInModulePurview(D) && D->getASTContext().getLangOpts().ModulesTS) - return LinkageInfo(ModuleInternalLinkage, DefaultVisibility, false); - - return LinkageInfo::internal(); +static bool isDeclaredInModuleInterfaceOrPartition(const NamedDecl *D) { + if (auto *M = D->getOwningModule()) + return M->isInterfaceOrPartition(); + return false; } static LinkageInfo getExternalLinkageFor(const NamedDecl *D) { - // C++ Modules TS [basic.link]/6.8: - // - A name declared at namespace scope that does not have internal linkage - // by the previous rules and that is introduced by a non-exported - // declaration has module linkage. - // - // [basic.namespace.general]/p2 - // A namespace is never attached to a named module and never has a name with - // module linkage. - if (isInModulePurview(D) && - !isExportedFromModuleInterfaceUnit( - cast(D->getCanonicalDecl())) && - !isa(D)) - return LinkageInfo(ModuleLinkage, DefaultVisibility, false); - return LinkageInfo::external(); } @@ -658,21 +638,21 @@ LinkageComputer::getLVForNamespaceScopeDecl(const NamedDecl *D, // - a variable, variable template, function, or function template // that is explicitly declared static; or // (This bullet corresponds to C99 6.2.2p3.) - return getInternalLinkageFor(D); + return LinkageInfo::internal(); } if (const auto *Var = dyn_cast(D)) { // - a non-template variable of non-volatile const-qualified type, unless // - it is explicitly declared extern, or - // - it is inline or exported, or + // - it is declared in the purview of a module interface unit + // (outside the private-module-fragment, if any) or module partition, or + // - it is inline, or // - it was previously declared and the prior declaration did not have // internal linkage // (There is no equivalent in C99.) - if (Context.getLangOpts().CPlusPlus && - Var->getType().isConstQualified() && - !Var->getType().isVolatileQualified() && - !Var->isInline() && - !isExportedFromModuleInterfaceUnit(Var) && + if (Context.getLangOpts().CPlusPlus && Var->getType().isConstQualified() && + !Var->getType().isVolatileQualified() && !Var->isInline() && + !isDeclaredInModuleInterfaceOrPartition(Var) && !isa(Var) && !Var->getDescribedVarTemplate()) { const VarDecl *PrevVar = Var->getPreviousDecl(); @@ -682,7 +662,7 @@ LinkageComputer::getLVForNamespaceScopeDecl(const NamedDecl *D, if (Var->getStorageClass() != SC_Extern && Var->getStorageClass() != SC_PrivateExtern && !isSingleLineLanguageLinkage(*Var)) - return getInternalLinkageFor(Var); + return LinkageInfo::internal(); } for (const VarDecl *PrevVar = Var->getPreviousDecl(); PrevVar; @@ -692,7 +672,7 @@ LinkageComputer::getLVForNamespaceScopeDecl(const NamedDecl *D, return getDeclLinkageAndVisibility(PrevVar); // Explicitly declared static. if (PrevVar->getStorageClass() == SC_Static) - return getInternalLinkageFor(Var); + return LinkageInfo::internal(); } } else if (const auto *IFD = dyn_cast(D)) { // - a data member of an anonymous union. @@ -716,7 +696,7 @@ LinkageComputer::getLVForNamespaceScopeDecl(const NamedDecl *D, // within an unnamed namespace has internal linkage. if ((!Var || !isFirstInExternCContext(Var)) && (!Func || !isFirstInExternCContext(Func))) - return getInternalLinkageFor(D); + return LinkageInfo::internal(); } // Set up the defaults. @@ -837,7 +817,8 @@ LinkageComputer::getLVForNamespaceScopeDecl(const NamedDecl *D, // OpenMP target declare device functions are not callable from the host so // they should not be exported from the device image. This applies to all // functions as the host-callable kernel functions are emitted at codegen. - if (Context.getLangOpts().OpenMP && Context.getLangOpts().OpenMPIsDevice && + if (Context.getLangOpts().OpenMP && + Context.getLangOpts().OpenMPIsTargetDevice && ((Context.getTargetInfo().getTriple().isAMDGPU() || Context.getTargetInfo().getTriple().isNVPTX()) || OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(Function))) @@ -1025,7 +1006,8 @@ LinkageComputer::getLVForClassMember(const NamedDecl *D, // they should not be exported from the device image. This applies to all // functions as the host-callable kernel functions are emitted at codegen. ASTContext &Context = D->getASTContext(); - if (Context.getLangOpts().OpenMP && Context.getLangOpts().OpenMPIsDevice && + if (Context.getLangOpts().OpenMP && + Context.getLangOpts().OpenMPIsTargetDevice && ((Context.getTargetInfo().getTriple().isAMDGPU() || Context.getTargetInfo().getTriple().isNVPTX()) || OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(MD))) @@ -1173,6 +1155,29 @@ Linkage NamedDecl::getLinkageInternal() const { .getLinkage(); } +/// Get the linkage from a semantic point of view. Entities in +/// anonymous namespaces are external (in c++98). +Linkage NamedDecl::getFormalLinkage() const { + Linkage InternalLinkage = getLinkageInternal(); + + // C++ [basic.link]p4.8: + // - if the declaration of the name is attached to a named module and is not + // exported + // the name has module linkage; + // + // [basic.namespace.general]/p2 + // A namespace is never attached to a named module and never has a name with + // module linkage. + if (isInModulePurview(this) && + InternalLinkage == ExternalLinkage && + !isExportedFromModuleInterfaceUnit( + cast(this->getCanonicalDecl())) && + !isa(this)) + InternalLinkage = ModuleLinkage; + + return clang::getFormalLinkage(InternalLinkage); +} + LinkageInfo NamedDecl::getLinkageAndVisibility() const { return LinkageComputer{}.getDeclLinkageAndVisibility(this); } @@ -1305,11 +1310,11 @@ LinkageInfo LinkageComputer::getLVForLocalDecl(const NamedDecl *D, if (const auto *Function = dyn_cast(D)) { if (Function->isInAnonymousNamespace() && !isFirstInExternCContext(Function)) - return getInternalLinkageFor(Function); + return LinkageInfo::internal(); // This is a "void f();" which got merged with a file static. if (Function->getCanonicalDecl()->getStorageClass() == SC_Static) - return getInternalLinkageFor(Function); + return LinkageInfo::internal(); LinkageInfo LV; if (!hasExplicitVisibilityAlready(computation)) { @@ -1328,7 +1333,7 @@ LinkageInfo LinkageComputer::getLVForLocalDecl(const NamedDecl *D, if (const auto *Var = dyn_cast(D)) { if (Var->hasExternalStorage()) { if (Var->isInAnonymousNamespace() && !isFirstInExternCContext(Var)) - return getInternalLinkageFor(Var); + return LinkageInfo::internal(); LinkageInfo LV; if (Var->getStorageClass() == SC_PrivateExtern) @@ -1408,7 +1413,7 @@ LinkageInfo LinkageComputer::computeLVForDecl(const NamedDecl *D, bool IgnoreVarTypeLinkage) { // Internal_linkage attribute overrides other considerations. if (D->hasAttr()) - return getInternalLinkageFor(D); + return LinkageInfo::internal(); // Objective-C: treat all Objective-C declarations as having external // linkage. @@ -1466,7 +1471,7 @@ LinkageInfo LinkageComputer::computeLVForDecl(const NamedDecl *D, if (Record->hasKnownLambdaInternalLinkage() || !Record->getLambdaManglingNumber()) { // This lambda has no mangling number, so it's internal. - return getInternalLinkageFor(D); + return LinkageInfo::internal(); } return getLVForClosure( @@ -1525,7 +1530,7 @@ LinkageInfo LinkageComputer::getLVForDecl(const NamedDecl *D, LVComputationKind computation) { // Internal_linkage attribute overrides other considerations. if (D->hasAttr()) - return getInternalLinkageFor(D); + return LinkageInfo::internal(); if (computation.IgnoreAllVisibility && D->hasCachedLinkage()) return LinkageInfo(D->getCachedLinkage(), DefaultVisibility, false); @@ -1593,12 +1598,14 @@ Module *Decl::getOwningModuleForLinkage(bool IgnoreLinkage) const { return nullptr; case Module::ModuleInterfaceUnit: + case Module::ModuleImplementationUnit: case Module::ModulePartitionInterface: case Module::ModulePartitionImplementation: return M; case Module::ModuleHeaderUnit: - case Module::GlobalModuleFragment: { + case Module::ExplicitGlobalModuleFragment: + case Module::ImplicitGlobalModuleFragment: { // External linkage declarations in the global module have no owning module // for linkage purposes. But internal linkage declarations in the global // module fragment of a particular module are owned by that module for @@ -1626,8 +1633,8 @@ Module *Decl::getOwningModuleForLinkage(bool IgnoreLinkage) const { llvm_unreachable("unknown module kind"); } -void NamedDecl::printName(raw_ostream &OS, const PrintingPolicy&) const { - OS << Name; +void NamedDecl::printName(raw_ostream &OS, const PrintingPolicy &Policy) const { + Name.print(OS, Policy); } void NamedDecl::printName(raw_ostream &OS) const { @@ -2347,12 +2354,15 @@ Expr *VarDecl::getInit() { if (auto *S = Init.dyn_cast()) return cast(S); - return cast_or_null(Init.get()->Value); + auto *Eval = getEvaluatedStmt(); + return cast(Eval->Value.isOffset() + ? Eval->Value.get(getASTContext().getExternalSource()) + : Eval->Value.get(nullptr)); } Stmt **VarDecl::getInitAddress() { if (auto *ES = Init.dyn_cast()) - return &ES->Value; + return ES->Value.getAddressOfPointer(getASTContext().getExternalSource()); return Init.getAddrOfPtr1(); } @@ -2482,14 +2492,14 @@ EvaluatedStmt *VarDecl::getEvaluatedStmt() const { APValue *VarDecl::evaluateValue() const { SmallVector Notes; - return evaluateValue(Notes); + return evaluateValueImpl(Notes, hasConstantInitialization()); } -APValue *VarDecl::evaluateValue( - SmallVectorImpl &Notes) const { +APValue *VarDecl::evaluateValueImpl(SmallVectorImpl &Notes, + bool IsConstantInitialization) const { EvaluatedStmt *Eval = ensureEvaluatedStmt(); - const auto *Init = cast(Eval->Value); + const auto *Init = getInit(); assert(!Init->isValueDependent()); // We only produce notes indicating why an initializer is non-constant the @@ -2505,8 +2515,16 @@ APValue *VarDecl::evaluateValue( Eval->IsEvaluating = true; - bool Result = Init->EvaluateAsInitializer(Eval->Evaluated, getASTContext(), - this, Notes); + ASTContext &Ctx = getASTContext(); + bool Result = Init->EvaluateAsInitializer(Eval->Evaluated, Ctx, this, Notes, + IsConstantInitialization); + + // In C++11, this isn't a constant initializer if we produced notes. In that + // case, we can't keep the result, because it may only be correct under the + // assumption that the initializer is a constant context. + if (IsConstantInitialization && Ctx.getLangOpts().CPlusPlus11 && + !Notes.empty()) + Result = false; // Ensure the computed APValue is cleaned up later if evaluation succeeded, // or that it's empty (so that there's nothing to clean up) if evaluation @@ -2514,7 +2532,7 @@ APValue *VarDecl::evaluateValue( if (!Result) Eval->Evaluated = APValue(); else if (Eval->Evaluated.needsCleanup()) - getASTContext().addDestruction(&Eval->Evaluated); + Ctx.addDestruction(&Eval->Evaluated); Eval->IsEvaluating = false; Eval->WasEvaluated = true; @@ -2565,10 +2583,17 @@ bool VarDecl::checkForConstantInitialization( "already evaluated var value before checking for constant init"); assert(getASTContext().getLangOpts().CPlusPlus && "only meaningful in C++"); - assert(!cast(Eval->Value)->isValueDependent()); + assert(!getInit()->isValueDependent()); // Evaluate the initializer to check whether it's a constant expression. - Eval->HasConstantInitialization = evaluateValue(Notes) && Notes.empty(); + Eval->HasConstantInitialization = + evaluateValueImpl(Notes, true) && Notes.empty(); + + // If evaluation as a constant initializer failed, allow re-evaluation as a + // non-constant initializer if we later find we want the value. + if (!Eval->HasConstantInitialization) + Eval->WasEvaluated = false; + return Eval->HasConstantInitialization; } @@ -2975,13 +3000,15 @@ FunctionDecl::FunctionDecl(Kind DK, ASTContext &C, DeclContext *DC, FunctionDeclBits.HasImplicitReturnZero = false; FunctionDeclBits.IsLateTemplateParsed = false; FunctionDeclBits.ConstexprKind = static_cast(ConstexprKind); + FunctionDeclBits.BodyContainsImmediateEscalatingExpression = false; FunctionDeclBits.InstantiationIsPending = false; FunctionDeclBits.UsesSEHTry = false; FunctionDeclBits.UsesFPIntrin = UsesFPIntrin; FunctionDeclBits.HasSkippedBody = false; FunctionDeclBits.WillHaveBody = false; FunctionDeclBits.IsMultiVersion = false; - FunctionDeclBits.IsCopyDeductionCandidate = false; + FunctionDeclBits.DeductionCandidateKind = + static_cast(DeductionCandidate::Normal); FunctionDeclBits.HasODRHash = false; FunctionDeclBits.FriendConstraintRefersToEnclosingTemplate = false; if (TrailingRequiresClause) @@ -3140,6 +3167,44 @@ static bool isNamed(const NamedDecl *ND, const char (&Str)[Len]) { return II && II->isStr(Str); } +bool FunctionDecl::isImmediateEscalating() const { + // C++23 [expr.const]/p17 + // An immediate-escalating function is + // - the call operator of a lambda that is not declared with the consteval + // specifier, + if (isLambdaCallOperator(this) && !isConsteval()) + return true; + // - a defaulted special member function that is not declared with the + // consteval specifier, + if (isDefaulted() && !isConsteval()) + return true; + // - a function that results from the instantiation of a templated entity + // defined with the constexpr specifier. + TemplatedKind TK = getTemplatedKind(); + if (TK != TK_NonTemplate && TK != TK_DependentNonTemplate && + isConstexprSpecified()) + return true; + return false; +} + +bool FunctionDecl::isImmediateFunction() const { + // C++23 [expr.const]/p18 + // An immediate function is a function or constructor that is + // - declared with the consteval specifier + if (isConsteval()) + return true; + // - an immediate-escalating function F whose function body contains an + // immediate-escalating expression + if (isImmediateEscalating() && BodyContainsImmediateEscalatingExpressions()) + return true; + + if (const auto *MD = dyn_cast(this); + MD && MD->isLambdaStaticInvoker()) + return MD->getParent()->getLambdaCallOperator()->isImmediateFunction(); + + return false; +} + bool FunctionDecl::isMain() const { const TranslationUnitDecl *tunit = dyn_cast(getDeclContext()->getRedeclContext()); @@ -3218,7 +3283,7 @@ bool FunctionDecl::isReplaceableGlobalAllocationFunction( return false; const auto *FPT = getType()->castAs(); - if (FPT->getNumParams() == 0 || FPT->getNumParams() > 3 || FPT->isVariadic()) + if (FPT->getNumParams() == 0 || FPT->getNumParams() > 4 || FPT->isVariadic()) return false; // If this is a single-parameter function, it must be a replaceable global @@ -3253,8 +3318,8 @@ bool FunctionDecl::isReplaceableGlobalAllocationFunction( *AlignmentParam = Params; } - // Finally, if this is not a sized delete, the final parameter can - // be a 'const std::nothrow_t&'. + // If this is not a sized delete, the next parameter can be a + // 'const std::nothrow_t&'. if (!IsSizedDelete && !Ty.isNull() && Ty->isReferenceType()) { Ty = Ty->getPointeeType(); if (Ty.getCVRQualifiers() != Qualifiers::Const) @@ -3266,6 +3331,19 @@ bool FunctionDecl::isReplaceableGlobalAllocationFunction( } } + // Finally, recognize the not yet standard versions of new that take a + // hot/cold allocation hint (__hot_cold_t). These are currently supported by + // tcmalloc (see + // https://github.com/google/tcmalloc/blob/220043886d4e2efff7a5702d5172cb8065253664/tcmalloc/malloc_extension.h#L53). + if (!IsSizedDelete && !Ty.isNull() && Ty->isEnumeralType()) { + QualType T = Ty; + while (const auto *TD = T->getAs()) + T = TD->getDecl()->getUnderlyingType(); + IdentifierInfo *II = T->castAs()->getDecl()->getIdentifier(); + if (II && II->isStr("__hot_cold_t")) + Consume(); + } + return Params == FPT->getNumParams(); } @@ -3274,9 +3352,24 @@ bool FunctionDecl::isInlineBuiltinDeclaration() const { return false; const FunctionDecl *Definition; - return hasBody(Definition) && Definition->isInlineSpecified() && - Definition->hasAttr() && - Definition->hasAttr(); + if (!hasBody(Definition)) + return false; + + if (!Definition->isInlineSpecified() || + !Definition->hasAttr()) + return false; + + ASTContext &Context = getASTContext(); + switch (Context.GetGVALinkageForFunction(Definition)) { + case GVA_Internal: + case GVA_DiscardableODR: + case GVA_StrongODR: + return false; + case GVA_AvailableExternally: + case GVA_StrongExternal: + return true; + } + llvm_unreachable("Unknown GVALinkage"); } bool FunctionDecl::isDestroyingOperatorDelete() const { @@ -3341,6 +3434,27 @@ bool FunctionDecl::isNoReturn() const { return false; } +bool FunctionDecl::isMemberLikeConstrainedFriend() const { + // C++20 [temp.friend]p9: + // A non-template friend declaration with a requires-clause [or] + // a friend function template with a constraint that depends on a template + // parameter from an enclosing template [...] does not declare the same + // function or function template as a declaration in any other scope. + + // If this isn't a friend then it's not a member-like constrained friend. + if (!getFriendObjectKind()) { + return false; + } + + if (!getDescribedFunctionTemplate()) { + // If these friends don't have constraints, they aren't constrained, and + // thus don't fall under temp.friend p9. Else the simple presence of a + // constraint makes them unique. + return getTrailingRequiresClause(); + } + + return FriendConstraintRefersToEnclosingTemplate(); +} MultiVersionKind FunctionDecl::getMultiVersionKind() const { if (hasAttr()) @@ -3452,7 +3566,7 @@ unsigned FunctionDecl::getBuiltinID(bool ConsiderWrapperFunctions) const { // library, none of the predefined library functions except printf and malloc // should be treated as a builtin i.e. 0 should be returned for them. if (Context.getTargetInfo().getTriple().isAMDGCN() && - Context.getLangOpts().OpenMPIsDevice && + Context.getLangOpts().OpenMPIsTargetDevice && Context.BuiltinInfo.isPredefinedLibFunction(BuiltinID) && !(BuiltinID == Builtin::BIprintf || BuiltinID == Builtin::BImalloc)) return 0; @@ -4297,6 +4411,28 @@ bool FieldDecl::isAnonymousStructOrUnion() const { return false; } +Expr *FieldDecl::getInClassInitializer() const { + if (!hasInClassInitializer()) + return nullptr; + + LazyDeclStmtPtr InitPtr = BitField ? InitAndBitWidth->Init : Init; + return cast_or_null( + InitPtr.isOffset() ? InitPtr.get(getASTContext().getExternalSource()) + : InitPtr.get(nullptr)); +} + +void FieldDecl::setInClassInitializer(Expr *NewInit) { + setLazyInClassInitializer(LazyDeclStmtPtr(NewInit)); +} + +void FieldDecl::setLazyInClassInitializer(LazyDeclStmtPtr NewInit) { + assert(hasInClassInitializer() && !getInClassInitializer()); + if (BitField) + InitAndBitWidth->Init = NewInit; + else + Init = NewInit; +} + unsigned FieldDecl::getBitWidthValue(const ASTContext &Ctx) const { assert(isBitField() && "not a bitfield"); return getBitWidth()->EvaluateKnownConstInt(Ctx).getZExtValue(); @@ -4340,6 +4476,10 @@ bool FieldDecl::isZeroSize(const ASTContext &Ctx) const { return true; } +bool FieldDecl::isPotentiallyOverlapping() const { + return hasAttr() && getType()->getAsCXXRecordDecl(); +} + unsigned FieldDecl::getFieldIndex() const { const FieldDecl *Canonical = getCanonicalDecl(); if (Canonical != this) @@ -4353,6 +4493,8 @@ unsigned FieldDecl::getFieldIndex() const { for (auto *Field : RD->fields()) { Field->getCanonicalDecl()->CachedFieldIndex = Index + 1; + assert(Field->getCanonicalDecl()->CachedFieldIndex == Index + 1 && + "overflow in field numbering"); ++Index; } @@ -4372,11 +4514,11 @@ SourceRange FieldDecl::getSourceRange() const { void FieldDecl::setCapturedVLAType(const VariableArrayType *VLAType) { assert((getParent()->isLambda() || getParent()->isCapturedRecord()) && "capturing type in non-lambda or captured record."); - assert(InitStorage.getInt() == ISK_NoInit && - InitStorage.getPointer() == nullptr && - "bit width, initializer or captured type already set"); - InitStorage.setPointerAndInt(const_cast(VLAType), - ISK_CapturedVLAType); + assert(StorageKind == ISK_NoInit && !BitField && + "bit-field or field with default member initializer cannot capture " + "VLA type"); + StorageKind = ISK_CapturedVLAType; + CapturedVLAType = VLAType; } //===----------------------------------------------------------------------===// @@ -4755,7 +4897,10 @@ bool RecordDecl::isOrContainsUnion() const { RecordDecl::field_iterator RecordDecl::field_begin() const { if (hasExternalLexicalStorage() && !hasLoadedFieldsFromExternalStorage()) LoadFieldsFromExternalStorage(); - + // This is necessary for correctness for C++ with modules. + // FIXME: Come up with a test case that breaks without definition. + if (RecordDecl *D = getDefinition(); D && D != this) + return D->field_begin(); return field_iterator(decl_iterator(FirstDecl)); } @@ -4808,8 +4953,13 @@ void RecordDecl::LoadFieldsFromExternalStorage() const { if (Decls.empty()) return; - std::tie(FirstDecl, LastDecl) = BuildDeclChain(Decls, - /*FieldsAlreadyLoaded=*/false); + auto [ExternalFirst, ExternalLast] = + BuildDeclChain(Decls, + /*FieldsAlreadyLoaded=*/false); + ExternalLast->NextInContextAndBits.setPointer(FirstDecl); + FirstDecl = ExternalFirst; + if (!LastDecl) + LastDecl = ExternalLast; } bool RecordDecl::mayInsertExtraPadding(bool EmitRemark) const { diff --git a/contrib/llvm-project/clang/lib/AST/DeclBase.cpp b/contrib/llvm-project/clang/lib/AST/DeclBase.cpp index c94fc602155..834beef49a4 100644 --- a/contrib/llvm-project/clang/lib/AST/DeclBase.cpp +++ b/contrib/llvm-project/clang/lib/AST/DeclBase.cpp @@ -30,6 +30,7 @@ #include "clang/Basic/IdentifierTable.h" #include "clang/Basic/LLVM.h" #include "clang/Basic/LangOptions.h" +#include "clang/Basic/Module.h" #include "clang/Basic/ObjCRuntime.h" #include "clang/Basic/PartialDiagnostic.h" #include "clang/Basic/SourceLocation.h" @@ -1022,6 +1023,28 @@ bool Decl::isInExportDeclContext() const { return DC && isa(DC); } +bool Decl::isInAnotherModuleUnit() const { + auto *M = getOwningModule(); + + if (!M) + return false; + + M = M->getTopLevelModule(); + // FIXME: It is problematic if the header module lives in another module + // unit. Consider to fix this by techniques like + // ExternalASTSource::hasExternalDefinitions. + if (M->isHeaderLikeModule()) + return false; + + // A global module without parent implies that we're parsing the global + // module. So it can't be in another module unit. + if (M->isGlobalModule()) + return false; + + assert(M->isModulePurview() && "New module kind?"); + return M != getASTContext().getCurrentNamedModule(); +} + static Decl::Kind getKind(const Decl *D) { return D->getKind(); } static Decl::Kind getKind(const DeclContext *DC) { return DC->getDeclKind(); } @@ -1048,6 +1071,18 @@ const FunctionType *Decl::getFunctionType(bool BlocksToo) const { return Ty->getAs(); } +bool Decl::isFunctionPointerType() const { + QualType Ty; + if (const auto *D = dyn_cast(this)) + Ty = D->getType(); + else if (const auto *D = dyn_cast(this)) + Ty = D->getUnderlyingType(); + else + return false; + + return Ty.getCanonicalType()->isFunctionPointerType(); +} + DeclContext *Decl::getNonTransparentDeclContext() { assert(getDeclContext()); return getDeclContext()->getNonTransparentContext(); diff --git a/contrib/llvm-project/clang/lib/AST/DeclCXX.cpp b/contrib/llvm-project/clang/lib/AST/DeclCXX.cpp index 3cf35571410..e4572aab5b0 100644 --- a/contrib/llvm-project/clang/lib/AST/DeclCXX.cpp +++ b/contrib/llvm-project/clang/lib/AST/DeclCXX.cpp @@ -1646,18 +1646,20 @@ Decl *CXXRecordDecl::getLambdaContextDecl() const { return getLambdaData().ContextDecl.get(Source); } -void CXXRecordDecl::setDeviceLambdaManglingNumber(unsigned Num) const { +void CXXRecordDecl::setLambdaNumbering(LambdaNumbering Numbering) { assert(isLambda() && "Not a lambda closure type!"); - if (Num) - getASTContext().DeviceLambdaManglingNumbers[this] = Num; + getLambdaData().ManglingNumber = Numbering.ManglingNumber; + if (Numbering.DeviceManglingNumber) + getASTContext().DeviceLambdaManglingNumbers[this] = + Numbering.DeviceManglingNumber; + getLambdaData().IndexInContext = Numbering.IndexInContext; + getLambdaData().ContextDecl = Numbering.ContextDecl; + getLambdaData().HasKnownInternalLinkage = Numbering.HasKnownInternalLinkage; } unsigned CXXRecordDecl::getDeviceLambdaManglingNumber() const { assert(isLambda() && "Not a lambda closure type!"); - auto I = getASTContext().DeviceLambdaManglingNumbers.find(this); - if (I != getASTContext().DeviceLambdaManglingNumbers.end()) - return I->second; - return 0; + return getASTContext().DeviceLambdaManglingNumbers.lookup(this); } static CanQualType GetConversionType(ASTContext &Context, NamedDecl *Conv) { @@ -2110,21 +2112,21 @@ ExplicitSpecifier ExplicitSpecifier::getFromDecl(FunctionDecl *Function) { } } -CXXDeductionGuideDecl * -CXXDeductionGuideDecl::Create(ASTContext &C, DeclContext *DC, - SourceLocation StartLoc, ExplicitSpecifier ES, - const DeclarationNameInfo &NameInfo, QualType T, - TypeSourceInfo *TInfo, SourceLocation EndLocation, - CXXConstructorDecl *Ctor) { +CXXDeductionGuideDecl *CXXDeductionGuideDecl::Create( + ASTContext &C, DeclContext *DC, SourceLocation StartLoc, + ExplicitSpecifier ES, const DeclarationNameInfo &NameInfo, QualType T, + TypeSourceInfo *TInfo, SourceLocation EndLocation, CXXConstructorDecl *Ctor, + DeductionCandidate Kind) { return new (C, DC) CXXDeductionGuideDecl(C, DC, StartLoc, ES, NameInfo, T, - TInfo, EndLocation, Ctor); + TInfo, EndLocation, Ctor, Kind); } CXXDeductionGuideDecl *CXXDeductionGuideDecl::CreateDeserialized(ASTContext &C, unsigned ID) { return new (C, ID) CXXDeductionGuideDecl( C, nullptr, SourceLocation(), ExplicitSpecifier(), DeclarationNameInfo(), - QualType(), nullptr, SourceLocation(), nullptr); + QualType(), nullptr, SourceLocation(), nullptr, + DeductionCandidate::Normal); } RequiresExprBodyDecl *RequiresExprBodyDecl::Create( @@ -3235,8 +3237,7 @@ void StaticAssertDecl::anchor() {} StaticAssertDecl *StaticAssertDecl::Create(ASTContext &C, DeclContext *DC, SourceLocation StaticAssertLoc, - Expr *AssertExpr, - StringLiteral *Message, + Expr *AssertExpr, Expr *Message, SourceLocation RParenLoc, bool Failed) { return new (C, DC) StaticAssertDecl(DC, StaticAssertLoc, AssertExpr, Message, diff --git a/contrib/llvm-project/clang/lib/AST/DeclPrinter.cpp b/contrib/llvm-project/clang/lib/AST/DeclPrinter.cpp index f3bad9f45b7..a6a9911c899 100644 --- a/contrib/llvm-project/clang/lib/AST/DeclPrinter.cpp +++ b/contrib/llvm-project/clang/lib/AST/DeclPrinter.cpp @@ -622,6 +622,8 @@ void DeclPrinter::VisitFunctionDecl(FunctionDecl *D) { if (D->isConstexprSpecified() && !D->isExplicitlyDefaulted()) Out << "constexpr "; if (D->isConsteval()) Out << "consteval "; + else if (D->isImmediateFunction()) + Out << "immediate "; ExplicitSpecifier ExplicitSpec = ExplicitSpecifier::getFromDecl(D); if (ExplicitSpec.isSpecified()) printExplicitSpecifier(ExplicitSpec, Out, Policy, Indentation, Context); @@ -947,9 +949,9 @@ void DeclPrinter::VisitStaticAssertDecl(StaticAssertDecl *D) { Out << "static_assert("; D->getAssertExpr()->printPretty(Out, nullptr, Policy, Indentation, "\n", &Context); - if (StringLiteral *SL = D->getMessage()) { + if (Expr *E = D->getMessage()) { Out << ", "; - SL->printPretty(Out, nullptr, Policy, Indentation, "\n", &Context); + E->printPretty(Out, nullptr, Policy, Indentation, "\n", &Context); } Out << ")"; } @@ -997,7 +999,10 @@ void DeclPrinter::VisitCXXRecordDecl(CXXRecordDecl *D) { prettyPrintAttributes(D); if (D->getIdentifier()) { - Out << ' ' << *D; + Out << ' '; + if (auto *NNS = D->getQualifier()) + NNS->print(Out, Policy); + Out << *D; if (auto S = dyn_cast(D)) { ArrayRef Args = S->getTemplateArgs().asArray(); diff --git a/contrib/llvm-project/clang/lib/AST/DeclTemplate.cpp b/contrib/llvm-project/clang/lib/AST/DeclTemplate.cpp index 531be708b6f..fd4c8eafc1c 100755 --- a/contrib/llvm-project/clang/lib/AST/DeclTemplate.cpp +++ b/contrib/llvm-project/clang/lib/AST/DeclTemplate.cpp @@ -127,6 +127,39 @@ TemplateParameterList::Create(const ASTContext &C, SourceLocation TemplateLoc, RAngleLoc, RequiresClause); } +void TemplateParameterList::Profile(llvm::FoldingSetNodeID &ID, + const ASTContext &C) const { + const Expr *RC = getRequiresClause(); + ID.AddBoolean(RC != nullptr); + if (RC) + RC->Profile(ID, C, /*Canonical=*/true); + ID.AddInteger(size()); + for (NamedDecl *D : *this) { + if (const auto *NTTP = dyn_cast(D)) { + ID.AddInteger(0); + ID.AddBoolean(NTTP->isParameterPack()); + NTTP->getType().getCanonicalType().Profile(ID); + ID.AddBoolean(NTTP->hasPlaceholderTypeConstraint()); + if (const Expr *E = NTTP->getPlaceholderTypeConstraint()) + E->Profile(ID, C, /*Canonical=*/true); + continue; + } + if (const auto *TTP = dyn_cast(D)) { + ID.AddInteger(1); + ID.AddBoolean(TTP->isParameterPack()); + ID.AddBoolean(TTP->hasTypeConstraint()); + if (const TypeConstraint *TC = TTP->getTypeConstraint()) + TC->getImmediatelyDeclaredConstraint()->Profile(ID, C, + /*Canonical=*/true); + continue; + } + const auto *TTP = cast(D); + ID.AddInteger(2); + ID.AddBoolean(TTP->isParameterPack()); + TTP->getTemplateParameters()->Profile(ID, C); + } +} + unsigned TemplateParameterList::getMinRequiredArguments() const { unsigned NumRequiredArgs = 0; for (const NamedDecl *P : asArray()) { @@ -517,47 +550,13 @@ ClassTemplateDecl::findPartialSpecialization( TPL); } -static void ProfileTemplateParameterList(ASTContext &C, - llvm::FoldingSetNodeID &ID, const TemplateParameterList *TPL) { - const Expr *RC = TPL->getRequiresClause(); - ID.AddBoolean(RC != nullptr); - if (RC) - RC->Profile(ID, C, /*Canonical=*/true); - ID.AddInteger(TPL->size()); - for (NamedDecl *D : *TPL) { - if (const auto *NTTP = dyn_cast(D)) { - ID.AddInteger(0); - ID.AddBoolean(NTTP->isParameterPack()); - NTTP->getType().getCanonicalType().Profile(ID); - ID.AddBoolean(NTTP->hasPlaceholderTypeConstraint()); - if (const Expr *E = NTTP->getPlaceholderTypeConstraint()) - E->Profile(ID, C, /*Canonical=*/true); - continue; - } - if (const auto *TTP = dyn_cast(D)) { - ID.AddInteger(1); - ID.AddBoolean(TTP->isParameterPack()); - ID.AddBoolean(TTP->hasTypeConstraint()); - if (const TypeConstraint *TC = TTP->getTypeConstraint()) - TC->getImmediatelyDeclaredConstraint()->Profile(ID, C, - /*Canonical=*/true); - continue; - } - const auto *TTP = cast(D); - ID.AddInteger(2); - ID.AddBoolean(TTP->isParameterPack()); - ProfileTemplateParameterList(C, ID, TTP->getTemplateParameters()); - } -} - -void -ClassTemplatePartialSpecializationDecl::Profile(llvm::FoldingSetNodeID &ID, - ArrayRef TemplateArgs, TemplateParameterList *TPL, - ASTContext &Context) { +void ClassTemplatePartialSpecializationDecl::Profile( + llvm::FoldingSetNodeID &ID, ArrayRef TemplateArgs, + TemplateParameterList *TPL, const ASTContext &Context) { ID.AddInteger(TemplateArgs.size()); for (const TemplateArgument &TemplateArg : TemplateArgs) TemplateArg.Profile(ID, Context); - ProfileTemplateParameterList(Context, ID, TPL); + TPL->Profile(ID, Context); } void ClassTemplateDecl::AddPartialSpecialization( @@ -1283,14 +1282,13 @@ VarTemplateDecl::findPartialSpecialization(ArrayRef Args, TPL); } -void -VarTemplatePartialSpecializationDecl::Profile(llvm::FoldingSetNodeID &ID, - ArrayRef TemplateArgs, TemplateParameterList *TPL, - ASTContext &Context) { +void VarTemplatePartialSpecializationDecl::Profile( + llvm::FoldingSetNodeID &ID, ArrayRef TemplateArgs, + TemplateParameterList *TPL, const ASTContext &Context) { ID.AddInteger(TemplateArgs.size()); for (const TemplateArgument &TemplateArg : TemplateArgs) TemplateArg.Profile(ID, Context); - ProfileTemplateParameterList(Context, ID, TPL); + TPL->Profile(ID, Context); } void VarTemplateDecl::AddPartialSpecialization( @@ -1402,6 +1400,15 @@ void VarTemplateSpecializationDecl::setTemplateArgsInfo( ASTTemplateArgumentListInfo::Create(getASTContext(), ArgsInfo); } +SourceRange VarTemplateSpecializationDecl::getSourceRange() const { + if (isExplicitSpecialization() && !hasInit()) { + if (const ASTTemplateArgumentListInfo *Info = getTemplateArgsInfo()) + return SourceRange(getOuterLocStart(), Info->getRAngleLoc()); + } + return VarDecl::getSourceRange(); +} + + //===----------------------------------------------------------------------===// // VarTemplatePartialSpecializationDecl Implementation //===----------------------------------------------------------------------===// @@ -1447,6 +1454,14 @@ VarTemplatePartialSpecializationDecl::CreateDeserialized(ASTContext &C, return new (C, ID) VarTemplatePartialSpecializationDecl(C); } +SourceRange VarTemplatePartialSpecializationDecl::getSourceRange() const { + if (isExplicitSpecialization() && !hasInit()) { + if (const ASTTemplateArgumentListInfo *Info = getTemplateArgsAsWritten()) + return SourceRange(getOuterLocStart(), Info->getRAngleLoc()); + } + return VarDecl::getSourceRange(); +} + static TemplateParameterList * createMakeIntegerSeqParameterList(const ASTContext &C, DeclContext *DC) { // typename T diff --git a/contrib/llvm-project/clang/lib/AST/DeclarationName.cpp b/contrib/llvm-project/clang/lib/AST/DeclarationName.cpp index c1219041a46..a3ac5551e0c 100644 --- a/contrib/llvm-project/clang/lib/AST/DeclarationName.cpp +++ b/contrib/llvm-project/clang/lib/AST/DeclarationName.cpp @@ -117,12 +117,12 @@ static void printCXXConstructorDestructorName(QualType ClassType, Policy.adjustForCPlusPlus(); if (const RecordType *ClassRec = ClassType->getAs()) { - OS << *ClassRec->getDecl(); + ClassRec->getDecl()->printName(OS, Policy); return; } if (Policy.SuppressTemplateArgsInCXXConstructors) { if (auto *InjTy = ClassType->getAs()) { - OS << *InjTy->getDecl(); + InjTy->getDecl()->printName(OS, Policy); return; } } @@ -365,7 +365,7 @@ DeclarationNameTable::getCXXSpecialName(DeclarationName::NameKind Kind, } DeclarationName -DeclarationNameTable::getCXXLiteralOperatorName(IdentifierInfo *II) { +DeclarationNameTable::getCXXLiteralOperatorName(const IdentifierInfo *II) { llvm::FoldingSetNodeID ID; ID.AddPointer(II); diff --git a/contrib/llvm-project/clang/lib/AST/Expr.cpp b/contrib/llvm-project/clang/lib/AST/Expr.cpp index e45ae68cd5f..6164a419d21 100644 --- a/contrib/llvm-project/clang/lib/AST/Expr.cpp +++ b/contrib/llvm-project/clang/lib/AST/Expr.cpp @@ -492,6 +492,7 @@ DeclRefExpr::DeclRefExpr(const ASTContext &Ctx, ValueDecl *D, DeclRefExprBits.RefersToEnclosingVariableOrCapture = RefersToEnclosingVariableOrCapture; DeclRefExprBits.NonOdrUseReason = NOUR; + DeclRefExprBits.IsImmediateEscalating = false; DeclRefExprBits.Loc = L; setDependence(computeDependence(this, Ctx)); } @@ -529,6 +530,7 @@ DeclRefExpr::DeclRefExpr(const ASTContext &Ctx, getTrailingObjects()->initializeFrom( TemplateKWLoc); } + DeclRefExprBits.IsImmediateEscalating = false; DeclRefExprBits.HadMultipleCandidates = 0; setDependence(computeDependence(this, Ctx)); } @@ -663,13 +665,14 @@ std::string SYCLUniqueStableNameExpr::ComputeName(ASTContext &Context, } PredefinedExpr::PredefinedExpr(SourceLocation L, QualType FNTy, IdentKind IK, - StringLiteral *SL) + bool IsTransparent, StringLiteral *SL) : Expr(PredefinedExprClass, FNTy, VK_LValue, OK_Ordinary) { PredefinedExprBits.Kind = IK; assert((getIdentKind() == IK) && "IdentKind do not fit in PredefinedExprBitfields!"); bool HasFunctionName = SL != nullptr; PredefinedExprBits.HasFunctionName = HasFunctionName; + PredefinedExprBits.IsTransparent = IsTransparent; PredefinedExprBits.Loc = L; if (HasFunctionName) setFunctionName(SL); @@ -683,11 +686,11 @@ PredefinedExpr::PredefinedExpr(EmptyShell Empty, bool HasFunctionName) PredefinedExpr *PredefinedExpr::Create(const ASTContext &Ctx, SourceLocation L, QualType FNTy, IdentKind IK, - StringLiteral *SL) { + bool IsTransparent, StringLiteral *SL) { bool HasFunctionName = SL != nullptr; void *Mem = Ctx.Allocate(totalSizeToAlloc(HasFunctionName), alignof(PredefinedExpr)); - return new (Mem) PredefinedExpr(L, FNTy, IK, SL); + return new (Mem) PredefinedExpr(L, FNTy, IK, IsTransparent, SL); } PredefinedExpr *PredefinedExpr::CreateEmpty(const ASTContext &Ctx, @@ -783,7 +786,21 @@ std::string PredefinedExpr::ComputeName(IdentKind IK, const Decl *CurrentDecl) { Out << "static "; } + class PrettyCallbacks final : public PrintingCallbacks { + public: + PrettyCallbacks(const LangOptions &LO) : LO(LO) {} + std::string remapPath(StringRef Path) const override { + SmallString<128> p(Path); + LO.remapPathPrefix(p); + return std::string(p); + } + + private: + const LangOptions &LO; + }; PrintingPolicy Policy(Context.getLangOpts()); + PrettyCallbacks PrettyCB(Context.getLangOpts()); + Policy.Callbacks = &PrettyCB; std::string Proto; llvm::raw_string_ostream POut(Proto); @@ -1119,6 +1136,8 @@ unsigned StringLiteral::mapCharByteWidth(TargetInfo const &Target, case UTF32: CharByteWidth = Target.getChar32Width(); break; + case Unevaluated: + return sizeof(char); // Host; } assert((CharByteWidth & 7) == 0 && "Assumes character size is byte multiple"); CharByteWidth /= 8; @@ -1132,35 +1151,45 @@ StringLiteral::StringLiteral(const ASTContext &Ctx, StringRef Str, const SourceLocation *Loc, unsigned NumConcatenated) : Expr(StringLiteralClass, Ty, VK_LValue, OK_Ordinary) { - assert(Ctx.getAsConstantArrayType(Ty) && - "StringLiteral must be of constant array type!"); - unsigned CharByteWidth = mapCharByteWidth(Ctx.getTargetInfo(), Kind); - unsigned ByteLength = Str.size(); - assert((ByteLength % CharByteWidth == 0) && - "The size of the data must be a multiple of CharByteWidth!"); - // Avoid the expensive division. The compiler should be able to figure it - // out by itself. However as of clang 7, even with the appropriate - // llvm_unreachable added just here, it is not able to do so. - unsigned Length; - switch (CharByteWidth) { - case 1: - Length = ByteLength; - break; - case 2: - Length = ByteLength / 2; - break; - case 4: - Length = ByteLength / 4; - break; - default: - llvm_unreachable("Unsupported character width!"); - } + unsigned Length = Str.size(); StringLiteralBits.Kind = Kind; - StringLiteralBits.CharByteWidth = CharByteWidth; - StringLiteralBits.IsPascal = Pascal; StringLiteralBits.NumConcatenated = NumConcatenated; + + if (Kind != StringKind::Unevaluated) { + assert(Ctx.getAsConstantArrayType(Ty) && + "StringLiteral must be of constant array type!"); + unsigned CharByteWidth = mapCharByteWidth(Ctx.getTargetInfo(), Kind); + unsigned ByteLength = Str.size(); + assert((ByteLength % CharByteWidth == 0) && + "The size of the data must be a multiple of CharByteWidth!"); + + // Avoid the expensive division. The compiler should be able to figure it + // out by itself. However as of clang 7, even with the appropriate + // llvm_unreachable added just here, it is not able to do so. + switch (CharByteWidth) { + case 1: + Length = ByteLength; + break; + case 2: + Length = ByteLength / 2; + break; + case 4: + Length = ByteLength / 4; + break; + default: + llvm_unreachable("Unsupported character width!"); + } + + StringLiteralBits.CharByteWidth = CharByteWidth; + StringLiteralBits.IsPascal = Pascal; + } else { + assert(!Pascal && "Can't make an unevaluated Pascal string"); + StringLiteralBits.CharByteWidth = 1; + StringLiteralBits.IsPascal = false; + } + *getTrailingObjects() = Length; // Initialize the trailing array of SourceLocation. @@ -1169,7 +1198,7 @@ StringLiteral::StringLiteral(const ASTContext &Ctx, StringRef Str, NumConcatenated * sizeof(SourceLocation)); // Initialize the trailing array of char holding the string data. - std::memcpy(getTrailingObjects(), Str.data(), ByteLength); + std::memcpy(getTrailingObjects(), Str.data(), Str.size()); setDependence(ExprDependence::None); } @@ -1206,6 +1235,7 @@ StringLiteral *StringLiteral::CreateEmpty(const ASTContext &Ctx, void StringLiteral::outputString(raw_ostream &OS) const { switch (getKind()) { + case Unevaluated: case Ordinary: break; // no prefix. case Wide: OS << 'L'; break; @@ -1316,7 +1346,8 @@ StringLiteral::getLocationOfByte(unsigned ByteNo, const SourceManager &SM, const TargetInfo &Target, unsigned *StartToken, unsigned *StartTokenByteOffset) const { assert((getKind() == StringLiteral::Ordinary || - getKind() == StringLiteral::UTF8) && + getKind() == StringLiteral::UTF8 || + getKind() == StringLiteral::Unevaluated) && "Only narrow string literals are currently supported"); // Loop over all of the tokens in this string until we find the one that @@ -1529,19 +1560,17 @@ unsigned CallExpr::offsetToTrailingObjects(StmtClass SC) { Decl *Expr::getReferencedDeclOfCallee() { Expr *CEE = IgnoreParenImpCasts(); - while (SubstNonTypeTemplateParmExpr *NTTP = - dyn_cast(CEE)) { + while (auto *NTTP = dyn_cast(CEE)) CEE = NTTP->getReplacement()->IgnoreParenImpCasts(); - } // If we're calling a dereference, look at the pointer instead. while (true) { - if (BinaryOperator *BO = dyn_cast(CEE)) { + if (auto *BO = dyn_cast(CEE)) { if (BO->isPtrMemOp()) { CEE = BO->getRHS()->IgnoreParenImpCasts(); continue; } - } else if (UnaryOperator *UO = dyn_cast(CEE)) { + } else if (auto *UO = dyn_cast(CEE)) { if (UO->getOpcode() == UO_Deref || UO->getOpcode() == UO_AddrOf || UO->getOpcode() == UO_Plus) { CEE = UO->getSubExpr()->IgnoreParenImpCasts(); @@ -1551,9 +1580,9 @@ Decl *Expr::getReferencedDeclOfCallee() { break; } - if (DeclRefExpr *DRE = dyn_cast(CEE)) + if (auto *DRE = dyn_cast(CEE)) return DRE->getDecl(); - if (MemberExpr *ME = dyn_cast(CEE)) + if (auto *ME = dyn_cast(CEE)) return ME->getMemberDecl(); if (auto *BE = dyn_cast(CEE)) return BE->getBlockDecl(); @@ -1563,7 +1592,7 @@ Decl *Expr::getReferencedDeclOfCallee() { /// If this is a call to a builtin, return the builtin ID. If not, return 0. unsigned CallExpr::getBuiltinCallee() const { - auto *FDecl = getDirectCallee(); + const auto *FDecl = getDirectCallee(); return FDecl ? FDecl->getBuiltinID() : 0; } @@ -1618,8 +1647,8 @@ const Attr *CallExpr::getUnusedResultAttr(const ASTContext &Ctx) const { } SourceLocation CallExpr::getBeginLoc() const { - if (isa(this)) - return cast(this)->getBeginLoc(); + if (const auto *OCE = dyn_cast(this)) + return OCE->getBeginLoc(); SourceLocation begin = getCallee()->getBeginLoc(); if (begin.isInvalid() && getNumArgs() > 0 && getArg(0)) @@ -1627,8 +1656,8 @@ SourceLocation CallExpr::getBeginLoc() const { return begin; } SourceLocation CallExpr::getEndLoc() const { - if (isa(this)) - return cast(this)->getEndLoc(); + if (const auto *OCE = dyn_cast(this)) + return OCE->getEndLoc(); SourceLocation end = getRParenLoc(); if (end.isInvalid() && getNumArgs() > 0 && getArg(getNumArgs() - 1)) @@ -1730,16 +1759,7 @@ MemberExpr *MemberExpr::Create( MemberExpr *E = new (Mem) MemberExpr(Base, IsArrow, OperatorLoc, MemberDecl, NameInfo, T, VK, OK, NOUR); - // FIXME: remove remaining dependence computation to computeDependence(). - auto Deps = E->getDependence(); if (HasQualOrFound) { - // FIXME: Wrong. We should be looking at the member declaration we found. - if (QualifierLoc && QualifierLoc.getNestedNameSpecifier()->isDependent()) - Deps |= ExprDependence::TypeValueInstantiation; - else if (QualifierLoc && - QualifierLoc.getNestedNameSpecifier()->isInstantiationDependent()) - Deps |= ExprDependence::Instantiation; - E->MemberExprBits.HasQualifierOrFoundDecl = true; MemberExprNameQualifier *NQ = @@ -1751,13 +1771,16 @@ MemberExpr *MemberExpr::Create( E->MemberExprBits.HasTemplateKWAndArgsInfo = TemplateArgs || TemplateKWLoc.isValid(); + // FIXME: remove remaining dependence computation to computeDependence(). + auto Deps = E->getDependence(); if (TemplateArgs) { auto TemplateArgDeps = TemplateArgumentDependence::None; E->getTrailingObjects()->initializeFrom( TemplateKWLoc, *TemplateArgs, E->getTrailingObjects(), TemplateArgDeps); - if (TemplateArgDeps & TemplateArgumentDependence::Instantiation) - Deps |= ExprDependence::Instantiation; + for (const TemplateArgumentLoc &ArgLoc : TemplateArgs->arguments()) { + Deps |= toExprDependence(ArgLoc.getArgument().getDependence()); + } } else if (TemplateKWLoc.isValid()) { E->getTrailingObjects()->initializeFrom( TemplateKWLoc); @@ -1953,7 +1976,7 @@ const char *CastExpr::getCastKindName(CastKind CK) { namespace { // Skip over implicit nodes produced as part of semantic analysis. // Designed for use with IgnoreExprNodes. -Expr *ignoreImplicitSemaNodes(Expr *E) { +static Expr *ignoreImplicitSemaNodes(Expr *E) { if (auto *Materialize = dyn_cast(E)) return Materialize->getSubExpr(); @@ -2198,12 +2221,13 @@ OverloadedOperatorKind BinaryOperator::getOverloadedOperator(Opcode Opc) { bool BinaryOperator::isNullPointerArithmeticExtension(ASTContext &Ctx, Opcode Opc, - Expr *LHS, Expr *RHS) { + const Expr *LHS, + const Expr *RHS) { if (Opc != BO_Add) return false; // Check that we have one pointer and one integer operand. - Expr *PExp; + const Expr *PExp; if (LHS->getType()->isPointerType()) { if (!RHS->getType()->isIntegerType()) return false; @@ -2243,8 +2267,12 @@ StringRef SourceLocExpr::getBuiltinStr() const { switch (getIdentKind()) { case File: return "__builtin_FILE"; + case FileName: + return "__builtin_FILE_NAME"; case Function: return "__builtin_FUNCTION"; + case FuncSig: + return "__builtin_FUNCSIG"; case Line: return "__builtin_LINE"; case Column: @@ -2260,14 +2288,17 @@ APValue SourceLocExpr::EvaluateInContext(const ASTContext &Ctx, SourceLocation Loc; const DeclContext *Context; - std::tie(Loc, - Context) = [&]() -> std::pair { - if (auto *DIE = dyn_cast_or_null(DefaultExpr)) - return {DIE->getUsedLocation(), DIE->getUsedContext()}; - if (auto *DAE = dyn_cast_or_null(DefaultExpr)) - return {DAE->getUsedLocation(), DAE->getUsedContext()}; - return {this->getLocation(), this->getParentContext()}; - }(); + if (const auto *DIE = dyn_cast_if_present(DefaultExpr)) { + Loc = DIE->getUsedLocation(); + Context = DIE->getUsedContext(); + } else if (const auto *DAE = + dyn_cast_if_present(DefaultExpr)) { + Loc = DAE->getUsedLocation(); + Context = DAE->getUsedContext(); + } else { + Loc = getLocation(); + Context = getParentContext(); + } PresumedLoc PLoc = Ctx.getSourceManager().getPresumedLoc( Ctx.getSourceManager().getExpansionRange(Loc).getEnd()); @@ -2281,26 +2312,33 @@ APValue SourceLocExpr::EvaluateInContext(const ASTContext &Ctx, }; switch (getIdentKind()) { + case SourceLocExpr::FileName: { + // __builtin_FILE_NAME() is a Clang-specific extension that expands to the + // the last part of __builtin_FILE(). + SmallString<256> FileName; + clang::Preprocessor::processPathToFileName( + FileName, PLoc, Ctx.getLangOpts(), Ctx.getTargetInfo()); + return MakeStringLiteral(FileName); + } case SourceLocExpr::File: { SmallString<256> Path(PLoc.getFilename()); clang::Preprocessor::processPathForFileMacro(Path, Ctx.getLangOpts(), Ctx.getTargetInfo()); return MakeStringLiteral(Path); } - case SourceLocExpr::Function: { + case SourceLocExpr::Function: + case SourceLocExpr::FuncSig: { const auto *CurDecl = dyn_cast(Context); + const auto Kind = getIdentKind() == SourceLocExpr::Function + ? PredefinedExpr::Function + : PredefinedExpr::FuncSig; return MakeStringLiteral( - CurDecl ? PredefinedExpr::ComputeName(PredefinedExpr::Function, CurDecl) - : std::string("")); + CurDecl ? PredefinedExpr::ComputeName(Kind, CurDecl) : std::string("")); } case SourceLocExpr::Line: - case SourceLocExpr::Column: { - llvm::APSInt IntVal(Ctx.getIntWidth(Ctx.UnsignedIntTy), - /*isUnsigned=*/true); - IntVal = getIdentKind() == SourceLocExpr::Line ? PLoc.getLine() - : PLoc.getColumn(); - return APValue(IntVal); - } + return APValue(Ctx.MakeIntValue(PLoc.getLine(), Ctx.UnsignedIntTy)); + case SourceLocExpr::Column: + return APValue(Ctx.MakeIntValue(PLoc.getColumn(), Ctx.UnsignedIntTy)); case SourceLocExpr::SourceLocStruct: { // Fill in a std::source_location::__impl structure, by creating an // artificial file-scoped CompoundLiteralExpr, and returning a pointer to @@ -2313,7 +2351,7 @@ APValue SourceLocExpr::EvaluateInContext(const ASTContext &Ctx, // the ImplDecl type is as expected. APValue Value(APValue::UninitStruct(), 0, 4); - for (FieldDecl *F : ImplDecl->fields()) { + for (const FieldDecl *F : ImplDecl->fields()) { StringRef Name = F->getName(); if (Name == "_M_file_name") { SmallString<256> Path(PLoc.getFilename()); @@ -2330,16 +2368,10 @@ APValue SourceLocExpr::EvaluateInContext(const ASTContext &Ctx, PredefinedExpr::PrettyFunction, CurDecl)) : ""); } else if (Name == "_M_line") { - QualType Ty = F->getType(); - llvm::APSInt IntVal(Ctx.getIntWidth(Ty), - Ty->hasUnsignedIntegerRepresentation()); - IntVal = PLoc.getLine(); + llvm::APSInt IntVal = Ctx.MakeIntValue(PLoc.getLine(), F->getType()); Value.getStructField(F->getFieldIndex()) = APValue(IntVal); } else if (Name == "_M_column") { - QualType Ty = F->getType(); - llvm::APSInt IntVal(Ctx.getIntWidth(Ty), - Ty->hasUnsignedIntegerRepresentation()); - IntVal = PLoc.getColumn(); + llvm::APSInt IntVal = Ctx.MakeIntValue(PLoc.getColumn(), F->getType()); Value.getStructField(F->getFieldIndex()) = APValue(IntVal); } } @@ -3280,6 +3312,10 @@ bool Expr::isConstantInitializer(ASTContext &Ctx, bool IsForRef, // kill the second parameter. if (IsForRef) { + if (auto *EWC = dyn_cast(this)) + return EWC->getSubExpr()->isConstantInitializer(Ctx, true, Culprit); + if (auto *MTE = dyn_cast(this)) + return MTE->getSubExpr()->isConstantInitializer(Ctx, false, Culprit); EvalResult Result; if (EvaluateAsLValue(Result, Ctx) && !Result.HasSideEffects) return true; @@ -3417,6 +3453,7 @@ bool Expr::isConstantInitializer(ASTContext &Ctx, bool IsForRef, CE->getCastKind() == CK_ConstructorConversion || CE->getCastKind() == CK_NonAtomicToAtomic || CE->getCastKind() == CK_AtomicToNonAtomic || + CE->getCastKind() == CK_NullToPointer || CE->getCastKind() == CK_IntToOCLSampler) return CE->getSubExpr()->isConstantInitializer(Ctx, false, Culprit); @@ -4310,18 +4347,48 @@ GenericSelectionExpr::GenericSelectionExpr( AssocExprs[ResultIndex]->getValueKind(), AssocExprs[ResultIndex]->getObjectKind()), NumAssocs(AssocExprs.size()), ResultIndex(ResultIndex), - DefaultLoc(DefaultLoc), RParenLoc(RParenLoc) { + IsExprPredicate(true), DefaultLoc(DefaultLoc), RParenLoc(RParenLoc) { assert(AssocTypes.size() == AssocExprs.size() && "Must have the same number of association expressions" " and TypeSourceInfo!"); assert(ResultIndex < NumAssocs && "ResultIndex is out-of-bounds!"); GenericSelectionExprBits.GenericLoc = GenericLoc; - getTrailingObjects()[ControllingIndex] = ControllingExpr; + getTrailingObjects()[getIndexOfControllingExpression()] = + ControllingExpr; std::copy(AssocExprs.begin(), AssocExprs.end(), - getTrailingObjects() + AssocExprStartIndex); + getTrailingObjects() + getIndexOfStartOfAssociatedExprs()); std::copy(AssocTypes.begin(), AssocTypes.end(), - getTrailingObjects()); + getTrailingObjects() + + getIndexOfStartOfAssociatedTypes()); + + setDependence(computeDependence(this, ContainsUnexpandedParameterPack)); +} + +GenericSelectionExpr::GenericSelectionExpr( + const ASTContext &, SourceLocation GenericLoc, + TypeSourceInfo *ControllingType, ArrayRef AssocTypes, + ArrayRef AssocExprs, SourceLocation DefaultLoc, + SourceLocation RParenLoc, bool ContainsUnexpandedParameterPack, + unsigned ResultIndex) + : Expr(GenericSelectionExprClass, AssocExprs[ResultIndex]->getType(), + AssocExprs[ResultIndex]->getValueKind(), + AssocExprs[ResultIndex]->getObjectKind()), + NumAssocs(AssocExprs.size()), ResultIndex(ResultIndex), + IsExprPredicate(false), DefaultLoc(DefaultLoc), RParenLoc(RParenLoc) { + assert(AssocTypes.size() == AssocExprs.size() && + "Must have the same number of association expressions" + " and TypeSourceInfo!"); + assert(ResultIndex < NumAssocs && "ResultIndex is out-of-bounds!"); + + GenericSelectionExprBits.GenericLoc = GenericLoc; + getTrailingObjects()[getIndexOfControllingType()] = + ControllingType; + std::copy(AssocExprs.begin(), AssocExprs.end(), + getTrailingObjects() + getIndexOfStartOfAssociatedExprs()); + std::copy(AssocTypes.begin(), AssocTypes.end(), + getTrailingObjects() + + getIndexOfStartOfAssociatedTypes()); setDependence(computeDependence(this, ContainsUnexpandedParameterPack)); } @@ -4334,17 +4401,44 @@ GenericSelectionExpr::GenericSelectionExpr( : Expr(GenericSelectionExprClass, Context.DependentTy, VK_PRValue, OK_Ordinary), NumAssocs(AssocExprs.size()), ResultIndex(ResultDependentIndex), - DefaultLoc(DefaultLoc), RParenLoc(RParenLoc) { + IsExprPredicate(true), DefaultLoc(DefaultLoc), RParenLoc(RParenLoc) { assert(AssocTypes.size() == AssocExprs.size() && "Must have the same number of association expressions" " and TypeSourceInfo!"); GenericSelectionExprBits.GenericLoc = GenericLoc; - getTrailingObjects()[ControllingIndex] = ControllingExpr; + getTrailingObjects()[getIndexOfControllingExpression()] = + ControllingExpr; std::copy(AssocExprs.begin(), AssocExprs.end(), - getTrailingObjects() + AssocExprStartIndex); + getTrailingObjects() + getIndexOfStartOfAssociatedExprs()); std::copy(AssocTypes.begin(), AssocTypes.end(), - getTrailingObjects()); + getTrailingObjects() + + getIndexOfStartOfAssociatedTypes()); + + setDependence(computeDependence(this, ContainsUnexpandedParameterPack)); +} + +GenericSelectionExpr::GenericSelectionExpr( + const ASTContext &Context, SourceLocation GenericLoc, + TypeSourceInfo *ControllingType, ArrayRef AssocTypes, + ArrayRef AssocExprs, SourceLocation DefaultLoc, + SourceLocation RParenLoc, bool ContainsUnexpandedParameterPack) + : Expr(GenericSelectionExprClass, Context.DependentTy, VK_PRValue, + OK_Ordinary), + NumAssocs(AssocExprs.size()), ResultIndex(ResultDependentIndex), + IsExprPredicate(false), DefaultLoc(DefaultLoc), RParenLoc(RParenLoc) { + assert(AssocTypes.size() == AssocExprs.size() && + "Must have the same number of association expressions" + " and TypeSourceInfo!"); + + GenericSelectionExprBits.GenericLoc = GenericLoc; + getTrailingObjects()[getIndexOfControllingType()] = + ControllingType; + std::copy(AssocExprs.begin(), AssocExprs.end(), + getTrailingObjects() + getIndexOfStartOfAssociatedExprs()); + std::copy(AssocTypes.begin(), AssocTypes.end(), + getTrailingObjects() + + getIndexOfStartOfAssociatedTypes()); setDependence(computeDependence(this, ContainsUnexpandedParameterPack)); } @@ -4380,6 +4474,35 @@ GenericSelectionExpr *GenericSelectionExpr::Create( RParenLoc, ContainsUnexpandedParameterPack); } +GenericSelectionExpr *GenericSelectionExpr::Create( + const ASTContext &Context, SourceLocation GenericLoc, + TypeSourceInfo *ControllingType, ArrayRef AssocTypes, + ArrayRef AssocExprs, SourceLocation DefaultLoc, + SourceLocation RParenLoc, bool ContainsUnexpandedParameterPack, + unsigned ResultIndex) { + unsigned NumAssocs = AssocExprs.size(); + void *Mem = Context.Allocate( + totalSizeToAlloc(1 + NumAssocs, NumAssocs), + alignof(GenericSelectionExpr)); + return new (Mem) GenericSelectionExpr( + Context, GenericLoc, ControllingType, AssocTypes, AssocExprs, DefaultLoc, + RParenLoc, ContainsUnexpandedParameterPack, ResultIndex); +} + +GenericSelectionExpr *GenericSelectionExpr::Create( + const ASTContext &Context, SourceLocation GenericLoc, + TypeSourceInfo *ControllingType, ArrayRef AssocTypes, + ArrayRef AssocExprs, SourceLocation DefaultLoc, + SourceLocation RParenLoc, bool ContainsUnexpandedParameterPack) { + unsigned NumAssocs = AssocExprs.size(); + void *Mem = Context.Allocate( + totalSizeToAlloc(1 + NumAssocs, NumAssocs), + alignof(GenericSelectionExpr)); + return new (Mem) GenericSelectionExpr( + Context, GenericLoc, ControllingType, AssocTypes, AssocExprs, DefaultLoc, + RParenLoc, ContainsUnexpandedParameterPack); +} + GenericSelectionExpr * GenericSelectionExpr::CreateEmpty(const ASTContext &Context, unsigned NumAssocs) { @@ -4393,11 +4516,11 @@ GenericSelectionExpr::CreateEmpty(const ASTContext &Context, // DesignatedInitExpr //===----------------------------------------------------------------------===// -IdentifierInfo *DesignatedInitExpr::Designator::getFieldName() const { - assert(Kind == FieldDesignator && "Only valid on a field designator"); - if (Field.NameOrField & 0x01) - return reinterpret_cast(Field.NameOrField & ~0x01); - return getField()->getIdentifier(); +const IdentifierInfo *DesignatedInitExpr::Designator::getFieldName() const { + assert(isFieldDesignator() && "Only valid on a field designator"); + if (FieldInfo.NameOrField & 0x01) + return reinterpret_cast(FieldInfo.NameOrField & ~0x01); + return getFieldDecl()->getIdentifier(); } DesignatedInitExpr::DesignatedInitExpr(const ASTContext &C, QualType Ty, @@ -4472,14 +4595,11 @@ SourceRange DesignatedInitExpr::getDesignatorsSourceRange() const { } SourceLocation DesignatedInitExpr::getBeginLoc() const { - SourceLocation StartLoc; auto *DIE = const_cast(this); Designator &First = *DIE->getDesignator(0); if (First.isFieldDesignator()) - StartLoc = GNUSyntax ? First.Field.FieldLoc : First.Field.DotLoc; - else - StartLoc = First.ArrayOrRange.LBracketLoc; - return StartLoc; + return GNUSyntax ? First.getFieldLoc() : First.getDotLoc(); + return First.getLBracketLoc(); } SourceLocation DesignatedInitExpr::getEndLoc() const { @@ -4487,20 +4607,18 @@ SourceLocation DesignatedInitExpr::getEndLoc() const { } Expr *DesignatedInitExpr::getArrayIndex(const Designator& D) const { - assert(D.Kind == Designator::ArrayDesignator && "Requires array designator"); - return getSubExpr(D.ArrayOrRange.Index + 1); + assert(D.isArrayDesignator() && "Requires array designator"); + return getSubExpr(D.getArrayIndex() + 1); } Expr *DesignatedInitExpr::getArrayRangeStart(const Designator &D) const { - assert(D.Kind == Designator::ArrayRangeDesignator && - "Requires array range designator"); - return getSubExpr(D.ArrayOrRange.Index + 1); + assert(D.isArrayRangeDesignator() && "Requires array range designator"); + return getSubExpr(D.getArrayIndex() + 1); } Expr *DesignatedInitExpr::getArrayRangeEnd(const Designator &D) const { - assert(D.Kind == Designator::ArrayRangeDesignator && - "Requires array range designator"); - return getSubExpr(D.ArrayOrRange.Index + 2); + assert(D.isArrayRangeDesignator() && "Requires array range designator"); + return getSubExpr(D.getArrayIndex() + 2); } /// Replaces the designator at index @p Idx with the series @@ -4846,6 +4964,7 @@ unsigned AtomicExpr::getNumSubExprs(AtomicOp Op) { case AO__hip_atomic_exchange: case AO__hip_atomic_fetch_add: + case AO__hip_atomic_fetch_sub: case AO__hip_atomic_fetch_and: case AO__hip_atomic_fetch_or: case AO__hip_atomic_fetch_xor: diff --git a/contrib/llvm-project/clang/lib/AST/ExprCXX.cpp b/contrib/llvm-project/clang/lib/AST/ExprCXX.cpp index 2a9e3359501..72feb206cc3 100644 --- a/contrib/llvm-project/clang/lib/AST/ExprCXX.cpp +++ b/contrib/llvm-project/clang/lib/AST/ExprCXX.cpp @@ -276,6 +276,8 @@ CXXNewExpr *CXXNewExpr::CreateEmpty(const ASTContext &Ctx, bool IsArray, } bool CXXNewExpr::shouldNullCheckAllocation() const { + if (getOperatorNew()->getLangOpts().CheckNew) + return true; return !getOperatorNew()->hasAttr() && getOperatorNew() ->getType() @@ -765,29 +767,35 @@ CXXDynamicCastExpr *CXXDynamicCastExpr::CreateEmpty(const ASTContext &C, /// struct C { }; /// /// C *f(B* b) { return dynamic_cast(b); } -bool CXXDynamicCastExpr::isAlwaysNull() const -{ +bool CXXDynamicCastExpr::isAlwaysNull() const { + if (isValueDependent() || getCastKind() != CK_Dynamic) + return false; + QualType SrcType = getSubExpr()->getType(); QualType DestType = getType(); - if (const auto *SrcPTy = SrcType->getAs()) { - SrcType = SrcPTy->getPointeeType(); - DestType = DestType->castAs()->getPointeeType(); + if (DestType->isVoidPointerType()) + return false; + + if (DestType->isPointerType()) { + SrcType = SrcType->getPointeeType(); + DestType = DestType->getPointeeType(); } - if (DestType->isVoidType()) - return false; + const auto *SrcRD = SrcType->getAsCXXRecordDecl(); + const auto *DestRD = DestType->getAsCXXRecordDecl(); + assert(SrcRD && DestRD); - const auto *SrcRD = - cast(SrcType->castAs()->getDecl()); + if (SrcRD->isEffectivelyFinal()) { + assert(!SrcRD->isDerivedFrom(DestRD) && + "upcasts should not use CK_Dynamic"); + return true; + } - if (!SrcRD->hasAttr()) - return false; + if (DestRD->isEffectivelyFinal() && !DestRD->isDerivedFrom(SrcRD)) + return true; - const auto *DestRD = - cast(DestType->castAs()->getDecl()); - - return !DestRD->isDerivedFrom(SrcRD); + return false; } CXXReinterpretCastExpr * @@ -1136,6 +1144,7 @@ CXXConstructExpr::CXXConstructExpr( CXXConstructExprBits.StdInitListInitialization = StdInitListInitialization; CXXConstructExprBits.ZeroInitialization = ZeroInitialization; CXXConstructExprBits.ConstructionKind = ConstructKind; + CXXConstructExprBits.IsImmediateEscalating = false; CXXConstructExprBits.Loc = Loc; Stmt **TrailingArgs = getTrailingArgs(); @@ -1392,17 +1401,16 @@ ExprWithCleanups *ExprWithCleanups::Create(const ASTContext &C, return new (buffer) ExprWithCleanups(empty, numObjects); } -CXXUnresolvedConstructExpr::CXXUnresolvedConstructExpr(QualType T, - TypeSourceInfo *TSI, - SourceLocation LParenLoc, - ArrayRef Args, - SourceLocation RParenLoc) +CXXUnresolvedConstructExpr::CXXUnresolvedConstructExpr( + QualType T, TypeSourceInfo *TSI, SourceLocation LParenLoc, + ArrayRef Args, SourceLocation RParenLoc, bool IsListInit) : Expr(CXXUnresolvedConstructExprClass, T, (TSI->getType()->isLValueReferenceType() ? VK_LValue : TSI->getType()->isRValueReferenceType() ? VK_XValue : VK_PRValue), OK_Ordinary), - TSI(TSI), LParenLoc(LParenLoc), RParenLoc(RParenLoc) { + TypeAndInitForm(TSI, IsListInit), LParenLoc(LParenLoc), + RParenLoc(RParenLoc) { CXXUnresolvedConstructExprBits.NumArgs = Args.size(); auto **StoredArgs = getTrailingObjects(); for (unsigned I = 0; I != Args.size(); ++I) @@ -1411,11 +1419,12 @@ CXXUnresolvedConstructExpr::CXXUnresolvedConstructExpr(QualType T, } CXXUnresolvedConstructExpr *CXXUnresolvedConstructExpr::Create( - const ASTContext &Context, QualType T, TypeSourceInfo *TSI, SourceLocation LParenLoc, - ArrayRef Args, SourceLocation RParenLoc) { + const ASTContext &Context, QualType T, TypeSourceInfo *TSI, + SourceLocation LParenLoc, ArrayRef Args, SourceLocation RParenLoc, + bool IsListInit) { void *Mem = Context.Allocate(totalSizeToAlloc(Args.size())); - return new (Mem) - CXXUnresolvedConstructExpr(T, TSI, LParenLoc, Args, RParenLoc); + return new (Mem) CXXUnresolvedConstructExpr(T, TSI, LParenLoc, Args, + RParenLoc, IsListInit); } CXXUnresolvedConstructExpr * @@ -1426,7 +1435,7 @@ CXXUnresolvedConstructExpr::CreateEmpty(const ASTContext &Context, } SourceLocation CXXUnresolvedConstructExpr::getBeginLoc() const { - return TSI->getTypeLoc().getBeginLoc(); + return TypeAndInitForm.getPointer()->getTypeLoc().getBeginLoc(); } CXXDependentScopeMemberExpr::CXXDependentScopeMemberExpr( diff --git a/contrib/llvm-project/clang/lib/AST/ExprConcepts.cpp b/contrib/llvm-project/clang/lib/AST/ExprConcepts.cpp index cdc13c2d396..5698b78d193 100644 --- a/contrib/llvm-project/clang/lib/AST/ExprConcepts.cpp +++ b/contrib/llvm-project/clang/lib/AST/ExprConcepts.cpp @@ -58,15 +58,6 @@ ConceptSpecializationExpr::ConceptSpecializationExpr( ConceptSpecializationExpr::ConceptSpecializationExpr(EmptyShell Empty) : Expr(ConceptSpecializationExprClass, Empty) {} -ConceptSpecializationExpr *ConceptSpecializationExpr::Create( - const ASTContext &C, ConceptDecl *NamedConcept, - ImplicitConceptSpecializationDecl *SpecDecl, - const ConstraintSatisfaction *Satisfaction, bool Dependent, - bool ContainsUnexpandedParameterPack) { - return Create(C, NamedConcept, /*ArgsAsWritten*/ nullptr, SpecDecl, Satisfaction, - Dependent, ContainsUnexpandedParameterPack); -} - ConceptSpecializationExpr *ConceptSpecializationExpr::Create( const ASTContext &C, NestedNameSpecifierLoc NNS, SourceLocation TemplateKWLoc, DeclarationNameInfo ConceptNameInfo, @@ -123,6 +114,19 @@ concepts::ExprRequirement::ReturnTypeRequirement::getTypeConstraint() const { ->getTypeConstraint(); } +// Search through the requirements, and see if any have a RecoveryExpr in it, +// which means this RequiresExpr ALSO needs to be invalid. +static bool RequirementContainsError(concepts::Requirement *R) { + if (auto *ExprReq = dyn_cast(R)) + return ExprReq->getExpr() && ExprReq->getExpr()->containsErrors(); + + if (auto *NestedReq = dyn_cast(R)) + return !NestedReq->hasInvalidConstraint() && + NestedReq->getConstraintExpr() && + NestedReq->getConstraintExpr()->containsErrors(); + return false; +} + RequiresExpr::RequiresExpr(ASTContext &C, SourceLocation RequiresKWLoc, RequiresExprBodyDecl *Body, ArrayRef LocalParameters, @@ -149,6 +153,9 @@ RequiresExpr::RequiresExpr(ASTContext &C, SourceLocation RequiresKWLoc, if (!RequiresExprBits.IsSatisfied) break; } + + if (RequirementContainsError(R)) + setDependence(getDependence() | ExprDependence::Error); } std::copy(LocalParameters.begin(), LocalParameters.end(), getTrailingObjects()); diff --git a/contrib/llvm-project/clang/lib/AST/ExprConstant.cpp b/contrib/llvm-project/clang/lib/AST/ExprConstant.cpp index db6c07d4ab7..f1c842e2619 100644 --- a/contrib/llvm-project/clang/lib/AST/ExprConstant.cpp +++ b/contrib/llvm-project/clang/lib/AST/ExprConstant.cpp @@ -50,9 +50,11 @@ #include "clang/AST/StmtVisitor.h" #include "clang/AST/TypeLoc.h" #include "clang/Basic/Builtins.h" +#include "clang/Basic/DiagnosticSema.h" #include "clang/Basic/TargetInfo.h" #include "llvm/ADT/APFixedPoint.h" #include "llvm/ADT/SmallBitVector.h" +#include "llvm/ADT/StringExtras.h" #include "llvm/Support/Debug.h" #include "llvm/Support/SaveAndRestore.h" #include "llvm/Support/TimeProfiler.h" @@ -530,6 +532,9 @@ namespace { /// This - The binding for the this pointer in this call, if any. const LValue *This; + /// CallExpr - The syntactical structure of member function calls + const Expr *CallExpr; + /// Information on how to find the arguments to this call. Our arguments /// are stored in our parent's CallStackFrame, using the ParmVarDecl* as a /// key and this value as the version. @@ -579,11 +584,11 @@ namespace { /// LambdaCaptureFields - Mapping from captured variables/this to /// corresponding data members in the closure class. llvm::DenseMap LambdaCaptureFields; - FieldDecl *LambdaThisCaptureField; + FieldDecl *LambdaThisCaptureField = nullptr; CallStackFrame(EvalInfo &Info, SourceLocation CallLoc, const FunctionDecl *Callee, const LValue *This, - CallRef Arguments); + const Expr *CallExpr, CallRef Arguments); ~CallStackFrame(); // Return the temporary for Key whose version number is Version. @@ -622,7 +627,7 @@ namespace { /// Allocate storage for a parameter of a function call made in this frame. APValue &createParam(CallRef Args, const ParmVarDecl *PVD, LValue &LV); - void describe(llvm::raw_ostream &OS) override; + void describe(llvm::raw_ostream &OS) const override; Frame *getCaller() const override { return Caller; } SourceLocation getCallLocation() const override { return CallLoc; } @@ -977,7 +982,9 @@ namespace { CallStackDepth(0), NextCallIndex(1), StepsLeft(C.getLangOpts().ConstexprStepLimit), EnableNewConstInterp(C.getLangOpts().EnableNewConstInterp), - BottomFrame(*this, SourceLocation(), nullptr, nullptr, CallRef()), + BottomFrame(*this, SourceLocation(), /*Callee=*/nullptr, + /*This=*/nullptr, + /*CallExpr=*/nullptr, CallRef()), EvaluatingDecl((const ValueDecl *)nullptr), EvaluatingDeclValue(nullptr), HasActiveDiagnostic(false), HasFoldFailureDiagnostic(false), EvalMode(Mode) {} @@ -1294,7 +1301,7 @@ namespace { class SpeculativeEvaluationRAII { EvalInfo *Info = nullptr; Expr::EvalStatus OldStatus; - unsigned OldSpeculativeEvaluationDepth; + unsigned OldSpeculativeEvaluationDepth = 0; void moveFromAndCancel(SpeculativeEvaluationRAII &&Other) { Info = Other.Info; @@ -1435,9 +1442,10 @@ void SubobjectDesignator::diagnosePointerArithmetic(EvalInfo &Info, CallStackFrame::CallStackFrame(EvalInfo &Info, SourceLocation CallLoc, const FunctionDecl *Callee, const LValue *This, - CallRef Call) + const Expr *CallExpr, CallRef Call) : Info(Info), Caller(Info.CurrentCall), Callee(Callee), This(This), - Arguments(Call), CallLoc(CallLoc), Index(Info.NextCallIndex++) { + CallExpr(CallExpr), Arguments(Call), CallLoc(CallLoc), + Index(Info.NextCallIndex++) { Info.CurrentCall = this; ++Info.CallStackDepth; } @@ -1907,7 +1915,7 @@ APValue *EvalInfo::createHeapAlloc(const Expr *E, QualType T, LValue &LV) { } /// Produce a string describing the given constexpr call. -void CallStackFrame::describe(raw_ostream &Out) { +void CallStackFrame::describe(raw_ostream &Out) const { unsigned ArgIndex = 0; bool IsMemberCall = isa(Callee) && !isa(Callee) && @@ -1917,12 +1925,29 @@ void CallStackFrame::describe(raw_ostream &Out) { Out << *Callee << '('; if (This && IsMemberCall) { - APValue Val; - This->moveInto(Val); - Val.printPretty(Out, Info.Ctx, - This->Designator.MostDerivedType); - // FIXME: Add parens around Val if needed. - Out << "->" << *Callee << '('; + if (const auto *MCE = dyn_cast_if_present(CallExpr)) { + const Expr *Object = MCE->getImplicitObjectArgument(); + Object->printPretty(Out, /*Helper=*/nullptr, Info.Ctx.getPrintingPolicy(), + /*Indentation=*/0); + if (Object->getType()->isPointerType()) + Out << "->"; + else + Out << "."; + } else if (const auto *OCE = + dyn_cast_if_present(CallExpr)) { + OCE->getArg(0)->printPretty(Out, /*Helper=*/nullptr, + Info.Ctx.getPrintingPolicy(), + /*Indentation=*/0); + Out << "."; + } else { + APValue Val; + This->moveInto(Val); + Val.printPretty( + Out, Info.Ctx, + Info.Ctx.getLValueReferenceType(This->Designator.MostDerivedType)); + Out << "."; + } + Out << *Callee << '('; IsMemberCall = false; } @@ -1971,7 +1996,8 @@ static bool IsGlobalLValue(APValue::LValueBase B) { // ... a null pointer value, or a prvalue core constant expression of type // std::nullptr_t. - if (!B) return true; + if (!B) + return true; if (const ValueDecl *D = B.dyn_cast()) { // ... the address of an object with static storage duration, @@ -2102,6 +2128,7 @@ static void NoteLValueLocation(EvalInfo &Info, APValue::LValueBase Base) { Info.Note((*Alloc)->AllocExpr->getExprLoc(), diag::note_constexpr_dynamic_alloc_here); } + // We have no information to show for a typeid(T) object. } @@ -2119,7 +2146,7 @@ static bool CheckEvaluationResult(CheckEvaluationResultKind CERK, EvalInfo &Info, SourceLocation DiagLoc, QualType Type, const APValue &Value, ConstantExprKind Kind, - SourceLocation SubobjectLoc, + const FieldDecl *SubobjectDecl, CheckedTemporaries &CheckedTemps); /// Check that this reference or pointer core constant expression is a valid @@ -2163,13 +2190,12 @@ static bool CheckLValueConstantExpression(EvalInfo &Info, SourceLocation Loc, } } - if (auto *FD = dyn_cast_or_null(BaseVD)) { - if (FD->isConsteval()) { - Info.FFDiag(Loc, diag::note_consteval_address_accessible) - << !Type->isAnyPointerType(); - Info.Note(FD->getLocation(), diag::note_declared_at); - return false; - } + if (auto *FD = dyn_cast_or_null(BaseVD); + FD && FD->isImmediateFunction()) { + Info.FFDiag(Loc, diag::note_consteval_address_accessible) + << !Type->isAnyPointerType(); + Info.Note(FD->getLocation(), diag::note_declared_at); + return false; } // Check that the object is a global. Note that the fake 'this' object we @@ -2266,8 +2292,8 @@ static bool CheckLValueConstantExpression(EvalInfo &Info, SourceLocation Loc, APValue *V = MTE->getOrCreateValue(false); assert(V && "evasluation result refers to uninitialised temporary"); if (!CheckEvaluationResult(CheckEvaluationResultKind::ConstantExpression, - Info, MTE->getExprLoc(), TempType, *V, - Kind, SourceLocation(), CheckedTemps)) + Info, MTE->getExprLoc(), TempType, *V, Kind, + /*SubobjectDecl=*/nullptr, CheckedTemps)) return false; } } @@ -2305,7 +2331,7 @@ static bool CheckMemberPointerConstantExpression(EvalInfo &Info, const auto *FD = dyn_cast_or_null(Member); if (!FD) return true; - if (FD->isConsteval()) { + if (FD->isImmediateFunction()) { Info.FFDiag(Loc, diag::note_consteval_address_accessible) << /*pointer*/ 0; Info.Note(FD->getLocation(), diag::note_declared_at); return false; @@ -2350,13 +2376,13 @@ static bool CheckEvaluationResult(CheckEvaluationResultKind CERK, EvalInfo &Info, SourceLocation DiagLoc, QualType Type, const APValue &Value, ConstantExprKind Kind, - SourceLocation SubobjectLoc, + const FieldDecl *SubobjectDecl, CheckedTemporaries &CheckedTemps) { if (!Value.hasValue()) { - Info.FFDiag(DiagLoc, diag::note_constexpr_uninitialized) - << true << Type; - if (SubobjectLoc.isValid()) - Info.Note(SubobjectLoc, diag::note_constexpr_subobject_declared_here); + assert(SubobjectDecl && "SubobjectDecl shall be non-null"); + Info.FFDiag(DiagLoc, diag::note_constexpr_uninitialized) << SubobjectDecl; + Info.Note(SubobjectDecl->getLocation(), + diag::note_constexpr_subobject_declared_here); return false; } @@ -2373,20 +2399,19 @@ static bool CheckEvaluationResult(CheckEvaluationResultKind CERK, for (unsigned I = 0, N = Value.getArrayInitializedElts(); I != N; ++I) { if (!CheckEvaluationResult(CERK, Info, DiagLoc, EltTy, Value.getArrayInitializedElt(I), Kind, - SubobjectLoc, CheckedTemps)) + SubobjectDecl, CheckedTemps)) return false; } if (!Value.hasArrayFiller()) return true; return CheckEvaluationResult(CERK, Info, DiagLoc, EltTy, - Value.getArrayFiller(), Kind, SubobjectLoc, + Value.getArrayFiller(), Kind, SubobjectDecl, CheckedTemps); } if (Value.isUnion() && Value.getUnionField()) { return CheckEvaluationResult( CERK, Info, DiagLoc, Value.getUnionField()->getType(), - Value.getUnionValue(), Kind, Value.getUnionField()->getLocation(), - CheckedTemps); + Value.getUnionValue(), Kind, Value.getUnionField(), CheckedTemps); } if (Value.isStruct()) { RecordDecl *RD = Type->castAs()->getDecl(); @@ -2395,7 +2420,7 @@ static bool CheckEvaluationResult(CheckEvaluationResultKind CERK, for (const CXXBaseSpecifier &BS : CD->bases()) { if (!CheckEvaluationResult(CERK, Info, DiagLoc, BS.getType(), Value.getStructBase(BaseIndex), Kind, - BS.getBeginLoc(), CheckedTemps)) + /*SubobjectDecl=*/nullptr, CheckedTemps)) return false; ++BaseIndex; } @@ -2405,8 +2430,8 @@ static bool CheckEvaluationResult(CheckEvaluationResultKind CERK, continue; if (!CheckEvaluationResult(CERK, Info, DiagLoc, I->getType(), - Value.getStructField(I->getFieldIndex()), - Kind, I->getLocation(), CheckedTemps)) + Value.getStructField(I->getFieldIndex()), Kind, + I, CheckedTemps)) return false; } } @@ -2440,7 +2465,7 @@ static bool CheckConstantExpression(EvalInfo &Info, SourceLocation DiagLoc, CheckedTemporaries CheckedTemps; return CheckEvaluationResult(CheckEvaluationResultKind::ConstantExpression, Info, DiagLoc, Type, Value, Kind, - SourceLocation(), CheckedTemps); + /*SubobjectDecl=*/nullptr, CheckedTemps); } /// Check that this evaluated value is fully-initialized and can be loaded by @@ -2450,7 +2475,7 @@ static bool CheckFullyInitialized(EvalInfo &Info, SourceLocation DiagLoc, CheckedTemporaries CheckedTemps; return CheckEvaluationResult( CheckEvaluationResultKind::FullyInitialized, Info, DiagLoc, Type, Value, - ConstantExprKind::Normal, SourceLocation(), CheckedTemps); + ConstantExprKind::Normal, /*SubobjectDecl=*/nullptr, CheckedTemps); } /// Enforce C++2a [expr.const]/4.17, which disallows new-expressions unless @@ -2802,7 +2827,7 @@ static bool handleIntIntBinOp(EvalInfo &Info, const Expr *E, const APSInt &LHS, // E1 x 2^E2 module 2^N. if (LHS.isNegative()) Info.CCEDiag(E, diag::note_constexpr_lshift_of_negative) << LHS; - else if (LHS.countLeadingZeros() < SA) + else if (LHS.countl_zero() < SA) Info.CCEDiag(E, diag::note_constexpr_lshift_discards); } Result = LHS << SA; @@ -3326,12 +3351,9 @@ static bool evaluateVarDeclInit(EvalInfo &Info, const Expr *E, // 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; + if (!VD->evaluateValue()) { + Info.FFDiag(E, diag::note_constexpr_var_init_non_constant, 1) << VD; NoteLValueLocation(Info, Base); - Info.addNotes(Notes); return false; } @@ -4988,12 +5010,13 @@ static EvalStmtResult EvaluateSwitch(StmtResult &Result, EvalInfo &Info, !EvaluateDecl(Info, SS->getConditionVariable())) return ESR_Failed; if (SS->getCond()->isValueDependent()) { - if (!EvaluateDependentExpr(SS->getCond(), Info)) - return ESR_Failed; - } else { - if (!EvaluateInteger(SS->getCond(), Value, Info)) - return ESR_Failed; + // We don't know what the value is, and which branch should jump to. + EvaluateDependentExpr(SS->getCond(), Info); + return ESR_Failed; } + if (!EvaluateInteger(SS->getCond(), Value, Info)) + return ESR_Failed; + if (!CondScope.destroy()) return ESR_Failed; } @@ -5046,7 +5069,7 @@ static EvalStmtResult EvaluateSwitch(StmtResult &Result, EvalInfo &Info, static bool CheckLocalVariableDeclaration(EvalInfo &Info, const VarDecl *VD) { // An expression E is a core constant expression unless the evaluation of E - // would evaluate one of the following: [C++2b] - a control flow that passes + // would evaluate one of the following: [C++23] - a control flow that passes // through a declaration of a variable with static or thread storage duration // unless that variable is usable in constant expressions. if (VD->isLocalVarDecl() && VD->isStaticLocal() && @@ -6165,13 +6188,13 @@ static bool handleTrivialCopy(EvalInfo &Info, const ParmVarDecl *Param, /// Evaluate a function call. static bool HandleFunctionCall(SourceLocation CallLoc, const FunctionDecl *Callee, const LValue *This, - ArrayRef Args, CallRef Call, - const Stmt *Body, EvalInfo &Info, + const Expr *E, ArrayRef Args, + CallRef Call, const Stmt *Body, EvalInfo &Info, APValue &Result, const LValue *ResultSlot) { if (!Info.CheckCallLimit(CallLoc)) return false; - CallStackFrame Frame(Info, CallLoc, Callee, This, Call); + CallStackFrame Frame(Info, CallLoc, Callee, This, E, Call); // For a trivial copy or move assignment, perform an APValue copy. This is // essential for unions, where the operations performed by the assignment @@ -6236,7 +6259,7 @@ static bool HandleConstructorCall(const Expr *E, const LValue &This, Info, ObjectUnderConstruction{This.getLValueBase(), This.Designator.Entries}, RD->getNumBases()); - CallStackFrame Frame(Info, CallLoc, Definition, &This, Call); + CallStackFrame Frame(Info, CallLoc, Definition, &This, E, Call); // FIXME: Creating an APValue just to hold a nonexistent return value is // wasteful. @@ -6537,7 +6560,8 @@ static bool HandleDestructionImpl(EvalInfo &Info, SourceLocation CallLoc, if (!CheckConstexprFunction(Info, CallLoc, DD, Definition, Body)) return false; - CallStackFrame Frame(Info, CallLoc, Definition, &This, CallRef()); + CallStackFrame Frame(Info, CallLoc, Definition, &This, /*CallExpr=*/nullptr, + CallRef()); // We're now in the period of destruction of this object. unsigned BasesLeft = RD->getNumBases(); @@ -7671,6 +7695,11 @@ public: if (!CalleeLV.getLValueOffset().isZero()) return Error(Callee); + if (CalleeLV.isNullPointer()) { + Info.FFDiag(Callee, diag::note_constexpr_null_callee) + << const_cast(Callee); + return false; + } FD = dyn_cast_or_null( CalleeLV.getLValueBase().dyn_cast()); if (!FD) @@ -7801,7 +7830,7 @@ public: Stmt *Body = FD->getBody(Definition); if (!CheckConstexprFunction(Info, E->getExprLoc(), FD, Definition, Body) || - !HandleFunctionCall(E->getExprLoc(), Definition, This, Args, Call, + !HandleFunctionCall(E->getExprLoc(), Definition, This, E, Args, Call, Body, Info, Result, ResultSlot)) return false; @@ -8342,6 +8371,7 @@ bool LValueExprEvaluator::VisitCallExpr(const CallExpr *E) { return false; case Builtin::BIas_const: case Builtin::BIforward: + case Builtin::BIforward_like: case Builtin::BImove: case Builtin::BImove_if_noexcept: if (cast(E->getCalleeDecl())->isConstexpr()) @@ -8361,8 +8391,8 @@ bool LValueExprEvaluator::VisitMaterializeTemporaryExpr( E->getSubExpr()->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])) + for (const Expr *E : CommaLHSs) + if (!EvaluateIgnoredValue(Info, E)) return false; // A materialized temporary with static storage duration can appear within the @@ -8370,6 +8400,8 @@ bool LValueExprEvaluator::VisitMaterializeTemporaryExpr( // value for use outside this evaluation. APValue *Value; if (E->getStorageDuration() == SD_Static) { + if (Info.EvalMode == EvalInfo::EM_ConstantFold) + return false; // FIXME: What about SD_Thread? Value = E->getOrCreateValue(true); *Value = APValue(); @@ -8760,16 +8792,19 @@ public: 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)) { - // Ensure we actually have captured 'this'. (an error will have - // been previously reported if not). - if (!Info.CurrentCall->LambdaThisCaptureField) - return false; + if (isLambdaCallOperator(Info.CurrentCall->Callee)) { + // Ensure we actually have captured 'this'. If something was wrong with + // 'this' capture, the error would have been previously reported. + // Otherwise we can be inside of a default initialization of an object + // declared by lambda's body, so no need to return false. + if (!Info.CurrentCall->LambdaThisCaptureField) + return true; + + // If we have captured 'this', 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'. // Update 'Result' to refer to the data member/field of the closure object // that represents the '*this' capture. if (!HandleLValueMember(Info, E, Result, @@ -8892,9 +8927,10 @@ bool PointerExprEvaluator::VisitCastExpr(const CastExpr *E) { if (!E->getType()->isVoidPointerType()) { // In some circumstances, we permit casting from void* to cv1 T*, when the // actual pointee object is actually a cv2 T. + bool HasValidResult = !Result.InvalidBase && !Result.Designator.Invalid && + !Result.IsNullPtr; bool VoidPtrCastMaybeOK = - !Result.InvalidBase && !Result.Designator.Invalid && - !Result.IsNullPtr && + HasValidResult && Info.Ctx.hasSameUnqualifiedType(Result.Designator.getType(Info.Ctx), E->getType()->getPointeeType()); // 1. We'll allow it in std::allocator::allocate, and anything which that @@ -8906,16 +8942,23 @@ bool PointerExprEvaluator::VisitCastExpr(const CastExpr *E) { // that back to `const __impl*` in its body. if (VoidPtrCastMaybeOK && (Info.getStdAllocatorCaller("allocate") || - IsDeclSourceLocationCurrent(Info.CurrentCall->Callee))) { + IsDeclSourceLocationCurrent(Info.CurrentCall->Callee) || + Info.getLangOpts().CPlusPlus26)) { // Permitted. } else { - Result.Designator.setInvalid(); - if (SubExpr->getType()->isVoidPointerType()) - CCEDiag(E, diag::note_constexpr_invalid_cast) - << 3 << SubExpr->getType(); - else + if (SubExpr->getType()->isVoidPointerType()) { + if (HasValidResult) + CCEDiag(E, diag::note_constexpr_invalid_void_star_cast) + << SubExpr->getType() << Info.getLangOpts().CPlusPlus26 + << Result.Designator.getType(Info.Ctx).getCanonicalType() + << E->getType()->getPointeeType(); + else + CCEDiag(E, diag::note_constexpr_invalid_cast) + << 3 << SubExpr->getType(); + } else CCEDiag(E, diag::note_constexpr_invalid_cast) << 2 << Info.Ctx.getLangOpts().CPlusPlus; + Result.Designator.setInvalid(); } } if (E->getCastKind() == CK_AddressSpaceConversion && Result.IsNullPtr) @@ -9020,8 +9063,7 @@ 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(); + T = T.getNonReferenceType(); if (T.getQualifiers().hasUnaligned()) return CharUnits::One(); @@ -10168,6 +10210,8 @@ bool RecordExprEvaluator::VisitCXXStdInitializerListExpr( if (!EvaluateLValue(E->getSubExpr(), Array, Info)) return false; + assert(ArrayType && "unexpected type for array initializer"); + // Get a pointer to the first element of the array. Array.addArray(Info, E, ArrayType); @@ -11284,7 +11328,6 @@ 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) @@ -11297,7 +11340,7 @@ EvaluateBuiltinClassifyType(QualType T, const LangOptions &LangOpts) { llvm_unreachable("unexpected non-canonical or dependent type"); case Type::Builtin: - switch (BT->getKind()) { + switch (cast(CanTy)->getKind()) { #define BUILTIN_TYPE(ID, SINGLETON_ID) #define SIGNED_TYPE(ID, SINGLETON_ID) \ case BuiltinType::ID: return GCCTypeClass::Integer; @@ -11363,6 +11406,8 @@ EvaluateBuiltinClassifyType(QualType T, const LangOptions &LangOpts) { #include "clang/Basic/PPCTypes.def" #define RVV_TYPE(Name, Id, SingletonId) case BuiltinType::Id: #include "clang/Basic/RISCVVTypes.def" +#define WASM_TYPE(Name, Id, SingletonId) case BuiltinType::Id: +#include "clang/Basic/WebAssemblyReferenceTypes.def" return GCCTypeClass::None; case BuiltinType::Dependent: @@ -11711,6 +11756,18 @@ static bool convertUnsignedAPIntToCharUnits(const llvm::APInt &Int, return true; } +/// If we're evaluating the object size of an instance of a struct that +/// contains a flexible array member, add the size of the initializer. +static void addFlexibleArrayMemberInitSize(EvalInfo &Info, const QualType &T, + const LValue &LV, CharUnits &Size) { + if (!T.isNull() && T->isStructureType() && + T->getAsStructureType()->getDecl()->hasFlexibleArrayMember()) + if (const auto *V = LV.getLValueBase().dyn_cast()) + if (const auto *VD = dyn_cast(V)) + if (VD->hasInit()) + Size += VD->getFlexibleArrayInitChars(Info.Ctx); +} + /// 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 @@ -11745,7 +11802,9 @@ static bool determineEndOffset(EvalInfo &Info, SourceLocation ExprLoc, return false; QualType BaseTy = getObjectType(LVal.getLValueBase()); - return CheckedHandleSizeof(BaseTy, EndOffset); + const bool Ret = CheckedHandleSizeof(BaseTy, EndOffset); + addFlexibleArrayMemberInitSize(Info, BaseTy, LVal, EndOffset); + return Ret; } // We want to evaluate the size of a subobject. @@ -12008,7 +12067,7 @@ bool IntExprEvaluator::VisitBuiltinCallExpr(const CallExpr *E, if (!EvaluateInteger(E->getArg(0), Val, Info)) return false; - return Success(Val.getBitWidth() - Val.getMinSignedBits(), E); + return Success(Val.getBitWidth() - Val.getSignificantBits(), E); } case Builtin::BI__builtin_clz: @@ -12021,7 +12080,7 @@ bool IntExprEvaluator::VisitBuiltinCallExpr(const CallExpr *E, if (!Val) return Error(E); - return Success(Val.countLeadingZeros(), E); + return Success(Val.countl_zero(), E); } case Builtin::BI__builtin_constant_p: { @@ -12067,7 +12126,7 @@ bool IntExprEvaluator::VisitBuiltinCallExpr(const CallExpr *E, if (!Val) return Error(E); - return Success(Val.countTrailingZeros(), E); + return Success(Val.countr_zero(), E); } case Builtin::BI__builtin_eh_return_data_regno: { @@ -12087,7 +12146,7 @@ bool IntExprEvaluator::VisitBuiltinCallExpr(const CallExpr *E, if (!EvaluateInteger(E->getArg(0), Val, Info)) return false; - unsigned N = Val.countTrailingZeros(); + unsigned N = Val.countr_zero(); return Success(N == Val.getBitWidth() ? 0 : N + 1, E); } @@ -12135,6 +12194,16 @@ bool IntExprEvaluator::VisitBuiltinCallExpr(const CallExpr *E, Success(Val.isNormal() ? 1 : 0, E); } + case Builtin::BI__builtin_isfpclass: { + APSInt MaskVal; + if (!EvaluateInteger(E->getArg(1), MaskVal, Info)) + return false; + unsigned Test = static_cast(MaskVal.getZExtValue()); + APFloat Val(0.0); + return EvaluateFloat(E->getArg(0), Val, Info) && + Success((Val.classify() & Test) ? 1 : 0, E); + } + case Builtin::BI__builtin_parity: case Builtin::BI__builtin_parityl: case Builtin::BI__builtin_parityll: { @@ -12142,7 +12211,7 @@ bool IntExprEvaluator::VisitBuiltinCallExpr(const CallExpr *E, if (!EvaluateInteger(E->getArg(0), Val, Info)) return false; - return Success(Val.countPopulation() % 2, E); + return Success(Val.popcount() % 2, E); } case Builtin::BI__builtin_popcount: @@ -12152,7 +12221,7 @@ bool IntExprEvaluator::VisitBuiltinCallExpr(const CallExpr *E, if (!EvaluateInteger(E->getArg(0), Val, Info)) return false; - return Success(Val.countPopulation(), E); + return Success(Val.popcount(), E); } case Builtin::BI__builtin_rotateleft8: @@ -13134,12 +13203,12 @@ EvaluateComparisonBinaryOperator(EvalInfo &Info, const BinaryOperator *E, if (LHSValue.getDecl() && LHSValue.getDecl()->isWeak()) { Info.FFDiag(E, diag::note_constexpr_mem_pointer_weak_comparison) << LHSValue.getDecl(); - return true; + return false; } if (RHSValue.getDecl() && RHSValue.getDecl()->isWeak()) { Info.FFDiag(E, diag::note_constexpr_mem_pointer_weak_comparison) << RHSValue.getDecl(); - return true; + return false; } // C++11 [expr.eq]p2: @@ -13502,10 +13571,16 @@ bool IntExprEvaluator::VisitUnaryOperator(const UnaryOperator *E) { 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; + if (Value.isSigned() && Value.isMinSignedValue() && E->canOverflow()) { + if (Info.checkingForUndefinedBehavior()) + Info.Ctx.getDiagnostics().Report(E->getExprLoc(), + diag::warn_integer_constant_overflow) + << toString(Value, 10) << E->getType(); + + if (!HandleOverflow(Info, E, -Value.extend(Value.getBitWidth() + 1), + E->getType())) + return false; + } return Success(-Value, E); } case UO_Not: { @@ -14826,6 +14901,9 @@ public: switch (E->getCastKind()) { default: return ExprEvaluatorBaseTy::VisitCastExpr(E); + case CK_NullToPointer: + VisitIgnoredValue(E->getSubExpr()); + return ZeroInitialization(E); case CK_NonAtomicToAtomic: return This ? EvaluateInPlace(Result, Info, *This, E->getSubExpr()) : Evaluate(Result, Info, E->getSubExpr()); @@ -15038,6 +15116,7 @@ static bool Evaluate(APValue &Result, EvalInfo &Info, const Expr *E) { E, Unqual, ScopeKind::FullExpression, LV); if (!EvaluateAtomic(E, &LV, Value, Info)) return false; + Result = Value; } else { if (!EvaluateAtomic(E, nullptr, Result, Info)) return false; @@ -15340,8 +15419,16 @@ bool Expr::EvaluateAsConstantExpr(EvalResult &Result, const ASTContext &Ctx, LValue LVal; LVal.set(Base); - if (!::EvaluateInPlace(Result.Val, Info, LVal, this) || Result.HasSideEffects) - return false; + { + // C++23 [intro.execution]/p5 + // A full-expression is [...] a constant-expression + // So we need to make sure temporary objects are destroyed after having + // evaluating the expression (per C++23 [class.temporary]/p4). + FullExpressionRAII Scope(Info); + if (!::EvaluateInPlace(Result.Val, Info, LVal, this) || + Result.HasSideEffects || !Scope.destroy()) + return false; + } if (!Info.discardCleanups()) llvm_unreachable("Unhandled cleanup; missing full expression marker?"); @@ -15368,7 +15455,8 @@ bool Expr::EvaluateAsConstantExpr(EvalResult &Result, const ASTContext &Ctx, bool Expr::EvaluateAsInitializer(APValue &Value, const ASTContext &Ctx, const VarDecl *VD, - SmallVectorImpl &Notes) const { + SmallVectorImpl &Notes, + bool IsConstantInitialization) const { assert(!isValueDependent() && "Expression evaluator can't be called on a dependent expression."); @@ -15388,14 +15476,12 @@ bool Expr::EvaluateAsInitializer(APValue &Value, const ASTContext &Ctx, Expr::EvalStatus EStatus; EStatus.Diag = &Notes; - EvalInfo Info(Ctx, EStatus, VD->isConstexpr() - ? EvalInfo::EM_ConstantExpression - : EvalInfo::EM_ConstantFold); + EvalInfo Info(Ctx, EStatus, + (IsConstantInitialization && Ctx.getLangOpts().CPlusPlus) + ? EvalInfo::EM_ConstantExpression + : EvalInfo::EM_ConstantFold); Info.setEvaluatingDecl(VD, Value); - Info.InConstantContext = true; - - SourceLocation DeclLoc = VD->getLocation(); - QualType DeclTy = VD->getType(); + Info.InConstantContext = IsConstantInitialization; if (Info.EnableNewConstInterp) { auto &InterpCtx = const_cast(Ctx).getInterpContext(); @@ -15417,6 +15503,9 @@ bool Expr::EvaluateAsInitializer(APValue &Value, const ASTContext &Ctx, if (!Info.discardCleanups()) llvm_unreachable("Unhandled cleanup; missing full expression marker?"); } + + SourceLocation DeclLoc = VD->getLocation(); + QualType DeclTy = VD->getType(); return CheckConstantExpression(Info, DeclLoc, DeclTy, Value, ConstantExprKind::Normal) && CheckMemoryLeaks(Info); @@ -16147,7 +16236,8 @@ bool Expr::EvaluateWithSubstitution(APValue &Value, ASTContext &Ctx, Info.EvalStatus.HasSideEffects = false; // Build fake call to Callee. - CallStackFrame Frame(Info, Callee->getLocation(), Callee, ThisPtr, Call); + CallStackFrame Frame(Info, Callee->getLocation(), Callee, ThisPtr, This, + Call); // FIXME: Missing ExprWithCleanups in enable_if conditions? FullExpressionRAII Scope(Info); return Evaluate(Value, Info, this) && Scope.destroy() && @@ -16204,7 +16294,8 @@ bool Expr::isPotentialConstantExpr(const FunctionDecl *FD, } else { SourceLocation Loc = FD->getLocation(); HandleFunctionCall(Loc, FD, (MD && MD->isInstance()) ? &This : nullptr, - Args, CallRef(), FD->getBody(), Info, Scratch, nullptr); + &VIE, Args, CallRef(), FD->getBody(), Info, Scratch, + /*ResultSlot=*/nullptr); } return Diags.empty(); @@ -16226,7 +16317,8 @@ bool Expr::isPotentialConstantExprUnevaluated(Expr *E, Info.CheckingPotentialConstantExpression = true; // Fabricate a call stack frame to give the arguments a plausible cover story. - CallStackFrame Frame(Info, SourceLocation(), FD, /*This*/ nullptr, CallRef()); + CallStackFrame Frame(Info, SourceLocation(), FD, /*This=*/nullptr, + /*CallExpr=*/nullptr, CallRef()); APValue ResultScratch; Evaluate(ResultScratch, Info, E); @@ -16292,6 +16384,45 @@ static bool EvaluateBuiltinStrLen(const Expr *E, uint64_t &Result, } } +bool Expr::EvaluateCharRangeAsString(std::string &Result, + const Expr *SizeExpression, + const Expr *PtrExpression, ASTContext &Ctx, + EvalResult &Status) const { + LValue String; + EvalInfo Info(Ctx, Status, EvalInfo::EM_ConstantExpression); + Info.InConstantContext = true; + + FullExpressionRAII Scope(Info); + APSInt SizeValue; + if (!::EvaluateInteger(SizeExpression, SizeValue, Info)) + return false; + + int64_t Size = SizeValue.getExtValue(); + + if (!::EvaluatePointer(PtrExpression, String, Info)) + return false; + + QualType CharTy = PtrExpression->getType()->getPointeeType(); + for (int64_t I = 0; I < Size; ++I) { + APValue Char; + if (!handleLValueToRValueConversion(Info, PtrExpression, CharTy, String, + Char)) + return false; + + APSInt C = Char.getInt(); + Result.push_back(static_cast(C.getExtValue())); + if (!HandleLValueArrayAdjustment(Info, PtrExpression, String, CharTy, 1)) + return false; + } + if (!Scope.destroy()) + return false; + + if (!CheckMemoryLeaks(Info)) + return false; + + return true; +} + bool Expr::tryEvaluateStrLen(uint64_t &Result, ASTContext &Ctx) const { Expr::EvalStatus Status; EvalInfo Info(Ctx, Status, EvalInfo::EM_ConstantFold); diff --git a/contrib/llvm-project/clang/lib/AST/ExternalASTMerger.cpp b/contrib/llvm-project/clang/lib/AST/ExternalASTMerger.cpp index a2ef270d7a9..8bad3b36244 100644 --- a/contrib/llvm-project/clang/lib/AST/ExternalASTMerger.cpp +++ b/contrib/llvm-project/clang/lib/AST/ExternalASTMerger.cpp @@ -187,10 +187,7 @@ public: /// Implements the ASTImporter interface for tracking back a declaration /// to its original declaration it came from. Decl *GetOriginalDecl(Decl *To) override { - auto It = ToOrigin.find(To); - if (It != ToOrigin.end()) - return It->second; - return nullptr; + return ToOrigin.lookup(To); } /// Whenever a DeclContext is imported, ensure that ExternalASTSource's origin @@ -541,4 +538,3 @@ void ExternalASTMerger::FindExternalLexicalDecls( return false; }); } - diff --git a/contrib/llvm-project/clang/lib/AST/FormatString.cpp b/contrib/llvm-project/clang/lib/AST/FormatString.cpp index c7dee2d421b..ad5af950898 100644 --- a/contrib/llvm-project/clang/lib/AST/FormatString.cpp +++ b/contrib/llvm-project/clang/lib/AST/FormatString.cpp @@ -351,10 +351,12 @@ ArgType::matchesType(ASTContext &C, QualType argTy) const { case AnyCharTy: { if (const auto *ETy = argTy->getAs()) { // If the enum is incomplete we know nothing about the underlying type. - // Assume that it's 'int'. + // Assume that it's 'int'. Do not use the underlying type for a scoped + // enumeration. if (!ETy->getDecl()->isComplete()) return NoMatch; - argTy = ETy->getDecl()->getIntegerType(); + if (ETy->isUnscopedEnumerationType()) + argTy = ETy->getDecl()->getIntegerType(); } if (const auto *BT = argTy->getAs()) { @@ -391,10 +393,11 @@ ArgType::matchesType(ASTContext &C, QualType argTy) const { case SpecificTy: { if (const EnumType *ETy = argTy->getAs()) { // If the enum is incomplete we know nothing about the underlying type. - // Assume that it's 'int'. + // Assume that it's 'int'. Do not use the underlying type for a scoped + // enumeration as that needs an exact match. if (!ETy->getDecl()->isComplete()) argTy = C.IntTy; - else + else if (ETy->isUnscopedEnumerationType()) argTy = ETy->getDecl()->getIntegerType(); } argTy = C.getCanonicalType(argTy).getUnqualifiedType(); @@ -848,6 +851,8 @@ bool FormatSpecifier::hasValidLengthModifier(const TargetInfo &Target, } switch (CS.getKind()) { + case ConversionSpecifier::bArg: + case ConversionSpecifier::BArg: case ConversionSpecifier::dArg: case ConversionSpecifier::DArg: case ConversionSpecifier::iArg: diff --git a/contrib/llvm-project/clang/lib/AST/Interp/Boolean.h b/contrib/llvm-project/clang/lib/AST/Interp/Boolean.h index 3122388a49a..579842ce46a 100644 --- a/contrib/llvm-project/clang/lib/AST/Interp/Boolean.h +++ b/contrib/llvm-project/clang/lib/AST/Interp/Boolean.h @@ -27,12 +27,10 @@ class Boolean final { /// Underlying boolean. bool V; - /// Construct a wrapper from a boolean. - explicit Boolean(bool V) : V(V) {} - public: /// Zero-initializes a boolean. Boolean() : V(false) {} + explicit Boolean(bool V) : V(V) {} bool operator<(Boolean RHS) const { return V < RHS.V; } bool operator>(Boolean RHS) const { return V > RHS.V; } @@ -66,7 +64,7 @@ class Boolean final { Boolean toUnsigned() const { return *this; } - constexpr static unsigned bitWidth() { return true; } + constexpr static unsigned bitWidth() { return 1; } bool isZero() const { return !V; } bool isMin() const { return isZero(); } diff --git a/contrib/llvm-project/clang/lib/AST/Interp/ByteCodeEmitter.cpp b/contrib/llvm-project/clang/lib/AST/Interp/ByteCodeEmitter.cpp index 4633d1e0823..f2072f974c4 100644 --- a/contrib/llvm-project/clang/lib/AST/Interp/ByteCodeEmitter.cpp +++ b/contrib/llvm-project/clang/lib/AST/Interp/ByteCodeEmitter.cpp @@ -8,8 +8,10 @@ #include "ByteCodeEmitter.h" #include "Context.h" +#include "Floating.h" #include "Opcode.h" #include "Program.h" +#include "clang/AST/ASTLambda.h" #include "clang/AST/DeclCXX.h" #include @@ -21,59 +23,77 @@ using Error = llvm::Error; Expected ByteCodeEmitter::compileFunc(const FunctionDecl *FuncDecl) { - // Function is not defined at all or not yet. We will - // create a Function instance but not compile the body. That - // will (maybe) happen later. - bool HasBody = FuncDecl->hasBody(FuncDecl); + // Set up argument indices. + unsigned ParamOffset = 0; + SmallVector ParamTypes; + SmallVector ParamOffsets; + llvm::DenseMap ParamDescriptors; + + // If the return is not a primitive, a pointer to the storage where the + // value is initialized in is passed as the first argument. See 'RVO' + // elsewhere in the code. + QualType Ty = FuncDecl->getReturnType(); + bool HasRVO = false; + if (!Ty->isVoidType() && !Ctx.classify(Ty)) { + HasRVO = true; + ParamTypes.push_back(PT_Ptr); + ParamOffsets.push_back(ParamOffset); + ParamOffset += align(primSize(PT_Ptr)); + } + + // If the function decl is a member decl, the next parameter is + // the 'this' pointer. This parameter is pop()ed from the + // InterpStack when calling the function. + bool HasThisPointer = false; + if (const auto *MD = dyn_cast(FuncDecl)) { + if (MD->isInstance()) { + HasThisPointer = true; + ParamTypes.push_back(PT_Ptr); + ParamOffsets.push_back(ParamOffset); + ParamOffset += align(primSize(PT_Ptr)); + } + + // Set up lambda capture to closure record field mapping. + if (isLambdaCallOperator(MD)) { + const Record *R = P.getOrCreateRecord(MD->getParent()); + llvm::DenseMap LC; + FieldDecl *LTC; + + MD->getParent()->getCaptureFields(LC, LTC); + + for (auto Cap : LC) { + unsigned Offset = R->getField(Cap.second)->Offset; + this->LambdaCaptures[Cap.first] = { + Offset, Cap.second->getType()->isReferenceType()}; + } + // FIXME: LambdaThisCapture + (void)LTC; + } + } + + // Assign descriptors to all parameters. + // Composite objects are lowered to pointers. + for (const ParmVarDecl *PD : FuncDecl->parameters()) { + PrimType Ty = Ctx.classify(PD->getType()).value_or(PT_Ptr); + Descriptor *Desc = P.createDescriptor(PD, Ty); + ParamDescriptors.insert({ParamOffset, {Ty, Desc}}); + Params.insert({PD, ParamOffset}); + ParamOffsets.push_back(ParamOffset); + ParamOffset += align(primSize(Ty)); + ParamTypes.push_back(Ty); + } // Create a handle over the emitted code. Function *Func = P.getFunction(FuncDecl); - if (!Func) { - // Set up argument indices. - unsigned ParamOffset = 0; - SmallVector ParamTypes; - llvm::DenseMap ParamDescriptors; - - // If the return is not a primitive, a pointer to the storage where the - // value is initialized in is passed as the first argument. See 'RVO' - // elsewhere in the code. - QualType Ty = FuncDecl->getReturnType(); - bool HasRVO = false; - if (!Ty->isVoidType() && !Ctx.classify(Ty)) { - HasRVO = true; - ParamTypes.push_back(PT_Ptr); - ParamOffset += align(primSize(PT_Ptr)); - } - - // If the function decl is a member decl, the next parameter is - // the 'this' pointer. This parameter is pop()ed from the - // InterpStack when calling the function. - bool HasThisPointer = false; - if (const auto *MD = dyn_cast(FuncDecl); - MD && MD->isInstance()) { - HasThisPointer = true; - ParamTypes.push_back(PT_Ptr); - ParamOffset += align(primSize(PT_Ptr)); - } - - // Assign descriptors to all parameters. - // Composite objects are lowered to pointers. - for (const ParmVarDecl *PD : FuncDecl->parameters()) { - PrimType Ty = Ctx.classify(PD->getType()).value_or(PT_Ptr); - Descriptor *Desc = P.createDescriptor(PD, Ty); - ParamDescriptors.insert({ParamOffset, {Ty, Desc}}); - Params.insert({PD, ParamOffset}); - ParamOffset += align(primSize(Ty)); - ParamTypes.push_back(Ty); - } - - Func = - P.createFunction(FuncDecl, ParamOffset, std::move(ParamTypes), - std::move(ParamDescriptors), HasThisPointer, HasRVO); - } + if (!Func) + Func = P.createFunction(FuncDecl, ParamOffset, std::move(ParamTypes), + std::move(ParamDescriptors), + std::move(ParamOffsets), HasThisPointer, HasRVO); assert(Func); - if (!HasBody) + // For not-yet-defined functions, we only create a Function instance and + // compile their body later. + if (!FuncDecl->isDefined()) return Func; // Compile the function body. @@ -94,7 +114,7 @@ ByteCodeEmitter::compileFunc(const FunctionDecl *FuncDecl) { // Set the function's code. Func->setCode(NextLocalOffset, std::move(Code), std::move(SrcMap), - std::move(Scopes)); + std::move(Scopes), FuncDecl->hasBody()); Func->setIsFullyCompiled(true); return Func; } @@ -110,12 +130,13 @@ Scope::Local ByteCodeEmitter::createLocal(Descriptor *D) { void ByteCodeEmitter::emitLabel(LabelTy Label) { const size_t Target = Code.size(); LabelOffsets.insert({Label, Target}); - auto It = LabelRelocs.find(Label); - if (It != LabelRelocs.end()) { + + if (auto It = LabelRelocs.find(Label); + It != LabelRelocs.end()) { for (unsigned Reloc : It->second) { using namespace llvm::support; - /// Rewrite the operand of all jumps to this label. + // Rewrite the operand of all jumps to this label. void *Location = Code.data() + Reloc - align(sizeof(int32_t)); assert(aligned(Location)); const int32_t Offset = Target - static_cast(Reloc); @@ -132,10 +153,9 @@ int32_t ByteCodeEmitter::getOffset(LabelTy Label) { assert(aligned(Position)); // If target is known, compute jump offset. - auto It = LabelOffsets.find(Label); - if (It != LabelOffsets.end()) { + if (auto It = LabelOffsets.find(Label); + It != LabelOffsets.end()) return It->second - Position; - } // Otherwise, record relocation and return dummy offset. LabelRelocs[Label].push_back(Position); @@ -151,7 +171,7 @@ bool ByteCodeEmitter::bail(const SourceLocation &Loc) { /// Helper to write bytecode and bail out if 32-bit offsets become invalid. /// Pointers will be automatically marshalled as 32-bit IDs. template -static void emit(Program &P, std::vector &Code, const T &Val, +static void emit(Program &P, std::vector &Code, const T &Val, bool &Success) { size_t Size; @@ -183,14 +203,14 @@ template bool ByteCodeEmitter::emitOp(Opcode Op, const Tys &... Args, const SourceInfo &SI) { bool Success = true; - /// The opcode is followed by arguments. The source info is - /// attached to the address after the opcode. + // The opcode is followed by arguments. The source info is + // attached to the address after the opcode. emit(P, Code, Op, Success); if (SI) SrcMap.emplace_back(Code.size(), SI); - /// The initializer list forces the expression to be evaluated - /// for each argument in the variadic template, in order. + // The initializer list forces the expression to be evaluated + // for each argument in the variadic template, in order. (void)std::initializer_list{(emit(P, Code, Args, Success), 0)...}; return Success; diff --git a/contrib/llvm-project/clang/lib/AST/Interp/ByteCodeEmitter.h b/contrib/llvm-project/clang/lib/AST/Interp/ByteCodeEmitter.h index 30da06b2025..795534696d9 100644 --- a/contrib/llvm-project/clang/lib/AST/Interp/ByteCodeEmitter.h +++ b/contrib/llvm-project/clang/lib/AST/Interp/ByteCodeEmitter.h @@ -70,6 +70,10 @@ protected: /// Parameter indices. llvm::DenseMap Params; + /// Lambda captures. + /// Map from Decl* to [Offset, IsReference] pair. + llvm::DenseMap> LambdaCaptures; + unsigned LambdaThisCapture; /// Local descriptors. llvm::SmallVector, 2> Descriptors; @@ -89,7 +93,7 @@ private: /// Location of label relocations. llvm::DenseMap> LabelRelocs; /// Program code. - std::vector Code; + std::vector Code; /// Opcode to expression mapping. SourceMap SrcMap; diff --git a/contrib/llvm-project/clang/lib/AST/Interp/ByteCodeExprGen.cpp b/contrib/llvm-project/clang/lib/AST/Interp/ByteCodeExprGen.cpp index 615dbdefefb..9f3eb158576 100644 --- a/contrib/llvm-project/clang/lib/AST/Interp/ByteCodeExprGen.cpp +++ b/contrib/llvm-project/clang/lib/AST/Interp/ByteCodeExprGen.cpp @@ -11,6 +11,7 @@ #include "ByteCodeGenError.h" #include "ByteCodeStmtGen.h" #include "Context.h" +#include "Floating.h" #include "Function.h" #include "PrimType.h" #include "Program.h" @@ -25,10 +26,10 @@ namespace clang { namespace interp { /// Scope used to handle temporaries in toplevel variable declarations. -template class DeclScope final : public LocalScope { +template class DeclScope final : public VariableScope { public: - DeclScope(ByteCodeExprGen *Ctx, const VarDecl *VD) - : LocalScope(Ctx), Scope(Ctx->P, VD) {} + DeclScope(ByteCodeExprGen *Ctx, const ValueDecl *VD) + : VariableScope(Ctx), Scope(Ctx->P, VD) {} void addExtended(const Scope::Local &Local) override { return this->addLocal(Local); @@ -39,7 +40,7 @@ private: }; /// Scope used to handle initialization methods. -template class OptionScope { +template class OptionScope final { public: /// Root constructor, compiling or discarding primitives. OptionScope(ByteCodeExprGen *Ctx, bool NewDiscardResult) @@ -66,7 +67,7 @@ bool ByteCodeExprGen::VisitCastExpr(const CastExpr *CE) { case CK_LValueToRValue: { return dereference( - CE->getSubExpr(), DerefKind::Read, + SubExpr, DerefKind::Read, [](PrimType) { // Value loaded - nothing to do here. return true; @@ -84,17 +85,48 @@ bool ByteCodeExprGen::VisitCastExpr(const CastExpr *CE) { if (!this->visit(SubExpr)) return false; - const CXXRecordDecl *FromDecl = getRecordDecl(SubExpr); - assert(FromDecl); - const CXXRecordDecl *ToDecl = getRecordDecl(CE); - assert(ToDecl); - const Record *R = getRecord(FromDecl); - const Record::Base *ToBase = R->getBase(ToDecl); - assert(ToBase); - - return this->emitGetPtrBase(ToBase->Offset, CE); + return this->emitDerivedToBaseCasts(getRecordTy(SubExpr->getType()), + getRecordTy(CE->getType()), CE); } + case CK_FloatingCast: { + if (!this->visit(SubExpr)) + return false; + const auto *TargetSemantics = &Ctx.getFloatSemantics(CE->getType()); + return this->emitCastFP(TargetSemantics, getRoundingMode(CE), CE); + } + + case CK_IntegralToFloating: { + std::optional FromT = classify(SubExpr->getType()); + if (!FromT) + return false; + + if (!this->visit(SubExpr)) + return false; + + const auto *TargetSemantics = &Ctx.getFloatSemantics(CE->getType()); + llvm::RoundingMode RM = getRoundingMode(CE); + return this->emitCastIntegralFloating(*FromT, TargetSemantics, RM, CE); + } + + case CK_FloatingToBoolean: + case CK_FloatingToIntegral: { + std::optional ToT = classify(CE->getType()); + + if (!ToT) + return false; + + if (!this->visit(SubExpr)) + return false; + + return this->emitCastFloatingIntegral(*ToT, CE); + } + + case CK_NullToPointer: + if (DiscardResult) + return true; + return this->emitNull(classifyPrim(CE->getType()), CE); + case CK_ArrayToPointerDecay: case CK_AtomicToNonAtomic: case CK_ConstructorConversion: @@ -102,7 +134,6 @@ bool ByteCodeExprGen::VisitCastExpr(const CastExpr *CE) { case CK_NonAtomicToAtomic: case CK_NoOp: case CK_UserDefinedConversion: - case CK_NullToPointer: return this->visit(SubExpr); case CK_IntegralToBoolean: @@ -115,10 +146,23 @@ bool ByteCodeExprGen::VisitCastExpr(const CastExpr *CE) { if (!this->visit(SubExpr)) return false; - // TODO: Emit this only if FromT != ToT. + if (FromT == ToT) + return true; + return this->emitCast(*FromT, *ToT, CE); } + case CK_PointerToBoolean: { + // Just emit p != nullptr for this. + if (!this->visit(SubExpr)) + return false; + + if (!this->emitNullPtr(CE)) + return false; + + return this->emitNEPtr(CE); + } + case CK_ToVoid: return discard(SubExpr); @@ -136,28 +180,33 @@ bool ByteCodeExprGen::VisitIntegerLiteral(const IntegerLiteral *LE) { return this->emitConst(LE->getValue(), LE); } +template +bool ByteCodeExprGen::VisitFloatingLiteral(const FloatingLiteral *E) { + if (DiscardResult) + return true; + + return this->emitConstFloat(E->getValue(), E); +} + template bool ByteCodeExprGen::VisitParenExpr(const ParenExpr *PE) { - return this->visit(PE->getSubExpr()); + const Expr *SubExpr = PE->getSubExpr(); + + if (DiscardResult) + return this->discard(SubExpr); + + return this->visit(SubExpr); } template bool ByteCodeExprGen::VisitBinaryOperator(const BinaryOperator *BO) { + // Need short-circuiting for these. + if (BO->isLogicalOp()) + return this->VisitLogicalBinOp(BO); + const Expr *LHS = BO->getLHS(); const Expr *RHS = BO->getRHS(); - // Deal with operations which have composite or void types. - switch (BO->getOpcode()) { - case BO_Comma: - if (!discard(LHS)) - return false; - if (!this->visit(RHS)) - return false; - return true; - default: - break; - } - // Typecheck the args. std::optional LT = classify(LHS->getType()); std::optional RT = classify(RHS->getType()); @@ -172,37 +221,64 @@ bool ByteCodeExprGen::VisitBinaryOperator(const BinaryOperator *BO) { return DiscardResult ? this->emitPop(*T, BO) : true; }; + // Deal with operations which have composite or void types. + if (BO->isCommaOp()) { + if (!discard(LHS)) + return false; + return Discard(this->visit(RHS)); + } + // Pointer arithmetic special case. if (BO->getOpcode() == BO_Add || BO->getOpcode() == BO_Sub) { - if (*T == PT_Ptr || (*LT == PT_Ptr && *RT == PT_Ptr)) + if (T == PT_Ptr || (LT == PT_Ptr && RT == PT_Ptr)) return this->VisitPointerArithBinOp(BO); } if (!visit(LHS) || !visit(RHS)) return false; + // For languages such as C, cast the result of one + // of our comparision opcodes to T (which is usually int). + auto MaybeCastToBool = [this, T, BO](bool Result) { + if (!Result) + return false; + if (DiscardResult) + return this->emitPop(*T, BO); + if (T != PT_Bool) + return this->emitCast(PT_Bool, *T, BO); + return true; + }; + switch (BO->getOpcode()) { case BO_EQ: - return Discard(this->emitEQ(*LT, BO)); + return MaybeCastToBool(this->emitEQ(*LT, BO)); case BO_NE: - return Discard(this->emitNE(*LT, BO)); + return MaybeCastToBool(this->emitNE(*LT, BO)); case BO_LT: - return Discard(this->emitLT(*LT, BO)); + return MaybeCastToBool(this->emitLT(*LT, BO)); case BO_LE: - return Discard(this->emitLE(*LT, BO)); + return MaybeCastToBool(this->emitLE(*LT, BO)); case BO_GT: - return Discard(this->emitGT(*LT, BO)); + return MaybeCastToBool(this->emitGT(*LT, BO)); case BO_GE: - return Discard(this->emitGE(*LT, BO)); + return MaybeCastToBool(this->emitGE(*LT, BO)); case BO_Sub: + if (BO->getType()->isFloatingType()) + return Discard(this->emitSubf(getRoundingMode(BO), BO)); return Discard(this->emitSub(*T, BO)); case BO_Add: + if (BO->getType()->isFloatingType()) + return Discard(this->emitAddf(getRoundingMode(BO), BO)); return Discard(this->emitAdd(*T, BO)); case BO_Mul: + if (BO->getType()->isFloatingType()) + return Discard(this->emitMulf(getRoundingMode(BO), BO)); return Discard(this->emitMul(*T, BO)); case BO_Rem: return Discard(this->emitRem(*T, BO)); case BO_Div: + if (BO->getType()->isFloatingType()) + return Discard(this->emitDivf(getRoundingMode(BO), BO)); return Discard(this->emitDiv(*T, BO)); case BO_Assign: if (DiscardResult) @@ -218,8 +294,9 @@ bool ByteCodeExprGen::VisitBinaryOperator(const BinaryOperator *BO) { return Discard(this->emitShr(*LT, *RT, BO)); case BO_Xor: return Discard(this->emitBitXor(*T, BO)); - case BO_LAnd: case BO_LOr: + case BO_LAnd: + llvm_unreachable("Already handled earlier"); default: return this->bail(BO); } @@ -278,11 +355,72 @@ bool ByteCodeExprGen::VisitPointerArithBinOp(const BinaryOperator *E) { } template -bool ByteCodeExprGen::VisitImplicitValueInitExpr(const ImplicitValueInitExpr *E) { - if (std::optional T = classify(E)) - return this->emitZero(*T, E); +bool ByteCodeExprGen::VisitLogicalBinOp(const BinaryOperator *E) { + assert(E->isLogicalOp()); + BinaryOperatorKind Op = E->getOpcode(); + const Expr *LHS = E->getLHS(); + const Expr *RHS = E->getRHS(); - return false; + if (Op == BO_LOr) { + // Logical OR. Visit LHS and only evaluate RHS if LHS was FALSE. + LabelTy LabelTrue = this->getLabel(); + LabelTy LabelEnd = this->getLabel(); + + if (!this->visit(LHS)) + return false; + if (!this->jumpTrue(LabelTrue)) + return false; + + if (!this->visit(RHS)) + return false; + if (!this->jump(LabelEnd)) + return false; + + this->emitLabel(LabelTrue); + this->emitConstBool(true, E); + this->fallthrough(LabelEnd); + this->emitLabel(LabelEnd); + + if (DiscardResult) + return this->emitPopBool(E); + + return true; + } + + // Logical AND. + // Visit LHS. Only visit RHS if LHS was TRUE. + LabelTy LabelFalse = this->getLabel(); + LabelTy LabelEnd = this->getLabel(); + + if (!this->visit(LHS)) + return false; + if (!this->jumpFalse(LabelFalse)) + return false; + + if (!this->visit(RHS)) + return false; + if (!this->jump(LabelEnd)) + return false; + + this->emitLabel(LabelFalse); + this->emitConstBool(false, E); + this->fallthrough(LabelEnd); + this->emitLabel(LabelEnd); + + if (DiscardResult) + return this->emitPopBool(E); + + return true; +} + +template +bool ByteCodeExprGen::VisitImplicitValueInitExpr(const ImplicitValueInitExpr *E) { + std::optional T = classify(E); + + if (!T) + return false; + + return this->visitZeroInitializer(E->getType(), E); } template @@ -292,7 +430,7 @@ bool ByteCodeExprGen::VisitArraySubscriptExpr( const Expr *Index = E->getIdx(); PrimType IndexT = classifyPrim(Index->getType()); - // Take pointer of LHS, add offset from RHS, narrow result. + // Take pointer of LHS, add offset from RHS. // What's left on the stack after this is a pointer. if (!this->visit(Base)) return false; @@ -300,10 +438,7 @@ bool ByteCodeExprGen::VisitArraySubscriptExpr( if (!this->visit(Index)) return false; - if (!this->emitAddOffset(IndexT, E)) - return false; - - if (!this->emitNarrowPtr(E)) + if (!this->emitArrayElemPtrPop(IndexT, E)) return false; if (DiscardResult) @@ -453,32 +588,8 @@ bool ByteCodeExprGen::VisitOpaqueValueExpr(const OpaqueValueExpr *E) { template bool ByteCodeExprGen::VisitAbstractConditionalOperator( const AbstractConditionalOperator *E) { - const Expr *Condition = E->getCond(); - const Expr *TrueExpr = E->getTrueExpr(); - const Expr *FalseExpr = E->getFalseExpr(); - - LabelTy LabelEnd = this->getLabel(); // Label after the operator. - LabelTy LabelFalse = this->getLabel(); // Label for the false expr. - - if (!this->visit(Condition)) - return false; - if (!this->jumpFalse(LabelFalse)) - return false; - - if (!this->visit(TrueExpr)) - return false; - if (!this->jump(LabelEnd)) - return false; - - this->emitLabel(LabelFalse); - - if (!this->visit(FalseExpr)) - return false; - - this->fallthrough(LabelEnd); - this->emitLabel(LabelEnd); - - return true; + return this->visitConditional( + E, [this](const Expr *E) { return this->visit(E); }); } template @@ -494,69 +605,377 @@ bool ByteCodeExprGen::VisitCharacterLiteral( } template -bool ByteCodeExprGen::VisitCompoundAssignOperator( +bool ByteCodeExprGen::VisitFloatCompoundAssignOperator( const CompoundAssignOperator *E) { + assert(E->getType()->isFloatingType()); + const Expr *LHS = E->getLHS(); const Expr *RHS = E->getRHS(); - std::optional LT = classify(E->getLHS()->getType()); - std::optional RT = classify(E->getRHS()->getType()); + llvm::RoundingMode RM = getRoundingMode(E); + QualType LHSComputationType = E->getComputationLHSType(); + QualType ResultType = E->getComputationResultType(); + std::optional LT = classify(LHSComputationType); + std::optional RT = classify(ResultType); if (!LT || !RT) return false; - assert(!E->getType()->isPointerType() && - "Support pointer arithmethic in compound assignment operators"); + // C++17 onwards require that we evaluate the RHS first. + // Compute RHS and save it in a temporary variable so we can + // load it again later. + if (!visit(RHS)) + return false; - // Get LHS pointer, load its value and get RHS value. + unsigned TempOffset = this->allocateLocalPrimitive(E, *RT, /*IsConst=*/true); + if (!this->emitSetLocal(*RT, TempOffset, E)) + return false; + + // First, visit LHS. if (!visit(LHS)) return false; if (!this->emitLoad(*LT, E)) return false; - if (!visit(RHS)) + + // If necessary, convert LHS to its computation type. + if (LHS->getType() != LHSComputationType) { + const auto *TargetSemantics = &Ctx.getFloatSemantics(LHSComputationType); + + if (!this->emitCastFP(TargetSemantics, RM, E)) + return false; + } + + // Now load RHS. + if (!this->emitGetLocal(*RT, TempOffset, E)) return false; - // Perform operation. switch (E->getOpcode()) { case BO_AddAssign: - if (!this->emitAdd(*LT, E)) + if (!this->emitAddf(RM, E)) return false; break; case BO_SubAssign: - if (!this->emitSub(*LT, E)) + if (!this->emitSubf(RM, E)) return false; break; - case BO_MulAssign: + if (!this->emitMulf(RM, E)) + return false; + break; case BO_DivAssign: - case BO_RemAssign: - case BO_ShlAssign: - if (!this->emitShl(*LT, *RT, E)) + if (!this->emitDivf(RM, E)) return false; break; - case BO_ShrAssign: - if (!this->emitShr(*LT, *RT, E)) - return false; - break; - case BO_AndAssign: - case BO_XorAssign: - case BO_OrAssign: default: - llvm_unreachable("Unimplemented compound assign operator"); + return false; + } + + // If necessary, convert result to LHS's type. + if (LHS->getType() != ResultType) { + const auto *TargetSemantics = &Ctx.getFloatSemantics(LHS->getType()); + + if (!this->emitCastFP(TargetSemantics, RM, E)) + return false; } - // And store the result in LHS. if (DiscardResult) return this->emitStorePop(*LT, E); return this->emitStore(*LT, E); } +template +bool ByteCodeExprGen::VisitPointerCompoundAssignOperator( + const CompoundAssignOperator *E) { + BinaryOperatorKind Op = E->getOpcode(); + const Expr *LHS = E->getLHS(); + const Expr *RHS = E->getRHS(); + std::optional LT = classify(LHS->getType()); + std::optional RT = classify(RHS->getType()); + + if (Op != BO_AddAssign && Op != BO_SubAssign) + return false; + + if (!LT || !RT) + return false; + assert(*LT == PT_Ptr); + + if (!visit(LHS)) + return false; + + if (!this->emitLoadPtr(LHS)) + return false; + + if (!visit(RHS)) + return false; + + if (Op == BO_AddAssign) + this->emitAddOffset(*RT, E); + else + this->emitSubOffset(*RT, E); + + if (DiscardResult) + return this->emitStorePopPtr(E); + return this->emitStorePtr(E); +} + +template +bool ByteCodeExprGen::VisitCompoundAssignOperator( + const CompoundAssignOperator *E) { + + // Handle floating point operations separately here, since they + // require special care. + if (E->getType()->isFloatingType()) + return VisitFloatCompoundAssignOperator(E); + + if (E->getType()->isPointerType()) + return VisitPointerCompoundAssignOperator(E); + + const Expr *LHS = E->getLHS(); + const Expr *RHS = E->getRHS(); + std::optional LHSComputationT = + classify(E->getComputationLHSType()); + std::optional LT = classify(LHS->getType()); + std::optional RT = classify(E->getComputationResultType()); + std::optional ResultT = classify(E->getType()); + + if (!LT || !RT || !ResultT || !LHSComputationT) + return false; + + assert(!E->getType()->isPointerType() && "Handled above"); + assert(!E->getType()->isFloatingType() && "Handled above"); + + // C++17 onwards require that we evaluate the RHS first. + // Compute RHS and save it in a temporary variable so we can + // load it again later. + // FIXME: Compound assignments are unsequenced in C, so we might + // have to figure out how to reject them. + if (!visit(RHS)) + return false; + + unsigned TempOffset = this->allocateLocalPrimitive(E, *RT, /*IsConst=*/true); + + if (!this->emitSetLocal(*RT, TempOffset, E)) + return false; + + // Get LHS pointer, load its value and cast it to the + // computation type if necessary. + if (!visit(LHS)) + return false; + if (!this->emitLoad(*LT, E)) + return false; + if (*LT != *LHSComputationT) { + if (!this->emitCast(*LT, *LHSComputationT, E)) + return false; + } + + // Get the RHS value on the stack. + if (!this->emitGetLocal(*RT, TempOffset, E)) + return false; + + // Perform operation. + switch (E->getOpcode()) { + case BO_AddAssign: + if (!this->emitAdd(*LHSComputationT, E)) + return false; + break; + case BO_SubAssign: + if (!this->emitSub(*LHSComputationT, E)) + return false; + break; + case BO_MulAssign: + if (!this->emitMul(*LHSComputationT, E)) + return false; + break; + case BO_DivAssign: + if (!this->emitDiv(*LHSComputationT, E)) + return false; + break; + case BO_RemAssign: + if (!this->emitRem(*LHSComputationT, E)) + return false; + break; + case BO_ShlAssign: + if (!this->emitShl(*LHSComputationT, *RT, E)) + return false; + break; + case BO_ShrAssign: + if (!this->emitShr(*LHSComputationT, *RT, E)) + return false; + break; + case BO_AndAssign: + if (!this->emitBitAnd(*LHSComputationT, E)) + return false; + break; + case BO_XorAssign: + if (!this->emitBitXor(*LHSComputationT, E)) + return false; + break; + case BO_OrAssign: + if (!this->emitBitOr(*LHSComputationT, E)) + return false; + break; + default: + llvm_unreachable("Unimplemented compound assign operator"); + } + + // And now cast from LHSComputationT to ResultT. + if (*ResultT != *LHSComputationT) { + if (!this->emitCast(*LHSComputationT, *ResultT, E)) + return false; + } + + // And store the result in LHS. + if (DiscardResult) + return this->emitStorePop(*ResultT, E); + return this->emitStore(*ResultT, E); +} + +template +bool ByteCodeExprGen::VisitExprWithCleanups( + const ExprWithCleanups *E) { + const Expr *SubExpr = E->getSubExpr(); + + assert(E->getNumObjects() == 0 && "TODO: Implement cleanups"); + if (DiscardResult) + return this->discard(SubExpr); + + return this->visit(SubExpr); +} + +template +bool ByteCodeExprGen::VisitMaterializeTemporaryExpr( + const MaterializeTemporaryExpr *E) { + const Expr *SubExpr = E->getSubExpr(); + std::optional SubExprT = classify(SubExpr); + + if (E->getStorageDuration() == SD_Static) { + if (std::optional GlobalIndex = P.createGlobal(E)) { + const LifetimeExtendedTemporaryDecl *TempDecl = + E->getLifetimeExtendedTemporaryDecl(); + + if (!this->visitInitializer(SubExpr)) + return false; + + if (!this->emitInitGlobalTemp(*SubExprT, *GlobalIndex, TempDecl, E)) + return false; + return this->emitGetPtrGlobal(*GlobalIndex, E); + } + + return false; + } + + // For everyhing else, use local variables. + if (SubExprT) { + if (std::optional LocalIndex = allocateLocalPrimitive( + SubExpr, *SubExprT, /*IsConst=*/true, /*IsExtended=*/true)) { + if (!this->visitInitializer(SubExpr)) + return false; + this->emitSetLocal(*SubExprT, *LocalIndex, E); + return this->emitGetPtrLocal(*LocalIndex, E); + } + } else { + if (std::optional LocalIndex = + allocateLocal(SubExpr, /*IsExtended=*/true)) { + if (!this->emitGetPtrLocal(*LocalIndex, E)) + return false; + return this->visitInitializer(SubExpr); + } + } + return false; +} + +template +bool ByteCodeExprGen::VisitCompoundLiteralExpr( + const CompoundLiteralExpr *E) { + std::optional T = classify(E->getType()); + const Expr *Init = E->getInitializer(); + if (E->isFileScope()) { + if (std::optional GlobalIndex = P.createGlobal(E)) { + if (classify(E->getType())) + return this->visit(Init); + if (!this->emitGetPtrGlobal(*GlobalIndex, E)) + return false; + return this->visitInitializer(Init); + } + } + + // Otherwise, use a local variable. + if (T) { + // For primitive types, we just visit the initializer. + return this->visit(Init); + } else { + if (std::optional LocalIndex = allocateLocal(Init)) { + if (!this->emitGetPtrLocal(*LocalIndex, E)) + return false; + return this->visitInitializer(Init); + } + } + + return false; +} + +template +bool ByteCodeExprGen::VisitTypeTraitExpr(const TypeTraitExpr *E) { + return this->emitConstBool(E->getValue(), E); +} + +template +bool ByteCodeExprGen::VisitLambdaExpr(const LambdaExpr *E) { + // XXX We assume here that a pointer-to-initialize is on the stack. + + const Record *R = P.getOrCreateRecord(E->getLambdaClass()); + + auto *CaptureInitIt = E->capture_init_begin(); + // Initialize all fields (which represent lambda captures) of the + // record with their initializers. + for (const Record::Field &F : R->fields()) { + const Expr *Init = *CaptureInitIt; + ++CaptureInitIt; + + if (std::optional T = classify(Init)) { + if (!this->visit(Init)) + return false; + + if (!this->emitSetField(*T, F.Offset, E)) + return false; + } else { + if (!this->emitDupPtr(E)) + return false; + + if (!this->emitGetPtrField(F.Offset, E)) + return false; + + if (!this->visitInitializer(Init)) + return false; + + if (!this->emitPopPtr(E)) + return false; + } + } + + return true; +} + +template +bool ByteCodeExprGen::VisitPredefinedExpr(const PredefinedExpr *E) { + if (DiscardResult) + return true; + + return this->visit(E->getFunctionName()); +} + template bool ByteCodeExprGen::discard(const Expr *E) { + if (E->containsErrors()) + return false; + OptionScope Scope(this, /*NewDiscardResult=*/true); return this->Visit(E); } template bool ByteCodeExprGen::visit(const Expr *E) { + if (E->containsErrors()) + return false; + OptionScope Scope(this, /*NewDiscardResult=*/false); return this->Visit(E); } @@ -570,8 +989,57 @@ bool ByteCodeExprGen::visitBool(const Expr *E) { } } +/// Visit a conditional operator, i.e. `A ? B : C`. +/// \V determines what function to call for the B and C expressions. template -bool ByteCodeExprGen::visitZeroInitializer(PrimType T, const Expr *E) { +bool ByteCodeExprGen::visitConditional( + const AbstractConditionalOperator *E, + llvm::function_ref V) { + + const Expr *Condition = E->getCond(); + const Expr *TrueExpr = E->getTrueExpr(); + const Expr *FalseExpr = E->getFalseExpr(); + + LabelTy LabelEnd = this->getLabel(); // Label after the operator. + LabelTy LabelFalse = this->getLabel(); // Label for the false expr. + + if (!this->visit(Condition)) + return false; + + // C special case: Convert to bool because our jump ops need that. + // TODO: We probably want this to be done in visitBool(). + if (std::optional CondT = classify(Condition->getType()); + CondT && CondT != PT_Bool) { + if (!this->emitCast(*CondT, PT_Bool, E)) + return false; + } + + if (!this->jumpFalse(LabelFalse)) + return false; + + if (!V(TrueExpr)) + return false; + if (!this->jump(LabelEnd)) + return false; + + this->emitLabel(LabelFalse); + + if (!V(FalseExpr)) + return false; + + this->fallthrough(LabelEnd); + this->emitLabel(LabelEnd); + + return true; +} + +template +bool ByteCodeExprGen::visitZeroInitializer(QualType QT, + const Expr *E) { + // FIXME: We need the QualType to get the float semantics, but that means we + // classify it over and over again in array situations. + PrimType T = classifyPrim(QT); + switch (T) { case PT_Bool: return this->emitZeroBool(E); @@ -593,6 +1061,11 @@ bool ByteCodeExprGen::visitZeroInitializer(PrimType T, const Expr *E) { return this->emitZeroUint64(E); case PT_Ptr: return this->emitNullPtr(E); + case PT_FnPtr: + return this->emitNullFnPtr(E); + case PT_Float: { + return this->emitConstFloat(APFloat::getZero(Ctx.getFloatSemantics(QT)), E); + } } llvm_unreachable("unknown primitive type"); } @@ -604,11 +1077,11 @@ bool ByteCodeExprGen::dereference( if (std::optional T = classify(LV->getType())) { if (!LV->refersToBitField()) { // Only primitive, non bit-field types can be dereferenced directly. - if (auto *DE = dyn_cast(LV)) { + if (const auto *DE = dyn_cast(LV)) { if (!DE->getDecl()->getType()->isReferenceType()) { - if (auto *PD = dyn_cast(DE->getDecl())) + if (const auto *PD = dyn_cast(DE->getDecl())) return dereferenceParam(LV, *T, PD, AK, Direct, Indirect); - if (auto *VD = dyn_cast(DE->getDecl())) + if (const auto *VD = dyn_cast(DE->getDecl())) return dereferenceVar(LV, *T, VD, AK, Direct, Indirect); } } @@ -757,6 +1230,8 @@ bool ByteCodeExprGen::emitConst(T Value, const Expr *E) { case PT_Bool: return this->emitConstBool(Value, E); case PT_Ptr: + case PT_FnPtr: + case PT_Float: llvm_unreachable("Invalid integral type"); break; } @@ -779,7 +1254,7 @@ unsigned ByteCodeExprGen::allocateLocalPrimitive(DeclTy &&Src, if (const auto *VD = dyn_cast_if_present(Src.dyn_cast())) { assert(!P.getGlobal(VD)); - assert(Locals.find(VD) == Locals.end()); + assert(!Locals.contains(VD)); } // FIXME: There are cases where Src.is() is wrong, e.g. @@ -788,7 +1263,7 @@ unsigned ByteCodeExprGen::allocateLocalPrimitive(DeclTy &&Src, Descriptor *D = P.createDescriptor(Src, Ty, Descriptor::InlineDescMD, IsConst, Src.is()); Scope::Local Local = this->createLocal(D); - if (auto *VD = dyn_cast_or_null(Src.dyn_cast())) + if (auto *VD = dyn_cast_if_present(Src.dyn_cast())) Locals.insert({VD, Local}); VarScope->add(Local, IsExtended); return Local.Offset; @@ -801,7 +1276,7 @@ ByteCodeExprGen::allocateLocal(DeclTy &&Src, bool IsExtended) { if (const auto *VD = dyn_cast_if_present(Src.dyn_cast())) { assert(!P.getGlobal(VD)); - assert(Locals.find(VD) == Locals.end()); + assert(!Locals.contains(VD)); } QualType Ty; @@ -845,29 +1320,22 @@ bool ByteCodeExprGen::visitArrayInitializer(const Expr *Initializer) { for (const Expr *Init : InitList->inits()) { if (std::optional T = classify(Init->getType())) { // Visit the primitive element like normal. - if (!this->emitDupPtr(Init)) - return false; if (!this->visit(Init)) return false; if (!this->emitInitElem(*T, ElementIndex, Init)) return false; } else { // Advance the pointer currently on the stack to the given - // dimension and narrow(). - if (!this->emitDupPtr(Init)) - return false; + // dimension. if (!this->emitConstUint32(ElementIndex, Init)) return false; - if (!this->emitAddOffsetUint32(Init)) + if (!this->emitArrayElemPtrUint32(Init)) return false; - if (!this->emitNarrowPtr(Init)) - return false; - if (!visitInitializer(Init)) return false; - } if (!this->emitPopPtr(Init)) return false; + } ++ElementIndex; } @@ -888,31 +1356,22 @@ bool ByteCodeExprGen::visitArrayInitializer(const Expr *Initializer) { for (size_t I = 0; I != Size; ++I) { ArrayIndexScope IndexScope(this, I); - if (!this->emitDupPtr(SubExpr)) // LHS - return false; - if (ElemT) { if (!this->visit(SubExpr)) return false; if (!this->emitInitElem(*ElemT, I, Initializer)) return false; } else { - // Narrow to our array element and recurse into visitInitializer() + // Get to our array element and recurse into visitInitializer() if (!this->emitConstUint64(I, SubExpr)) return false; - - if (!this->emitAddOffsetUint64(SubExpr)) + if (!this->emitArrayElemPtrUint64(SubExpr)) return false; - - if (!this->emitNarrowPtr(SubExpr)) - return false; - if (!visitInitializer(SubExpr)) return false; + if (!this->emitPopPtr(Initializer)) + return false; } - - if (!this->emitPopPtr(Initializer)) - return false; } return true; } else if (const auto *IVIE = dyn_cast(Initializer)) { @@ -926,7 +1385,7 @@ bool ByteCodeExprGen::visitArrayInitializer(const Expr *Initializer) { // since we memset our Block*s to 0 and so we have the desired value // without this. for (size_t I = 0; I != NumElems; ++I) { - if (!this->emitZero(*ElemT, Initializer)) + if (!this->visitZeroInitializer(CAT->getElementType(), Initializer)) return false; if (!this->emitInitElem(*ElemT, I, Initializer)) return false; @@ -948,13 +1407,9 @@ bool ByteCodeExprGen::visitArrayInitializer(const Expr *Initializer) { // FIXME(perf): We're calling the constructor once per array element here, // in the old intepreter we had a special-case for trivial constructors. for (size_t I = 0; I != NumElems; ++I) { - if (!this->emitDupPtr(Initializer)) - return false; if (!this->emitConstUint64(I, Initializer)) return false; - if (!this->emitAddOffsetUint64(Initializer)) - return false; - if (!this->emitNarrowPtr(Initializer)) + if (!this->emitArrayElemPtrUint64(Initializer)) return false; // Constructor arguments. @@ -967,6 +1422,38 @@ bool ByteCodeExprGen::visitArrayInitializer(const Expr *Initializer) { return false; } return true; + } else if (const auto *SL = dyn_cast(Initializer)) { + const ConstantArrayType *CAT = + Ctx.getASTContext().getAsConstantArrayType(SL->getType()); + assert(CAT && "a string literal that's not a constant array?"); + + // If the initializer string is too long, a diagnostic has already been + // emitted. Read only the array length from the string literal. + unsigned N = + std::min(unsigned(CAT->getSize().getZExtValue()), SL->getLength()); + size_t CharWidth = SL->getCharByteWidth(); + + for (unsigned I = 0; I != N; ++I) { + uint32_t CodeUnit = SL->getCodeUnit(I); + + if (CharWidth == 1) { + this->emitConstSint8(CodeUnit, SL); + this->emitInitElemSint8(I, SL); + } else if (CharWidth == 2) { + this->emitConstUint16(CodeUnit, SL); + this->emitInitElemUint16(I, SL); + } else if (CharWidth == 4) { + this->emitConstUint32(CodeUnit, SL); + this->emitInitElemUint32(I, SL); + } else { + llvm_unreachable("unsupported character width"); + } + } + return true; + } else if (const auto *CLE = dyn_cast(Initializer)) { + return visitInitializer(CLE->getInitializer()); + } else if (const auto *EWC = dyn_cast(Initializer)) { + return visitInitializer(EWC->getSubExpr()); } assert(false && "Unknown expression for array initialization"); @@ -981,7 +1468,7 @@ bool ByteCodeExprGen::visitRecordInitializer(const Expr *Initializer) { if (const auto CtorExpr = dyn_cast(Initializer)) { const Function *Func = getFunction(CtorExpr->getConstructor()); - if (!Func || !Func->isConstexpr()) + if (!Func) return false; // The This pointer is already on the stack because this is an initializer, @@ -1001,12 +1488,12 @@ bool ByteCodeExprGen::visitRecordInitializer(const Expr *Initializer) { unsigned InitIndex = 0; for (const Expr *Init : InitList->inits()) { - const Record::Field *FieldToInit = R->getField(InitIndex); if (!this->emitDupPtr(Initializer)) return false; if (std::optional T = classify(Init)) { + const Record::Field *FieldToInit = R->getField(InitIndex); if (!this->visit(Init)) return false; @@ -1015,19 +1502,35 @@ bool ByteCodeExprGen::visitRecordInitializer(const Expr *Initializer) { if (!this->emitPopPtr(Initializer)) return false; + ++InitIndex; } else { - // Non-primitive case. Get a pointer to the field-to-initialize - // on the stack and recurse into visitInitializer(). - if (!this->emitGetPtrField(FieldToInit->Offset, Init)) - return false; + // Initializer for a direct base class. + if (const Record::Base *B = R->getBase(Init->getType())) { + if (!this->emitGetPtrBasePop(B->Offset, Init)) + return false; - if (!this->visitInitializer(Init)) - return false; + if (!this->visitInitializer(Init)) + return false; - if (!this->emitPopPtr(Initializer)) - return false; + if (!this->emitPopPtr(Initializer)) + return false; + // Base initializers don't increase InitIndex, since they don't count + // into the Record's fields. + } else { + const Record::Field *FieldToInit = R->getField(InitIndex); + // Non-primitive case. Get a pointer to the field-to-initialize + // on the stack and recurse into visitInitializer(). + if (!this->emitGetPtrField(FieldToInit->Offset, Init)) + return false; + + if (!this->visitInitializer(Init)) + return false; + + if (!this->emitPopPtr(Initializer)) + return false; + ++InitIndex; + } } - ++InitIndex; } return true; @@ -1037,9 +1540,19 @@ bool ByteCodeExprGen::visitRecordInitializer(const Expr *Initializer) { if (!this->emitDupPtr(Initializer)) return false; - return this->VisitCallExpr(CE); + return this->visit(CE); } else if (const auto *DIE = dyn_cast(Initializer)) { return this->visitInitializer(DIE->getExpr()); + } else if (const auto *CE = dyn_cast(Initializer)) { + return this->visitInitializer(CE->getSubExpr()); + } else if (const auto *CE = dyn_cast(Initializer)) { + return this->visitInitializer(CE->getSubExpr()); + } else if (const auto *ACO = + dyn_cast(Initializer)) { + return this->visitConditional( + ACO, [this](const Expr *E) { return this->visitRecordInitializer(E); }); + } else if (const auto *LE = dyn_cast(Initializer)) { + return this->VisitLambdaExpr(LE); } return false; @@ -1085,7 +1598,7 @@ const Function *ByteCodeExprGen::getFunction(const FunctionDecl *FD) { assert(FD); const Function *Func = P.getFunction(FD); bool IsBeingCompiled = Func && !Func->isFullyCompiled(); - bool WasNotDefined = Func && !Func->hasBody(); + bool WasNotDefined = Func && !Func->isConstexpr() && !Func->hasBody(); if (IsBeingCompiled) return Func; @@ -1119,14 +1632,14 @@ bool ByteCodeExprGen::visitExpr(const Expr *Exp) { /// We need to evaluate the initializer and return its value. template bool ByteCodeExprGen::visitDecl(const VarDecl *VD) { - std::optional VarT = classify(VD->getType()); + assert(!VD->isInvalidDecl() && "Trying to constant evaluate an invalid decl"); // Create and initialize the variable. if (!this->visitVarDecl(VD)) return false; // Get a pointer to the variable - if (shouldBeGloballyIndexed(VD)) { + if (Context::shouldBeGloballyIndexed(VD)) { auto GlobalIndex = P.getGlobal(VD); assert(GlobalIndex); // visitVarDecl() didn't return false. if (!this->emitGetPtrGlobal(*GlobalIndex, VD)) @@ -1139,7 +1652,7 @@ bool ByteCodeExprGen::visitDecl(const VarDecl *VD) { } // Return the value - if (VarT) { + if (std::optional VarT = classify(VD->getType())) { if (!this->emitLoadPop(*VarT, VD)) return false; @@ -1151,11 +1664,19 @@ bool ByteCodeExprGen::visitDecl(const VarDecl *VD) { template bool ByteCodeExprGen::visitVarDecl(const VarDecl *VD) { + // We don't know what to do with these, so just return false. + if (VD->getType().isNull()) + return false; + const Expr *Init = VD->getInit(); std::optional VarT = classify(VD->getType()); - if (shouldBeGloballyIndexed(VD)) { - std::optional GlobalIndex = P.getOrCreateGlobal(VD, Init); + if (Context::shouldBeGloballyIndexed(VD)) { + // We've already seen and initialized this global. + if (P.getGlobal(VD)) + return true; + + std::optional GlobalIndex = P.createGlobal(VD, Init); if (!GlobalIndex) return this->bail(VD); @@ -1197,11 +1718,55 @@ bool ByteCodeExprGen::visitVarDecl(const VarDecl *VD) { } template -bool ByteCodeExprGen::VisitCallExpr(const CallExpr *E) { - assert(!E->getBuiltinCallee() && "Builtin functions aren't supported yet"); +bool ByteCodeExprGen::VisitBuiltinCallExpr(const CallExpr *E) { + const Function *Func = getFunction(E->getDirectCallee()); + if (!Func) + return false; - const Decl *Callee = E->getCalleeDecl(); - if (const auto *FuncDecl = dyn_cast_or_null(Callee)) { + // Put arguments on the stack. + for (const auto *Arg : E->arguments()) { + if (!this->visit(Arg)) + return false; + } + + if (!this->emitCallBI(Func, E)) + return false; + + QualType ReturnType = E->getCallReturnType(Ctx.getASTContext()); + if (DiscardResult && !ReturnType->isVoidType()) { + PrimType T = classifyPrim(ReturnType); + return this->emitPop(T, E); + } + + return true; +} + +template +bool ByteCodeExprGen::VisitCallExpr(const CallExpr *E) { + if (E->getBuiltinCallee()) + return VisitBuiltinCallExpr(E); + + QualType ReturnType = E->getCallReturnType(Ctx.getASTContext()); + std::optional T = classify(ReturnType); + bool HasRVO = !ReturnType->isVoidType() && !T; + + if (HasRVO && DiscardResult) { + // If we need to discard the return value but the function returns its + // value via an RVO pointer, we need to create one such pointer just + // for this call. + if (std::optional LocalIndex = allocateLocal(E)) { + if (!this->emitGetPtrLocal(*LocalIndex, E)) + return false; + } + } + + // Put arguments on the stack. + for (const auto *Arg : E->arguments()) { + if (!this->visit(Arg)) + return false; + } + + if (const FunctionDecl *FuncDecl = E->getDirectCallee()) { const Function *Func = getFunction(FuncDecl); if (!Func) return false; @@ -1213,40 +1778,42 @@ bool ByteCodeExprGen::VisitCallExpr(const CallExpr *E) { if (Func->isFullyCompiled() && !Func->isConstexpr()) return false; - QualType ReturnType = E->getCallReturnType(Ctx.getASTContext()); - std::optional T = classify(ReturnType); + assert(HasRVO == Func->hasRVO()); - if (Func->hasRVO() && DiscardResult) { - // If we need to discard the return value but the function returns its - // value via an RVO pointer, we need to create one such pointer just - // for this call. - if (std::optional LocalIndex = allocateLocal(E)) { - if (!this->emitGetPtrLocal(*LocalIndex, E)) - return false; - } - } + bool HasQualifier = false; + if (const auto *ME = dyn_cast(E->getCallee())) + HasQualifier = ME->hasQualifier(); - // Put arguments on the stack. - for (const auto *Arg : E->arguments()) { - if (!this->visit(Arg)) + bool IsVirtual = false; + if (const auto *MD = dyn_cast(FuncDecl)) + IsVirtual = MD->isVirtual(); + + // In any case call the function. The return value will end up on the stack + // and if the function has RVO, we already have the pointer on the stack to + // write the result into. + if (IsVirtual && !HasQualifier) { + if (!this->emitCallVirt(Func, E)) + return false; + } else { + if (!this->emitCall(Func, E)) return false; } - - // In any case call the function. The return value will end up on the stack and - // if the function has RVO, we already have the pointer on the stack to write - // the result into. - if (!this->emitCall(Func, E)) + } else { + // Indirect call. Visit the callee, which will leave a FunctionPointer on + // the stack. Cleanup of the returned value if necessary will be done after + // the function call completed. + if (!this->visit(E->getCallee())) return false; - if (DiscardResult && !ReturnType->isVoidType() && T) - return this->emitPop(*T, E); - - return true; - } else { - assert(false && "We don't support non-FunctionDecl callees right now."); + if (!this->emitCallPtr(E)) + return false; } - return false; + // Cleanup for discarded return values. + if (DiscardResult && !ReturnType->isVoidType() && T) + return this->emitPop(*T, E); + + return true; } template @@ -1262,6 +1829,7 @@ bool ByteCodeExprGen::VisitCXXMemberCallExpr( template bool ByteCodeExprGen::VisitCXXDefaultInitExpr( const CXXDefaultInitExpr *E) { + assert(classify(E->getType())); return this->visit(E->getExpr()); } @@ -1301,28 +1869,68 @@ bool ByteCodeExprGen::VisitUnaryOperator(const UnaryOperator *E) { const Expr *SubExpr = E->getSubExpr(); std::optional T = classify(SubExpr->getType()); - // TODO: Support pointers for inc/dec operators. switch (E->getOpcode()) { case UO_PostInc: { // x++ if (!this->visit(SubExpr)) return false; + if (T == PT_Ptr) { + if (!this->emitIncPtr(E)) + return false; + + return DiscardResult ? this->emitPopPtr(E) : true; + } + + if (T == PT_Float) { + return DiscardResult ? this->emitIncfPop(getRoundingMode(E), E) + : this->emitIncf(getRoundingMode(E), E); + } + return DiscardResult ? this->emitIncPop(*T, E) : this->emitInc(*T, E); } case UO_PostDec: { // x-- if (!this->visit(SubExpr)) return false; + if (T == PT_Ptr) { + if (!this->emitDecPtr(E)) + return false; + + return DiscardResult ? this->emitPopPtr(E) : true; + } + + if (T == PT_Float) { + return DiscardResult ? this->emitDecfPop(getRoundingMode(E), E) + : this->emitDecf(getRoundingMode(E), E); + } + return DiscardResult ? this->emitDecPop(*T, E) : this->emitDec(*T, E); } case UO_PreInc: { // ++x if (!this->visit(SubExpr)) return false; - // Post-inc and pre-inc are the same if the value is to be discarded. - if (DiscardResult) - return this->emitIncPop(*T, E); + if (T == PT_Ptr) { + this->emitLoadPtr(E); + this->emitConstUint8(1, E); + this->emitAddOffsetUint8(E); + return DiscardResult ? this->emitStorePopPtr(E) : this->emitStorePtr(E); + } + // Post-inc and pre-inc are the same if the value is to be discarded. + if (DiscardResult) { + if (T == PT_Float) + return this->emitIncfPop(getRoundingMode(E), E); + return this->emitIncPop(*T, E); + } + + if (T == PT_Float) { + const auto &TargetSemantics = Ctx.getFloatSemantics(E->getType()); + this->emitLoadFloat(E); + this->emitConstFloat(llvm::APFloat(TargetSemantics, 1), E); + this->emitAddf(getRoundingMode(E), E); + return this->emitStoreFloat(E); + } this->emitLoad(*T, E); this->emitConst(1, E); this->emitAdd(*T, E); @@ -1332,10 +1940,27 @@ bool ByteCodeExprGen::VisitUnaryOperator(const UnaryOperator *E) { if (!this->visit(SubExpr)) return false; - // Post-dec and pre-dec are the same if the value is to be discarded. - if (DiscardResult) - return this->emitDecPop(*T, E); + if (T == PT_Ptr) { + this->emitLoadPtr(E); + this->emitConstUint8(1, E); + this->emitSubOffsetUint8(E); + return DiscardResult ? this->emitStorePopPtr(E) : this->emitStorePtr(E); + } + // Post-dec and pre-dec are the same if the value is to be discarded. + if (DiscardResult) { + if (T == PT_Float) + return this->emitDecfPop(getRoundingMode(E), E); + return this->emitDecPop(*T, E); + } + + if (T == PT_Float) { + const auto &TargetSemantics = Ctx.getFloatSemantics(E->getType()); + this->emitLoadFloat(E); + this->emitConstFloat(llvm::APFloat(TargetSemantics, 1), E); + this->emitSubf(getRoundingMode(E), E); + return this->emitStoreFloat(E); + } this->emitLoad(*T, E); this->emitConst(1, E); this->emitSub(*T, E); @@ -1385,32 +2010,54 @@ bool ByteCodeExprGen::VisitUnaryOperator(const UnaryOperator *E) { template bool ByteCodeExprGen::VisitDeclRefExpr(const DeclRefExpr *E) { - const auto *Decl = E->getDecl(); + if (DiscardResult) + return true; + + const auto *D = E->getDecl(); + + if (const auto *ECD = dyn_cast(D)) { + return this->emitConst(ECD->getInitVal(), E); + } else if (const auto *BD = dyn_cast(D)) { + return this->visit(BD->getBinding()); + } else if (const auto *FuncDecl = dyn_cast(D)) { + const Function *F = getFunction(FuncDecl); + return F && this->emitGetFnPtr(F, E); + } + // References are implemented via pointers, so when we see a DeclRefExpr // pointing to a reference, we need to get its value directly (i.e. the // pointer to the actual value) instead of a pointer to the pointer to the // value. - bool IsReference = Decl->getType()->isReferenceType(); + bool IsReference = D->getType()->isReferenceType(); - if (auto It = Locals.find(Decl); It != Locals.end()) { + // Check for local/global variables and parameters. + if (auto It = Locals.find(D); It != Locals.end()) { const unsigned Offset = It->second.Offset; if (IsReference) return this->emitGetLocal(PT_Ptr, Offset, E); return this->emitGetPtrLocal(Offset, E); - } else if (auto GlobalIndex = P.getGlobal(Decl)) { + } else if (auto GlobalIndex = P.getGlobal(D)) { if (IsReference) - return this->emitGetGlobal(PT_Ptr, *GlobalIndex, E); + return this->emitGetGlobalPtr(*GlobalIndex, E); return this->emitGetPtrGlobal(*GlobalIndex, E); - } else if (const auto *PVD = dyn_cast(Decl)) { + } else if (const auto *PVD = dyn_cast(D)) { if (auto It = this->Params.find(PVD); It != this->Params.end()) { if (IsReference) - return this->emitGetParam(PT_Ptr, It->second, E); + return this->emitGetParamPtr(It->second, E); return this->emitGetPtrParam(It->second, E); } - } else if (const auto *ECD = dyn_cast(Decl)) { - return this->emitConst(ECD->getInitVal(), E); + } + + // Handle lambda captures. + if (auto It = this->LambdaCaptures.find(D); + It != this->LambdaCaptures.end()) { + auto [Offset, IsReference] = It->second; + + if (IsReference) + return this->emitGetThisFieldPtr(Offset, E); + return this->emitGetPtrThisField(Offset, E); } return false; @@ -1422,6 +2069,112 @@ void ByteCodeExprGen::emitCleanup() { C->emitDestruction(); } +template +bool ByteCodeExprGen::emitDerivedToBaseCasts( + const RecordType *DerivedType, const RecordType *BaseType, const Expr *E) { + // Pointer of derived type is already on the stack. + const auto *FinalDecl = cast(BaseType->getDecl()); + const RecordDecl *CurDecl = DerivedType->getDecl(); + const Record *CurRecord = getRecord(CurDecl); + assert(CurDecl && FinalDecl); + for (;;) { + assert(CurRecord->getNumBases() > 0); + // One level up + for (const Record::Base &B : CurRecord->bases()) { + const auto *BaseDecl = cast(B.Decl); + + if (BaseDecl == FinalDecl || BaseDecl->isDerivedFrom(FinalDecl)) { + // This decl will lead us to the final decl, so emit a base cast. + if (!this->emitGetPtrBasePop(B.Offset, E)) + return false; + + CurRecord = B.R; + CurDecl = BaseDecl; + break; + } + } + if (CurDecl == FinalDecl) + return true; + } + + llvm_unreachable("Couldn't find the base class?"); + return false; +} + +/// When calling this, we have a pointer of the local-to-destroy +/// on the stack. +/// Emit destruction of record types (or arrays of record types). +/// FIXME: Handle virtual destructors. +template +bool ByteCodeExprGen::emitRecordDestruction(const Descriptor *Desc) { + assert(Desc); + assert(!Desc->isPrimitive()); + assert(!Desc->isPrimitiveArray()); + + // Arrays. + if (Desc->isArray()) { + const Descriptor *ElemDesc = Desc->ElemDesc; + const Record *ElemRecord = ElemDesc->ElemRecord; + assert(ElemRecord); // This is not a primitive array. + + if (const CXXDestructorDecl *Dtor = ElemRecord->getDestructor(); + Dtor && !Dtor->isTrivial()) { + for (ssize_t I = Desc->getNumElems() - 1; I >= 0; --I) { + if (!this->emitConstUint64(I, SourceInfo{})) + return false; + if (!this->emitArrayElemPtrUint64(SourceInfo{})) + return false; + if (!this->emitRecordDestruction(Desc->ElemDesc)) + return false; + } + } + return this->emitPopPtr(SourceInfo{}); + } + + const Record *R = Desc->ElemRecord; + assert(R); + // First, destroy all fields. + for (const Record::Field &Field : llvm::reverse(R->fields())) { + const Descriptor *D = Field.Desc; + if (!D->isPrimitive() && !D->isPrimitiveArray()) { + if (!this->emitDupPtr(SourceInfo{})) + return false; + if (!this->emitGetPtrField(Field.Offset, SourceInfo{})) + return false; + if (!this->emitRecordDestruction(D)) + return false; + } + } + + // FIXME: Unions need to be handled differently here. We don't want to + // call the destructor of its members. + + // Now emit the destructor and recurse into base classes. + if (const CXXDestructorDecl *Dtor = R->getDestructor(); + Dtor && !Dtor->isTrivial()) { + const Function *DtorFunc = getFunction(Dtor); + if (DtorFunc && DtorFunc->isConstexpr()) { + assert(DtorFunc->hasThisPointer()); + assert(DtorFunc->getNumParams() == 1); + if (!this->emitDupPtr(SourceInfo{})) + return false; + if (!this->emitCall(DtorFunc, SourceInfo{})) + return false; + } + } + + for (const Record::Base &Base : llvm::reverse(R->bases())) { + if (!this->emitGetPtrBase(Base.Offset, SourceInfo{})) + return false; + if (!this->emitRecordDestruction(Base.Desc)) + return false; + } + // FIXME: Virtual bases. + + // Remove the instance pointer. + return this->emitPopPtr(SourceInfo{}); +} + namespace clang { namespace interp { diff --git a/contrib/llvm-project/clang/lib/AST/Interp/ByteCodeExprGen.h b/contrib/llvm-project/clang/lib/AST/Interp/ByteCodeExprGen.h index c7fcc59e5a6..57b0af9459e 100644 --- a/contrib/llvm-project/clang/lib/AST/Interp/ByteCodeExprGen.h +++ b/contrib/llvm-project/clang/lib/AST/Interp/ByteCodeExprGen.h @@ -29,6 +29,7 @@ class QualType; namespace interp { template class LocalScope; +template class DestructorScope; template class RecordScope; template class VariableScope; template class DeclScope; @@ -58,11 +59,14 @@ public: // Expression visitors - result returned on interp stack. bool VisitCastExpr(const CastExpr *E); bool VisitIntegerLiteral(const IntegerLiteral *E); + bool VisitFloatingLiteral(const FloatingLiteral *E); bool VisitParenExpr(const ParenExpr *E); bool VisitBinaryOperator(const BinaryOperator *E); + bool VisitLogicalBinOp(const BinaryOperator *E); bool VisitPointerArithBinOp(const BinaryOperator *E); bool VisitCXXDefaultArgExpr(const CXXDefaultArgExpr *E); bool VisitCallExpr(const CallExpr *E); + bool VisitBuiltinCallExpr(const CallExpr *E); bool VisitCXXMemberCallExpr(const CXXMemberCallExpr *E); bool VisitCXXDefaultInitExpr(const CXXDefaultInitExpr *E); bool VisitCXXBoolLiteralExpr(const CXXBoolLiteralExpr *E); @@ -83,6 +87,14 @@ public: bool VisitStringLiteral(const StringLiteral *E); bool VisitCharacterLiteral(const CharacterLiteral *E); bool VisitCompoundAssignOperator(const CompoundAssignOperator *E); + bool VisitFloatCompoundAssignOperator(const CompoundAssignOperator *E); + bool VisitPointerCompoundAssignOperator(const CompoundAssignOperator *E); + bool VisitExprWithCleanups(const ExprWithCleanups *E); + bool VisitMaterializeTemporaryExpr(const MaterializeTemporaryExpr *E); + bool VisitCompoundLiteralExpr(const CompoundLiteralExpr *E); + bool VisitTypeTraitExpr(const TypeTraitExpr *E); + bool VisitLambdaExpr(const LambdaExpr *E); + bool VisitPredefinedExpr(const PredefinedExpr *E); protected: bool visitExpr(const Expr *E) override; @@ -154,6 +166,10 @@ protected: if (!visitInitializer(Init)) return false; + if ((Init->getType()->isArrayType() || Init->getType()->isRecordType()) && + !this->emitCheckGlobalCtor(Init)) + return false; + return this->emitPopPtr(Init); } @@ -168,8 +184,11 @@ protected: return this->emitPopPtr(I); } + bool visitConditional(const AbstractConditionalOperator *E, + llvm::function_ref V); + /// Creates a local primitive value. - unsigned allocateLocalPrimitive(DeclTy &&Decl, PrimType Ty, bool IsMutable, + unsigned allocateLocalPrimitive(DeclTy &&Decl, PrimType Ty, bool IsConst, bool IsExtended = false); /// Allocates a space storing a local given its type. @@ -178,13 +197,14 @@ protected: private: friend class VariableScope; friend class LocalScope; + friend class DestructorScope; friend class RecordScope; friend class DeclScope; friend class OptionScope; friend class ArrayIndexScope; /// Emits a zero initializer. - bool visitZeroInitializer(PrimType T, const Expr *E); + bool visitZeroInitializer(QualType QT, const Expr *E); enum class DerefKind { /// Value is read and pushed to stack. @@ -210,9 +230,9 @@ private: llvm::function_ref Indirect); /// Emits an APSInt constant. - bool emitConst(const APSInt &Value, const Expr *E); - bool emitConst(const APInt &Value, const Expr *E) { - return emitConst(static_cast(Value), E); + bool emitConst(const llvm::APSInt &Value, const Expr *E); + bool emitConst(const llvm::APInt &Value, const Expr *E) { + return emitConst(static_cast(Value), E); } /// Emits an integer constant. @@ -227,12 +247,19 @@ private: return T->getAsCXXRecordDecl(); } - /// Returns whether we should create a global variable for the - /// given VarDecl. - bool shouldBeGloballyIndexed(const VarDecl *VD) const { - return VD->hasGlobalStorage() || VD->isConstexpr(); + llvm::RoundingMode getRoundingMode(const Expr *E) const { + FPOptions FPO = E->getFPFeaturesInEffect(Ctx.getLangOpts()); + + if (FPO.getRoundingMode() == llvm::RoundingMode::Dynamic) + return llvm::RoundingMode::NearestTiesToEven; + + return FPO.getRoundingMode(); } + bool emitRecordDestruction(const Descriptor *Desc); + bool emitDerivedToBaseCasts(const RecordType *DerivedType, + const RecordType *BaseType, const Expr *E); + protected: /// Variable to storage mapping. llvm::DenseMap Locals; @@ -281,8 +308,8 @@ public: } virtual void emitDestruction() {} - - VariableScope *getParent() { return Parent; } + virtual void emitDestructors() {} + VariableScope *getParent() const { return Parent; } protected: /// ByteCodeExprGen instance. @@ -291,15 +318,26 @@ protected: VariableScope *Parent; }; -/// Scope for local variables. -/// -/// When the scope is destroyed, instructions are emitted to tear down -/// all variables declared in this scope. +/// Generic scope for local variables. template class LocalScope : public VariableScope { public: LocalScope(ByteCodeExprGen *Ctx) : VariableScope(Ctx) {} - ~LocalScope() override { this->emitDestruction(); } + /// Emit a Destroy op for this scope. + ~LocalScope() override { + if (!Idx) + return; + this->Ctx->emitDestroy(*Idx, SourceInfo{}); + } + + /// Overriden to support explicit destruction. + void emitDestruction() override { + if (!Idx) + return; + this->emitDestructors(); + this->Ctx->emitDestroy(*Idx, SourceInfo{}); + this->Idx = std::nullopt; + } void addLocal(const Scope::Local &Local) override { if (!Idx) { @@ -310,36 +348,69 @@ public: this->Ctx->Descriptors[*Idx].emplace_back(Local); } - void emitDestruction() override { + void emitDestructors() override { if (!Idx) return; - this->Ctx->emitDestroy(*Idx, SourceInfo{}); + // Emit destructor calls for local variables of record + // type with a destructor. + for (Scope::Local &Local : this->Ctx->Descriptors[*Idx]) { + if (!Local.Desc->isPrimitive() && !Local.Desc->isPrimitiveArray()) { + this->Ctx->emitGetPtrLocal(Local.Offset, SourceInfo{}); + this->Ctx->emitRecordDestruction(Local.Desc); + } + } } -protected: /// Index of the scope in the chain. std::optional Idx; }; -/// Scope for storage declared in a compound statement. -template class BlockScope final : public LocalScope { +/// Emits the destructors of the variables of \param OtherScope +/// when this scope is destroyed. Does not create a Scope in the bytecode at +/// all, this is just a RAII object to emit destructors. +template class DestructorScope final { public: - BlockScope(ByteCodeExprGen *Ctx) : LocalScope(Ctx) {} + DestructorScope(LocalScope &OtherScope) : OtherScope(OtherScope) {} + + ~DestructorScope() { OtherScope.emitDestructors(); } + +private: + LocalScope &OtherScope; +}; + +/// Like a regular LocalScope, except that the destructors of all local +/// variables are automatically emitted when the AutoScope is destroyed. +template class AutoScope : public LocalScope { +public: + AutoScope(ByteCodeExprGen *Ctx) + : LocalScope(Ctx), DS(*this) {} + +private: + DestructorScope DS; +}; + +/// Scope for storage declared in a compound statement. +template class BlockScope final : public AutoScope { +public: + BlockScope(ByteCodeExprGen *Ctx) : AutoScope(Ctx) {} void addExtended(const Scope::Local &Local) override { - llvm_unreachable("Cannot create temporaries in full scopes"); + // If we to this point, just add the variable as a normal local + // variable. It will be destroyed at the end of the block just + // like all others. + this->addLocal(Local); } }; /// Expression scope which tracks potentially lifetime extended /// temporaries which are hoisted to the parent scope on exit. -template class ExprScope final : public LocalScope { +template class ExprScope final : public AutoScope { public: - ExprScope(ByteCodeExprGen *Ctx) : LocalScope(Ctx) {} + ExprScope(ByteCodeExprGen *Ctx) : AutoScope(Ctx) {} void addExtended(const Scope::Local &Local) override { - assert(this->Parent); - this->Parent->addLocal(Local); + if (this->Parent) + this->Parent->addLocal(Local); } }; diff --git a/contrib/llvm-project/clang/lib/AST/Interp/ByteCodeStmtGen.cpp b/contrib/llvm-project/clang/lib/AST/Interp/ByteCodeStmtGen.cpp index af97c57c98b..0c512950c29 100644 --- a/contrib/llvm-project/clang/lib/AST/Interp/ByteCodeStmtGen.cpp +++ b/contrib/llvm-project/clang/lib/AST/Interp/ByteCodeStmtGen.cpp @@ -95,28 +95,25 @@ bool ByteCodeStmtGen::visitFunc(const FunctionDecl *F) { ReturnType = this->classify(F->getReturnType()); // Constructor. Set up field initializers. - if (const auto Ctor = dyn_cast(F)) { + if (const auto *Ctor = dyn_cast(F)) { const RecordDecl *RD = Ctor->getParent(); const Record *R = this->getRecord(RD); if (!R) return false; for (const auto *Init : Ctor->inits()) { + // Scope needed for the initializers. + BlockScope Scope(this); + const Expr *InitExpr = Init->getInit(); if (const FieldDecl *Member = Init->getMember()) { const Record::Field *F = R->getField(Member); if (std::optional T = this->classify(InitExpr)) { - if (!this->emitThis(InitExpr)) - return false; - if (!this->visit(InitExpr)) return false; - if (!this->emitInitField(*T, F->Offset, InitExpr)) - return false; - - if (!this->emitPopPtr(InitExpr)) + if (!this->emitInitThisField(*T, F->Offset, InitExpr)) return false; } else { // Non-primitive case. Get a pointer to the field-to-initialize @@ -136,7 +133,7 @@ bool ByteCodeStmtGen::visitFunc(const FunctionDecl *F) { } else if (const Type *Base = Init->getBaseClass()) { // Base class initializer. // Get This Base and call initializer on it. - auto *BaseDecl = Base->getAsCXXRecordDecl(); + const auto *BaseDecl = Base->getAsCXXRecordDecl(); assert(BaseDecl); const Record::Base *B = R->getBase(BaseDecl); assert(B); @@ -178,10 +175,18 @@ bool ByteCodeStmtGen::visitStmt(const Stmt *S) { return visitDoStmt(cast(S)); case Stmt::ForStmtClass: return visitForStmt(cast(S)); + case Stmt::CXXForRangeStmtClass: + return visitCXXForRangeStmt(cast(S)); case Stmt::BreakStmtClass: return visitBreakStmt(cast(S)); case Stmt::ContinueStmtClass: return visitContinueStmt(cast(S)); + case Stmt::SwitchStmtClass: + return visitSwitchStmt(cast(S)); + case Stmt::CaseStmtClass: + return visitCaseStmt(cast(S)); + case Stmt::DefaultStmtClass: + return visitDefaultStmt(cast(S)); case Stmt::NullStmtClass: return true; default: { @@ -192,6 +197,23 @@ bool ByteCodeStmtGen::visitStmt(const Stmt *S) { } } +/// Visits the given statment without creating a variable +/// scope for it in case it is a compound statement. +template +bool ByteCodeStmtGen::visitLoopBody(const Stmt *S) { + if (isa(S)) + return true; + + if (const auto *CS = dyn_cast(S)) { + for (auto *InnerStmt : CS->body()) + if (!visitStmt(InnerStmt)) + return false; + return true; + } + + return this->visitStmt(S); +} + template bool ByteCodeStmtGen::visitCompoundStmt( const CompoundStmt *CompoundStmt) { @@ -205,17 +227,14 @@ bool ByteCodeStmtGen::visitCompoundStmt( template bool ByteCodeStmtGen::visitDeclStmt(const DeclStmt *DS) { for (auto *D : DS->decls()) { - // Variable declarator. - if (auto *VD = dyn_cast(D)) { - if (!this->visitVarDecl(VD)) - return false; + if (isa(D)) continue; - } - // Decomposition declarator. - if (auto *DD = dyn_cast(D)) { - return this->bail(DD); - } + const auto *VD = dyn_cast(D); + if (!VD) + return false; + if (!this->visitVarDecl(VD)) + return false; } return true; @@ -310,11 +329,15 @@ bool ByteCodeStmtGen::visitWhileStmt(const WhileStmt *S) { if (!this->jumpFalse(EndLabel)) return false; - if (!this->visitStmt(Body)) - return false; + LocalScope Scope(this); + { + DestructorScope DS(Scope); + if (!this->visitLoopBody(Body)) + return false; + } + if (!this->jump(CondLabel)) return false; - this->emitLabel(EndLabel); return true; @@ -329,15 +352,21 @@ bool ByteCodeStmtGen::visitDoStmt(const DoStmt *S) { LabelTy EndLabel = this->getLabel(); LabelTy CondLabel = this->getLabel(); LoopScope LS(this, EndLabel, CondLabel); + LocalScope Scope(this); this->emitLabel(StartLabel); - if (!this->visitStmt(Body)) - return false; - this->emitLabel(CondLabel); - if (!this->visitBool(Cond)) - return false; + { + DestructorScope DS(Scope); + + if (!this->visitLoopBody(Body)) + return false; + this->emitLabel(CondLabel); + if (!this->visitBool(Cond)) + return false; + } if (!this->jumpTrue(StartLabel)) return false; + this->emitLabel(EndLabel); return true; } @@ -354,6 +383,7 @@ bool ByteCodeStmtGen::visitForStmt(const ForStmt *S) { LabelTy CondLabel = this->getLabel(); LabelTy IncLabel = this->getLabel(); LoopScope LS(this, EndLabel, IncLabel); + LocalScope Scope(this); if (Init && !this->visitStmt(Init)) return false; @@ -364,22 +394,83 @@ bool ByteCodeStmtGen::visitForStmt(const ForStmt *S) { if (!this->jumpFalse(EndLabel)) return false; } - if (Body && !this->visitStmt(Body)) - return false; - this->emitLabel(IncLabel); - if (Inc && !this->discard(Inc)) - return false; + + { + DestructorScope DS(Scope); + + if (Body && !this->visitLoopBody(Body)) + return false; + this->emitLabel(IncLabel); + if (Inc && !this->discard(Inc)) + return false; + } + if (!this->jump(CondLabel)) return false; this->emitLabel(EndLabel); return true; } +template +bool ByteCodeStmtGen::visitCXXForRangeStmt(const CXXForRangeStmt *S) { + const Stmt *Init = S->getInit(); + const Expr *Cond = S->getCond(); + const Expr *Inc = S->getInc(); + const Stmt *Body = S->getBody(); + const Stmt *BeginStmt = S->getBeginStmt(); + const Stmt *RangeStmt = S->getRangeStmt(); + const Stmt *EndStmt = S->getEndStmt(); + const VarDecl *LoopVar = S->getLoopVariable(); + + LabelTy EndLabel = this->getLabel(); + LabelTy CondLabel = this->getLabel(); + LabelTy IncLabel = this->getLabel(); + LoopScope LS(this, EndLabel, IncLabel); + + // Emit declarations needed in the loop. + if (Init && !this->visitStmt(Init)) + return false; + if (!this->visitStmt(RangeStmt)) + return false; + if (!this->visitStmt(BeginStmt)) + return false; + if (!this->visitStmt(EndStmt)) + return false; + + // Now the condition as well as the loop variable assignment. + this->emitLabel(CondLabel); + if (!this->visitBool(Cond)) + return false; + if (!this->jumpFalse(EndLabel)) + return false; + + if (!this->visitVarDecl(LoopVar)) + return false; + + // Body. + LocalScope Scope(this); + { + DestructorScope DS(Scope); + + if (!this->visitLoopBody(Body)) + return false; + this->emitLabel(IncLabel); + if (!this->discard(Inc)) + return false; + } + if (!this->jump(CondLabel)) + return false; + + this->emitLabel(EndLabel); + return true; +} + template bool ByteCodeStmtGen::visitBreakStmt(const BreakStmt *S) { if (!BreakLabel) return false; + this->VarScope->emitDestructors(); return this->jump(*BreakLabel); } @@ -388,9 +479,88 @@ bool ByteCodeStmtGen::visitContinueStmt(const ContinueStmt *S) { if (!ContinueLabel) return false; + this->VarScope->emitDestructors(); return this->jump(*ContinueLabel); } +template +bool ByteCodeStmtGen::visitSwitchStmt(const SwitchStmt *S) { + const Expr *Cond = S->getCond(); + PrimType CondT = this->classifyPrim(Cond->getType()); + + LabelTy EndLabel = this->getLabel(); + OptLabelTy DefaultLabel = std::nullopt; + unsigned CondVar = this->allocateLocalPrimitive(Cond, CondT, true, false); + + if (const auto *CondInit = S->getInit()) + if (!visitStmt(CondInit)) + return false; + + // Initialize condition variable. + if (!this->visit(Cond)) + return false; + if (!this->emitSetLocal(CondT, CondVar, S)) + return false; + + CaseMap CaseLabels; + // Create labels and comparison ops for all case statements. + for (const SwitchCase *SC = S->getSwitchCaseList(); SC; + SC = SC->getNextSwitchCase()) { + if (const auto *CS = dyn_cast(SC)) { + // FIXME: Implement ranges. + if (CS->caseStmtIsGNURange()) + return false; + CaseLabels[SC] = this->getLabel(); + + const Expr *Value = CS->getLHS(); + PrimType ValueT = this->classifyPrim(Value->getType()); + + // Compare the case statement's value to the switch condition. + if (!this->emitGetLocal(CondT, CondVar, CS)) + return false; + if (!this->visit(Value)) + return false; + + // Compare and jump to the case label. + if (!this->emitEQ(ValueT, S)) + return false; + if (!this->jumpTrue(CaseLabels[CS])) + return false; + } else { + assert(!DefaultLabel); + DefaultLabel = this->getLabel(); + } + } + + // If none of the conditions above were true, fall through to the default + // statement or jump after the switch statement. + if (DefaultLabel) { + if (!this->jump(*DefaultLabel)) + return false; + } else { + if (!this->jump(EndLabel)) + return false; + } + + SwitchScope SS(this, std::move(CaseLabels), EndLabel, DefaultLabel); + if (!this->visitStmt(S->getBody())) + return false; + this->emitLabel(EndLabel); + return true; +} + +template +bool ByteCodeStmtGen::visitCaseStmt(const CaseStmt *S) { + this->emitLabel(CaseLabels[S]); + return this->visitStmt(S->getSubStmt()); +} + +template +bool ByteCodeStmtGen::visitDefaultStmt(const DefaultStmt *S) { + this->emitLabel(*DefaultLabel); + return this->visitStmt(S->getSubStmt()); +} + namespace clang { namespace interp { diff --git a/contrib/llvm-project/clang/lib/AST/Interp/ByteCodeStmtGen.h b/contrib/llvm-project/clang/lib/AST/Interp/ByteCodeStmtGen.h index 829e199f827..8d9277a11dd 100644 --- a/contrib/llvm-project/clang/lib/AST/Interp/ByteCodeStmtGen.h +++ b/contrib/llvm-project/clang/lib/AST/Interp/ByteCodeStmtGen.h @@ -54,14 +54,19 @@ private: // Statement visitors. bool visitStmt(const Stmt *S); bool visitCompoundStmt(const CompoundStmt *S); + bool visitLoopBody(const Stmt *S); bool visitDeclStmt(const DeclStmt *DS); bool visitReturnStmt(const ReturnStmt *RS); bool visitIfStmt(const IfStmt *IS); bool visitWhileStmt(const WhileStmt *S); bool visitDoStmt(const DoStmt *S); bool visitForStmt(const ForStmt *S); + bool visitCXXForRangeStmt(const CXXForRangeStmt *S); bool visitBreakStmt(const BreakStmt *S); bool visitContinueStmt(const ContinueStmt *S); + bool visitSwitchStmt(const SwitchStmt *S); + bool visitCaseStmt(const CaseStmt *S); + bool visitDefaultStmt(const DefaultStmt *S); /// Type of the expression returned by the function. std::optional ReturnType; diff --git a/contrib/llvm-project/clang/lib/AST/Interp/Context.cpp b/contrib/llvm-project/clang/lib/AST/Interp/Context.cpp index 16471242f32..eeb7fa9379f 100644 --- a/contrib/llvm-project/clang/lib/AST/Interp/Context.cpp +++ b/contrib/llvm-project/clang/lib/AST/Interp/Context.cpp @@ -42,6 +42,11 @@ bool Context::isPotentialConstantExpr(State &Parent, const FunctionDecl *FD) { } } + APValue DummyResult; + if (!Run(Parent, Func, DummyResult)) { + return false; + } + return Func->isConstexpr(); } @@ -50,6 +55,11 @@ bool Context::evaluateAsRValue(State &Parent, const Expr *E, APValue &Result) { ByteCodeExprGen C(*this, *P, Parent, Stk, Result); if (Check(Parent, C.interpretExpr(E))) { assert(Stk.empty()); +#ifndef NDEBUG + // Make sure we don't rely on some value being still alive in + // InterpStack memory. + Stk.clear(); +#endif return true; } @@ -63,6 +73,11 @@ bool Context::evaluateAsInitializer(State &Parent, const VarDecl *VD, ByteCodeExprGen C(*this, *P, Parent, Stk, Result); if (Check(Parent, C.interpretDecl(VD))) { assert(Stk.empty()); +#ifndef NDEBUG + // Make sure we don't rely on some value being still alive in + // InterpStack memory. + Stk.clear(); +#endif return true; } @@ -73,9 +88,11 @@ bool Context::evaluateAsInitializer(State &Parent, const VarDecl *VD, const LangOptions &Context::getLangOpts() const { return Ctx.getLangOpts(); } std::optional Context::classify(QualType T) const { - if (T->isReferenceType() || T->isPointerType()) { + if (T->isFunctionPointerType() || T->isFunctionReferenceType()) + return PT_FnPtr; + + if (T->isReferenceType() || T->isPointerType()) return PT_Ptr; - } if (T->isBooleanType()) return PT_Bool; @@ -113,6 +130,9 @@ std::optional Context::classify(QualType T) const { if (T->isNullPtrType()) return PT_Ptr; + if (T->isFloatingType()) + return PT_Float; + if (auto *AT = dyn_cast(T)) return classify(AT->getValueType()); @@ -123,7 +143,13 @@ unsigned Context::getCharBit() const { return Ctx.getTargetInfo().getCharWidth(); } -bool Context::Run(State &Parent, Function *Func, APValue &Result) { +/// Simple wrapper around getFloatTypeSemantics() to make code a +/// little shorter. +const llvm::fltSemantics &Context::getFloatSemantics(QualType T) const { + return Ctx.getFloatTypeSemantics(T); +} + +bool Context::Run(State &Parent, const Function *Func, APValue &Result) { InterpState State(Parent, *P, Stk, *this); State.Current = new InterpFrame(State, Func, /*Caller=*/nullptr, {}); if (Interpret(State, Result)) @@ -142,3 +168,38 @@ bool Context::Check(State &Parent, llvm::Expected &&Flag) { }); return false; } + +// TODO: Virtual bases? +const CXXMethodDecl * +Context::getOverridingFunction(const CXXRecordDecl *DynamicDecl, + const CXXRecordDecl *StaticDecl, + const CXXMethodDecl *InitialFunction) const { + + const CXXRecordDecl *CurRecord = DynamicDecl; + const CXXMethodDecl *FoundFunction = InitialFunction; + for (;;) { + const CXXMethodDecl *Overrider = + FoundFunction->getCorrespondingMethodDeclaredInClass(CurRecord, false); + if (Overrider) + return Overrider; + + // Common case of only one base class. + if (CurRecord->getNumBases() == 1) { + CurRecord = CurRecord->bases_begin()->getType()->getAsCXXRecordDecl(); + continue; + } + + // Otherwise, go to the base class that will lead to the StaticDecl. + for (const CXXBaseSpecifier &Spec : CurRecord->bases()) { + const CXXRecordDecl *Base = Spec.getType()->getAsCXXRecordDecl(); + if (Base == StaticDecl || Base->isDerivedFrom(StaticDecl)) { + CurRecord = Base; + break; + } + } + } + + llvm_unreachable( + "Couldn't find an overriding function in the class hierarchy?"); + return nullptr; +} diff --git a/contrib/llvm-project/clang/lib/AST/Interp/Context.h b/contrib/llvm-project/clang/lib/AST/Interp/Context.h index e49422e64b8..19d480d9121 100644 --- a/contrib/llvm-project/clang/lib/AST/Interp/Context.h +++ b/contrib/llvm-project/clang/lib/AST/Interp/Context.h @@ -57,13 +57,28 @@ public: InterpStack &getStack() { return Stk; } /// Returns CHAR_BIT. unsigned getCharBit() const; + /// Return the floating-point semantics for T. + const llvm::fltSemantics &getFloatSemantics(QualType T) const; /// Classifies an expression. std::optional classify(QualType T) const; + const CXXMethodDecl * + getOverridingFunction(const CXXRecordDecl *DynamicDecl, + const CXXRecordDecl *StaticDecl, + const CXXMethodDecl *InitialFunction) const; + /// Returns whether we should create a global variable for the + /// given ValueDecl. + static bool shouldBeGloballyIndexed(const ValueDecl *VD) { + if (const auto *V = dyn_cast(VD)) + return V->hasGlobalStorage() || V->isConstexpr(); + + return false; + } + private: /// Runs a function. - bool Run(State &Parent, Function *Func, APValue &Result); + bool Run(State &Parent, const Function *Func, APValue &Result); /// Checks a result from the interpreter. bool Check(State &Parent, llvm::Expected &&R); diff --git a/contrib/llvm-project/clang/lib/AST/Interp/Descriptor.cpp b/contrib/llvm-project/clang/lib/AST/Interp/Descriptor.cpp index 04bc8681dd6..ccd2a993e9f 100644 --- a/contrib/llvm-project/clang/lib/AST/Interp/Descriptor.cpp +++ b/contrib/llvm-project/clang/lib/AST/Interp/Descriptor.cpp @@ -8,6 +8,8 @@ #include "Descriptor.h" #include "Boolean.h" +#include "Floating.h" +#include "FunctionPointer.h" #include "Pointer.h" #include "PrimType.h" #include "Record.h" @@ -16,30 +18,32 @@ using namespace clang; using namespace clang::interp; template -static void ctorTy(Block *, char *Ptr, bool, bool, bool, Descriptor *) { +static void ctorTy(Block *, char *Ptr, bool, bool, bool, const Descriptor *) { new (Ptr) T(); } -template static void dtorTy(Block *, char *Ptr, Descriptor *) { +template +static void dtorTy(Block *, char *Ptr, const Descriptor *) { reinterpret_cast(Ptr)->~T(); } template -static void moveTy(Block *, char *Src, char *Dst, Descriptor *) { - auto *SrcPtr = reinterpret_cast(Src); +static void moveTy(Block *, const char *Src, char *Dst, const Descriptor *) { + const auto *SrcPtr = reinterpret_cast(Src); auto *DstPtr = reinterpret_cast(Dst); new (DstPtr) T(std::move(*SrcPtr)); } template -static void ctorArrayTy(Block *, char *Ptr, bool, bool, bool, Descriptor *D) { +static void ctorArrayTy(Block *, char *Ptr, bool, bool, bool, + const Descriptor *D) { for (unsigned I = 0, NE = D->getNumElems(); I < NE; ++I) { new (&reinterpret_cast(Ptr)[I]) T(); } } template -static void dtorArrayTy(Block *, char *Ptr, Descriptor *D) { +static void dtorArrayTy(Block *, char *Ptr, const Descriptor *D) { InitMap *IM = *reinterpret_cast(Ptr); if (IM != (InitMap *)-1) free(IM); @@ -51,16 +55,17 @@ static void dtorArrayTy(Block *, char *Ptr, Descriptor *D) { } template -static void moveArrayTy(Block *, char *Src, char *Dst, Descriptor *D) { +static void moveArrayTy(Block *, const char *Src, char *Dst, + const Descriptor *D) { for (unsigned I = 0, NE = D->getNumElems(); I < NE; ++I) { - auto *SrcPtr = &reinterpret_cast(Src)[I]; + const auto *SrcPtr = &reinterpret_cast(Src)[I]; auto *DstPtr = &reinterpret_cast(Dst)[I]; new (DstPtr) T(std::move(*SrcPtr)); } } static void ctorArrayDesc(Block *B, char *Ptr, bool IsConst, bool IsMutable, - bool IsActive, Descriptor *D) { + bool IsActive, const Descriptor *D) { const unsigned NumElems = D->getNumElems(); const unsigned ElemSize = D->ElemDesc->getAllocSize() + sizeof(InlineDescriptor); @@ -85,7 +90,7 @@ static void ctorArrayDesc(Block *B, char *Ptr, bool IsConst, bool IsMutable, } } -static void dtorArrayDesc(Block *B, char *Ptr, Descriptor *D) { +static void dtorArrayDesc(Block *B, char *Ptr, const Descriptor *D) { const unsigned NumElems = D->getNumElems(); const unsigned ElemSize = D->ElemDesc->getAllocSize() + sizeof(InlineDescriptor); @@ -100,18 +105,19 @@ static void dtorArrayDesc(Block *B, char *Ptr, Descriptor *D) { } } -static void moveArrayDesc(Block *B, char *Src, char *Dst, Descriptor *D) { +static void moveArrayDesc(Block *B, const char *Src, char *Dst, + const Descriptor *D) { const unsigned NumElems = D->getNumElems(); const unsigned ElemSize = D->ElemDesc->getAllocSize() + sizeof(InlineDescriptor); unsigned ElemOffset = 0; for (unsigned I = 0; I < NumElems; ++I, ElemOffset += ElemSize) { - auto *SrcPtr = Src + ElemOffset; + const auto *SrcPtr = Src + ElemOffset; auto *DstPtr = Dst + ElemOffset; - auto *SrcDesc = reinterpret_cast(SrcPtr); - auto *SrcElemLoc = reinterpret_cast(SrcDesc + 1); + const auto *SrcDesc = reinterpret_cast(SrcPtr); + const auto *SrcElemLoc = reinterpret_cast(SrcDesc + 1); auto *DstDesc = reinterpret_cast(DstPtr); auto *DstElemLoc = reinterpret_cast(DstDesc + 1); @@ -122,7 +128,7 @@ static void moveArrayDesc(Block *B, char *Src, char *Dst, Descriptor *D) { } static void ctorRecord(Block *B, char *Ptr, bool IsConst, bool IsMutable, - bool IsActive, Descriptor *D) { + bool IsActive, const Descriptor *D) { const bool IsUnion = D->ElemRecord->isUnion(); auto CtorSub = [=](unsigned SubOff, Descriptor *F, bool IsBase) { auto *Desc = reinterpret_cast(Ptr + SubOff) - 1; @@ -145,7 +151,7 @@ static void ctorRecord(Block *B, char *Ptr, bool IsConst, bool IsMutable, CtorSub(V.Offset, V.Desc, /*isBase=*/true); } -static void dtorRecord(Block *B, char *Ptr, Descriptor *D) { +static void dtorRecord(Block *B, char *Ptr, const Descriptor *D) { auto DtorSub = [=](unsigned SubOff, Descriptor *F) { if (auto Fn = F->DtorFn) Fn(B, Ptr + SubOff, F); @@ -158,7 +164,8 @@ static void dtorRecord(Block *B, char *Ptr, Descriptor *D) { DtorSub(F.Offset, F.Desc); } -static void moveRecord(Block *B, char *Src, char *Dst, Descriptor *D) { +static void moveRecord(Block *B, const char *Src, char *Dst, + const Descriptor *D) { for (const auto &F : D->ElemRecord->fields()) { auto FieldOff = F.Offset; auto FieldDesc = F.Desc; @@ -170,10 +177,20 @@ static void moveRecord(Block *B, char *Src, char *Dst, Descriptor *D) { } static BlockCtorFn getCtorPrim(PrimType Type) { + // Floating types are special. They are primitives, but need their + // constructor called. + if (Type == PT_Float) + return ctorTy::T>; + COMPOSITE_TYPE_SWITCH(Type, return ctorTy, return nullptr); } static BlockDtorFn getDtorPrim(PrimType Type) { + // Floating types are special. They are primitives, but need their + // destructor called, since they might allocate memory. + if (Type == PT_Float) + return dtorTy::T>; + COMPOSITE_TYPE_SWITCH(Type, return dtorTy, return nullptr); } @@ -262,6 +279,8 @@ QualType Descriptor::getType() const { return E->getType(); if (auto *D = asValueDecl()) return D->getType(); + if (auto *T = dyn_cast(asDecl())) + return QualType(T->getTypeForDecl(), 0); llvm_unreachable("Invalid descriptor type"); } diff --git a/contrib/llvm-project/clang/lib/AST/Interp/Descriptor.h b/contrib/llvm-project/clang/lib/AST/Interp/Descriptor.h index 6ef4fc2f4c9..b2dbd892b55 100644 --- a/contrib/llvm-project/clang/lib/AST/Interp/Descriptor.h +++ b/contrib/llvm-project/clang/lib/AST/Interp/Descriptor.h @@ -30,22 +30,19 @@ using DeclTy = llvm::PointerUnion; /// all the fields which contain non-trivial types. using BlockCtorFn = void (*)(Block *Storage, char *FieldPtr, bool IsConst, bool IsMutable, bool IsActive, - Descriptor *FieldDesc); + const Descriptor *FieldDesc); /// Invoked when a block is destroyed. Invokes the destructors of all /// non-trivial nested fields of arrays and records. using BlockDtorFn = void (*)(Block *Storage, char *FieldPtr, - Descriptor *FieldDesc); + const Descriptor *FieldDesc); /// Invoked when a block with pointers referencing it goes out of scope. Such /// blocks are persisted: the move function copies all inline descriptors and /// non-trivial fields, as existing pointers might need to reference those /// descriptors. Data is not copied since it cannot be legally read. -using BlockMoveFn = void (*)(Block *Storage, char *SrcFieldPtr, - char *DstFieldPtr, Descriptor *FieldDesc); - -/// Object size as used by the interpreter. -using InterpSize = unsigned; +using BlockMoveFn = void (*)(Block *Storage, const char *SrcFieldPtr, + char *DstFieldPtr, const Descriptor *FieldDesc); /// Inline descriptor embedded in structures and arrays. /// @@ -81,13 +78,13 @@ private: /// Original declaration, used to emit the error message. const DeclTy Source; /// Size of an element, in host bytes. - const InterpSize ElemSize; + const unsigned ElemSize; /// Size of the storage, in host bytes. - const InterpSize Size; + const unsigned Size; // Size of the metadata. - const InterpSize MDSize; + const unsigned MDSize; /// Size of the allocation (storage + metadata), in host bytes. - const InterpSize AllocSize; + const unsigned AllocSize; /// Value to denote arrays of unknown size. static constexpr unsigned UnknownSizeMark = (unsigned)-1; @@ -96,7 +93,7 @@ public: /// Token to denote structures of unknown size. struct UnknownSize {}; - using MetadataSize = std::optional; + using MetadataSize = std::optional; static constexpr MetadataSize InlineDescMD = sizeof(InlineDescriptor); /// Pointer to the record, if block contains records. @@ -177,6 +174,8 @@ public: /// Checks if the descriptor is of an array of primitives. bool isPrimitiveArray() const { return IsArray && !ElemDesc; } + /// Checks if the descriptor is of an array of composites. + bool isCompositeArray() const { return IsArray && ElemDesc; } /// Checks if the descriptor is of an array of zero size. bool isZeroSizeArray() const { return Size == 0; } /// Checks if the descriptor is of an array of unknown size. diff --git a/contrib/llvm-project/clang/lib/AST/Interp/Disasm.cpp b/contrib/llvm-project/clang/lib/AST/Interp/Disasm.cpp index d31e879d516..35ed5d12869 100644 --- a/contrib/llvm-project/clang/lib/AST/Interp/Disasm.cpp +++ b/contrib/llvm-project/clang/lib/AST/Interp/Disasm.cpp @@ -10,6 +10,7 @@ // //===----------------------------------------------------------------------===// +#include "Floating.h" #include "Function.h" #include "Opcode.h" #include "PrimType.h" @@ -33,18 +34,7 @@ template inline T ReadArg(Program &P, CodePtr &OpPC) { LLVM_DUMP_METHOD void Function::dump() const { dump(llvm::errs()); } LLVM_DUMP_METHOD void Function::dump(llvm::raw_ostream &OS) const { - if (F) { - if (auto *Cons = dyn_cast(F)) { - DeclarationName Name = Cons->getParent()->getDeclName(); - OS << Name << "::" << Name; - } else { - OS << F->getDeclName(); - } - OS << " " << (const void*)this << ":\n"; - } else { - OS << "<>\n"; - } - + OS << getName() << " " << (const void *)this << "\n"; OS << "frame size: " << getFrameSize() << "\n"; OS << "arg size: " << getArgSize() << "\n"; OS << "rvo: " << hasRVO() << "\n"; @@ -52,9 +42,9 @@ LLVM_DUMP_METHOD void Function::dump(llvm::raw_ostream &OS) const { auto PrintName = [&OS](const char *Name) { OS << Name; - for (long I = 0, N = strlen(Name); I < 30 - N; ++I) { - OS << ' '; - } + long N = 30 - strlen(Name); + if (N > 0) + OS.indent(N); }; for (CodePtr Start = getCodeBegin(), PC = Start; PC != getCodeEnd();) { diff --git a/contrib/llvm-project/clang/lib/AST/Interp/EvalEmitter.cpp b/contrib/llvm-project/clang/lib/AST/Interp/EvalEmitter.cpp index 72fd3b45254..f22cca90d4f 100644 --- a/contrib/llvm-project/clang/lib/AST/Interp/EvalEmitter.cpp +++ b/contrib/llvm-project/clang/lib/AST/Interp/EvalEmitter.cpp @@ -123,7 +123,7 @@ bool EvalEmitter::emitRetValue(const SourceInfo &Info) { Ty = AT->getValueType(); if (auto *RT = Ty->getAs()) { - auto *Record = Ptr.getRecord(); + const auto *Record = Ptr.getRecord(); assert(Record && "Missing record descriptor"); bool Ok = true; @@ -208,9 +208,7 @@ bool EvalEmitter::emitGetPtrLocal(uint32_t I, const SourceInfo &Info) { if (!isActive()) return true; - auto It = Locals.find(I); - assert(It != Locals.end() && "Missing local variable"); - Block *B = reinterpret_cast(It->second.get()); + Block *B = getLocal(I); S.Stk.push(B, sizeof(InlineDescriptor)); return true; } @@ -222,9 +220,7 @@ bool EvalEmitter::emitGetLocal(uint32_t I, const SourceInfo &Info) { using T = typename PrimConv::T; - auto It = Locals.find(I); - assert(It != Locals.end() && "Missing local variable"); - auto *B = reinterpret_cast(It->second.get()); + Block *B = getLocal(I); S.Stk.push(*reinterpret_cast(B->data())); return true; } @@ -236,9 +232,7 @@ bool EvalEmitter::emitSetLocal(uint32_t I, const SourceInfo &Info) { using T = typename PrimConv::T; - auto It = Locals.find(I); - assert(It != Locals.end() && "Missing local variable"); - auto *B = reinterpret_cast(It->second.get()); + Block *B = getLocal(I); *reinterpret_cast(B->data()) = S.Stk.pop(); InlineDescriptor &Desc = *reinterpret_cast(B->rawData()); Desc.IsInitialized = true; @@ -251,9 +245,8 @@ bool EvalEmitter::emitDestroy(uint32_t I, const SourceInfo &Info) { return true; for (auto &Local : Descriptors[I]) { - auto It = Locals.find(Local.Offset); - assert(It != Locals.end() && "Missing local variable"); - S.deallocate(reinterpret_cast(It->second.get())); + Block *B = getLocal(Local.Offset); + S.deallocate(B); } return true; diff --git a/contrib/llvm-project/clang/lib/AST/Interp/EvalEmitter.h b/contrib/llvm-project/clang/lib/AST/Interp/EvalEmitter.h index 6b6d0d62190..d1901359f2c 100644 --- a/contrib/llvm-project/clang/lib/AST/Interp/EvalEmitter.h +++ b/contrib/llvm-project/clang/lib/AST/Interp/EvalEmitter.h @@ -71,11 +71,15 @@ protected: /// Returns the source location of the current opcode. SourceInfo getSource(const Function *F, CodePtr PC) const override { - return F ? F->getSource(PC) : CurrentSource; + return (F && F->hasBody()) ? F->getSource(PC) : CurrentSource; } /// Parameter indices. llvm::DenseMap Params; + /// Lambda captures. + /// Map from Decl* to [Offset, IsReference] pair. + llvm::DenseMap> LambdaCaptures; + unsigned LambdaThisCapture; /// Local descriptors. llvm::SmallVector, 2> Descriptors; @@ -92,6 +96,12 @@ private: /// Temporaries which require storage. llvm::DenseMap> Locals; + Block *getLocal(unsigned Index) const { + auto It = Locals.find(Index); + assert(It != Locals.end() && "Missing local variable"); + return reinterpret_cast(It->second.get()); + } + // The emitter always tracks the current instruction and sets OpPC to a token // value which is mapped to the location of the opcode being evaluated. CodePtr OpPC; diff --git a/contrib/llvm-project/clang/lib/AST/Interp/Floating.cpp b/contrib/llvm-project/clang/lib/AST/Interp/Floating.cpp new file mode 100644 index 00000000000..922e17ad145 --- /dev/null +++ b/contrib/llvm-project/clang/lib/AST/Interp/Floating.cpp @@ -0,0 +1,22 @@ +//===---- Floating.cpp - Support for floating point values ------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#include "Floating.h" + +namespace clang { +namespace interp { + +llvm::raw_ostream &operator<<(llvm::raw_ostream &OS, Floating F) { + F.print(OS); + return OS; +} + +Floating getSwappedBytes(Floating F) { return F; } + +} // namespace interp +} // namespace clang diff --git a/contrib/llvm-project/clang/lib/AST/Interp/Floating.h b/contrib/llvm-project/clang/lib/AST/Interp/Floating.h new file mode 100644 index 00000000000..85876236a99 --- /dev/null +++ b/contrib/llvm-project/clang/lib/AST/Interp/Floating.h @@ -0,0 +1,158 @@ +//===--- Floating.h - Types for the constexpr VM ----------------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +// +// Defines the VM types and helpers operating on types. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CLANG_AST_INTERP_FLOATING_H +#define LLVM_CLANG_AST_INTERP_FLOATING_H + +#include "Primitives.h" +#include "clang/AST/APValue.h" +#include "llvm/ADT/APFloat.h" + +namespace clang { +namespace interp { + +using APFloat = llvm::APFloat; +using APSInt = llvm::APSInt; + +class Floating final { +private: + // The underlying value storage. + APFloat F; + +public: + /// Zero-initializes a Floating. + Floating() : F(0.0f) {} + Floating(const APFloat &F) : F(F) {} + + // Static constructors for special floating point values. + static Floating getInf(const llvm::fltSemantics &Sem) { + return Floating(APFloat::getInf(Sem)); + } + const APFloat &getAPFloat() const { return F; } + + bool operator<(Floating RHS) const { return F < RHS.F; } + bool operator>(Floating RHS) const { return F > RHS.F; } + bool operator<=(Floating RHS) const { return F <= RHS.F; } + bool operator>=(Floating RHS) const { return F >= RHS.F; } + bool operator==(Floating RHS) const { return F == RHS.F; } + bool operator!=(Floating RHS) const { return F != RHS.F; } + Floating operator-() const { return Floating(-F); } + + APFloat::opStatus convertToInteger(APSInt &Result) const { + bool IsExact; + return F.convertToInteger(Result, llvm::APFloat::rmTowardZero, &IsExact); + } + + Floating toSemantics(const llvm::fltSemantics *Sem, + llvm::RoundingMode RM) const { + APFloat Copy = F; + bool LosesInfo; + Copy.convert(*Sem, RM, &LosesInfo); + (void)LosesInfo; + return Floating(Copy); + } + + /// Convert this Floating to one with the same semantics as \Other. + Floating toSemantics(const Floating &Other, llvm::RoundingMode RM) const { + return toSemantics(&Other.F.getSemantics(), RM); + } + + APSInt toAPSInt(unsigned NumBits = 0) const { + return APSInt(F.bitcastToAPInt()); + } + APValue toAPValue() const { return APValue(F); } + void print(llvm::raw_ostream &OS) const { + // Can't use APFloat::print() since it appends a newline. + SmallVector Buffer; + F.toString(Buffer); + OS << Buffer; + } + + unsigned bitWidth() const { return F.semanticsSizeInBits(F.getSemantics()); } + + bool isSigned() const { return true; } + bool isNegative() const { return F.isNegative(); } + bool isPositive() const { return !F.isNegative(); } + bool isZero() const { return F.isZero(); } + bool isNonZero() const { return F.isNonZero(); } + bool isMin() const { return F.isSmallest(); } + bool isMinusOne() const { return F.isExactlyValue(-1.0); } + bool isNan() const { return F.isNaN(); } + bool isFinite() const { return F.isFinite(); } + + ComparisonCategoryResult compare(const Floating &RHS) const { + return Compare(F, RHS.F); + } + + static APFloat::opStatus fromIntegral(APSInt Val, + const llvm::fltSemantics &Sem, + llvm::RoundingMode RM, + Floating &Result) { + APFloat F = APFloat(Sem); + APFloat::opStatus Status = F.convertFromAPInt(Val, Val.isSigned(), RM); + Result = Floating(F); + return Status; + } + + // ------- + + static APFloat::opStatus add(const Floating &A, const Floating &B, + llvm::RoundingMode RM, Floating *R) { + *R = Floating(A.F); + return R->F.add(B.F, RM); + } + + static APFloat::opStatus increment(const Floating &A, llvm::RoundingMode RM, + Floating *R) { + APFloat One(A.F.getSemantics(), 1); + *R = Floating(A.F); + return R->F.add(One, RM); + } + + static APFloat::opStatus sub(const Floating &A, const Floating &B, + llvm::RoundingMode RM, Floating *R) { + *R = Floating(A.F); + return R->F.subtract(B.F, RM); + } + + static APFloat::opStatus decrement(const Floating &A, llvm::RoundingMode RM, + Floating *R) { + APFloat One(A.F.getSemantics(), 1); + *R = Floating(A.F); + return R->F.subtract(One, RM); + } + + static APFloat::opStatus mul(const Floating &A, const Floating &B, + llvm::RoundingMode RM, Floating *R) { + *R = Floating(A.F); + return R->F.multiply(B.F, RM); + } + + static APFloat::opStatus div(const Floating &A, const Floating &B, + llvm::RoundingMode RM, Floating *R) { + *R = Floating(A.F); + return R->F.divide(B.F, RM); + } + + static bool neg(const Floating &A, Floating *R) { + *R = -A; + return false; + } +}; + +llvm::raw_ostream &operator<<(llvm::raw_ostream &OS, Floating F); +Floating getSwappedBytes(Floating F); + +} // namespace interp +} // namespace clang + +#endif diff --git a/contrib/llvm-project/clang/lib/AST/Interp/Frame.h b/contrib/llvm-project/clang/lib/AST/Interp/Frame.h index b9a0ea9412f..304f0d108ca 100644 --- a/contrib/llvm-project/clang/lib/AST/Interp/Frame.h +++ b/contrib/llvm-project/clang/lib/AST/Interp/Frame.h @@ -27,7 +27,7 @@ public: virtual ~Frame(); /// Generates a human-readable description of the call site. - virtual void describe(llvm::raw_ostream &OS) = 0; + virtual void describe(llvm::raw_ostream &OS) const = 0; /// Returns a pointer to the caller frame. virtual Frame *getCaller() const = 0; diff --git a/contrib/llvm-project/clang/lib/AST/Interp/Function.cpp b/contrib/llvm-project/clang/lib/AST/Interp/Function.cpp index 40001faad41..75312999d23 100644 --- a/contrib/llvm-project/clang/lib/AST/Interp/Function.cpp +++ b/contrib/llvm-project/clang/lib/AST/Interp/Function.cpp @@ -16,12 +16,14 @@ using namespace clang; using namespace clang::interp; Function::Function(Program &P, const FunctionDecl *F, unsigned ArgSize, - llvm::SmallVector &&ParamTypes, + llvm::SmallVectorImpl &&ParamTypes, llvm::DenseMap &&Params, + llvm::SmallVectorImpl &&ParamOffsets, bool HasThisPointer, bool HasRVO) : P(P), Loc(F->getBeginLoc()), F(F), ArgSize(ArgSize), ParamTypes(std::move(ParamTypes)), Params(std::move(Params)), - HasThisPointer(HasThisPointer), HasRVO(HasRVO) {} + ParamOffsets(std::move(ParamOffsets)), HasThisPointer(HasThisPointer), + HasRVO(HasRVO) {} Function::ParamDescriptor Function::getParamDescriptor(unsigned Offset) const { auto It = Params.find(Offset); @@ -32,6 +34,7 @@ Function::ParamDescriptor Function::getParamDescriptor(unsigned Offset) const { SourceInfo Function::getSource(CodePtr PC) const { assert(PC >= getCodeBegin() && "PC does not belong to this function"); assert(PC <= getCodeEnd() && "PC Does not belong to this function"); + assert(hasBody() && "Function has no body"); unsigned Offset = PC - getCodeBegin(); using Elem = std::pair; auto It = llvm::lower_bound(SrcMap, Elem{Offset, {}}, llvm::less_first()); diff --git a/contrib/llvm-project/clang/lib/AST/Interp/Function.h b/contrib/llvm-project/clang/lib/AST/Interp/Function.h index 5b2a77f1a12..55a23ff288e 100644 --- a/contrib/llvm-project/clang/lib/AST/Interp/Function.h +++ b/contrib/llvm-project/clang/lib/AST/Interp/Function.h @@ -90,7 +90,12 @@ public: /// Returns the name of the function decl this code /// was generated for. - const std::string getName() const { return F->getNameInfo().getAsString(); } + const std::string getName() const { + if (!F) + return "<>"; + + return F->getQualifiedNameAsString(); + } /// Returns the location. SourceLocation getLoc() const { return Loc; } @@ -129,33 +134,50 @@ public: /// Checks if the function is a constructor. bool isConstructor() const { return isa(F); } + /// Checks if the function is a destructor. + bool isDestructor() const { return isa(F); } + + /// Returns the parent record decl, if any. + const CXXRecordDecl *getParentDecl() const { + if (const auto *MD = dyn_cast(F)) + return MD->getParent(); + return nullptr; + } /// Checks if the function is fully done compiling. bool isFullyCompiled() const { return IsFullyCompiled; } bool hasThisPointer() const { return HasThisPointer; } - // Checks if the funtion already has a body attached. + /// Checks if the function already has a body attached. bool hasBody() const { return HasBody; } + unsigned getBuiltinID() const { return F->getBuiltinID(); } + unsigned getNumParams() const { return ParamTypes.size(); } + unsigned getParamOffset(unsigned ParamIndex) const { + return ParamOffsets[ParamIndex]; + } + private: /// Construct a function representing an actual function. Function(Program &P, const FunctionDecl *F, unsigned ArgSize, - llvm::SmallVector &&ParamTypes, + llvm::SmallVectorImpl &&ParamTypes, llvm::DenseMap &&Params, - bool HasThisPointer, bool HasRVO); + llvm::SmallVectorImpl &&ParamOffsets, bool HasThisPointer, + bool HasRVO); /// Sets the code of a function. - void setCode(unsigned NewFrameSize, std::vector &&NewCode, SourceMap &&NewSrcMap, - llvm::SmallVector &&NewScopes) { + void setCode(unsigned NewFrameSize, std::vector &&NewCode, + SourceMap &&NewSrcMap, llvm::SmallVector &&NewScopes, + bool NewHasBody) { FrameSize = NewFrameSize; Code = std::move(NewCode); SrcMap = std::move(NewSrcMap); Scopes = std::move(NewScopes); IsValid = true; - HasBody = true; + HasBody = NewHasBody; } void setIsFullyCompiled(bool FC) { IsFullyCompiled = FC; } @@ -175,7 +197,7 @@ private: /// Size of the argument stack. unsigned ArgSize; /// Program code. - std::vector Code; + std::vector Code; /// Opcode-to-expression mapping. SourceMap SrcMap; /// List of block descriptors. @@ -184,6 +206,8 @@ private: llvm::SmallVector ParamTypes; /// Map from byte offset to parameter descriptor. llvm::DenseMap Params; + /// List of parameter offsets. + llvm::SmallVector ParamOffsets; /// Flag to indicate if the function is valid. bool IsValid = false; /// Flag to indicate if the function is done being diff --git a/contrib/llvm-project/clang/lib/AST/Interp/FunctionPointer.h b/contrib/llvm-project/clang/lib/AST/Interp/FunctionPointer.h new file mode 100644 index 00000000000..4a3f993d488 --- /dev/null +++ b/contrib/llvm-project/clang/lib/AST/Interp/FunctionPointer.h @@ -0,0 +1,71 @@ +//===--- FunctionPointer.h - Types for the constexpr VM ----------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CLANG_AST_INTERP_FUNCTION_POINTER_H +#define LLVM_CLANG_AST_INTERP_FUNCTION_POINTER_H + +#include "Function.h" +#include "Primitives.h" +#include "clang/AST/APValue.h" + +namespace clang { +class ASTContext; +namespace interp { + +class FunctionPointer final { +private: + const Function *Func; + +public: + FunctionPointer() : Func(nullptr) {} + FunctionPointer(const Function *Func) : Func(Func) { assert(Func); } + + const Function *getFunction() const { return Func; } + + APValue toAPValue() const { + if (!Func) + return APValue(static_cast(nullptr), CharUnits::Zero(), {}, + /*OnePastTheEnd=*/false, /*IsNull=*/true); + + return APValue(Func->getDecl(), CharUnits::Zero(), {}, + /*OnePastTheEnd=*/false, /*IsNull=*/false); + } + + void print(llvm::raw_ostream &OS) const { + OS << "FnPtr("; + if (Func) + OS << Func->getName(); + else + OS << "nullptr"; + OS << ")"; + } + + std::string toDiagnosticString(const ASTContext &Ctx) const { + if (!Func) + return "nullptr"; + + return toAPValue().getAsString(Ctx, Func->getDecl()->getType()); + } + + ComparisonCategoryResult compare(const FunctionPointer &RHS) const { + if (Func == RHS.Func) + return ComparisonCategoryResult::Equal; + return ComparisonCategoryResult::Unordered; + } +}; + +inline llvm::raw_ostream &operator<<(llvm::raw_ostream &OS, + FunctionPointer FP) { + FP.print(OS); + return OS; +} + +} // namespace interp +} // namespace clang + +#endif diff --git a/contrib/llvm-project/clang/lib/AST/Interp/Integral.h b/contrib/llvm-project/clang/lib/AST/Interp/Integral.h index 8a742333ae5..de588ab8c9f 100644 --- a/contrib/llvm-project/clang/lib/AST/Interp/Integral.h +++ b/contrib/llvm-project/clang/lib/AST/Interp/Integral.h @@ -21,22 +21,14 @@ #include #include +#include "Primitives.h" + namespace clang { namespace interp { using APInt = llvm::APInt; using APSInt = llvm::APSInt; -/// Helper to compare two comparable types. -template -ComparisonCategoryResult Compare(const T &X, const T &Y) { - if (X < Y) - return ComparisonCategoryResult::Less; - if (X > Y) - return ComparisonCategoryResult::Greater; - return ComparisonCategoryResult::Equal; -} - // Helper structure to select the representation. template struct Repr; template <> struct Repr<8, false> { using Type = uint8_t; }; @@ -136,7 +128,9 @@ public: } unsigned countLeadingZeros() const { - return llvm::countLeadingZeros(V); + if constexpr (!Signed) + return llvm::countl_zero(V); + llvm_unreachable("Don't call countLeadingZeros() on signed types."); } Integral truncate(unsigned TruncBits) const { @@ -233,6 +227,9 @@ public: } static bool neg(Integral A, Integral *R) { + if (Signed && A.isMin()) + return true; + *R = -A; return false; } @@ -242,6 +239,18 @@ public: return false; } + template + static void shiftLeft(const Integral A, const Integral B, + unsigned OpBits, Integral *R) { + *R = Integral::from(A.V << B.V, OpBits); + } + + template + static void shiftRight(const Integral A, const Integral B, + unsigned OpBits, Integral *R) { + *R = Integral::from(A.V >> B.V, OpBits); + } + private: template static bool CheckAddUB(T A, T B, T &R) { if constexpr (std::is_signed_v) { diff --git a/contrib/llvm-project/clang/lib/AST/Interp/Interp.cpp b/contrib/llvm-project/clang/lib/AST/Interp/Interp.cpp index 6a600b306ba..4917f43f951 100644 --- a/contrib/llvm-project/clang/lib/AST/Interp/Interp.cpp +++ b/contrib/llvm-project/clang/lib/AST/Interp/Interp.cpp @@ -26,51 +26,6 @@ using namespace clang; using namespace clang::interp; -//===----------------------------------------------------------------------===// -// Ret -//===----------------------------------------------------------------------===// - -template ::T> -static bool Ret(InterpState &S, CodePtr &PC, APValue &Result) { - S.CallStackDepth--; - const T &Ret = S.Stk.pop(); - - assert(S.Current->getFrameOffset() == S.Stk.size() && "Invalid frame"); - if (!S.checkingPotentialConstantExpression()) - S.Current->popArgs(); - - if (InterpFrame *Caller = S.Current->Caller) { - PC = S.Current->getRetPC(); - delete S.Current; - S.Current = Caller; - S.Stk.push(Ret); - } else { - delete S.Current; - S.Current = nullptr; - if (!ReturnValue(Ret, Result)) - return false; - } - return true; -} - -static bool RetVoid(InterpState &S, CodePtr &PC, APValue &Result) { - S.CallStackDepth--; - - assert(S.Current->getFrameOffset() == S.Stk.size() && "Invalid frame"); - if (!S.checkingPotentialConstantExpression()) - S.Current->popArgs(); - - if (InterpFrame *Caller = S.Current->Caller) { - PC = S.Current->getRetPC(); - delete S.Current; - S.Current = Caller; - } else { - delete S.Current; - S.Current = nullptr; - } - return true; -} - static bool RetValue(InterpState &S, CodePtr &Pt, APValue &Result) { llvm::report_fatal_error("Interpreter cannot return values"); } @@ -98,17 +53,6 @@ static bool Jf(InterpState &S, CodePtr &PC, int32_t Offset) { return true; } -static bool CheckInitialized(InterpState &S, CodePtr OpPC, const Pointer &Ptr, - AccessKinds AK) { - if (Ptr.isInitialized()) - return true; - if (!S.checkingPotentialConstantExpression()) { - const SourceInfo &Loc = S.Current->getSource(OpPC); - S.FFDiag(Loc, diag::note_constexpr_access_uninit) << AK << false; - } - return false; -} - static bool CheckActive(InterpState &S, CodePtr OpPC, const Pointer &Ptr, AccessKinds AK) { if (Ptr.isActive()) @@ -124,7 +68,7 @@ static bool CheckActive(InterpState &S, CodePtr OpPC, const Pointer &Ptr, } // Find the active field of the union. - Record *R = U.getRecord(); + const Record *R = U.getRecord(); assert(R && R->isUnion() && "Not a union"); const FieldDecl *ActiveField = nullptr; for (unsigned I = 0, N = R->getNumFields(); I < N; ++I) { @@ -183,7 +127,7 @@ bool CheckExtern(InterpState &S, CodePtr OpPC, const Pointer &Ptr) { return true; if (!S.checkingPotentialConstantExpression()) { - auto *VD = Ptr.getDeclDesc()->asValueDecl(); + const auto *VD = Ptr.getDeclDesc()->asValueDecl(); const SourceInfo &Loc = S.Current->getSource(OpPC); S.FFDiag(Loc, diag::note_constexpr_ltor_non_constexpr, 1) << VD; S.Note(VD->getLocation(), diag::note_declared_at); @@ -258,7 +202,14 @@ bool CheckRange(InterpState &S, CodePtr OpPC, const Pointer &Ptr, bool CheckConst(InterpState &S, CodePtr OpPC, const Pointer &Ptr) { assert(Ptr.isLive() && "Pointer is not live"); - if (!Ptr.isConst()) { + if (!Ptr.isConst()) + return true; + + // The This pointer is writable in constructors and destructors, + // even if isConst() returns true. + if (const Function *Func = S.Current->getFunction(); + Func && (Func->isConstructor() || Func->isDestructor()) && + Ptr.block() == S.Current->getThis().block()) { return true; } @@ -281,6 +232,19 @@ bool CheckMutable(InterpState &S, CodePtr OpPC, const Pointer &Ptr) { return false; } +bool CheckInitialized(InterpState &S, CodePtr OpPC, const Pointer &Ptr, + AccessKinds AK) { + if (Ptr.isInitialized()) + return true; + + if (!S.checkingPotentialConstantExpression()) { + const SourceInfo &Loc = S.Current->getSource(OpPC); + S.FFDiag(Loc, diag::note_constexpr_access_uninit) + << AK << /*uninitialized=*/true; + } + return false; +} + bool CheckLoad(InterpState &S, CodePtr OpPC, const Pointer &Ptr) { if (!CheckLive(S, OpPC, Ptr, AK_Read)) return false; @@ -333,24 +297,27 @@ bool CheckInit(InterpState &S, CodePtr OpPC, const Pointer &Ptr) { bool CheckCallable(InterpState &S, CodePtr OpPC, const Function *F) { - if (F->isVirtual()) { - if (!S.getLangOpts().CPlusPlus20) { - const SourceLocation &Loc = S.Current->getLocation(OpPC); - S.CCEDiag(Loc, diag::note_constexpr_virtual_call); - return false; - } + if (F->isVirtual() && !S.getLangOpts().CPlusPlus20) { + const SourceLocation &Loc = S.Current->getLocation(OpPC); + S.CCEDiag(Loc, diag::note_constexpr_virtual_call); + return false; } if (!F->isConstexpr()) { + // Don't emit anything if we're checking for a potential constant + // expression. That will happen later when actually executing. + if (S.checkingPotentialConstantExpression()) + return false; + const SourceLocation &Loc = S.Current->getLocation(OpPC); if (S.getLangOpts().CPlusPlus11) { const FunctionDecl *DiagDecl = F->getDecl(); // If this function is not constexpr because it is an inherited // non-constexpr constructor, diagnose that directly. - auto *CD = dyn_cast(DiagDecl); + const auto *CD = dyn_cast(DiagDecl); if (CD && CD->isInheritingConstructor()) { - auto *Inherited = CD->getInheritedConstructor().getConstructor(); + const auto *Inherited = CD->getInheritedConstructor().getConstructor(); if (!Inherited->isConstexpr()) DiagDecl = CD = Inherited; } @@ -374,6 +341,17 @@ bool CheckCallable(InterpState &S, CodePtr OpPC, const Function *F) { return true; } +bool CheckCallDepth(InterpState &S, CodePtr OpPC) { + if ((S.Current->getDepth() + 1) > S.getLangOpts().ConstexprCallDepth) { + S.FFDiag(S.Current->getSource(OpPC), + diag::note_constexpr_depth_limit_exceeded) + << S.getLangOpts().ConstexprCallDepth; + return false; + } + + return true; +} + bool CheckThis(InterpState &S, CodePtr OpPC, const Pointer &This) { if (!This.isZero()) return true; @@ -381,7 +359,7 @@ bool CheckThis(InterpState &S, CodePtr OpPC, const Pointer &This) { const SourceInfo &Loc = S.Current->getSource(OpPC); bool IsImplicit = false; - if (auto *E = dyn_cast_or_null(Loc.asExpr())) + if (const auto *E = dyn_cast_if_present(Loc.asExpr())) IsImplicit = E->isImplicit(); if (S.getLangOpts().CPlusPlus11) @@ -402,11 +380,11 @@ bool CheckPure(InterpState &S, CodePtr OpPC, const CXXMethodDecl *MD) { } static void DiagnoseUninitializedSubobject(InterpState &S, const SourceInfo &SI, - QualType SubObjType, - SourceLocation SubObjLoc) { - S.FFDiag(SI, diag::note_constexpr_uninitialized) << true << SubObjType; - if (SubObjLoc.isValid()) - S.Note(SubObjLoc, diag::note_constexpr_subobject_declared_here); + const FieldDecl *SubObjDecl) { + assert(SubObjDecl && "Subobject declaration does not exist"); + S.FFDiag(SI, diag::note_constexpr_uninitialized) << SubObjDecl; + S.Note(SubObjDecl->getLocation(), + diag::note_constexpr_subobject_declared_here); } static bool CheckFieldsInitialized(InterpState &S, CodePtr OpPC, @@ -419,13 +397,13 @@ static bool CheckArrayInitialized(InterpState &S, CodePtr OpPC, size_t NumElems = CAT->getSize().getZExtValue(); QualType ElemType = CAT->getElementType(); - if (isa(ElemType.getTypePtr())) { + if (ElemType->isRecordType()) { const Record *R = BasePtr.getElemRecord(); for (size_t I = 0; I != NumElems; ++I) { Pointer ElemPtr = BasePtr.atIndex(I).narrow(); Result &= CheckFieldsInitialized(S, OpPC, ElemPtr, R); } - } else if (auto *ElemCAT = dyn_cast(ElemType)) { + } else if (const auto *ElemCAT = dyn_cast(ElemType)) { for (size_t I = 0; I != NumElems; ++I) { Pointer ElemPtr = BasePtr.atIndex(I).narrow(); Result &= CheckArrayInitialized(S, OpPC, ElemPtr, ElemCAT); @@ -433,8 +411,8 @@ static bool CheckArrayInitialized(InterpState &S, CodePtr OpPC, } else { for (size_t I = 0; I != NumElems; ++I) { if (!BasePtr.atIndex(I).isInitialized()) { - DiagnoseUninitializedSubobject(S, S.Current->getSource(OpPC), ElemType, - BasePtr.getFieldDesc()->getLocation()); + DiagnoseUninitializedSubobject(S, S.Current->getSource(OpPC), + BasePtr.getField()); Result = false; } } @@ -459,18 +437,64 @@ static bool CheckFieldsInitialized(InterpState &S, CodePtr OpPC, cast(FieldType->getAsArrayTypeUnsafe()); Result &= CheckArrayInitialized(S, OpPC, FieldPtr, CAT); } else if (!FieldPtr.isInitialized()) { - DiagnoseUninitializedSubobject(S, S.Current->getSource(OpPC), - F.Decl->getType(), F.Decl->getLocation()); + DiagnoseUninitializedSubobject(S, S.Current->getSource(OpPC), F.Decl); Result = false; } } + + // Check Fields in all bases + for (const Record::Base &B : R->bases()) { + Pointer P = BasePtr.atField(B.Offset); + Result &= CheckFieldsInitialized(S, OpPC, P, B.R); + } + + // TODO: Virtual bases + return Result; } bool CheckCtorCall(InterpState &S, CodePtr OpPC, const Pointer &This) { assert(!This.isZero()); - const Record *R = This.getRecord(); - return CheckFieldsInitialized(S, OpPC, This, R); + if (const Record *R = This.getRecord()) + return CheckFieldsInitialized(S, OpPC, This, R); + const auto *CAT = + cast(This.getType()->getAsArrayTypeUnsafe()); + return CheckArrayInitialized(S, OpPC, This, CAT); +} + +bool CheckFloatResult(InterpState &S, CodePtr OpPC, APFloat::opStatus Status) { + // In a constant context, assume that any dynamic rounding mode or FP + // exception state matches the default floating-point environment. + if (S.inConstantContext()) + return true; + + const SourceInfo &E = S.Current->getSource(OpPC); + FPOptions FPO = E.asExpr()->getFPFeaturesInEffect(S.Ctx.getLangOpts()); + + if ((Status & APFloat::opInexact) && + FPO.getRoundingMode() == llvm::RoundingMode::Dynamic) { + // Inexact result means that it depends on rounding mode. If the requested + // mode is dynamic, the evaluation cannot be made in compile time. + S.FFDiag(E, diag::note_constexpr_dynamic_rounding); + return false; + } + + if ((Status != APFloat::opOK) && + (FPO.getRoundingMode() == llvm::RoundingMode::Dynamic || + FPO.getExceptionMode() != LangOptions::FPE_Ignore || + FPO.getAllowFEnvAccess())) { + S.FFDiag(E, diag::note_constexpr_float_arithmetic_strict); + return false; + } + + if ((Status & APFloat::opStatus::opInvalidOp) && + FPO.getExceptionMode() != LangOptions::FPE_Ignore) { + // There is no usefully definable result. + S.FFDiag(E); + return false; + } + + return true; } bool Interpret(InterpState &S, APValue &Result) { diff --git a/contrib/llvm-project/clang/lib/AST/Interp/Interp.h b/contrib/llvm-project/clang/lib/AST/Interp/Interp.h index ed3accd98a9..ff67e873a08 100644 --- a/contrib/llvm-project/clang/lib/AST/Interp/Interp.h +++ b/contrib/llvm-project/clang/lib/AST/Interp/Interp.h @@ -14,7 +14,9 @@ #define LLVM_CLANG_AST_INTERP_INTERP_H #include "Boolean.h" +#include "Floating.h" #include "Function.h" +#include "FunctionPointer.h" #include "InterpFrame.h" #include "InterpStack.h" #include "InterpState.h" @@ -74,6 +76,9 @@ bool CheckMutable(InterpState &S, CodePtr OpPC, const Pointer &Ptr); /// Checks if a value can be loaded from a block. bool CheckLoad(InterpState &S, CodePtr OpPC, const Pointer &Ptr); +bool CheckInitialized(InterpState &S, CodePtr OpPC, const Pointer &Ptr, + AccessKinds AK); + /// Checks if a value can be stored in a block. bool CheckStore(InterpState &S, CodePtr OpPC, const Pointer &Ptr); @@ -86,6 +91,10 @@ bool CheckInit(InterpState &S, CodePtr OpPC, const Pointer &Ptr); /// Checks if a method can be called. bool CheckCallable(InterpState &S, CodePtr OpPC, const Function *F); +/// Checks if calling the currently active function would exceed +/// the allowed call depth. +bool CheckCallDepth(InterpState &S, CodePtr OpPC); + /// Checks the 'this' pointer. bool CheckThis(InterpState &S, CodePtr OpPC, const Pointer &This); @@ -96,8 +105,9 @@ bool CheckPure(InterpState &S, CodePtr OpPC, const CXXMethodDecl *MD); bool CheckCtorCall(InterpState &S, CodePtr OpPC, const Pointer &This); /// Checks if the shift operation is legal. -template -bool CheckShift(InterpState &S, CodePtr OpPC, const RT &RHS, unsigned Bits) { +template +bool CheckShift(InterpState &S, CodePtr OpPC, const LT &LHS, const RT &RHS, + unsigned Bits) { if (RHS.isNegative()) { const SourceInfo &Loc = S.Current->getSource(OpPC); S.CCEDiag(Loc, diag::note_constexpr_negative_shift) << RHS.toAPSInt(); @@ -113,6 +123,20 @@ bool CheckShift(InterpState &S, CodePtr OpPC, const RT &RHS, unsigned Bits) { S.CCEDiag(E, diag::note_constexpr_large_shift) << Val << Ty << Bits; return false; } + + if (LHS.isSigned() && !S.getLangOpts().CPlusPlus20) { + const Expr *E = S.Current->getExpr(OpPC); + // 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()) + S.CCEDiag(E, diag::note_constexpr_lshift_of_negative) << LHS.toAPSInt(); + else if (LHS.toUnsigned().countLeadingZeros() < static_cast(RHS)) + S.CCEDiag(E, diag::note_constexpr_lshift_discards); + } + + // C++2a [expr.shift]p2: [P0907R4]: + // E1 << E2 is the unique value congruent to + // E1 x 2^E2 module 2^N. return true; } @@ -137,9 +161,62 @@ bool CheckDivRem(InterpState &S, CodePtr OpPC, const T &LHS, const T &RHS) { return true; } +/// Checks if the result is a floating-point operation is valid +/// in the current context. +bool CheckFloatResult(InterpState &S, CodePtr OpPC, APFloat::opStatus Status); + /// Interpreter entry point. bool Interpret(InterpState &S, APValue &Result); +/// Interpret a builtin function. +bool InterpretBuiltin(InterpState &S, CodePtr OpPC, const Function *F); + +enum class ArithOp { Add, Sub }; + +//===----------------------------------------------------------------------===// +// Returning values +//===----------------------------------------------------------------------===// + +template ::T> +bool Ret(InterpState &S, CodePtr &PC, APValue &Result) { + const T &Ret = S.Stk.pop(); + + assert(S.Current->getFrameOffset() == S.Stk.size() && "Invalid frame"); + if (Builtin || !S.checkingPotentialConstantExpression()) + S.Current->popArgs(); + + if (InterpFrame *Caller = S.Current->Caller) { + PC = S.Current->getRetPC(); + delete S.Current; + S.Current = Caller; + S.Stk.push(Ret); + } else { + delete S.Current; + S.Current = nullptr; + if (!ReturnValue(Ret, Result)) + return false; + } + return true; +} + +template +inline bool RetVoid(InterpState &S, CodePtr &PC, APValue &Result) { + assert(S.Current->getFrameOffset() == S.Stk.size() && "Invalid frame"); + if (Builtin || !S.checkingPotentialConstantExpression()) + S.Current->popArgs(); + + if (InterpFrame *Caller = S.Current->Caller) { + PC = S.Current->getRetPC(); + delete S.Current; + S.Current = Caller; + } else { + delete S.Current; + S.Current = nullptr; + } + return true; +} + //===----------------------------------------------------------------------===// // Add, Sub, Mul //===----------------------------------------------------------------------===// @@ -184,6 +261,16 @@ bool Add(InterpState &S, CodePtr OpPC) { return AddSubMulHelper(S, OpPC, Bits, LHS, RHS); } +inline bool Addf(InterpState &S, CodePtr OpPC, llvm::RoundingMode RM) { + const Floating &RHS = S.Stk.pop(); + const Floating &LHS = S.Stk.pop(); + + Floating Result; + auto Status = Floating::add(LHS, RHS, RM, &Result); + S.Stk.push(Result); + return CheckFloatResult(S, OpPC, Status); +} + template ::T> bool Sub(InterpState &S, CodePtr OpPC) { const T &RHS = S.Stk.pop(); @@ -192,6 +279,16 @@ bool Sub(InterpState &S, CodePtr OpPC) { return AddSubMulHelper(S, OpPC, Bits, LHS, RHS); } +inline bool Subf(InterpState &S, CodePtr OpPC, llvm::RoundingMode RM) { + const Floating &RHS = S.Stk.pop(); + const Floating &LHS = S.Stk.pop(); + + Floating Result; + auto Status = Floating::sub(LHS, RHS, RM, &Result); + S.Stk.push(Result); + return CheckFloatResult(S, OpPC, Status); +} + template ::T> bool Mul(InterpState &S, CodePtr OpPC) { const T &RHS = S.Stk.pop(); @@ -200,6 +297,15 @@ bool Mul(InterpState &S, CodePtr OpPC) { return AddSubMulHelper(S, OpPC, Bits, LHS, RHS); } +inline bool Mulf(InterpState &S, CodePtr OpPC, llvm::RoundingMode RM) { + const Floating &RHS = S.Stk.pop(); + const Floating &LHS = S.Stk.pop(); + + Floating Result; + auto Status = Floating::mul(LHS, RHS, RM, &Result); + S.Stk.push(Result); + return CheckFloatResult(S, OpPC, Status); +} /// 1) Pops the RHS from the stack. /// 2) Pops the LHS from the stack. /// 3) Pushes 'LHS & RHS' on the stack @@ -291,6 +397,19 @@ bool Div(InterpState &S, CodePtr OpPC) { return false; } +inline bool Divf(InterpState &S, CodePtr OpPC, llvm::RoundingMode RM) { + const Floating &RHS = S.Stk.pop(); + const Floating &LHS = S.Stk.pop(); + + if (!CheckDivRem(S, OpPC, LHS, RHS)) + return false; + + Floating Result; + auto Status = Floating::div(LHS, RHS, RM, &Result); + S.Stk.push(Result); + return CheckFloatResult(S, OpPC, Status); +} + //===----------------------------------------------------------------------===// // Inv //===----------------------------------------------------------------------===// @@ -313,12 +432,32 @@ bool Inv(InterpState &S, CodePtr OpPC) { template ::T> bool Neg(InterpState &S, CodePtr OpPC) { - const T &Val = S.Stk.pop(); + const T &Value = S.Stk.pop(); T Result; - T::neg(Val, &Result); + if (!T::neg(Value, &Result)) { + S.Stk.push(Result); + return true; + } + + assert(isIntegralType(Name) && + "don't expect other types to fail at constexpr negation"); S.Stk.push(Result); - return true; + + APSInt NegatedValue = -Value.toAPSInt(Value.bitWidth() + 1); + const Expr *E = S.Current->getExpr(OpPC); + QualType Type = E->getType(); + + if (S.checkingForUndefinedBehavior()) { + SmallString<32> Trunc; + NegatedValue.trunc(Result.bitWidth()).toString(Trunc, 10); + auto Loc = E->getExprLoc(); + S.report(Loc, diag::warn_integer_constant_overflow) << Trunc << Type; + return true; + } + + S.CCEDiag(E, diag::note_constexpr_overflow) << NegatedValue << Type; + return S.noteUndefinedBehavior(); } enum class PushVal : bool { @@ -336,7 +475,7 @@ bool IncDecHelper(InterpState &S, CodePtr OpPC, const Pointer &Ptr) { T Result; if constexpr (DoPush == PushVal::Yes) - S.Stk.push(Result); + S.Stk.push(Value); if constexpr (Op == IncDecOp::Inc) { if (!T::increment(Value, &Result)) { @@ -380,9 +519,11 @@ bool IncDecHelper(InterpState &S, CodePtr OpPC, const Pointer &Ptr) { /// 4) Pushes the original (pre-inc) value on the stack. template ::T> bool Inc(InterpState &S, CodePtr OpPC) { - // FIXME: Check initialization of Ptr const Pointer &Ptr = S.Stk.pop(); + if (!CheckInitialized(S, OpPC, Ptr, AK_Increment)) + return false; + return IncDecHelper(S, OpPC, Ptr); } @@ -391,9 +532,11 @@ bool Inc(InterpState &S, CodePtr OpPC) { /// 3) Writes the value increased by one back to the pointer template ::T> bool IncPop(InterpState &S, CodePtr OpPC) { - // FIXME: Check initialization of Ptr const Pointer &Ptr = S.Stk.pop(); + if (!CheckInitialized(S, OpPC, Ptr, AK_Increment)) + return false; + return IncDecHelper(S, OpPC, Ptr); } @@ -403,9 +546,11 @@ bool IncPop(InterpState &S, CodePtr OpPC) { /// 4) Pushes the original (pre-dec) value on the stack. template ::T> bool Dec(InterpState &S, CodePtr OpPC) { - // FIXME: Check initialization of Ptr const Pointer &Ptr = S.Stk.pop(); + if (!CheckInitialized(S, OpPC, Ptr, AK_Decrement)) + return false; + return IncDecHelper(S, OpPC, Ptr); } @@ -414,12 +559,70 @@ bool Dec(InterpState &S, CodePtr OpPC) { /// 3) Writes the value decreased by one back to the pointer template ::T> bool DecPop(InterpState &S, CodePtr OpPC) { - // FIXME: Check initialization of Ptr const Pointer &Ptr = S.Stk.pop(); + if (!CheckInitialized(S, OpPC, Ptr, AK_Decrement)) + return false; + return IncDecHelper(S, OpPC, Ptr); } +template +bool IncDecFloatHelper(InterpState &S, CodePtr OpPC, const Pointer &Ptr, + llvm::RoundingMode RM) { + Floating Value = Ptr.deref(); + Floating Result; + + if constexpr (DoPush == PushVal::Yes) + S.Stk.push(Value); + + llvm::APFloat::opStatus Status; + if constexpr (Op == IncDecOp::Inc) + Status = Floating::increment(Value, RM, &Result); + else + Status = Floating::decrement(Value, RM, &Result); + + Ptr.deref() = Result; + + return CheckFloatResult(S, OpPC, Status); +} + +inline bool Incf(InterpState &S, CodePtr OpPC, llvm::RoundingMode RM) { + const Pointer &Ptr = S.Stk.pop(); + + if (!CheckInitialized(S, OpPC, Ptr, AK_Increment)) + return false; + + return IncDecFloatHelper(S, OpPC, Ptr, RM); +} + +inline bool IncfPop(InterpState &S, CodePtr OpPC, llvm::RoundingMode RM) { + const Pointer &Ptr = S.Stk.pop(); + + if (!CheckInitialized(S, OpPC, Ptr, AK_Increment)) + return false; + + return IncDecFloatHelper(S, OpPC, Ptr, RM); +} + +inline bool Decf(InterpState &S, CodePtr OpPC, llvm::RoundingMode RM) { + const Pointer &Ptr = S.Stk.pop(); + + if (!CheckInitialized(S, OpPC, Ptr, AK_Decrement)) + return false; + + return IncDecFloatHelper(S, OpPC, Ptr, RM); +} + +inline bool DecfPop(InterpState &S, CodePtr OpPC, llvm::RoundingMode RM) { + const Pointer &Ptr = S.Stk.pop(); + + if (!CheckInitialized(S, OpPC, Ptr, AK_Decrement)) + return false; + + return IncDecFloatHelper(S, OpPC, Ptr, RM); +} + /// 1) Pops the value from the stack. /// 2) Pushes the bitwise complemented value on the stack (~V). template ::T> @@ -454,6 +657,29 @@ bool CmpHelperEQ(InterpState &S, CodePtr OpPC, CompareFn Fn) { return CmpHelper(S, OpPC, Fn); } +/// Function pointers cannot be compared in an ordered way. +template <> +inline bool CmpHelper(InterpState &S, CodePtr OpPC, + CompareFn Fn) { + const auto &RHS = S.Stk.pop(); + const auto &LHS = S.Stk.pop(); + + const SourceInfo &Loc = S.Current->getSource(OpPC); + S.FFDiag(Loc, diag::note_constexpr_pointer_comparison_unspecified) + << LHS.toDiagnosticString(S.getCtx()) + << RHS.toDiagnosticString(S.getCtx()); + return false; +} + +template <> +inline bool CmpHelperEQ(InterpState &S, CodePtr OpPC, + CompareFn Fn) { + const auto &RHS = S.Stk.pop(); + const auto &LHS = S.Stk.pop(); + S.Stk.push(Boolean::from(Fn(LHS.compare(RHS)))); + return true; +} + template <> inline bool CmpHelper(InterpState &S, CodePtr OpPC, CompareFn Fn) { using BoolT = PrimConv::T; @@ -601,6 +827,9 @@ bool GetLocal(InterpState &S, CodePtr OpPC, uint32_t I) { return true; } +/// 1) Pops the value from the stack. +/// 2) Writes the value to the local variable with the +/// given offset. template ::T> bool SetLocal(InterpState &S, CodePtr OpPC, uint32_t I) { S.Current->setLocal(I, S.Stk.pop()); @@ -649,6 +878,7 @@ bool SetField(InterpState &S, CodePtr OpPC, uint32_t I) { const Pointer &Field = Obj.atField(I); if (!CheckStore(S, OpPC, Field)) return false; + Field.initialize(); Field.deref() = Value; return true; } @@ -719,6 +949,22 @@ bool InitGlobal(InterpState &S, CodePtr OpPC, uint32_t I) { return true; } +/// 1) Converts the value on top of the stack to an APValue +/// 2) Sets that APValue on \Temp +/// 3) Initialized global with index \I with that +template ::T> +bool InitGlobalTemp(InterpState &S, CodePtr OpPC, uint32_t I, + const LifetimeExtendedTemporaryDecl *Temp) { + assert(Temp); + const T Value = S.Stk.peek(); + APValue APV = Value.toAPValue(); + APValue *Cached = Temp->getOrCreateValue(true); + *Cached = APV; + + S.P.getGlobal(I)->deref() = S.Stk.pop(); + return true; +} + template ::T> bool InitThisField(InterpState &S, CodePtr OpPC, uint32_t I) { if (S.checkingPotentialConstantExpression()) @@ -867,6 +1113,14 @@ inline bool GetPtrActiveThisField(InterpState &S, CodePtr OpPC, uint32_t Off) { } inline bool GetPtrBase(InterpState &S, CodePtr OpPC, uint32_t Off) { + const Pointer &Ptr = S.Stk.peek(); + if (!CheckNull(S, OpPC, Ptr, CSK_Base)) + return false; + S.Stk.push(Ptr.atField(Off)); + return true; +} + +inline bool GetPtrBasePop(InterpState &S, CodePtr OpPC, uint32_t Off) { const Pointer &Ptr = S.Stk.pop(); if (!CheckNull(S, OpPC, Ptr, CSK_Base)) return false; @@ -1031,11 +1285,9 @@ bool InitElemPop(InterpState &S, CodePtr OpPC, uint32_t Idx) { // AddOffset, SubOffset //===----------------------------------------------------------------------===// -template bool OffsetHelper(InterpState &S, CodePtr OpPC) { - // Fetch the pointer and the offset. - const T &Offset = S.Stk.pop(); - const Pointer &Ptr = S.Stk.pop(); - +template +bool OffsetHelper(InterpState &S, CodePtr OpPC, const T &Offset, + const Pointer &Ptr) { if (!CheckRange(S, OpPC, Ptr, CSK_ArrayToPointer)) return false; @@ -1062,7 +1314,8 @@ template bool OffsetHelper(InterpState &S, CodePtr OpPC) { const unsigned Bits = Offset.bitWidth(); APSInt APOffset(Offset.toAPSInt().extend(Bits + 2), false); APSInt APIndex(Index.toAPSInt().extend(Bits + 2), false); - APSInt NewIndex = Add ? (APIndex + APOffset) : (APIndex - APOffset); + APSInt NewIndex = + (Op == ArithOp::Add) ? (APIndex + APOffset) : (APIndex - APOffset); S.CCEDiag(S.Current->getSource(OpPC), diag::note_constexpr_array_index) << NewIndex << /*array*/ static_cast(!Ptr.inArray()) @@ -1071,7 +1324,7 @@ template bool OffsetHelper(InterpState &S, CodePtr OpPC) { }; unsigned MaxOffset = MaxIndex - Ptr.getIndex(); - if constexpr (Add) { + if constexpr (Op == ArithOp::Add) { // If the new offset would be negative, bail out. if (Offset.isNegative() && (Offset.isMin() || -Offset > Index)) return InvalidOffset(); @@ -1093,7 +1346,7 @@ template bool OffsetHelper(InterpState &S, CodePtr OpPC) { int64_t WideIndex = static_cast(Index); int64_t WideOffset = static_cast(Offset); int64_t Result; - if constexpr (Add) + if constexpr (Op == ArithOp::Add) Result = WideIndex + WideOffset; else Result = WideIndex - WideOffset; @@ -1104,12 +1357,43 @@ template bool OffsetHelper(InterpState &S, CodePtr OpPC) { template ::T> bool AddOffset(InterpState &S, CodePtr OpPC) { - return OffsetHelper(S, OpPC); + const T &Offset = S.Stk.pop(); + const Pointer &Ptr = S.Stk.pop(); + return OffsetHelper(S, OpPC, Offset, Ptr); } template ::T> bool SubOffset(InterpState &S, CodePtr OpPC) { - return OffsetHelper(S, OpPC); + const T &Offset = S.Stk.pop(); + const Pointer &Ptr = S.Stk.pop(); + return OffsetHelper(S, OpPC, Offset, Ptr); +} + +template +static inline bool IncDecPtrHelper(InterpState &S, CodePtr OpPC) { + using OneT = Integral<8, false>; + const Pointer &Ptr = S.Stk.pop(); + + // Get the current value on the stack. + S.Stk.push(Ptr.deref()); + + // Now the current Ptr again and a constant 1. + Pointer P = Ptr.deref(); + OneT One = OneT::from(1); + if (!OffsetHelper(S, OpPC, One, P)) + return false; + + // Store the new value. + Ptr.deref() = S.Stk.pop(); + return true; +} + +static inline bool IncPtr(InterpState &S, CodePtr OpPC) { + return IncDecPtrHelper(S, OpPC); +} + +static inline bool DecPtr(InterpState &S, CodePtr OpPC) { + return IncDecPtrHelper(S, OpPC); } /// 1) Pops a Pointer from the stack. @@ -1150,6 +1434,56 @@ template bool Cast(InterpState &S, CodePtr OpPC) { return true; } +/// 1) Pops a Floating from the stack. +/// 2) Pushes a new floating on the stack that uses the given semantics. +inline bool CastFP(InterpState &S, CodePtr OpPC, const llvm::fltSemantics *Sem, + llvm::RoundingMode RM) { + Floating F = S.Stk.pop(); + Floating Result = F.toSemantics(Sem, RM); + S.Stk.push(Result); + return true; +} + +template ::T> +bool CastIntegralFloating(InterpState &S, CodePtr OpPC, + const llvm::fltSemantics *Sem, + llvm::RoundingMode RM) { + const T &From = S.Stk.pop(); + APSInt FromAP = From.toAPSInt(); + Floating Result; + + auto Status = Floating::fromIntegral(FromAP, *Sem, RM, Result); + S.Stk.push(Result); + + return CheckFloatResult(S, OpPC, Status); +} + +template ::T> +bool CastFloatingIntegral(InterpState &S, CodePtr OpPC) { + const Floating &F = S.Stk.pop(); + + if constexpr (std::is_same_v) { + S.Stk.push(T(F.isNonZero())); + return true; + } else { + APSInt Result(std::max(8u, T::bitWidth() + 1), + /*IsUnsigned=*/!T::isSigned()); + auto Status = F.convertToInteger(Result); + + // Float-to-Integral overflow check. + if ((Status & APFloat::opStatus::opInvalidOp) && F.isFinite()) { + const Expr *E = S.Current->getExpr(OpPC); + QualType Type = E->getType(); + + S.CCEDiag(E, diag::note_constexpr_overflow) << F.getAPFloat() << Type; + return S.noteUndefinedBehavior(); + } + + S.Stk.push(T(Result)); + return CheckFloatResult(S, OpPC, Status); + } +} + //===----------------------------------------------------------------------===// // Zero, Nullptr //===----------------------------------------------------------------------===// @@ -1186,6 +1520,8 @@ inline bool This(InterpState &S, CodePtr OpPC) { inline bool RVOPtr(InterpState &S, CodePtr OpPC) { assert(S.Current->getFunction()->hasRVO()); + if (S.checkingPotentialConstantExpression()) + return false; S.Stk.push(S.Current->getRVOPtr()); return true; } @@ -1202,11 +1538,12 @@ inline bool Shr(InterpState &S, CodePtr OpPC) { const auto &LHS = S.Stk.pop(); const unsigned Bits = LHS.bitWidth(); - if (!CheckShift(S, OpPC, RHS, Bits)) + if (!CheckShift(S, OpPC, LHS, RHS, Bits)) return false; - unsigned URHS = static_cast(RHS); - S.Stk.push(LT::from(static_cast(LHS) >> URHS, LHS.bitWidth())); + Integral R; + Integral::shiftRight(LHS.toUnsigned(), RHS, Bits, &R); + S.Stk.push(R); return true; } @@ -1218,12 +1555,12 @@ inline bool Shl(InterpState &S, CodePtr OpPC) { const auto &LHS = S.Stk.pop(); const unsigned Bits = LHS.bitWidth(); - if (!CheckShift(S, OpPC, RHS, Bits)) + if (!CheckShift(S, OpPC, LHS, RHS, Bits)) return false; - unsigned URHS = static_cast(RHS); - S.Stk.push(LT::from(static_cast(LHS) << URHS, LHS.bitWidth())); - + Integral R; + Integral::shiftLeft(LHS.toUnsigned(), RHS, Bits, &R); + S.Stk.push(R); return true; } @@ -1253,19 +1590,62 @@ inline bool ExpandPtr(InterpState &S, CodePtr OpPC) { return true; } -inline bool Call(InterpState &S, CodePtr &PC, const Function *Func) { - auto NewFrame = std::make_unique(S, Func, PC); - Pointer ThisPtr; - if (Func->hasThisPointer()) { - ThisPtr = NewFrame->getThis(); - if (!CheckInvoke(S, PC, ThisPtr)) { - return false; - } - } +// 1) Pops an integral value from the stack +// 2) Peeks a pointer +// 3) Pushes a new pointer that's a narrowed array +// element of the peeked pointer with the value +// from 1) added as offset. +// +// This leaves the original pointer on the stack and pushes a new one +// with the offset applied and narrowed. +template ::T> +inline bool ArrayElemPtr(InterpState &S, CodePtr OpPC) { + const T &Offset = S.Stk.pop(); + const Pointer &Ptr = S.Stk.peek(); - if (!CheckCallable(S, PC, Func)) + if (!OffsetHelper(S, OpPC, Offset, Ptr)) return false; + return NarrowPtr(S, OpPC); +} + +template ::T> +inline bool ArrayElemPtrPop(InterpState &S, CodePtr OpPC) { + const T &Offset = S.Stk.pop(); + const Pointer &Ptr = S.Stk.pop(); + + if (!OffsetHelper(S, OpPC, Offset, Ptr)) + return false; + + return NarrowPtr(S, OpPC); +} + +inline bool CheckGlobalCtor(InterpState &S, CodePtr OpPC) { + const Pointer &Obj = S.Stk.peek(); + return CheckCtorCall(S, OpPC, Obj); +} + +inline bool Call(InterpState &S, CodePtr OpPC, const Function *Func) { + if (Func->hasThisPointer()) { + size_t ThisOffset = + Func->getArgSize() + (Func->hasRVO() ? primSize(PT_Ptr) : 0); + + const Pointer &ThisPtr = S.Stk.peek(ThisOffset); + + if (!CheckInvoke(S, OpPC, ThisPtr)) + return false; + + if (S.checkingPotentialConstantExpression()) + return false; + } + + if (!CheckCallable(S, OpPC, Func)) + return false; + + if (!CheckCallDepth(S, OpPC)) + return false; + + auto NewFrame = std::make_unique(S, Func, OpPC); InterpFrame *FrameBefore = S.Current; S.Current = NewFrame.get(); @@ -1276,11 +1656,6 @@ inline bool Call(InterpState &S, CodePtr &PC, const Function *Func) { if (Interpret(S, CallResult)) { NewFrame.release(); // Frame was delete'd already. assert(S.Current == FrameBefore); - - // For constructors, check that all fields have been initialized. - if (Func->isConstructor() && !CheckCtorCall(S, PC, ThisPtr)) - return false; - return true; } @@ -1290,6 +1665,66 @@ inline bool Call(InterpState &S, CodePtr &PC, const Function *Func) { return false; } +inline bool CallVirt(InterpState &S, CodePtr OpPC, const Function *Func) { + assert(Func->hasThisPointer()); + assert(Func->isVirtual()); + size_t ThisOffset = + Func->getArgSize() + (Func->hasRVO() ? primSize(PT_Ptr) : 0); + Pointer &ThisPtr = S.Stk.peek(ThisOffset); + + const CXXRecordDecl *DynamicDecl = + ThisPtr.getDeclDesc()->getType()->getAsCXXRecordDecl(); + const auto *StaticDecl = cast(Func->getParentDecl()); + const auto *InitialFunction = cast(Func->getDecl()); + const CXXMethodDecl *Overrider = S.getContext().getOverridingFunction( + DynamicDecl, StaticDecl, InitialFunction); + + if (Overrider != InitialFunction) { + Func = S.P.getFunction(Overrider); + + const CXXRecordDecl *ThisFieldDecl = + ThisPtr.getFieldDesc()->getType()->getAsCXXRecordDecl(); + if (Func->getParentDecl()->isDerivedFrom(ThisFieldDecl)) { + // If the function we call is further DOWN the hierarchy than the + // FieldDesc of our pointer, just get the DeclDesc instead, which + // is the furthest we might go up in the hierarchy. + ThisPtr = ThisPtr.getDeclPtr(); + } + } + + return Call(S, OpPC, Func); +} + +inline bool CallBI(InterpState &S, CodePtr &PC, const Function *Func) { + auto NewFrame = std::make_unique(S, Func, PC); + + InterpFrame *FrameBefore = S.Current; + S.Current = NewFrame.get(); + + if (InterpretBuiltin(S, PC, Func)) { + NewFrame.release(); + return true; + } + S.Current = FrameBefore; + return false; +} + +inline bool CallPtr(InterpState &S, CodePtr OpPC) { + const FunctionPointer &FuncPtr = S.Stk.pop(); + + const Function *F = FuncPtr.getFunction(); + if (!F || !F->isConstexpr()) + return false; + + return Call(S, OpPC, F); +} + +inline bool GetFnPtr(InterpState &S, CodePtr OpPC, const Function *Func) { + assert(Func); + S.Stk.push(Func); + return true; +} + //===----------------------------------------------------------------------===// // Read opcode arguments //===----------------------------------------------------------------------===// diff --git a/contrib/llvm-project/clang/lib/AST/Interp/InterpBlock.cpp b/contrib/llvm-project/clang/lib/AST/Interp/InterpBlock.cpp index ed6e8910194..a62128d9cfa 100644 --- a/contrib/llvm-project/clang/lib/AST/Interp/InterpBlock.cpp +++ b/contrib/llvm-project/clang/lib/AST/Interp/InterpBlock.cpp @@ -16,11 +16,16 @@ using namespace clang; using namespace clang::interp; - - void Block::addPointer(Pointer *P) { - if (IsStatic) + assert(P); + if (IsStatic) { + assert(!Pointers); return; + } + +#ifndef NDEBUG + assert(!hasPointer(P)); +#endif if (Pointers) Pointers->Prev = P; P->Next = Pointers; @@ -29,10 +34,19 @@ void Block::addPointer(Pointer *P) { } void Block::removePointer(Pointer *P) { - if (IsStatic) + assert(P); + if (IsStatic) { + assert(!Pointers); return; + } + +#ifndef NDEBUG + assert(hasPointer(P)); +#endif + if (Pointers == P) Pointers = P->Next; + if (P->Prev) P->Prev->Next = P->Next; if (P->Next) @@ -44,22 +58,39 @@ void Block::cleanup() { (reinterpret_cast(this + 1) - 1)->free(); } -void Block::movePointer(Pointer *From, Pointer *To) { - if (IsStatic) +void Block::replacePointer(Pointer *Old, Pointer *New) { + assert(Old); + assert(New); + if (IsStatic) { + assert(!Pointers); return; - To->Prev = From->Prev; - if (To->Prev) - To->Prev->Next = To; - To->Next = From->Next; - if (To->Next) - To->Next->Prev = To; - if (Pointers == From) - Pointers = To; + } - From->Prev = nullptr; - From->Next = nullptr; +#ifndef NDEBUG + assert(hasPointer(Old)); +#endif + + removePointer(Old); + addPointer(New); + + Old->Pointee = nullptr; + +#ifndef NDEBUG + assert(!hasPointer(Old)); + assert(hasPointer(New)); +#endif } +#ifndef NDEBUG +bool Block::hasPointer(const Pointer *P) const { + for (const Pointer *C = Pointers; C; C = C->Next) { + if (C == P) + return true; + } + return false; +} +#endif + DeadBlock::DeadBlock(DeadBlock *&Root, Block *Blk) : Root(Root), B(Blk->Desc, Blk->IsStatic, Blk->IsExtern, /*isDead=*/true) { // Add the block to the chain of dead blocks. @@ -83,5 +114,5 @@ void DeadBlock::free() { Next->Prev = Prev; if (Root == this) Root = Next; - ::free(this); + std::free(this); } diff --git a/contrib/llvm-project/clang/lib/AST/Interp/InterpBlock.h b/contrib/llvm-project/clang/lib/AST/Interp/InterpBlock.h index f790c50a912..0080dad718e 100644 --- a/contrib/llvm-project/clang/lib/AST/Interp/InterpBlock.h +++ b/contrib/llvm-project/clang/lib/AST/Interp/InterpBlock.h @@ -48,7 +48,7 @@ enum PrimType : unsigned; /// class Block final { public: - // Creates a new block. + /// Creates a new block. Block(const std::optional &DeclID, Descriptor *Desc, bool IsStatic = false, bool IsExtern = false) : DeclID(DeclID), IsStatic(IsStatic), IsExtern(IsExtern), Desc(Desc) {} @@ -58,7 +58,7 @@ public: Desc(Desc) {} /// Returns the block's descriptor. - Descriptor *getDescriptor() const { return Desc; } + const Descriptor *getDescriptor() const { return Desc; } /// Checks if the block has any live pointers. bool hasPointers() const { return Pointers; } /// Checks if the block is extern. @@ -68,7 +68,7 @@ public: /// Checks if the block is temporary. bool isTemporary() const { return Desc->IsTemporary; } /// Returns the size of the block. - InterpSize getSize() const { return Desc->getAllocSize(); } + unsigned getSize() const { return Desc->getAllocSize(); } /// Returns the declaration ID. std::optional getDeclID() const { return DeclID; } @@ -104,7 +104,7 @@ public: /*isActive=*/true, Desc); } - // Invokes the Destructor. + /// Invokes the Destructor. void invokeDtor() { if (Desc->DtorFn) Desc->DtorFn(this, data(), Desc); @@ -118,13 +118,16 @@ protected: Block(Descriptor *Desc, bool IsExtern, bool IsStatic, bool IsDead) : IsStatic(IsStatic), IsExtern(IsExtern), IsDead(true), Desc(Desc) {} - // Deletes a dead block at the end of its lifetime. + /// Deletes a dead block at the end of its lifetime. void cleanup(); - // Pointer chain management. + /// Pointer chain management. void addPointer(Pointer *P); void removePointer(Pointer *P); - void movePointer(Pointer *From, Pointer *To); + void replacePointer(Pointer *Old, Pointer *New); +#ifndef NDEBUG + bool hasPointer(const Pointer *P) const; +#endif /// Start of the chain of pointers. Pointer *Pointers = nullptr; diff --git a/contrib/llvm-project/clang/lib/AST/Interp/InterpBuiltin.cpp b/contrib/llvm-project/clang/lib/AST/Interp/InterpBuiltin.cpp new file mode 100644 index 00000000000..c11f22aa94c --- /dev/null +++ b/contrib/llvm-project/clang/lib/AST/Interp/InterpBuiltin.cpp @@ -0,0 +1,82 @@ +//===--- InterpBuiltin.cpp - Interpreter for the constexpr VM ---*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +#include "Boolean.h" +#include "Interp.h" +#include "PrimType.h" +#include "clang/Basic/Builtins.h" + +namespace clang { +namespace interp { + +template T getParam(InterpFrame *Frame, unsigned Index) { + unsigned Offset = Frame->getFunction()->getParamOffset(Index); + return Frame->getParam(Offset); +} + +static bool interp__builtin_strcmp(InterpState &S, CodePtr OpPC, + InterpFrame *Frame) { + const Pointer &A = getParam(Frame, 0); + const Pointer &B = getParam(Frame, 1); + + if (!CheckLive(S, OpPC, A, AK_Read) || !CheckLive(S, OpPC, B, AK_Read)) + return false; + + assert(A.getFieldDesc()->isPrimitiveArray()); + assert(B.getFieldDesc()->isPrimitiveArray()); + + unsigned IndexA = A.getIndex(); + unsigned IndexB = B.getIndex(); + int32_t Result = 0; + for (;; ++IndexA, ++IndexB) { + const Pointer &PA = A.atIndex(IndexA); + const Pointer &PB = B.atIndex(IndexB); + if (!CheckRange(S, OpPC, PA, AK_Read) || + !CheckRange(S, OpPC, PB, AK_Read)) { + return false; + } + uint8_t CA = PA.deref(); + uint8_t CB = PB.deref(); + + if (CA > CB) { + Result = 1; + break; + } else if (CA < CB) { + Result = -1; + break; + } + if (CA == 0 || CB == 0) + break; + } + + S.Stk.push>(Integral<32, true>::from(Result)); + return true; +} + +bool InterpretBuiltin(InterpState &S, CodePtr OpPC, const Function *F) { + InterpFrame *Frame = S.Current; + APValue Dummy; + + switch (F->getBuiltinID()) { + case Builtin::BI__builtin_is_constant_evaluated: + S.Stk.push(Boolean::from(S.inConstantContext())); + return Ret(S, OpPC, Dummy); + case Builtin::BI__builtin_assume: + return RetVoid(S, OpPC, Dummy); + case Builtin::BI__builtin_strcmp: + if (interp__builtin_strcmp(S, OpPC, Frame)) + return Ret(S, OpPC, Dummy); + return false; + default: + return false; + } + + return false; +} + +} // namespace interp +} // namespace clang diff --git a/contrib/llvm-project/clang/lib/AST/Interp/InterpFrame.cpp b/contrib/llvm-project/clang/lib/AST/Interp/InterpFrame.cpp index 40644c538c6..2229aa7c08f 100644 --- a/contrib/llvm-project/clang/lib/AST/Interp/InterpFrame.cpp +++ b/contrib/llvm-project/clang/lib/AST/Interp/InterpFrame.cpp @@ -8,6 +8,7 @@ #include "InterpFrame.h" #include "Boolean.h" +#include "Floating.h" #include "Function.h" #include "InterpStack.h" #include "InterpState.h" @@ -22,8 +23,8 @@ using namespace clang::interp; InterpFrame::InterpFrame(InterpState &S, const Function *Func, InterpFrame *Caller, CodePtr RetPC) - : Caller(Caller), S(S), Func(Func), RetPC(RetPC), - ArgSize(Func ? Func->getArgSize() : 0), + : Caller(Caller), S(S), Depth(Caller ? Caller->Depth + 1 : 0), Func(Func), + RetPC(RetPC), ArgSize(Func ? Func->getArgSize() : 0), Args(static_cast(S.Stk.top())), FrameOffset(S.Stk.size()) { if (!Func) return; @@ -75,7 +76,7 @@ InterpFrame::~InterpFrame() { void InterpFrame::destroy(unsigned Idx) { for (auto &Local : Func->getScope(Idx).locals()) { - S.deallocate(reinterpret_cast(localBlock(Local.Offset))); + S.deallocate(localBlock(Local.Offset)); } } @@ -97,20 +98,19 @@ void print(llvm::raw_ostream &OS, const Pointer &P, ASTContext &Ctx, return; } - auto printDesc = [&OS, &Ctx](Descriptor *Desc) { - if (auto *D = Desc->asDecl()) { + auto printDesc = [&OS, &Ctx](const Descriptor *Desc) { + if (const auto *D = Desc->asDecl()) { // Subfields or named values. - if (auto *VD = dyn_cast(D)) { + if (const auto *VD = dyn_cast(D)) { OS << *VD; return; } // Base classes. - if (isa(D)) { + if (isa(D)) return; - } } // Temporary expression. - if (auto *E = Desc->asExpr()) { + if (const auto *E = Desc->asExpr()) { E->printPretty(OS, nullptr, Ctx.getPrintingPolicy()); return; } @@ -125,6 +125,10 @@ void print(llvm::raw_ostream &OS, const Pointer &P, ASTContext &Ctx, F = F.isArrayElement() ? F.getArray().expand() : F.getBase(); } + // Drop the first pointer since we print it unconditionally anyway. + if (!Levels.empty()) + Levels.erase(Levels.begin()); + printDesc(P.getDeclDesc()); for (const auto &It : Levels) { if (It.inArray()) { @@ -140,10 +144,10 @@ void print(llvm::raw_ostream &OS, const Pointer &P, ASTContext &Ctx, } } -void InterpFrame::describe(llvm::raw_ostream &OS) { +void InterpFrame::describe(llvm::raw_ostream &OS) const { const FunctionDecl *F = getCallee(); - auto *M = dyn_cast(F); - if (M && M->isInstance() && !isa(F)) { + if (const auto *M = dyn_cast(F); + M && M->isInstance() && !isa(F)) { print(OS, This, S.getCtx(), S.getCtx().getRecordType(M->getParent())); OS << "->"; } @@ -184,8 +188,7 @@ const FunctionDecl *InterpFrame::getCallee() const { Pointer InterpFrame::getLocalPointer(unsigned Offset) const { assert(Offset < Func->getFrameSize() && "Invalid local offset."); - return Pointer(reinterpret_cast(localBlock(Offset)), - sizeof(InlineDescriptor)); + return Pointer(localBlock(Offset), sizeof(InlineDescriptor)); } Pointer InterpFrame::getParamPointer(unsigned Off) { @@ -210,6 +213,11 @@ Pointer InterpFrame::getParamPointer(unsigned Off) { } SourceInfo InterpFrame::getSource(CodePtr PC) const { + // Implicitly created functions don't have any code we could point at, + // so return the call site. + if (Func && Func->getDecl()->isImplicit() && Caller) + return Caller->getSource(RetPC); + return S.getSource(Func, PC); } diff --git a/contrib/llvm-project/clang/lib/AST/Interp/InterpFrame.h b/contrib/llvm-project/clang/lib/AST/Interp/InterpFrame.h index bfa02c90ebe..ce58fb8d3f8 100644 --- a/contrib/llvm-project/clang/lib/AST/Interp/InterpFrame.h +++ b/contrib/llvm-project/clang/lib/AST/Interp/InterpFrame.h @@ -15,7 +15,6 @@ #include "Frame.h" #include "Program.h" -#include "State.h" #include #include @@ -51,7 +50,7 @@ public: void popArgs(); /// Describes the frame with arguments for diagnostic purposes. - void describe(llvm::raw_ostream &OS) override; + void describe(llvm::raw_ostream &OS) const override; /// Returns the parent frame object. Frame *getCaller() const override; @@ -120,6 +119,8 @@ public: const Expr *getExpr(CodePtr PC) const; SourceLocation getLocation(CodePtr PC) const; + unsigned getDepth() const { return Depth; } + private: /// Returns an original argument from the stack. template const T &stackRef(unsigned Offset) const { @@ -133,8 +134,8 @@ private: } /// Returns a pointer to a local's block. - void *localBlock(unsigned Offset) const { - return Locals.get() + Offset - sizeof(Block); + Block *localBlock(unsigned Offset) const { + return reinterpret_cast(Locals.get() + Offset - sizeof(Block)); } // Returns the inline descriptor of the local. @@ -145,6 +146,8 @@ private: private: /// Reference to the interpreter state. InterpState &S; + /// Depth of this frame. + unsigned Depth; /// Reference to the function being executed. const Function *Func; /// Current object pointer for methods. diff --git a/contrib/llvm-project/clang/lib/AST/Interp/InterpStack.cpp b/contrib/llvm-project/clang/lib/AST/Interp/InterpStack.cpp index 7fe678e6219..da4b36f8c1b 100644 --- a/contrib/llvm-project/clang/lib/AST/Interp/InterpStack.cpp +++ b/contrib/llvm-project/clang/lib/AST/Interp/InterpStack.cpp @@ -6,9 +6,12 @@ // //===----------------------------------------------------------------------===// +#include "InterpStack.h" +#include "Boolean.h" +#include "Floating.h" +#include "Integral.h" #include #include -#include "InterpStack.h" using namespace clang; using namespace clang::interp; @@ -19,11 +22,14 @@ InterpStack::~InterpStack() { void InterpStack::clear() { if (Chunk && Chunk->Next) - free(Chunk->Next); + std::free(Chunk->Next); if (Chunk) - free(Chunk); + std::free(Chunk); Chunk = nullptr; StackSize = 0; +#ifndef NDEBUG + ItemTypes.clear(); +#endif } void *InterpStack::grow(size_t Size) { @@ -33,7 +39,7 @@ void *InterpStack::grow(size_t Size) { if (Chunk && Chunk->Next) { Chunk = Chunk->Next; } else { - StackChunk *Next = new (malloc(ChunkSize)) StackChunk(Chunk); + StackChunk *Next = new (std::malloc(ChunkSize)) StackChunk(Chunk); if (Chunk) Chunk->Next = Next; Chunk = Next; @@ -46,7 +52,7 @@ void *InterpStack::grow(size_t Size) { return Object; } -void *InterpStack::peek(size_t Size) const { +void *InterpStack::peekData(size_t Size) const { assert(Chunk && "Stack is empty!"); StackChunk *Ptr = Chunk; @@ -65,7 +71,7 @@ void InterpStack::shrink(size_t Size) { while (Size > Chunk->size()) { Size -= Chunk->size(); if (Chunk->Next) { - free(Chunk->Next); + std::free(Chunk->Next); Chunk->Next = nullptr; } Chunk->End = Chunk->start(); @@ -76,3 +82,24 @@ void InterpStack::shrink(size_t Size) { Chunk->End -= Size; StackSize -= Size; } + +void InterpStack::dump() const { +#ifndef NDEBUG + llvm::errs() << "Items: " << ItemTypes.size() << ". Size: " << size() << "\n"; + if (ItemTypes.empty()) + return; + + size_t Index = 0; + size_t Offset = align(primSize(ItemTypes[0])); + for (PrimType Ty : ItemTypes) { + llvm::errs() << Index << "/" << Offset << ": "; + TYPE_SWITCH(Ty, { + const T &V = peek(Offset); + llvm::errs() << V; + }); + llvm::errs() << "\n"; + Offset += align(primSize(Ty)); + ++Index; + } +#endif +} diff --git a/contrib/llvm-project/clang/lib/AST/Interp/InterpStack.h b/contrib/llvm-project/clang/lib/AST/Interp/InterpStack.h index 3adaad96515..ab4351a6dc6 100644 --- a/contrib/llvm-project/clang/lib/AST/Interp/InterpStack.h +++ b/contrib/llvm-project/clang/lib/AST/Interp/InterpStack.h @@ -13,6 +13,7 @@ #ifndef LLVM_CLANG_AST_INTERP_INTERPSTACK_H #define LLVM_CLANG_AST_INTERP_INTERPSTACK_H +#include "FunctionPointer.h" #include "PrimType.h" #include #include @@ -43,8 +44,8 @@ public: assert(ItemTypes.back() == toPrimType()); ItemTypes.pop_back(); #endif - auto *Ptr = &peek(); - auto Value = std::move(*Ptr); + T *Ptr = &peekInternal(); + T Value = std::move(*Ptr); Ptr->~T(); shrink(aligned_size()); return Value; @@ -53,21 +54,31 @@ public: /// Discards the top value from the stack. template void discard() { #ifndef NDEBUG + assert(!ItemTypes.empty()); assert(ItemTypes.back() == toPrimType()); ItemTypes.pop_back(); #endif - auto *Ptr = &peek(); + T *Ptr = &peekInternal(); Ptr->~T(); shrink(aligned_size()); } /// Returns a reference to the value on the top of the stack. template T &peek() const { - return *reinterpret_cast(peek(aligned_size())); +#ifndef NDEBUG + assert(!ItemTypes.empty()); + assert(ItemTypes.back() == toPrimType()); +#endif + return peekInternal(); + } + + template T &peek(size_t Offset) const { + assert(aligned(Offset)); + return *reinterpret_cast(peekData(Offset)); } /// Returns a pointer to the top object. - void *top() const { return Chunk ? peek(0) : nullptr; } + void *top() const { return Chunk ? peekData(0) : nullptr; } /// Returns the size of the stack in bytes. size_t size() const { return StackSize; } @@ -75,9 +86,12 @@ public: /// Clears the stack without calling any destructors. void clear(); - // Returns whether the stack is empty. + /// Returns whether the stack is empty. bool empty() const { return StackSize == 0; } + /// dump the stack contents to stderr. + void dump() const; + private: /// All stack slots are aligned to the native pointer alignment for storage. /// The size of an object is rounded up to a pointer alignment multiple. @@ -86,10 +100,15 @@ private: return ((sizeof(T) + PtrAlign - 1) / PtrAlign) * PtrAlign; } + /// Like the public peek(), but without the debug type checks. + template T &peekInternal() const { + return *reinterpret_cast(peekData(aligned_size())); + } + /// Grows the stack to accommodate a value and returns a pointer to it. void *grow(size_t Size); /// Returns a pointer from the top of the stack. - void *peek(size_t Size) const; + void *peekData(size_t Size) const; /// Shrinks the stack. void shrink(size_t Size); @@ -160,6 +179,10 @@ private: else if constexpr (std::is_same_v || std::is_same_v>) return PT_Uint64; + else if constexpr (std::is_same_v) + return PT_Float; + else if constexpr (std::is_same_v) + return PT_FnPtr; llvm_unreachable("unknown type push()'ed into InterpStack"); } diff --git a/contrib/llvm-project/clang/lib/AST/Interp/InterpState.cpp b/contrib/llvm-project/clang/lib/AST/Interp/InterpState.cpp index 25684f3c093..2596c56b4e0 100644 --- a/contrib/llvm-project/clang/lib/AST/Interp/InterpState.cpp +++ b/contrib/llvm-project/clang/lib/AST/Interp/InterpState.cpp @@ -7,24 +7,17 @@ //===----------------------------------------------------------------------===// #include "InterpState.h" -#include -#include "Function.h" #include "InterpFrame.h" #include "InterpStack.h" -#include "Opcode.h" -#include "PrimType.h" #include "Program.h" #include "State.h" using namespace clang; using namespace clang::interp; -using APSInt = llvm::APSInt; - InterpState::InterpState(State &Parent, Program &P, InterpStack &Stk, Context &Ctx, SourceMapper *M) - : Parent(Parent), M(M), P(P), Stk(Stk), Ctx(Ctx), Current(nullptr), - CallStackDepth(Parent.getCallStackDepth() + 1) {} + : Parent(Parent), M(M), P(P), Stk(Stk), Ctx(Ctx), Current(nullptr) {} InterpState::~InterpState() { while (Current) { @@ -35,17 +28,15 @@ InterpState::~InterpState() { while (DeadBlocks) { DeadBlock *Next = DeadBlocks->Next; - free(DeadBlocks); + std::free(DeadBlocks); DeadBlocks = Next; } } Frame *InterpState::getCurrentFrame() { - if (Current && Current->Caller) { + if (Current && Current->Caller) return Current; - } else { - return Parent.getCurrentFrame(); - } + return Parent.getCurrentFrame(); } bool InterpState::reportOverflow(const Expr *E, const llvm::APSInt &Value) { @@ -55,12 +46,16 @@ bool InterpState::reportOverflow(const Expr *E, const llvm::APSInt &Value) { } void InterpState::deallocate(Block *B) { - Descriptor *Desc = B->getDescriptor(); + assert(B); + const Descriptor *Desc = B->getDescriptor(); + assert(Desc); + if (B->hasPointers()) { size_t Size = B->getSize(); // Allocate a new block, transferring over pointers. - char *Memory = reinterpret_cast(malloc(sizeof(DeadBlock) + Size)); + char *Memory = + reinterpret_cast(std::malloc(sizeof(DeadBlock) + Size)); auto *D = new (Memory) DeadBlock(DeadBlocks, B); // Move data from one block to another. diff --git a/contrib/llvm-project/clang/lib/AST/Interp/InterpState.h b/contrib/llvm-project/clang/lib/AST/Interp/InterpState.h index 03308063738..fc28c74002d 100644 --- a/contrib/llvm-project/clang/lib/AST/Interp/InterpState.h +++ b/contrib/llvm-project/clang/lib/AST/Interp/InterpState.h @@ -15,6 +15,7 @@ #include "Context.h" #include "Function.h" +#include "InterpFrame.h" #include "InterpStack.h" #include "State.h" #include "clang/AST/APValue.h" @@ -41,7 +42,9 @@ public: // Stack frame accessors. Frame *getSplitFrame() { return Parent.getCurrentFrame(); } Frame *getCurrentFrame() override; - unsigned getCallStackDepth() override { return CallStackDepth; } + unsigned getCallStackDepth() override { + return Current ? (Current->getDepth() + 1) : 1; + } const Frame *getBottomFrame() const override { return Parent.getBottomFrame(); } @@ -86,6 +89,8 @@ public: return M ? M->getSource(F, PC) : F->getSource(PC); } + Context &getContext() const { return Ctx; } + private: /// AST Walker state. State &Parent; @@ -103,8 +108,6 @@ public: Context &Ctx; /// The current frame. InterpFrame *Current = nullptr; - /// Call stack depth. - unsigned CallStackDepth; }; } // namespace interp diff --git a/contrib/llvm-project/clang/lib/AST/Interp/Opcodes.td b/contrib/llvm-project/clang/lib/AST/Interp/Opcodes.td index 058475b2d39..28074a350d0 100644 --- a/contrib/llvm-project/clang/lib/AST/Interp/Opcodes.td +++ b/contrib/llvm-project/clang/lib/AST/Interp/Opcodes.td @@ -25,7 +25,9 @@ def Sint32 : Type; def Uint32 : Type; def Sint64 : Type; def Uint64 : Type; +def Float : Type; def Ptr : Type; +def FnPtr : Type; //===----------------------------------------------------------------------===// // Types transferred to the interpreter. @@ -40,11 +42,15 @@ def ArgSint32 : ArgType { let Name = "int32_t"; } def ArgUint32 : ArgType { let Name = "uint32_t"; } def ArgSint64 : ArgType { let Name = "int64_t"; } def ArgUint64 : ArgType { let Name = "uint64_t"; } +def ArgFloat : ArgType { let Name = "Floating"; } def ArgBool : ArgType { let Name = "bool"; } def ArgFunction : ArgType { let Name = "const Function *"; } def ArgRecordDecl : ArgType { let Name = "const RecordDecl *"; } def ArgRecordField : ArgType { let Name = "const Record::Field *"; } +def ArgFltSemantics : ArgType { let Name = "const llvm::fltSemantics *"; } +def ArgRoundingMode : ArgType { let Name = "llvm::RoundingMode"; } +def ArgLETD: ArgType { let Name = "const LifetimeExtendedTemporaryDecl *"; } //===----------------------------------------------------------------------===// // Classes of types instructions operate on. @@ -54,34 +60,41 @@ class TypeClass { list Types; } -def NumberTypeClass : TypeClass { - let Types = [Sint8, Uint8, Sint16, Uint16, Sint32, - Uint32, Sint64, Uint64]; -} - def IntegerTypeClass : TypeClass { let Types = [Sint8, Uint8, Sint16, Uint16, Sint32, Uint32, Sint64, Uint64]; } +def NumberTypeClass : TypeClass { + let Types = !listconcat(IntegerTypeClass.Types, [Float]); +} + +def FloatTypeClass : TypeClass { + let Types = [Float]; +} + def AluTypeClass : TypeClass { - let Types = !listconcat(NumberTypeClass.Types, [Bool]); + let Types = !listconcat(IntegerTypeClass.Types, [Bool]); } def PtrTypeClass : TypeClass { - let Types = [Ptr]; + let Types = [Ptr, FnPtr]; } def BoolTypeClass : TypeClass { let Types = [Bool]; } +def NonPtrTypeClass : TypeClass { + let Types = !listconcat(IntegerTypeClass.Types, [Bool], [Float]); +} + def AllTypeClass : TypeClass { - let Types = !listconcat(AluTypeClass.Types, PtrTypeClass.Types); + let Types = !listconcat(AluTypeClass.Types, PtrTypeClass.Types, FloatTypeClass.Types); } def ComparableTypeClass : TypeClass { - let Types = !listconcat(AluTypeClass.Types, [Ptr]); + let Types = !listconcat(AluTypeClass.Types, [Ptr], [Float], [FnPtr]); } class SingletonTypeClass : TypeClass { @@ -108,6 +121,11 @@ class AluOpcode : Opcode { let HasGroup = 1; } +class FloatOpcode : Opcode { + let Types = []; + let Args = [ArgRoundingMode]; +} + class IntegerOpcode : Opcode { let Types = [IntegerTypeClass]; let HasGroup = 1; @@ -161,7 +179,21 @@ def NoRet : Opcode {} def Call : Opcode { let Args = [ArgFunction]; let Types = []; - let ChangesPC = 1; +} + +def CallVirt : Opcode { + let Args = [ArgFunction]; + let Types = []; +} + +def CallBI : Opcode { + let Args = [ArgFunction]; + let Types = []; +} + +def CallPtr : Opcode { + let Args = []; + let Types = []; } //===----------------------------------------------------------------------===// @@ -193,6 +225,7 @@ def ConstSint32 : ConstOpcode; def ConstUint32 : ConstOpcode; def ConstSint64 : ConstOpcode; def ConstUint64 : ConstOpcode; +def ConstFloat : ConstOpcode; def ConstBool : ConstOpcode; // [] -> [Integer] @@ -204,6 +237,7 @@ def Zero : Opcode { // [] -> [Pointer] def Null : Opcode { let Types = [PtrTypeClass]; + let HasGroup = 1; } //===----------------------------------------------------------------------===// @@ -251,6 +285,12 @@ def GetPtrBase : Opcode { // Offset of field, which is a base. let Args = [ArgUint32]; } +// [Pointer] -> [Pointer] +def GetPtrBasePop : Opcode { + // Offset of field, which is a base. + let Args = [ArgUint32]; +} + // [Pointer] -> [Pointer] def GetPtrVirtBase : Opcode { // RecordDecl of base class. @@ -276,6 +316,9 @@ def RVOPtr : Opcode; def NarrowPtr : Opcode; // [Pointer] -> [Pointer] def ExpandPtr : Opcode; +// [Pointer, Offset] -> [Pointer] +def ArrayElemPtr : AluOpcode; +def ArrayElemPtrPop : AluOpcode; //===----------------------------------------------------------------------===// // Direct field accessors @@ -298,11 +341,17 @@ def GetLocal : AccessOpcode { let HasCustomEval = 1; } // [] -> [Pointer] def SetLocal : AccessOpcode { let HasCustomEval = 1; } +def CheckGlobalCtor : Opcode {} + // [] -> [Value] def GetGlobal : AccessOpcode; // [Value] -> [] def InitGlobal : AccessOpcode; // [Value] -> [] +def InitGlobalTemp : AccessOpcode { + let Args = [ArgUint32, ArgLETD]; +} +// [Value] -> [] def SetGlobal : AccessOpcode; // [] -> [Value] @@ -393,24 +442,47 @@ def AddOffset : AluOpcode; // [Pointer, Integral] -> [Pointer] def SubOffset : AluOpcode; -// Pointer, Pointer] - [Integral] +// [Pointer, Pointer] -> [Integral] def SubPtr : Opcode { let Types = [IntegerTypeClass]; let HasGroup = 1; } +// [Pointer] -> [Pointer] +def IncPtr : Opcode { + let HasGroup = 0; +} +// [Pointer] -> [Pointer] +def DecPtr : Opcode { + let HasGroup = 0; +} + +//===----------------------------------------------------------------------===// +// Function pointers. +//===----------------------------------------------------------------------===// +def GetFnPtr : Opcode { + let Args = [ArgFunction]; +} + + //===----------------------------------------------------------------------===// // Binary operators. //===----------------------------------------------------------------------===// // [Real, Real] -> [Real] -def Sub : AluOpcode; -def Add : AluOpcode; -def Mul : AluOpcode; -def Rem : Opcode { - let Types = [NumberTypeClass]; - let HasGroup = 1; -} +def Add : AluOpcode; +def Addf : FloatOpcode; +def Sub : AluOpcode; +def Subf : FloatOpcode; +def Mul : AluOpcode; +def Mulf : FloatOpcode; +def Rem : IntegerOpcode; +def Div : IntegerOpcode; +def Divf : FloatOpcode; + +def BitAnd : IntegerOpcode; +def BitOr : IntegerOpcode; +def BitXor : IntegerOpcode; def Shl : Opcode { let Types = [IntegerTypeClass, IntegerTypeClass]; @@ -422,14 +494,6 @@ def Shr : Opcode { let HasGroup = 1; } -def BitAnd : IntegerOpcode; -def BitOr : IntegerOpcode; -def Div : Opcode { - let Types = [NumberTypeClass]; - let HasGroup = 1; -} -def BitXor : IntegerOpcode; - //===----------------------------------------------------------------------===// // Unary operators. //===----------------------------------------------------------------------===// @@ -440,27 +504,33 @@ def Inv: Opcode { let HasGroup = 1; } +// Increment and decrement. def Inc: IntegerOpcode; def IncPop : IntegerOpcode; def Dec: IntegerOpcode; def DecPop: IntegerOpcode; +// Float increment and decrement. +def Incf: FloatOpcode; +def IncfPop : FloatOpcode; +def Decf: FloatOpcode; +def DecfPop : FloatOpcode; + // [Real] -> [Real] def Neg: Opcode { - let Types = [AluTypeClass]; + let Types = [NonPtrTypeClass]; let HasGroup = 1; } // [Real] -> [Real] def Comp: Opcode { - let Types = [NumberTypeClass]; + let Types = [IntegerTypeClass]; let HasGroup = 1; } //===----------------------------------------------------------------------===// -// Cast. +// Cast, CastFP. //===----------------------------------------------------------------------===// -// TODO: Expand this to handle casts between more types. def FromCastTypeClass : TypeClass { let Types = [Uint8, Sint8, Uint16, Sint16, Uint32, Sint32, Uint64, Sint64, Bool]; @@ -475,6 +545,25 @@ def Cast: Opcode { let HasGroup = 1; } +def CastFP : Opcode { + let Types = []; + let Args = [ArgFltSemantics, ArgRoundingMode]; +} + +// Cast an integer to a floating type +def CastIntegralFloating : Opcode { + let Types = [AluTypeClass]; + let Args = [ArgFltSemantics, ArgRoundingMode]; + let HasGroup = 1; +} + +// Cast a floating to an integer type +def CastFloatingIntegral : Opcode { + let Types = [AluTypeClass]; + let Args = []; + let HasGroup = 1; +} + //===----------------------------------------------------------------------===// // Comparison opcodes. //===----------------------------------------------------------------------===// diff --git a/contrib/llvm-project/clang/lib/AST/Interp/Pointer.cpp b/contrib/llvm-project/clang/lib/AST/Interp/Pointer.cpp index fd8c98fae03..00943dc846d 100644 --- a/contrib/llvm-project/clang/lib/AST/Interp/Pointer.cpp +++ b/contrib/llvm-project/clang/lib/AST/Interp/Pointer.cpp @@ -24,7 +24,7 @@ Pointer::Pointer(const Pointer &P) : Pointer(P.Pointee, P.Base, P.Offset) {} Pointer::Pointer(Pointer &&P) : Pointee(P.Pointee), Base(P.Base), Offset(P.Offset) { if (Pointee) - Pointee->movePointer(&P, this); + Pointee->replacePointer(&P, this); } Pointer::Pointer(Block *Pointee, unsigned Base, unsigned Offset) @@ -69,7 +69,7 @@ void Pointer::operator=(Pointer &&P) { Pointee = P.Pointee; if (Pointee) - Pointee->movePointer(&P, this); + Pointee->replacePointer(&P, this); if (Old) Old->cleanup(); @@ -103,6 +103,10 @@ APValue Pointer::toAPValue() const { if (isUnknownSizeArray()) { IsOnePastEnd = false; Offset = CharUnits::Zero(); + } else if (Desc->asExpr()) { + // Pointer pointing to a an expression. + IsOnePastEnd = false; + Offset = CharUnits::Zero(); } else { // TODO: compute the offset into the object. Offset = CharUnits::Zero(); @@ -143,7 +147,7 @@ APValue Pointer::toAPValue() const { bool Pointer::isInitialized() const { assert(Pointee && "Cannot check if null pointer was initialized"); - Descriptor *Desc = getFieldDesc(); + const Descriptor *Desc = getFieldDesc(); assert(Desc); if (Desc->isPrimitiveArray()) { if (isStatic() && Base == 0) @@ -155,39 +159,38 @@ bool Pointer::isInitialized() const { if (Map == (InitMap *)-1) return true; return Map->isInitialized(getIndex()); - } else { - // Field has its bit in an inline descriptor. - return Base == 0 || getInlineDesc()->IsInitialized; } + + // Field has its bit in an inline descriptor. + return Base == 0 || getInlineDesc()->IsInitialized; } void Pointer::initialize() const { assert(Pointee && "Cannot initialize null pointer"); - Descriptor *Desc = getFieldDesc(); + const Descriptor *Desc = getFieldDesc(); assert(Desc); - if (Desc->isArray()) { - if (Desc->isPrimitiveArray()) { - // Primitive global arrays don't have an initmap. - if (isStatic() && Base == 0) - return; + if (Desc->isPrimitiveArray()) { + // Primitive global arrays don't have an initmap. + if (isStatic() && Base == 0) + return; - // Primitive array initializer. - InitMap *&Map = getInitMap(); - if (Map == (InitMap *)-1) - return; - if (Map == nullptr) - Map = InitMap::allocate(Desc->getNumElems()); - if (Map->initialize(getIndex())) { - free(Map); - Map = (InitMap *)-1; - } + // Primitive array initializer. + InitMap *&Map = getInitMap(); + if (Map == (InitMap *)-1) + return; + if (Map == nullptr) + Map = InitMap::allocate(Desc->getNumElems()); + if (Map->initialize(getIndex())) { + free(Map); + Map = (InitMap *)-1; } - } else { - // Field has its bit in an inline descriptor. - assert(Base != 0 && "Only composite fields can be initialised"); - getInlineDesc()->IsInitialized = true; + return; } + + // Field has its bit in an inline descriptor. + assert(Base != 0 && "Only composite fields can be initialised"); + getInlineDesc()->IsInitialized = true; } void Pointer::activate() const { diff --git a/contrib/llvm-project/clang/lib/AST/Interp/Pointer.h b/contrib/llvm-project/clang/lib/AST/Interp/Pointer.h index 1462d01c241..f795466f1db 100644 --- a/contrib/llvm-project/clang/lib/AST/Interp/Pointer.h +++ b/contrib/llvm-project/clang/lib/AST/Interp/Pointer.h @@ -200,6 +200,8 @@ public: /// Returns the type of the innermost field. QualType getType() const { return getFieldDesc()->getType(); } + Pointer getDeclPtr() const { return Pointer(Pointee); } + /// Returns the element size of the innermost field. size_t elemSize() const { if (Base == RootPtrMark) @@ -225,6 +227,10 @@ public: return Offset - Base - Adjust; } + /// Whether this array refers to an array, but not + /// to the first element. + bool isArrayRoot() const { return inArray() && Offset == Base; } + /// Checks if the innermost field is an array. bool inArray() const { return getFieldDesc()->IsArray; } /// Checks if the structure is a primitive array. @@ -241,9 +247,11 @@ public: } /// Returns the record descriptor of a class. - Record *getRecord() const { return getFieldDesc()->ElemRecord; } - // Returns the element record type, if this is a non-primive array. - Record *getElemRecord() const { return getFieldDesc()->ElemDesc->ElemRecord; } + const Record *getRecord() const { return getFieldDesc()->ElemRecord; } + /// Returns the element record type, if this is a non-primive array. + const Record *getElemRecord() const { + return getFieldDesc()->ElemDesc->ElemRecord; + } /// Returns the field information. const FieldDecl *getField() const { return getFieldDesc()->asFieldDecl(); } @@ -286,6 +294,8 @@ public: /// Returns the number of elements. unsigned getNumElems() const { return getSize() / elemSize(); } + const Block *block() const { return Pointee; } + /// Returns the index into an array. int64_t getIndex() const { if (isElementPastEnd()) @@ -306,12 +316,17 @@ public: /// Dereferences the pointer, if it's live. template T &deref() const { assert(isLive() && "Invalid pointer"); + if (isArrayRoot()) + return *reinterpret_cast(Pointee->rawData() + Base + + sizeof(InitMap *)); + return *reinterpret_cast(Pointee->rawData() + Offset); } /// Dereferences a primitive element. template T &elem(unsigned I) const { - return reinterpret_cast(Pointee->rawData())[I]; + assert(I < getNumElems()); + return reinterpret_cast(Pointee->data() + sizeof(InitMap *))[I]; } /// Initializes a field. diff --git a/contrib/llvm-project/clang/lib/AST/Interp/PrimType.cpp b/contrib/llvm-project/clang/lib/AST/Interp/PrimType.cpp index eda90e1c36c..a9b5d8ea8cc 100644 --- a/contrib/llvm-project/clang/lib/AST/Interp/PrimType.cpp +++ b/contrib/llvm-project/clang/lib/AST/Interp/PrimType.cpp @@ -8,6 +8,8 @@ #include "PrimType.h" #include "Boolean.h" +#include "Floating.h" +#include "FunctionPointer.h" #include "Pointer.h" using namespace clang; diff --git a/contrib/llvm-project/clang/lib/AST/Interp/PrimType.h b/contrib/llvm-project/clang/lib/AST/Interp/PrimType.h index c8f2a600fb3..693e5721060 100644 --- a/contrib/llvm-project/clang/lib/AST/Interp/PrimType.h +++ b/contrib/llvm-project/clang/lib/AST/Interp/PrimType.h @@ -13,7 +13,6 @@ #ifndef LLVM_CLANG_AST_INTERP_TYPE_H #define LLVM_CLANG_AST_INTERP_TYPE_H -#include "Integral.h" #include #include #include @@ -23,6 +22,9 @@ namespace interp { class Pointer; class Boolean; +class Floating; +class FunctionPointer; +template class Integral; /// Enumeration of the primitive types of the VM. enum PrimType : unsigned { @@ -35,9 +37,13 @@ enum PrimType : unsigned { PT_Sint64, PT_Uint64, PT_Bool, + PT_Float, PT_Ptr, + PT_FnPtr, }; +constexpr bool isIntegralType(PrimType T) { return T <= PT_Uint64; } + /// Mapping from primitive types to their representation. template struct PrimConv; template <> struct PrimConv { using T = Integral<8, true>; }; @@ -48,8 +54,12 @@ template <> struct PrimConv { using T = Integral<32, true>; }; template <> struct PrimConv { using T = Integral<32, false>; }; template <> struct PrimConv { using T = Integral<64, true>; }; template <> struct PrimConv { using T = Integral<64, false>; }; +template <> struct PrimConv { using T = Floating; }; template <> struct PrimConv { using T = Boolean; }; template <> struct PrimConv { using T = Pointer; }; +template <> struct PrimConv { + using T = FunctionPointer; +}; /// Returns the size of a primitive type in bytes. size_t primSize(PrimType Type); @@ -66,23 +76,6 @@ static inline bool aligned(const void *P) { return aligned(reinterpret_cast(P)); } -inline bool isPrimitiveIntegral(PrimType Type) { - switch (Type) { - case PT_Bool: - case PT_Sint8: - case PT_Uint8: - case PT_Sint16: - case PT_Uint16: - case PT_Sint32: - case PT_Uint32: - case PT_Sint64: - case PT_Uint64: - return true; - default: - return false; - } -} - } // namespace interp } // namespace clang @@ -101,8 +94,10 @@ inline bool isPrimitiveIntegral(PrimType Type) { TYPE_SWITCH_CASE(PT_Uint32, B) \ TYPE_SWITCH_CASE(PT_Sint64, B) \ TYPE_SWITCH_CASE(PT_Uint64, B) \ + TYPE_SWITCH_CASE(PT_Float, B) \ TYPE_SWITCH_CASE(PT_Bool, B) \ TYPE_SWITCH_CASE(PT_Ptr, B) \ + TYPE_SWITCH_CASE(PT_FnPtr, B) \ } \ } while (0) #define COMPOSITE_TYPE_SWITCH(Expr, B, D) \ diff --git a/contrib/llvm-project/clang/lib/AST/Interp/Primitives.h b/contrib/llvm-project/clang/lib/AST/Interp/Primitives.h new file mode 100644 index 00000000000..e935dbfd369 --- /dev/null +++ b/contrib/llvm-project/clang/lib/AST/Interp/Primitives.h @@ -0,0 +1,36 @@ +//===------ Primitives.h - Types for the constexpr VM -----------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +// +// Utilities and helper functions for all primitive types: +// - Integral +// - Floating +// - Boolean +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CLANG_AST_INTERP_PRIMITIVES_H +#define LLVM_CLANG_AST_INTERP_PRIMITIVES_H + +#include "clang/AST/ComparisonCategories.h" + +namespace clang { +namespace interp { + +/// Helper to compare two comparable types. +template ComparisonCategoryResult Compare(const T &X, const T &Y) { + if (X < Y) + return ComparisonCategoryResult::Less; + if (X > Y) + return ComparisonCategoryResult::Greater; + return ComparisonCategoryResult::Equal; +} + +} // namespace interp +} // namespace clang + +#endif diff --git a/contrib/llvm-project/clang/lib/AST/Interp/Program.cpp b/contrib/llvm-project/clang/lib/AST/Interp/Program.cpp index 5305ddd8de1..c1697bb7fa6 100644 --- a/contrib/llvm-project/clang/lib/AST/Interp/Program.cpp +++ b/contrib/llvm-project/clang/lib/AST/Interp/Program.cpp @@ -10,6 +10,7 @@ #include "ByteCodeStmtGen.h" #include "Context.h" #include "Function.h" +#include "Integral.h" #include "Opcode.h" #include "PrimType.h" #include "clang/AST/Decl.h" @@ -119,7 +120,7 @@ std::optional Program::getGlobal(const ValueDecl *VD) { // Map the decl to the existing index. if (Index) { GlobalIndices[VD] = *Index; - return {}; + return std::nullopt; } return Index; @@ -134,26 +135,26 @@ std::optional Program::getOrCreateGlobal(const ValueDecl *VD, GlobalIndices[VD] = *Idx; return Idx; } - return {}; + return std::nullopt; } std::optional Program::getOrCreateDummy(const ParmVarDecl *PD) { - auto &ASTCtx = Ctx.getASTContext(); + // Dedup blocks since they are immutable and pointers cannot be compared. + if (auto It = DummyParams.find(PD); + It != DummyParams.end()) + return It->second; + + auto &ASTCtx = Ctx.getASTContext(); // Create a pointer to an incomplete array of the specified elements. QualType ElemTy = PD->getType()->castAs()->getPointeeType(); QualType Ty = ASTCtx.getIncompleteArrayType(ElemTy, ArrayType::Normal, 0); - // Dedup blocks since they are immutable and pointers cannot be compared. - auto It = DummyParams.find(PD); - if (It != DummyParams.end()) - return It->second; - if (auto Idx = createGlobal(PD, Ty, /*isStatic=*/true, /*isExtern=*/true)) { DummyParams[PD] = *Idx; return Idx; } - return {}; + return std::nullopt; } std::optional Program::createGlobal(const ValueDecl *VD, @@ -161,7 +162,7 @@ std::optional Program::createGlobal(const ValueDecl *VD, assert(!getGlobal(VD)); bool IsStatic, IsExtern; if (auto *Var = dyn_cast(VD)) { - IsStatic = !Var->hasLocalStorage(); + IsStatic = Context::shouldBeGloballyIndexed(VD); IsExtern = !Var->getAnyInitializer(); } else { IsStatic = false; @@ -172,7 +173,7 @@ std::optional Program::createGlobal(const ValueDecl *VD, GlobalIndices[P] = *Idx; return *Idx; } - return {}; + return std::nullopt; } std::optional Program::createGlobal(const Expr *E) { @@ -193,7 +194,7 @@ std::optional Program::createGlobal(const DeclTy &D, QualType Ty, IsTemporary); } if (!Desc) - return {}; + return std::nullopt; // Allocate a block for storage. unsigned I = Globals.size(); @@ -221,10 +222,8 @@ Record *Program::getOrCreateRecord(const RecordDecl *RD) { return nullptr; // Deduplicate records. - auto It = Records.find(RD); - if (It != Records.end()) { + if (auto It = Records.find(RD); It != Records.end()) return It->second; - } // We insert nullptr now and replace that later, so recursive calls // to this function with the same RecordDecl don't run into @@ -340,7 +339,7 @@ Descriptor *Program::createDescriptor(const DeclTy &D, const Type *Ty, D, ElemTy.getTypePtr(), std::nullopt, IsConst, IsTemporary); if (!ElemDesc) return nullptr; - InterpSize ElemSize = + unsigned ElemSize = ElemDesc->getAllocSize() + sizeof(InlineDescriptor); if (std::numeric_limits::max() / ElemSize <= NumElems) return {}; diff --git a/contrib/llvm-project/clang/lib/AST/Interp/Program.h b/contrib/llvm-project/clang/lib/AST/Interp/Program.h index 5a80dd1ed74..4547ca7ac69 100644 --- a/contrib/llvm-project/clang/lib/AST/Interp/Program.h +++ b/contrib/llvm-project/clang/lib/AST/Interp/Program.h @@ -131,7 +131,9 @@ public: /// Context to manage declaration lifetimes. class DeclScope { public: - DeclScope(Program &P, const VarDecl *VD) : P(P) { P.startDeclaration(VD); } + DeclScope(Program &P, const ValueDecl *VD) : P(P) { + P.startDeclaration(VD); + } ~DeclScope() { P.endDeclaration(); } private: @@ -222,7 +224,7 @@ private: unsigned CurrentDeclaration = NoDeclaration; /// Starts evaluating a declaration. - void startDeclaration(const VarDecl *Decl) { + void startDeclaration(const ValueDecl *Decl) { LastDeclaration += 1; CurrentDeclaration = LastDeclaration; } diff --git a/contrib/llvm-project/clang/lib/AST/Interp/Record.cpp b/contrib/llvm-project/clang/lib/AST/Interp/Record.cpp index f440c470505..909416e6e1a 100644 --- a/contrib/llvm-project/clang/lib/AST/Interp/Record.cpp +++ b/contrib/llvm-project/clang/lib/AST/Interp/Record.cpp @@ -39,6 +39,14 @@ const Record::Base *Record::getBase(const RecordDecl *FD) const { return It->second; } +const Record::Base *Record::getBase(QualType T) const { + if (!T->isRecordType()) + return nullptr; + + const RecordDecl *RD = T->getAs()->getDecl(); + return BaseMap.lookup(RD); +} + const Record::Base *Record::getVirtualBase(const RecordDecl *FD) const { auto It = VirtualBaseMap.find(FD); assert(It != VirtualBaseMap.end() && "Missing virtual base"); diff --git a/contrib/llvm-project/clang/lib/AST/Interp/Record.h b/contrib/llvm-project/clang/lib/AST/Interp/Record.h index 1742cb1cc4e..940b4c9ebf5 100644 --- a/contrib/llvm-project/clang/lib/AST/Interp/Record.h +++ b/contrib/llvm-project/clang/lib/AST/Interp/Record.h @@ -61,9 +61,11 @@ public: const Field *getField(const FieldDecl *FD) const; /// Returns a base descriptor. const Base *getBase(const RecordDecl *FD) const; + /// Returns a base descriptor. + const Base *getBase(QualType T) const; /// Returns a virtual base descriptor. const Base *getVirtualBase(const RecordDecl *RD) const; - // Returns the destructor of the record, if any. + /// Returns the destructor of the record, if any. const CXXDestructorDecl *getDestructor() const { if (const auto *CXXDecl = dyn_cast(Decl)) return CXXDecl->getDestructor(); @@ -85,7 +87,7 @@ public: } unsigned getNumBases() const { return Bases.size(); } - Base *getBase(unsigned I) { return &Bases[I]; } + const Base *getBase(unsigned I) const { return &Bases[I]; } using const_virtual_iter = VirtualBaseList::const_iterator; llvm::iterator_range virtual_bases() const { @@ -93,7 +95,7 @@ public: } unsigned getNumVirtualBases() const { return VirtualBases.size(); } - Base *getVirtualBase(unsigned I) { return &VirtualBases[I]; } + const Base *getVirtualBase(unsigned I) const { return &VirtualBases[I]; } private: /// Constructor used by Program to create record descriptors. diff --git a/contrib/llvm-project/clang/lib/AST/Interp/Source.h b/contrib/llvm-project/clang/lib/AST/Interp/Source.h index 99ffce34c12..89fca9ac80f 100644 --- a/contrib/llvm-project/clang/lib/AST/Interp/Source.h +++ b/contrib/llvm-project/clang/lib/AST/Interp/Source.h @@ -55,15 +55,12 @@ public: return Value; } -private: - /// Constructor used by Function to generate pointers. - CodePtr(const char *Ptr) : Ptr(Ptr) {} - private: friend class Function; - + /// Constructor used by Function to generate pointers. + CodePtr(const std::byte *Ptr) : Ptr(Ptr) {} /// Pointer into the code owned by a function. - const char *Ptr; + const std::byte *Ptr; }; /// Describes the statement/declaration an opcode was generated from. diff --git a/contrib/llvm-project/clang/lib/AST/Interp/State.cpp b/contrib/llvm-project/clang/lib/AST/Interp/State.cpp index 56774f88fb4..9a327fb810d 100644 --- a/contrib/llvm-project/clang/lib/AST/Interp/State.cpp +++ b/contrib/llvm-project/clang/lib/AST/Interp/State.cpp @@ -11,6 +11,7 @@ #include "Program.h" #include "clang/AST/ASTContext.h" #include "clang/AST/CXXInheritance.h" +#include "clang/AST/OptionalDiagnostic.h" using namespace clang; using namespace clang::interp; @@ -125,9 +126,9 @@ void State::addCallStack(unsigned Limit) { // Walk the call stack and add the diagnostics. unsigned CallIdx = 0; - Frame *Top = getCurrentFrame(); + const Frame *Top = getCurrentFrame(); const Frame *Bottom = getBottomFrame(); - for (Frame *F = Top; F != Bottom; F = F->getCaller(), ++CallIdx) { + for (const Frame *F = Top; F != Bottom; F = F->getCaller(), ++CallIdx) { SourceLocation CallLocation = F->getCallLocation(); // Skip this call? @@ -142,12 +143,12 @@ void State::addCallStack(unsigned Limit) { // 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(F->getCallee())) { - if (CD->isInheritingConstructor()) { - addDiag(CallLocation, diag::note_constexpr_inherited_ctor_call_here) - << CD->getParent(); - continue; - } + if (const auto *CD = + dyn_cast_if_present(F->getCallee()); + CD && CD->isInheritingConstructor()) { + addDiag(CallLocation, diag::note_constexpr_inherited_ctor_call_here) + << CD->getParent(); + continue; } SmallString<128> Buffer; diff --git a/contrib/llvm-project/clang/lib/AST/Interp/State.h b/contrib/llvm-project/clang/lib/AST/Interp/State.h index 131fbcf3cff..d897b7c2027 100644 --- a/contrib/llvm-project/clang/lib/AST/Interp/State.h +++ b/contrib/llvm-project/clang/lib/AST/Interp/State.h @@ -15,9 +15,9 @@ #include "clang/AST/ASTDiagnostic.h" #include "clang/AST/Expr.h" -#include "clang/AST/OptionalDiagnostic.h" namespace clang { +class OptionalDiagnostic; /// Kinds of access we can perform on an object, for diagnostics. Note that /// we consider a member function call to be a kind of access, even though @@ -36,7 +36,7 @@ enum AccessKinds { AK_Destroy, }; -// The order of this enum is important for diagnostics. +/// The order of this enum is important for diagnostics. enum CheckSubobjectKind { CSK_Base, CSK_Derived, @@ -72,7 +72,7 @@ public: public: State() : InConstantContext(false) {} - // Diagnose that the evaluation could not be folded (FF => FoldFailure) + /// Diagnose that the evaluation could not be folded (FF => FoldFailure) OptionalDiagnostic FFDiag(SourceLocation Loc, diag::kind DiagId = diag::note_invalid_subexpr_in_const_expr, diff --git a/contrib/llvm-project/clang/lib/AST/ItaniumMangle.cpp b/contrib/llvm-project/clang/lib/AST/ItaniumMangle.cpp index b23bc5f8d88..f08286a0d4b 100644 --- a/contrib/llvm-project/clang/lib/AST/ItaniumMangle.cpp +++ b/contrib/llvm-project/clang/lib/AST/ItaniumMangle.cpp @@ -35,6 +35,7 @@ #include "llvm/ADT/StringExtras.h" #include "llvm/Support/ErrorHandling.h" #include "llvm/Support/raw_ostream.h" +#include "llvm/TargetParser/RISCVTargetParser.h" #include using namespace clang; @@ -109,8 +110,10 @@ public: void mangleCXXCtorVTable(const CXXRecordDecl *RD, int64_t Offset, const CXXRecordDecl *Type, raw_ostream &) override; void mangleCXXRTTI(QualType T, raw_ostream &) override; - void mangleCXXRTTIName(QualType T, raw_ostream &) override; - void mangleTypeName(QualType T, raw_ostream &) override; + void mangleCXXRTTIName(QualType T, raw_ostream &, + bool NormalizeIntegers) override; + void mangleTypeName(QualType T, raw_ostream &, + bool NormalizeIntegers) override; void mangleCXXCtorComdat(const CXXConstructorDecl *D, raw_ostream &) override; void mangleCXXDtorComdat(const CXXDestructorDecl *D, raw_ostream &) override; @@ -206,7 +209,6 @@ public: } bool isInternalLinkageDecl(const NamedDecl *ND); - const DeclContext *IgnoreLinkageSpecDecls(const DeclContext *DC); /// @} }; @@ -215,6 +217,10 @@ public: class CXXNameMangler { ItaniumMangleContextImpl &Context; raw_ostream &Out; + /// Normalize integer types for cross-language CFI support with other + /// languages that can't represent and encode C/C++ integer types. + bool NormalizeIntegers = false; + bool NullOut = false; /// In the "DisableDerivedAbiTags" mode derived ABI tags are not calculated. /// This mode is used when mangler creates another mangler recursively to @@ -390,7 +396,6 @@ class CXXNameMangler { bool isStdNamespace(const DeclContext *DC); const RecordDecl *GetLocalClassDecl(const Decl *D); - const DeclContext *IgnoreLinkageSpecDecls(const DeclContext *DC); bool isSpecializedAs(QualType S, llvm::StringRef Name, QualType A); bool isStdCharSpecialization(const ClassTemplateSpecializationDecl *SD, llvm::StringRef Name, bool HasAllocator); @@ -413,6 +418,10 @@ public: : Context(C), Out(Out_), Structor(getStructor(D)), StructorType(Type), AbiTagsRoot(AbiTags) {} + CXXNameMangler(ItaniumMangleContextImpl &C, raw_ostream &Out_, + bool NormalizeIntegers_) + : Context(C), Out(Out_), NormalizeIntegers(NormalizeIntegers_), + NullOut(false), Structor(nullptr), AbiTagsRoot(AbiTags) {} CXXNameMangler(CXXNameMangler &Outer, raw_ostream &Out_) : Context(Outer.Context), Out(Out_), Structor(Outer.Structor), StructorType(Outer.StructorType), SeqID(Outer.SeqID), @@ -553,6 +562,8 @@ private: void mangleAArch64NeonVectorType(const DependentVectorType *T); void mangleAArch64FixedSveVectorType(const VectorType *T); void mangleAArch64FixedSveVectorType(const DependentVectorType *T); + void mangleRISCVFixedRVVVectorType(const VectorType *T); + void mangleRISCVFixedRVVVectorType(const DependentVectorType *T); void mangleIntegerLiteral(QualType T, const llvm::APSInt &Value); void mangleFloatLiteral(QualType T, const llvm::APFloat &V); @@ -2937,6 +2948,85 @@ void CXXNameMangler::mangleType(const BuiltinType *T) { // ::= Dn # std::nullptr_t (i.e., decltype(nullptr)) // ::= u # vendor extended type std::string type_name; + // Normalize integer types as vendor extended types: + // ui + // uu + if (NormalizeIntegers && T->isInteger()) { + if (T->isSignedInteger()) { + switch (getASTContext().getTypeSize(T)) { + case 8: + // Pick a representative for each integer size in the substitution + // dictionary. (Its actual defined size is not relevant.) + if (mangleSubstitution(BuiltinType::SChar)) + break; + Out << "u2i8"; + addSubstitution(BuiltinType::SChar); + break; + case 16: + if (mangleSubstitution(BuiltinType::Short)) + break; + Out << "u3i16"; + addSubstitution(BuiltinType::Short); + break; + case 32: + if (mangleSubstitution(BuiltinType::Int)) + break; + Out << "u3i32"; + addSubstitution(BuiltinType::Int); + break; + case 64: + if (mangleSubstitution(BuiltinType::Long)) + break; + Out << "u3i64"; + addSubstitution(BuiltinType::Long); + break; + case 128: + if (mangleSubstitution(BuiltinType::Int128)) + break; + Out << "u4i128"; + addSubstitution(BuiltinType::Int128); + break; + default: + llvm_unreachable("Unknown integer size for normalization"); + } + } else { + switch (getASTContext().getTypeSize(T)) { + case 8: + if (mangleSubstitution(BuiltinType::UChar)) + break; + Out << "u2u8"; + addSubstitution(BuiltinType::UChar); + break; + case 16: + if (mangleSubstitution(BuiltinType::UShort)) + break; + Out << "u3u16"; + addSubstitution(BuiltinType::UShort); + break; + case 32: + if (mangleSubstitution(BuiltinType::UInt)) + break; + Out << "u3u32"; + addSubstitution(BuiltinType::UInt); + break; + case 64: + if (mangleSubstitution(BuiltinType::ULong)) + break; + Out << "u3u64"; + addSubstitution(BuiltinType::ULong); + break; + case 128: + if (mangleSubstitution(BuiltinType::UInt128)) + break; + Out << "u4u128"; + addSubstitution(BuiltinType::UInt128); + break; + default: + llvm_unreachable("Unknown integer size for normalization"); + } + } + return; + } switch (T->getKind()) { case BuiltinType::Void: Out << 'v'; @@ -3035,23 +3125,30 @@ void CXXNameMangler::mangleType(const BuiltinType *T) { Out << 'd'; break; case BuiltinType::LongDouble: { - const TargetInfo *TI = getASTContext().getLangOpts().OpenMP && - getASTContext().getLangOpts().OpenMPIsDevice - ? getASTContext().getAuxTargetInfo() - : &getASTContext().getTargetInfo(); + const TargetInfo *TI = + getASTContext().getLangOpts().OpenMP && + getASTContext().getLangOpts().OpenMPIsTargetDevice + ? getASTContext().getAuxTargetInfo() + : &getASTContext().getTargetInfo(); Out << TI->getLongDoubleMangling(); break; } case BuiltinType::Float128: { - const TargetInfo *TI = getASTContext().getLangOpts().OpenMP && - getASTContext().getLangOpts().OpenMPIsDevice - ? getASTContext().getAuxTargetInfo() - : &getASTContext().getTargetInfo(); + const TargetInfo *TI = + getASTContext().getLangOpts().OpenMP && + getASTContext().getLangOpts().OpenMPIsTargetDevice + ? getASTContext().getAuxTargetInfo() + : &getASTContext().getTargetInfo(); Out << TI->getFloat128Mangling(); break; } case BuiltinType::BFloat16: { - const TargetInfo *TI = &getASTContext().getTargetInfo(); + const TargetInfo *TI = + ((getASTContext().getLangOpts().OpenMP && + getASTContext().getLangOpts().OpenMPIsTargetDevice) || + getASTContext().getLangOpts().SYCLIsDevice) + ? getASTContext().getAuxTargetInfo() + : &getASTContext().getTargetInfo(); Out << TI->getBFloat16Mangling(); break; } @@ -3124,6 +3221,12 @@ void CXXNameMangler::mangleType(const BuiltinType *T) { Out << (type_name == InternalName ? "u" : "") << type_name.size() \ << type_name; \ break; +#define SVE_OPAQUE_TYPE(InternalName, MangledName, Id, SingletonId) \ + case BuiltinType::Id: \ + type_name = MangledName; \ + Out << (type_name == InternalName ? "u" : "") << type_name.size() \ + << type_name; \ + break; #include "clang/Basic/AArch64SVEACLETypes.def" #define PPC_VECTOR_TYPE(Name, Id, Size) \ case BuiltinType::Id: \ @@ -3138,6 +3241,12 @@ void CXXNameMangler::mangleType(const BuiltinType *T) { Out << 'u' << type_name.size() << type_name; \ break; #include "clang/Basic/RISCVVTypes.def" +#define WASM_REF_TYPE(InternalName, MangledName, Id, SingletonId, AS) \ + case BuiltinType::Id: \ + type_name = MangledName; \ + Out << 'u' << type_name.size() << type_name; \ + break; +#include "clang/Basic/WebAssemblyReferenceTypes.def" } } @@ -3707,6 +3816,82 @@ void CXXNameMangler::mangleAArch64FixedSveVectorType( Diags.Report(T->getAttributeLoc(), DiagID); } +void CXXNameMangler::mangleRISCVFixedRVVVectorType(const VectorType *T) { + assert(T->getVectorKind() == VectorType::RVVFixedLengthDataVector && + "expected fixed-length RVV vector!"); + + QualType EltType = T->getElementType(); + assert(EltType->isBuiltinType() && + "expected builtin type for fixed-length RVV vector!"); + + SmallString<20> TypeNameStr; + llvm::raw_svector_ostream TypeNameOS(TypeNameStr); + TypeNameOS << "__rvv_"; + switch (cast(EltType)->getKind()) { + case BuiltinType::SChar: + TypeNameOS << "int8"; + break; + case BuiltinType::UChar: + TypeNameOS << "uint8"; + break; + case BuiltinType::Short: + TypeNameOS << "int16"; + break; + case BuiltinType::UShort: + TypeNameOS << "uint16"; + break; + case BuiltinType::Int: + TypeNameOS << "int32"; + break; + case BuiltinType::UInt: + TypeNameOS << "uint32"; + break; + case BuiltinType::Long: + TypeNameOS << "int64"; + break; + case BuiltinType::ULong: + TypeNameOS << "uint64"; + break; + case BuiltinType::Half: + TypeNameOS << "float16"; + break; + case BuiltinType::Float: + TypeNameOS << "float32"; + break; + case BuiltinType::Double: + TypeNameOS << "float64"; + break; + default: + llvm_unreachable("unexpected element type for fixed-length RVV vector!"); + } + + unsigned VecSizeInBits = getASTContext().getTypeInfo(T).Width; + + // Apend the LMUL suffix. + auto VScale = getASTContext().getTargetInfo().getVScaleRange( + getASTContext().getLangOpts()); + unsigned VLen = VScale->first * llvm::RISCV::RVVBitsPerBlock; + TypeNameOS << 'm'; + if (VecSizeInBits >= VLen) + TypeNameOS << (VecSizeInBits / VLen); + else + TypeNameOS << 'f' << (VLen / VecSizeInBits); + + TypeNameOS << "_t"; + + Out << "9__RVV_VLSI" << 'u' << TypeNameStr.size() << TypeNameStr << "Lj" + << VecSizeInBits << "EE"; +} + +void CXXNameMangler::mangleRISCVFixedRVVVectorType( + const DependentVectorType *T) { + DiagnosticsEngine &Diags = Context.getDiags(); + unsigned DiagID = Diags.getCustomDiagID( + DiagnosticsEngine::Error, + "cannot mangle this dependent fixed-length RVV vector type yet"); + Diags.Report(T->getAttributeLoc(), DiagID); +} + // GNU extension: vector types // ::= // ::= Dv _ @@ -3731,6 +3916,9 @@ void CXXNameMangler::mangleType(const VectorType *T) { T->getVectorKind() == VectorType::SveFixedLengthPredicateVector) { mangleAArch64FixedSveVectorType(T); return; + } else if (T->getVectorKind() == VectorType::RVVFixedLengthDataVector) { + mangleRISCVFixedRVVVectorType(T); + return; } Out << "Dv" << T->getNumElements() << '_'; if (T->getVectorKind() == VectorType::AltiVecPixel) @@ -3757,6 +3945,9 @@ void CXXNameMangler::mangleType(const DependentVectorType *T) { T->getVectorKind() == VectorType::SveFixedLengthPredicateVector) { mangleAArch64FixedSveVectorType(T); return; + } else if (T->getVectorKind() == VectorType::RVVFixedLengthDataVector) { + mangleRISCVFixedRVVVectorType(T); + return; } Out << "Dv"; @@ -6519,16 +6710,17 @@ void ItaniumMangleContextImpl::mangleCXXRTTI(QualType Ty, raw_ostream &Out) { Mangler.mangleType(Ty); } -void ItaniumMangleContextImpl::mangleCXXRTTIName(QualType Ty, - raw_ostream &Out) { +void ItaniumMangleContextImpl::mangleCXXRTTIName( + QualType Ty, raw_ostream &Out, bool NormalizeIntegers = false) { // ::= TS # typeinfo name (null terminated byte string) - CXXNameMangler Mangler(*this, Out); + CXXNameMangler Mangler(*this, Out, NormalizeIntegers); Mangler.getStream() << "_ZTS"; Mangler.mangleType(Ty); } -void ItaniumMangleContextImpl::mangleTypeName(QualType Ty, raw_ostream &Out) { - mangleCXXRTTIName(Ty, Out); +void ItaniumMangleContextImpl::mangleTypeName(QualType Ty, raw_ostream &Out, + bool NormalizeIntegers = false) { + mangleCXXRTTIName(Ty, Out, NormalizeIntegers); } void ItaniumMangleContextImpl::mangleStringLiteral(const StringLiteral *, raw_ostream &) { diff --git a/contrib/llvm-project/clang/lib/AST/JSONNodeDumper.cpp b/contrib/llvm-project/clang/lib/AST/JSONNodeDumper.cpp index 83b097daf8a..958b0e6cf2e 100644 --- a/contrib/llvm-project/clang/lib/AST/JSONNodeDumper.cpp +++ b/contrib/llvm-project/clang/lib/AST/JSONNodeDumper.cpp @@ -3,6 +3,7 @@ #include "clang/Basic/SourceManager.h" #include "clang/Basic/Specifiers.h" #include "clang/Lex/Lexer.h" +#include "llvm/ADT/StringExtras.h" #include using namespace clang; @@ -662,6 +663,9 @@ void JSONNodeDumper::VisitVectorType(const VectorType *VT) { case VectorType::SveFixedLengthPredicateVector: JOS.attribute("vectorKind", "fixed-length sve predicate vector"); break; + case VectorType::RVVFixedLengthDataVector: + JOS.attribute("vectorKind", "fixed-length rvv data vector"); + break; } } @@ -770,6 +774,12 @@ void JSONNodeDumper::VisitNamedDecl(const NamedDecl *ND) { if (isa(ND->getDeclContext())) return; + // If the declaration is dependent or is in a dependent context, then the + // mangling is unlikely to be meaningful (and in some cases may cause + // "don't know how to mangle this" assertion failures. + if (ND->isTemplated()) + return; + // Mangled names are not meaningful for locals, and may not be well-defined // in the case of VLAs. auto *VD = dyn_cast(ND); @@ -880,6 +890,7 @@ void JSONNodeDumper::VisitFunctionDecl(const FunctionDecl *FD) { attributeOnlyIfTrue("explicitlyDeleted", FD->isDeletedAsWritten()); attributeOnlyIfTrue("constexpr", FD->isConstexpr()); attributeOnlyIfTrue("variadic", FD->isVariadic()); + attributeOnlyIfTrue("immediate", FD->isImmediateFunction()); if (FD->isDefaulted()) JOS.attribute("explicitlyDefaulted", @@ -1240,6 +1251,7 @@ void JSONNodeDumper::VisitDeclRefExpr(const DeclRefExpr *DRE) { case NOUR_Constant: JOS.attribute("nonOdrUseReason", "constant"); break; case NOUR_Discarded: JOS.attribute("nonOdrUseReason", "discarded"); break; } + attributeOnlyIfTrue("isImmediateEscalating", DRE->isImmediateEscalating()); } void JSONNodeDumper::VisitSYCLUniqueStableNameExpr( @@ -1399,6 +1411,7 @@ void JSONNodeDumper::VisitCXXConstructExpr(const CXXConstructExpr *CE) { attributeOnlyIfTrue("initializer_list", CE->isStdInitListInitialization()); attributeOnlyIfTrue("zeroing", CE->requiresZeroInitialization()); attributeOnlyIfTrue("hadMultipleCandidates", CE->hadMultipleCandidates()); + attributeOnlyIfTrue("isImmediateEscalating", CE->isImmediateEscalating()); switch (CE->getConstructionKind()) { case CXXConstructExpr::CK_Complete: diff --git a/contrib/llvm-project/clang/lib/AST/MicrosoftMangle.cpp b/contrib/llvm-project/clang/lib/AST/MicrosoftMangle.cpp index cdd2c93c4b1..3306d90dc85 100644 --- a/contrib/llvm-project/clang/lib/AST/MicrosoftMangle.cpp +++ b/contrib/llvm-project/clang/lib/AST/MicrosoftMangle.cpp @@ -29,12 +29,14 @@ #include "clang/Basic/FileManager.h" #include "clang/Basic/SourceManager.h" #include "clang/Basic/TargetInfo.h" +#include "llvm/ADT/SmallVector.h" #include "llvm/ADT/StringExtras.h" #include "llvm/Support/CRC.h" #include "llvm/Support/MD5.h" #include "llvm/Support/MathExtras.h" #include "llvm/Support/StringSaver.h" #include "llvm/Support/xxhash.h" +#include #include using namespace clang; @@ -180,7 +182,8 @@ public: int32_t VBPtrOffset, uint32_t VBIndex, raw_ostream &Out) override; void mangleCXXRTTI(QualType T, raw_ostream &Out) override; - void mangleCXXRTTIName(QualType T, raw_ostream &Out) override; + void mangleCXXRTTIName(QualType T, raw_ostream &Out, + bool NormalizeIntegers) override; void mangleCXXRTTIBaseClassDescriptor(const CXXRecordDecl *Derived, uint32_t NVOffset, int32_t VBPtrOffset, uint32_t VBTableOffset, uint32_t Flags, @@ -193,7 +196,8 @@ public: mangleCXXRTTICompleteObjectLocator(const CXXRecordDecl *Derived, ArrayRef BasePath, raw_ostream &Out) override; - void mangleTypeName(QualType T, raw_ostream &) override; + void mangleTypeName(QualType T, raw_ostream &, + bool NormalizeIntegers) override; void mangleReferenceTemporary(const VarDecl *, unsigned ManglingNumber, raw_ostream &) override; void mangleStaticGuardVariable(const VarDecl *D, raw_ostream &Out) override; @@ -286,12 +290,8 @@ public: assert(!RD->isExternallyVisible() && "RD must not be visible!"); assert(RD->getLambdaManglingNumber() == 0 && "RD must not have a mangling number!"); - llvm::DenseMap::iterator Result = - LambdaIds.find(RD); // The lambda should exist, but return 0 in case it doesn't. - if (Result == LambdaIds.end()) - return 0; - return Result->second; + return LambdaIds.lookup(RD); } /// Return a character sequence that is (somewhat) unique to the TU suitable @@ -325,8 +325,8 @@ class MicrosoftCXXNameMangler { typedef llvm::DenseMap TemplateArgStringMap; TemplateArgStringMap TemplateArgStrings; - llvm::StringSaver TemplateArgStringStorage; llvm::BumpPtrAllocator TemplateArgStringStorageAlloc; + llvm::StringSaver TemplateArgStringStorage; typedef std::set> PassObjectSizeArgsSet; PassObjectSizeArgsSet PassObjectSizeArgs; @@ -366,9 +366,13 @@ public: void mangleVariableEncoding(const VarDecl *VD); void mangleMemberDataPointer(const CXXRecordDecl *RD, const ValueDecl *VD, StringRef Prefix = "$"); + void mangleMemberDataPointerInClassNTTP(const CXXRecordDecl *, + const ValueDecl *); void mangleMemberFunctionPointer(const CXXRecordDecl *RD, const CXXMethodDecl *MD, StringRef Prefix = "$"); + void mangleMemberFunctionPointerInClassNTTP(const CXXRecordDecl *RD, + const CXXMethodDecl *MD); void mangleVirtualMemPtrThunk(const CXXMethodDecl *MD, const MethodVFTableLocation &ML); void mangleNumber(int64_t Number); @@ -481,7 +485,7 @@ MicrosoftMangleContextImpl::MicrosoftMangleContextImpl(ASTContext &Context, SourceManager &SM = Context.getSourceManager(); if (const FileEntry *FE = SM.getFileEntryForID(SM.getMainFileID())) { // Truncate the hash so we get 8 characters of hexadecimal. - uint32_t TruncatedHash = uint32_t(xxHash64(FE->getName())); + uint32_t TruncatedHash = uint32_t(xxh3_64bits(FE->getName())); AnonymousNamespaceHash = llvm::utohexstr(TruncatedHash); } else { // If we don't have a path to the main file, we'll just use 0. @@ -709,6 +713,28 @@ void MicrosoftCXXNameMangler::mangleMemberDataPointer(const CXXRecordDecl *RD, mangleNumber(VBTableOffset); } +void MicrosoftCXXNameMangler::mangleMemberDataPointerInClassNTTP( + const CXXRecordDecl *RD, const ValueDecl *VD) { + MSInheritanceModel IM = RD->getMSInheritanceModel(); + // ::= + // ::= N + // ::= 8 @ @ + + if (IM != MSInheritanceModel::Single && IM != MSInheritanceModel::Multiple) + return mangleMemberDataPointer(RD, VD, ""); + + if (!VD) { + Out << 'N'; + return; + } + + Out << '8'; + mangleNestedName(VD); + Out << '@'; + mangleUnqualifiedName(VD); + Out << '@'; +} + void MicrosoftCXXNameMangler::mangleMemberFunctionPointer(const CXXRecordDecl *RD, const CXXMethodDecl *MD, @@ -773,6 +799,34 @@ MicrosoftCXXNameMangler::mangleMemberFunctionPointer(const CXXRecordDecl *RD, mangleNumber(VBTableOffset); } +void MicrosoftCXXNameMangler::mangleMemberFunctionPointerInClassNTTP( + const CXXRecordDecl *RD, const CXXMethodDecl *MD) { + // ::= + // ::= N + // ::= E? + // ::= E? + + if (!MD) { + if (RD->getMSInheritanceModel() != MSInheritanceModel::Single) + return mangleMemberFunctionPointer(RD, MD, ""); + + Out << 'N'; + return; + } + + Out << "E?"; + if (MD->isVirtual()) { + MicrosoftVTableContext *VTContext = + cast(getASTContext().getVTableContext()); + MethodVFTableLocation ML = + VTContext->getMethodVFTableLocation(GlobalDecl(MD)); + mangleVirtualMemPtrThunk(MD, ML); + } else { + mangleName(MD); + mangleFunctionEncoding(MD, /*ShouldMangle=*/true); + } +} + void MicrosoftCXXNameMangler::mangleVirtualMemPtrThunk( const CXXMethodDecl *MD, const MethodVFTableLocation &ML) { // Get the vftable offset. @@ -841,6 +895,10 @@ void MicrosoftCXXNameMangler::mangleFloat(llvm::APFloat Number) { case APFloat::S_PPCDoubleDouble: Out << 'Z'; break; case APFloat::S_Float8E5M2: case APFloat::S_Float8E4M3FN: + case APFloat::S_Float8E5M2FNUZ: + case APFloat::S_Float8E4M3FNUZ: + case APFloat::S_Float8E4M3B11FNUZ: + case APFloat::S_FloatTF32: llvm_unreachable("Tried to mangle unexpected APFloat semantics"); } @@ -1183,6 +1241,11 @@ void MicrosoftCXXNameMangler::mangleUnqualifiedName(GlobalDecl GD, // ::= [] void MicrosoftCXXNameMangler::mangleNestedName(GlobalDecl GD) { const NamedDecl *ND = cast(GD.getDecl()); + + if (const auto *ID = dyn_cast(ND)) + for (unsigned I = 1, IE = ID->getChainingSize(); I < IE; ++I) + mangleSourceName(""); + const DeclContext *DC = getEffectiveDeclContext(ND); while (!DC->isTranslationUnit()) { if (isa(ND) || isa(ND)) { @@ -1565,7 +1628,6 @@ void MicrosoftCXXNameMangler::mangleTemplateArg(const TemplateDecl *TD, // ::= 8 @ // ::= A # float // ::= B # double - // ::= E # reference to D // # pointer to member, by component value // ::= F // ::= G @@ -1610,7 +1672,7 @@ void MicrosoftCXXNameMangler::mangleTemplateArg(const TemplateDecl *TD, mangleTemplateArgValue(TPO->getType().getUnqualifiedType(), TPO->getValue()); } else { - mangle(ND, TA.getParamTypeForDecl()->isReferenceType() ? "$E?" : "$1?"); + mangle(ND, "$1?"); } break; } @@ -1739,46 +1801,62 @@ void MicrosoftCXXNameMangler::mangleTemplateArgValue(QualType T, // FIXME: This can only happen as an extension. Invent a mangling. break; } else if (auto *VD = Base.dyn_cast()) { - Out << (T->isReferenceType() ? "E" : "1"); + Out << "E"; mangle(VD); } else { break; } } else { - unsigned NumAts = 0; - if (T->isPointerType()) { + if (T->isPointerType()) Out << "5"; - ++NumAts; - } - QualType T = Base.getType(); + SmallVector EntryTypes; + SmallVector, 2> EntryManglers; + QualType ET = Base.getType(); for (APValue::LValuePathEntry E : V.getLValuePath()) { - // We don't know how to mangle array subscripting yet. - if (T->isArrayType()) - goto mangling_unknown; + if (auto *AT = ET->getAsArrayTypeUnsafe()) { + EntryTypes.push_back('C'); + EntryManglers.push_back([this, I = E.getAsArrayIndex()] { + Out << '0'; + mangleNumber(I); + Out << '@'; + }); + ET = AT->getElementType(); + continue; + } const Decl *D = E.getAsBaseOrMember().getPointer(); - auto *FD = dyn_cast(D); - // We don't know how to mangle derived-to-base conversions yet. - if (!FD) - goto mangling_unknown; + if (auto *FD = dyn_cast(D)) { + ET = FD->getType(); + if (const auto *RD = ET->getAsRecordDecl()) + if (RD->isAnonymousStructOrUnion()) + continue; + } else { + ET = getASTContext().getRecordType(cast(D)); + // Bug in MSVC: fully qualified name of base class should be used for + // mangling to prevent collisions e.g. on base classes with same names + // in different namespaces. + } - Out << "6"; - ++NumAts; - T = FD->getType(); + EntryTypes.push_back('6'); + EntryManglers.push_back([this, D] { + mangleUnqualifiedName(cast(D)); + Out << '@'; + }); } + for (auto I = EntryTypes.rbegin(), E = EntryTypes.rend(); I != E; ++I) + Out << *I; + auto *VD = Base.dyn_cast(); if (!VD) break; Out << "E"; mangle(VD); - for (APValue::LValuePathEntry E : V.getLValuePath()) { - const Decl *D = E.getAsBaseOrMember().getPointer(); - mangleUnqualifiedName(cast(D)); - } - for (unsigned I = 0; I != NumAts; ++I) + for (const std::function &Mangler : EntryManglers) + Mangler(); + if (T->isPointerType()) Out << '@'; } @@ -1789,20 +1867,14 @@ void MicrosoftCXXNameMangler::mangleTemplateArgValue(QualType T, if (WithScalarType) mangleType(T, SourceRange(), QMM_Escape); - // FIXME: The below manglings don't include a conversion, so bail if there - // would be one. MSVC mangles the (possibly converted) value of the - // pointer-to-member object as if it were a struct, leading to collisions - // in some cases. - if (!V.getMemberPointerPath().empty()) - break; - const CXXRecordDecl *RD = T->castAs()->getMostRecentCXXRecordDecl(); const ValueDecl *D = V.getMemberPointerDecl(); if (T->isMemberDataPointerType()) - mangleMemberDataPointer(RD, D, ""); + mangleMemberDataPointerInClassNTTP(RD, D); else - mangleMemberFunctionPointer(RD, cast_or_null(D), ""); + mangleMemberFunctionPointerInClassNTTP(RD, + cast_or_null(D)); return; } @@ -1890,7 +1962,6 @@ void MicrosoftCXXNameMangler::mangleTemplateArgValue(QualType T, break; } -mangling_unknown: DiagnosticsEngine &Diags = Context.getDiags(); unsigned DiagID = Diags.getCustomDiagID( DiagnosticsEngine::Error, "cannot mangle this template argument yet"); @@ -2477,6 +2548,13 @@ void MicrosoftCXXNameMangler::mangleType(const BuiltinType *T, Qualifiers, mangleArtificialTagType(TTK_Struct, "__bf16", {"__clang"}); break; +#define WASM_REF_TYPE(InternalName, MangledName, Id, SingletonId, AS) \ + case BuiltinType::Id: \ + mangleArtificialTagType(TTK_Struct, MangledName); \ + mangleArtificialTagType(TTK_Struct, MangledName, {"__clang"}); \ + break; + +#include "clang/Basic/WebAssemblyReferenceTypes.def" #define SVE_TYPE(Name, Id, SingletonId) \ case BuiltinType::Id: #include "clang/Basic/AArch64SVEACLETypes.def" @@ -2612,7 +2690,7 @@ void MicrosoftCXXNameMangler::mangleFunctionType(const FunctionType *T, // Copy constructor closure always takes an unqualified reference. mangleFunctionArgumentType(getASTContext().getLValueReferenceType( Proto->getParamType(0) - ->getAs() + ->castAs() ->getPointeeType(), /*SpelledAsLValue=*/true), Range); @@ -3586,8 +3664,8 @@ void MicrosoftMangleContextImpl::mangleCXXRTTI(QualType T, raw_ostream &Out) { Mangler.getStream() << "@8"; } -void MicrosoftMangleContextImpl::mangleCXXRTTIName(QualType T, - raw_ostream &Out) { +void MicrosoftMangleContextImpl::mangleCXXRTTIName( + QualType T, raw_ostream &Out, bool NormalizeIntegers = false) { MicrosoftCXXNameMangler Mangler(*this, Out); Mangler.getStream() << '.'; Mangler.mangleType(T, SourceRange(), MicrosoftCXXNameMangler::QMM_Result); @@ -3754,7 +3832,8 @@ void MicrosoftMangleContextImpl::mangleSEHFinallyBlock( Mangler.mangleName(EnclosingDecl); } -void MicrosoftMangleContextImpl::mangleTypeName(QualType T, raw_ostream &Out) { +void MicrosoftMangleContextImpl::mangleTypeName( + QualType T, raw_ostream &Out, bool NormalizeIntegers = false) { // This is just a made up unique string for the purposes of tbaa. undname // does *not* know how to demangle it. MicrosoftCXXNameMangler Mangler(*this, Out); diff --git a/contrib/llvm-project/clang/lib/AST/NSAPI.cpp b/contrib/llvm-project/clang/lib/AST/NSAPI.cpp index 3621a2eaa57..86dee540e9e 100644 --- a/contrib/llvm-project/clang/lib/AST/NSAPI.cpp +++ b/contrib/llvm-project/clang/lib/AST/NSAPI.cpp @@ -481,6 +481,8 @@ NSAPI::getNSNumberFactoryMethodKind(QualType T) const { #include "clang/Basic/PPCTypes.def" #define RVV_TYPE(Name, Id, SingletonId) case BuiltinType::Id: #include "clang/Basic/RISCVVTypes.def" +#define WASM_TYPE(Name, Id, SingletonId) case BuiltinType::Id: +#include "clang/Basic/WebAssemblyReferenceTypes.def" case BuiltinType::BoundMember: case BuiltinType::Dependent: case BuiltinType::Overload: diff --git a/contrib/llvm-project/clang/lib/AST/ODRDiagsEmitter.cpp b/contrib/llvm-project/clang/lib/AST/ODRDiagsEmitter.cpp index b3fe070889c..0189a5de625 100644 --- a/contrib/llvm-project/clang/lib/AST/ODRDiagsEmitter.cpp +++ b/contrib/llvm-project/clang/lib/AST/ODRDiagsEmitter.cpp @@ -994,40 +994,43 @@ bool ODRDiagsEmitter::diagnoseMismatch( return true; } - const StringLiteral *FirstStr = FirstSA->getMessage(); - const StringLiteral *SecondStr = SecondSA->getMessage(); - assert((FirstStr || SecondStr) && "Both messages cannot be empty"); - if ((FirstStr && !SecondStr) || (!FirstStr && SecondStr)) { + const Expr *FirstMessage = FirstSA->getMessage(); + const Expr *SecondMessage = SecondSA->getMessage(); + assert((FirstMessage || SecondMessage) && "Both messages cannot be empty"); + if ((FirstMessage && !SecondMessage) || (!FirstMessage && SecondMessage)) { SourceLocation FirstLoc, SecondLoc; SourceRange FirstRange, SecondRange; - if (FirstStr) { - FirstLoc = FirstStr->getBeginLoc(); - FirstRange = FirstStr->getSourceRange(); + if (FirstMessage) { + FirstLoc = FirstMessage->getBeginLoc(); + FirstRange = FirstMessage->getSourceRange(); } else { FirstLoc = FirstSA->getBeginLoc(); FirstRange = FirstSA->getSourceRange(); } - if (SecondStr) { - SecondLoc = SecondStr->getBeginLoc(); - SecondRange = SecondStr->getSourceRange(); + if (SecondMessage) { + SecondLoc = SecondMessage->getBeginLoc(); + SecondRange = SecondMessage->getSourceRange(); } else { SecondLoc = SecondSA->getBeginLoc(); SecondRange = SecondSA->getSourceRange(); } DiagError(FirstLoc, FirstRange, StaticAssertOnlyMessage) - << (FirstStr == nullptr); + << (FirstMessage == nullptr); DiagNote(SecondLoc, SecondRange, StaticAssertOnlyMessage) - << (SecondStr == nullptr); + << (SecondMessage == nullptr); return true; } - if (FirstStr && SecondStr && - FirstStr->getString() != SecondStr->getString()) { - DiagError(FirstStr->getBeginLoc(), FirstStr->getSourceRange(), - StaticAssertMessage); - DiagNote(SecondStr->getBeginLoc(), SecondStr->getSourceRange(), - StaticAssertMessage); - return true; + if (FirstMessage && SecondMessage) { + unsigned FirstMessageODRHash = computeODRHash(FirstMessage); + unsigned SecondMessageODRHash = computeODRHash(SecondMessage); + if (FirstMessageODRHash != SecondMessageODRHash) { + DiagError(FirstMessage->getBeginLoc(), FirstMessage->getSourceRange(), + StaticAssertMessage); + DiagNote(SecondMessage->getBeginLoc(), SecondMessage->getSourceRange(), + StaticAssertMessage); + return true; + } } break; } @@ -1742,6 +1745,7 @@ bool ODRDiagsEmitter::diagnoseMismatch( return true; } + // Note, these calls can trigger deserialization. const Expr *FirstInit = FirstParam->getInit(); const Expr *SecondInit = SecondParam->getInit(); if ((FirstInit == nullptr) != (SecondInit == nullptr)) { @@ -2095,7 +2099,8 @@ bool ODRDiagsEmitter::diagnoseMismatch( << FirstDecl->getSourceRange(); Diag(SecondDecl->getLocation(), diag::note_module_odr_violation_mismatch_decl_unknown) - << SecondModule << FirstDiffType << SecondDecl->getSourceRange(); + << SecondModule.empty() << SecondModule << FirstDiffType + << SecondDecl->getSourceRange(); return true; } diff --git a/contrib/llvm-project/clang/lib/AST/ODRHash.cpp b/contrib/llvm-project/clang/lib/AST/ODRHash.cpp index 3374b49f5d8..507fb0b49f8 100644 --- a/contrib/llvm-project/clang/lib/AST/ODRHash.cpp +++ b/contrib/llvm-project/clang/lib/AST/ODRHash.cpp @@ -373,11 +373,9 @@ public: void VisitObjCMethodDecl(const ObjCMethodDecl *Method) { ID.AddInteger(Method->getDeclKind()); Hash.AddBoolean(Method->isInstanceMethod()); // false if class method - Hash.AddBoolean(Method->isPropertyAccessor()); Hash.AddBoolean(Method->isVariadic()); Hash.AddBoolean(Method->isSynthesizedAccessorStub()); Hash.AddBoolean(Method->isDefined()); - Hash.AddBoolean(Method->isOverriding()); Hash.AddBoolean(Method->isDirectMethod()); Hash.AddBoolean(Method->isThisDeclarationADesignatedInitializer()); Hash.AddBoolean(Method->hasSkippedBody()); @@ -594,7 +592,7 @@ void ODRHash::AddCXXRecordDecl(const CXXRecordDecl *Record) { ID.AddInteger(Record->getNumBases()); auto Bases = Record->bases(); - for (auto Base : Bases) { + for (const auto &Base : Bases) { AddQualType(Base.getType()); ID.AddInteger(Base.isVirtual()); ID.AddInteger(Base.getAccessSpecifierAsWritten()); diff --git a/contrib/llvm-project/clang/lib/AST/OpenMPClause.cpp b/contrib/llvm-project/clang/lib/AST/OpenMPClause.cpp index 2e88c08ae78..4c895822ffd 100644 --- a/contrib/llvm-project/clang/lib/AST/OpenMPClause.cpp +++ b/contrib/llvm-project/clang/lib/AST/OpenMPClause.cpp @@ -1669,6 +1669,52 @@ OMPBindClause::Create(const ASTContext &C, OpenMPBindClauseKind K, OMPBindClause *OMPBindClause::CreateEmpty(const ASTContext &C) { return new (C) OMPBindClause(); } + +OMPDoacrossClause * +OMPDoacrossClause::Create(const ASTContext &C, SourceLocation StartLoc, + SourceLocation LParenLoc, SourceLocation EndLoc, + OpenMPDoacrossClauseModifier DepType, + SourceLocation DepLoc, SourceLocation ColonLoc, + ArrayRef VL, unsigned NumLoops) { + void *Mem = C.Allocate(totalSizeToAlloc(VL.size() + NumLoops), + alignof(OMPDoacrossClause)); + OMPDoacrossClause *Clause = new (Mem) + OMPDoacrossClause(StartLoc, LParenLoc, EndLoc, VL.size(), NumLoops); + Clause->setDependenceType(DepType); + Clause->setDependenceLoc(DepLoc); + Clause->setColonLoc(ColonLoc); + Clause->setVarRefs(VL); + for (unsigned I = 0; I < NumLoops; ++I) + Clause->setLoopData(I, nullptr); + return Clause; +} + +OMPDoacrossClause *OMPDoacrossClause::CreateEmpty(const ASTContext &C, + unsigned N, + unsigned NumLoops) { + void *Mem = C.Allocate(totalSizeToAlloc(N + NumLoops), + alignof(OMPDoacrossClause)); + return new (Mem) OMPDoacrossClause(N, NumLoops); +} + +void OMPDoacrossClause::setLoopData(unsigned NumLoop, Expr *Cnt) { + assert(NumLoop < NumLoops && "Loop index must be less number of loops."); + auto *It = std::next(getVarRefs().end(), NumLoop); + *It = Cnt; +} + +Expr *OMPDoacrossClause::getLoopData(unsigned NumLoop) { + assert(NumLoop < NumLoops && "Loop index must be less number of loops."); + auto *It = std::next(getVarRefs().end(), NumLoop); + return *It; +} + +const Expr *OMPDoacrossClause::getLoopData(unsigned NumLoop) const { + assert(NumLoop < NumLoops && "Loop index must be less number of loops."); + const auto *It = std::next(getVarRefs().end(), NumLoop); + return *It; +} + //===----------------------------------------------------------------------===// // OpenMP clauses printing methods //===----------------------------------------------------------------------===// @@ -2464,6 +2510,30 @@ void OMPClausePrinter::VisitOMPXDynCGroupMemClause( OS << ")"; } +void OMPClausePrinter::VisitOMPDoacrossClause(OMPDoacrossClause *Node) { + OS << "doacross("; + OpenMPDoacrossClauseModifier DepType = Node->getDependenceType(); + + switch (DepType) { + case OMPC_DOACROSS_source: + OS << "source:"; + break; + case OMPC_DOACROSS_sink: + OS << "sink:"; + break; + case OMPC_DOACROSS_source_omp_cur_iteration: + OS << "source: omp_cur_iteration"; + break; + case OMPC_DOACROSS_sink_omp_cur_iteration: + OS << "sink: omp_cur_iteration - 1"; + break; + default: + llvm_unreachable("unknown docaross modifier"); + } + VisitOMPClauseList(Node, ' '); + OS << ")"; +} + void OMPTraitInfo::getAsVariantMatchInfo(ASTContext &ASTCtx, VariantMatchInfo &VMI) const { for (const OMPTraitSet &Set : Sets) { @@ -2642,7 +2712,7 @@ TargetOMPContext::TargetOMPContext( ASTContext &ASTCtx, std::function &&DiagUnknownTrait, const FunctionDecl *CurrentFunctionDecl, ArrayRef ConstructTraits) - : OMPContext(ASTCtx.getLangOpts().OpenMPIsDevice, + : OMPContext(ASTCtx.getLangOpts().OpenMPIsTargetDevice, ASTCtx.getTargetInfo().getTriple()), FeatureValidityCheck([&](StringRef FeatureName) { return ASTCtx.getTargetInfo().isValidFeatureName(FeatureName); diff --git a/contrib/llvm-project/clang/lib/AST/PrintfFormatString.cpp b/contrib/llvm-project/clang/lib/AST/PrintfFormatString.cpp index bcebf92bf76..c450e2239fe 100644 --- a/contrib/llvm-project/clang/lib/AST/PrintfFormatString.cpp +++ b/contrib/llvm-project/clang/lib/AST/PrintfFormatString.cpp @@ -800,6 +800,8 @@ bool PrintfSpecifier::fixType(QualType QT, const LangOptions &LangOpt, #include "clang/Basic/PPCTypes.def" #define RVV_TYPE(Name, Id, SingletonId) case BuiltinType::Id: #include "clang/Basic/RISCVVTypes.def" +#define WASM_TYPE(Name, Id, SingletonId) case BuiltinType::Id: +#include "clang/Basic/WebAssemblyReferenceTypes.def" #define SIGNED_TYPE(Id, SingletonId) #define UNSIGNED_TYPE(Id, SingletonId) #define FLOATING_TYPE(Id, SingletonId) diff --git a/contrib/llvm-project/clang/lib/AST/RecordLayoutBuilder.cpp b/contrib/llvm-project/clang/lib/AST/RecordLayoutBuilder.cpp index 2f546398338..3f836cb96be 100644 --- a/contrib/llvm-project/clang/lib/AST/RecordLayoutBuilder.cpp +++ b/contrib/llvm-project/clang/lib/AST/RecordLayoutBuilder.cpp @@ -1853,9 +1853,8 @@ void ItaniumRecordLayoutBuilder::LayoutBitField(const FieldDecl *D) { void ItaniumRecordLayoutBuilder::LayoutField(const FieldDecl *D, bool InsertExtraPadding) { auto *FieldClass = D->getType()->getAsCXXRecordDecl(); - bool PotentiallyOverlapping = D->hasAttr() && FieldClass; bool IsOverlappingEmptyField = - PotentiallyOverlapping && FieldClass->isEmpty(); + D->isPotentiallyOverlapping() && FieldClass->isEmpty(); CharUnits FieldOffset = (IsUnion || IsOverlappingEmptyField) ? CharUnits::Zero() : getDataSize(); @@ -1916,7 +1915,7 @@ void ItaniumRecordLayoutBuilder::LayoutField(const FieldDecl *D, // A potentially-overlapping field occupies its dsize or nvsize, whichever // is larger. - if (PotentiallyOverlapping) { + if (D->isPotentiallyOverlapping()) { const ASTRecordLayout &Layout = Context.getASTRecordLayout(FieldClass); EffectiveFieldSize = std::max(Layout.getNonVirtualSize(), Layout.getDataSize()); @@ -2199,11 +2198,19 @@ void ItaniumRecordLayoutBuilder::FinishLayout(const NamedDecl *D) { << (InBits ? 1 : 0); // (byte|bit) } + const auto *CXXRD = dyn_cast(RD); + // Warn if we packed it unnecessarily, when the unpacked alignment is not // greater than the one after packing, the size in bits doesn't change and // the offset of each field is identical. + // Unless the type is non-POD (for Clang ABI > 15), where the packed + // attribute on such a type does allow the type to be packed into other + // structures that use the packed attribute. if (Packed && UnpackedAlignment <= Alignment && - UnpackedSizeInBits == getSizeInBits() && !HasPackedField) + UnpackedSizeInBits == getSizeInBits() && !HasPackedField && + (!CXXRD || CXXRD->isPOD() || + Context.getLangOpts().getClangABICompat() <= + LangOptions::ClangABI::Ver15)) Diag(D->getLocation(), diag::warn_unnecessary_packed) << Context.getTypeDeclType(RD); } @@ -2919,8 +2926,7 @@ void MicrosoftRecordLayoutBuilder::layoutNonVirtualBase( bool FoundBase = false; if (UseExternalLayout) { FoundBase = External.getExternalNVBaseOffset(BaseDecl, BaseOffset); - if (FoundBase) { - assert(BaseOffset >= Size && "base offset already allocated"); + if (BaseOffset > Size) { Size = BaseOffset; } } @@ -3716,6 +3722,28 @@ void ASTContext::DumpRecordLayout(const RecordDecl *RD, raw_ostream &OS, if (Target->defaultsToAIXPowerAlignment()) OS << " PreferredAlignment:" << toBits(Info.getPreferredAlignment()) << "\n"; + if (const CXXRecordDecl *CXXRD = dyn_cast(RD)) { + OS << " BaseOffsets: ["; + const CXXRecordDecl *Base = nullptr; + for (auto I : CXXRD->bases()) { + if (I.isVirtual()) + continue; + if (Base) + OS << ", "; + Base = I.getType()->getAsCXXRecordDecl(); + OS << Info.CXXInfo->BaseOffsets[Base].getQuantity(); + } + OS << "]>\n"; + OS << " VBaseOffsets: ["; + const CXXRecordDecl *VBase = nullptr; + for (auto I : CXXRD->vbases()) { + if (VBase) + OS << ", "; + VBase = I.getType()->getAsCXXRecordDecl(); + OS << Info.CXXInfo->VBaseOffsets[VBase].VBaseOffset.getQuantity(); + } + OS << "]>\n"; + } OS << " FieldOffsets: ["; for (unsigned i = 0, e = Info.getFieldCount(); i != e; ++i) { if (i) diff --git a/contrib/llvm-project/clang/lib/AST/Stmt.cpp b/contrib/llvm-project/clang/lib/AST/Stmt.cpp index 8744bba6c6d..c31fb48a2ad 100644 --- a/contrib/llvm-project/clang/lib/AST/Stmt.cpp +++ b/contrib/llvm-project/clang/lib/AST/Stmt.cpp @@ -1345,6 +1345,11 @@ CapturedStmt::CapturedStmt(EmptyShell Empty, unsigned NumCaptures) : Stmt(CapturedStmtClass, Empty), NumCaptures(NumCaptures), CapDeclAndKind(nullptr, CR_Default) { getStoredStmts()[NumCaptures] = nullptr; + + // Construct default capture objects. + Capture *Buffer = getStoredCaptures(); + for (unsigned I = 0, N = NumCaptures; I != N; ++I) + new (Buffer++) Capture(); } CapturedStmt *CapturedStmt::Create(const ASTContext &Context, Stmt *S, diff --git a/contrib/llvm-project/clang/lib/AST/StmtCXX.cpp b/contrib/llvm-project/clang/lib/AST/StmtCXX.cpp index 33b0421ad10..0d6fc848f73 100644 --- a/contrib/llvm-project/clang/lib/AST/StmtCXX.cpp +++ b/contrib/llvm-project/clang/lib/AST/StmtCXX.cpp @@ -23,7 +23,8 @@ QualType CXXCatchStmt::getCaughtType() const { } CXXTryStmt *CXXTryStmt::Create(const ASTContext &C, SourceLocation tryLoc, - Stmt *tryBlock, ArrayRef handlers) { + CompoundStmt *tryBlock, + ArrayRef handlers) { const size_t Size = totalSizeToAlloc(handlers.size() + 1); void *Mem = C.Allocate(Size, alignof(CXXTryStmt)); return new (Mem) CXXTryStmt(tryLoc, tryBlock, handlers); @@ -36,7 +37,7 @@ CXXTryStmt *CXXTryStmt::Create(const ASTContext &C, EmptyShell Empty, return new (Mem) CXXTryStmt(Empty, numHandlers); } -CXXTryStmt::CXXTryStmt(SourceLocation tryLoc, Stmt *tryBlock, +CXXTryStmt::CXXTryStmt(SourceLocation tryLoc, CompoundStmt *tryBlock, ArrayRef handlers) : Stmt(CXXTryStmtClass), TryLoc(tryLoc), NumHandlers(handlers.size()) { Stmt **Stmts = getStmts(); @@ -117,6 +118,7 @@ CoroutineBodyStmt::CoroutineBodyStmt(CoroutineBodyStmt::CtorArgs const &Args) SubStmts[CoroutineBodyStmt::OnFallthrough] = Args.OnFallthrough; SubStmts[CoroutineBodyStmt::Allocate] = Args.Allocate; SubStmts[CoroutineBodyStmt::Deallocate] = Args.Deallocate; + SubStmts[CoroutineBodyStmt::ResultDecl] = Args.ResultDecl; SubStmts[CoroutineBodyStmt::ReturnValue] = Args.ReturnValue; SubStmts[CoroutineBodyStmt::ReturnStmt] = Args.ReturnStmt; SubStmts[CoroutineBodyStmt::ReturnStmtOnAllocFailure] = diff --git a/contrib/llvm-project/clang/lib/AST/StmtOpenMP.cpp b/contrib/llvm-project/clang/lib/AST/StmtOpenMP.cpp index 7c5b9f23fc2..a544732bb4c 100644 --- a/contrib/llvm-project/clang/lib/AST/StmtOpenMP.cpp +++ b/contrib/llvm-project/clang/lib/AST/StmtOpenMP.cpp @@ -2374,6 +2374,10 @@ OMPTeamsGenericLoopDirective *OMPTeamsGenericLoopDirective::Create( Dir->setNextLowerBound(Exprs.NLB); Dir->setNextUpperBound(Exprs.NUB); Dir->setNumIterations(Exprs.NumIterations); + Dir->setPrevLowerBoundVariable(Exprs.PrevLB); + Dir->setPrevUpperBoundVariable(Exprs.PrevUB); + Dir->setDistInc(Exprs.DistInc); + Dir->setPrevEnsureUpperBound(Exprs.PrevEUB); Dir->setCounters(Exprs.Counters); Dir->setPrivateCounters(Exprs.PrivateCounters); Dir->setInits(Exprs.Inits); @@ -2383,6 +2387,15 @@ OMPTeamsGenericLoopDirective *OMPTeamsGenericLoopDirective::Create( Dir->setDependentInits(Exprs.DependentInits); Dir->setFinalsConditions(Exprs.FinalsConditions); Dir->setPreInits(Exprs.PreInits); + Dir->setCombinedLowerBoundVariable(Exprs.DistCombinedFields.LB); + Dir->setCombinedUpperBoundVariable(Exprs.DistCombinedFields.UB); + Dir->setCombinedEnsureUpperBound(Exprs.DistCombinedFields.EUB); + Dir->setCombinedInit(Exprs.DistCombinedFields.Init); + Dir->setCombinedCond(Exprs.DistCombinedFields.Cond); + Dir->setCombinedNextLowerBound(Exprs.DistCombinedFields.NLB); + Dir->setCombinedNextUpperBound(Exprs.DistCombinedFields.NUB); + Dir->setCombinedDistCond(Exprs.DistCombinedFields.DistCond); + Dir->setCombinedParForInDistCond(Exprs.DistCombinedFields.ParForInDistCond); return Dir; } @@ -2418,6 +2431,10 @@ OMPTargetTeamsGenericLoopDirective *OMPTargetTeamsGenericLoopDirective::Create( Dir->setNextLowerBound(Exprs.NLB); Dir->setNextUpperBound(Exprs.NUB); Dir->setNumIterations(Exprs.NumIterations); + Dir->setPrevLowerBoundVariable(Exprs.PrevLB); + Dir->setPrevUpperBoundVariable(Exprs.PrevUB); + Dir->setDistInc(Exprs.DistInc); + Dir->setPrevEnsureUpperBound(Exprs.PrevEUB); Dir->setCounters(Exprs.Counters); Dir->setPrivateCounters(Exprs.PrivateCounters); Dir->setInits(Exprs.Inits); @@ -2427,6 +2444,15 @@ OMPTargetTeamsGenericLoopDirective *OMPTargetTeamsGenericLoopDirective::Create( Dir->setDependentInits(Exprs.DependentInits); Dir->setFinalsConditions(Exprs.FinalsConditions); Dir->setPreInits(Exprs.PreInits); + Dir->setCombinedLowerBoundVariable(Exprs.DistCombinedFields.LB); + Dir->setCombinedUpperBoundVariable(Exprs.DistCombinedFields.UB); + Dir->setCombinedEnsureUpperBound(Exprs.DistCombinedFields.EUB); + Dir->setCombinedInit(Exprs.DistCombinedFields.Init); + Dir->setCombinedCond(Exprs.DistCombinedFields.Cond); + Dir->setCombinedNextLowerBound(Exprs.DistCombinedFields.NLB); + Dir->setCombinedNextUpperBound(Exprs.DistCombinedFields.NUB); + Dir->setCombinedDistCond(Exprs.DistCombinedFields.DistCond); + Dir->setCombinedParForInDistCond(Exprs.DistCombinedFields.ParForInDistCond); return Dir; } diff --git a/contrib/llvm-project/clang/lib/AST/StmtPrinter.cpp b/contrib/llvm-project/clang/lib/AST/StmtPrinter.cpp index 0a879bb6df2..c3db500d8a8 100644 --- a/contrib/llvm-project/clang/lib/AST/StmtPrinter.cpp +++ b/contrib/llvm-project/clang/lib/AST/StmtPrinter.cpp @@ -400,7 +400,9 @@ void StmtPrinter::VisitForStmt(ForStmt *Node) { PrintInitStmt(Node->getInit(), 5); else OS << (Node->getCond() ? "; " : ";"); - if (Node->getCond()) + if (const DeclStmt *DS = Node->getConditionVariableDeclStmt()) + PrintRawDeclStmt(DS); + else if (Node->getCond()) PrintExpr(Node->getCond()); OS << ";"; if (Node->getInc()) { @@ -1458,8 +1460,12 @@ void StmtPrinter::VisitUnaryExprOrTypeTraitExpr( void StmtPrinter::VisitGenericSelectionExpr(GenericSelectionExpr *Node) { OS << "_Generic("; - PrintExpr(Node->getControllingExpr()); - for (const GenericSelectionExpr::Association Assoc : Node->associations()) { + if (Node->isExprPredicate()) + PrintExpr(Node->getControllingExpr()); + else + Node->getControllingType()->getType().print(OS, Policy); + + for (const GenericSelectionExpr::Association &Assoc : Node->associations()) { OS << ", "; QualType T = Assoc.getType(); if (T.isNull()) @@ -1740,7 +1746,7 @@ void StmtPrinter::VisitDesignatedInitExpr(DesignatedInitExpr *Node) { for (const DesignatedInitExpr::Designator &D : Node->designators()) { if (D.isFieldDesignator()) { if (D.getDotLoc().isInvalid()) { - if (IdentifierInfo *II = D.getFieldName()) { + if (const IdentifierInfo *II = D.getFieldName()) { OS << II->getName() << ":"; NeedsEquals = false; } @@ -2539,7 +2545,7 @@ void StmtPrinter::VisitRequiresExpr(RequiresExpr *E) { OS << "}"; } -// C++ Coroutines TS +// C++ Coroutines void StmtPrinter::VisitCoroutineBodyStmt(CoroutineBodyStmt *S) { Visit(S->getBody()); diff --git a/contrib/llvm-project/clang/lib/AST/StmtProfile.cpp b/contrib/llvm-project/clang/lib/AST/StmtProfile.cpp index 960cc4f4fc2..d8a667b2d0f 100644 --- a/contrib/llvm-project/clang/lib/AST/StmtProfile.cpp +++ b/contrib/llvm-project/clang/lib/AST/StmtProfile.cpp @@ -29,10 +29,12 @@ namespace { protected: llvm::FoldingSetNodeID &ID; bool Canonical; + bool ProfileLambdaExpr; public: - StmtProfiler(llvm::FoldingSetNodeID &ID, bool Canonical) - : ID(ID), Canonical(Canonical) {} + StmtProfiler(llvm::FoldingSetNodeID &ID, bool Canonical, + bool ProfileLambdaExpr) + : ID(ID), Canonical(Canonical), ProfileLambdaExpr(ProfileLambdaExpr) {} virtual ~StmtProfiler() {} @@ -83,8 +85,10 @@ namespace { public: StmtProfilerWithPointers(llvm::FoldingSetNodeID &ID, - const ASTContext &Context, bool Canonical) - : StmtProfiler(ID, Canonical), Context(Context) {} + const ASTContext &Context, bool Canonical, + bool ProfileLambdaExpr) + : StmtProfiler(ID, Canonical, ProfileLambdaExpr), Context(Context) {} + private: void HandleStmtClass(Stmt::StmtClass SC) override { ID.AddInteger(SC); @@ -99,7 +103,15 @@ namespace { ID.AddInteger(NTTP->getDepth()); ID.AddInteger(NTTP->getIndex()); ID.AddBoolean(NTTP->isParameterPack()); - VisitType(NTTP->getType()); + // C++20 [temp.over.link]p6: + // Two template-parameters are equivalent under the following + // conditions: [...] if they declare non-type template parameters, + // they have equivalent types ignoring the use of type-constraints + // for placeholder types + // + // TODO: Why do we need to include the type in the profile? It's not + // part of the mangling. + VisitType(Context.getUnconstrainedType(NTTP->getType())); return; } @@ -111,6 +123,9 @@ namespace { // definition of "equivalent" (per C++ [temp.over.link]) is at // least as strong as the definition of "equivalent" used for // name mangling. + // + // TODO: The Itanium C++ ABI only uses the top-level cv-qualifiers, + // not the entirety of the type. VisitType(Parm->getType()); ID.AddInteger(Parm->getFunctionScopeDepth()); ID.AddInteger(Parm->getFunctionScopeIndex()); @@ -170,7 +185,8 @@ namespace { ODRHash &Hash; public: StmtProfilerWithoutPointers(llvm::FoldingSetNodeID &ID, ODRHash &Hash) - : StmtProfiler(ID, false), Hash(Hash) {} + : StmtProfiler(ID, /*Canonical=*/false, /*ProfileLambdaExpr=*/false), + Hash(Hash) {} private: void HandleStmtClass(Stmt::StmtClass SC) override { @@ -909,6 +925,9 @@ void OMPClauseProfiler::VisitOMPXDynCGroupMemClause( if (Expr *Size = C->getSize()) Profiler->VisitStmt(Size); } +void OMPClauseProfiler::VisitOMPDoacrossClause(const OMPDoacrossClause *C) { + VisitOMPClauseList(C); +} } // namespace void @@ -1519,7 +1538,7 @@ void StmtProfiler::VisitDesignatedInitExpr(const DesignatedInitExpr *S) { assert(D.isArrayRangeDesignator()); ID.AddInteger(2); } - ID.AddInteger(D.getFirstExprIndex()); + ID.AddInteger(D.getArrayIndex()); } } @@ -1637,7 +1656,8 @@ void StmtProfiler::VisitRequiresExpr(const RequiresExpr *S) { static Stmt::StmtClass DecodeOperatorCall(const CXXOperatorCallExpr *S, UnaryOperatorKind &UnaryOp, - BinaryOperatorKind &BinaryOp) { + BinaryOperatorKind &BinaryOp, + unsigned &NumArgs) { switch (S->getOperator()) { case OO_None: case OO_New: @@ -1650,7 +1670,7 @@ static Stmt::StmtClass DecodeOperatorCall(const CXXOperatorCallExpr *S, llvm_unreachable("Invalid operator call kind"); case OO_Plus: - if (S->getNumArgs() == 1) { + if (NumArgs == 1) { UnaryOp = UO_Plus; return Stmt::UnaryOperatorClass; } @@ -1659,7 +1679,7 @@ static Stmt::StmtClass DecodeOperatorCall(const CXXOperatorCallExpr *S, return Stmt::BinaryOperatorClass; case OO_Minus: - if (S->getNumArgs() == 1) { + if (NumArgs == 1) { UnaryOp = UO_Minus; return Stmt::UnaryOperatorClass; } @@ -1668,7 +1688,7 @@ static Stmt::StmtClass DecodeOperatorCall(const CXXOperatorCallExpr *S, return Stmt::BinaryOperatorClass; case OO_Star: - if (S->getNumArgs() == 1) { + if (NumArgs == 1) { UnaryOp = UO_Deref; return Stmt::UnaryOperatorClass; } @@ -1689,7 +1709,7 @@ static Stmt::StmtClass DecodeOperatorCall(const CXXOperatorCallExpr *S, return Stmt::BinaryOperatorClass; case OO_Amp: - if (S->getNumArgs() == 1) { + if (NumArgs == 1) { UnaryOp = UO_AddrOf; return Stmt::UnaryOperatorClass; } @@ -1798,13 +1818,13 @@ static Stmt::StmtClass DecodeOperatorCall(const CXXOperatorCallExpr *S, return Stmt::BinaryOperatorClass; case OO_PlusPlus: - UnaryOp = S->getNumArgs() == 1? UO_PreInc - : UO_PostInc; + UnaryOp = NumArgs == 1 ? UO_PreInc : UO_PostInc; + NumArgs = 1; return Stmt::UnaryOperatorClass; case OO_MinusMinus: - UnaryOp = S->getNumArgs() == 1? UO_PreDec - : UO_PostDec; + UnaryOp = NumArgs == 1 ? UO_PreDec : UO_PostDec; + NumArgs = 1; return Stmt::UnaryOperatorClass; case OO_Comma: @@ -1850,10 +1870,11 @@ void StmtProfiler::VisitCXXOperatorCallExpr(const CXXOperatorCallExpr *S) { UnaryOperatorKind UnaryOp = UO_Extension; BinaryOperatorKind BinaryOp = BO_Comma; - Stmt::StmtClass SC = DecodeOperatorCall(S, UnaryOp, BinaryOp); + unsigned NumArgs = S->getNumArgs(); + Stmt::StmtClass SC = DecodeOperatorCall(S, UnaryOp, BinaryOp, NumArgs); ID.AddInteger(SC); - for (unsigned I = 0, N = S->getNumArgs(); I != N; ++I) + for (unsigned I = 0; I != NumArgs; ++I) Visit(S->getArg(I)); if (SC == Stmt::UnaryOperatorClass) ID.AddInteger(UnaryOp); @@ -2016,14 +2037,27 @@ StmtProfiler::VisitCXXTemporaryObjectExpr(const CXXTemporaryObjectExpr *S) { void StmtProfiler::VisitLambdaExpr(const LambdaExpr *S) { - // Do not recursively visit the children of this expression. Profiling the - // body would result in unnecessary work, and is not safe to do during - // deserialization. - VisitStmtNoChildren(S); + if (!ProfileLambdaExpr) { + // Do not recursively visit the children of this expression. Profiling the + // body would result in unnecessary work, and is not safe to do during + // deserialization. + VisitStmtNoChildren(S); - // C++20 [temp.over.link]p5: - // Two lambda-expressions are never considered equivalent. - VisitDecl(S->getLambdaClass()); + // C++20 [temp.over.link]p5: + // Two lambda-expressions are never considered equivalent. + VisitDecl(S->getLambdaClass()); + + return; + } + + CXXRecordDecl *Lambda = S->getLambdaClass(); + ID.AddInteger(Lambda->getODRHash()); + + for (const auto &Capture : Lambda->captures()) { + ID.AddInteger(Capture.getCaptureKind()); + if (Capture.capturesVariable()) + VisitDecl(Capture.getCapturedVar()); + } } void @@ -2377,8 +2411,8 @@ void StmtProfiler::VisitTemplateArgument(const TemplateArgument &Arg) { } void Stmt::Profile(llvm::FoldingSetNodeID &ID, const ASTContext &Context, - bool Canonical) const { - StmtProfilerWithPointers Profiler(ID, Context, Canonical); + bool Canonical, bool ProfileLambdaExpr) const { + StmtProfilerWithPointers Profiler(ID, Context, Canonical, ProfileLambdaExpr); Profiler.Visit(this); } diff --git a/contrib/llvm-project/clang/lib/AST/TemplateBase.cpp b/contrib/llvm-project/clang/lib/AST/TemplateBase.cpp index ceff7a31371..c46b3e3d0c5 100644 --- a/contrib/llvm-project/clang/lib/AST/TemplateBase.cpp +++ b/contrib/llvm-project/clang/lib/AST/TemplateBase.cpp @@ -161,8 +161,9 @@ static bool needsAmpersandOnTemplateArg(QualType paramType, QualType argType) { //===----------------------------------------------------------------------===// TemplateArgument::TemplateArgument(ASTContext &Ctx, const llvm::APSInt &Value, - QualType Type) { + QualType Type, bool IsDefaulted) { Integer.Kind = Integral; + Integer.IsDefaulted = IsDefaulted; // Copy the APSInt value into our decomposed form. Integer.BitWidth = Value.getBitWidth(); Integer.IsUnsigned = Value.isUnsigned(); @@ -326,9 +327,9 @@ void TemplateArgument::Profile(llvm::FoldingSetNodeID &ID, case TemplateExpansion: ID.AddInteger(TemplateArg.NumExpansions); - LLVM_FALLTHROUGH; + [[fallthrough]]; case Template: - getAsTemplateOrTemplatePattern().Profile(ID); + ID.AddPointer(TemplateArg.Name); break; case Integral: diff --git a/contrib/llvm-project/clang/lib/AST/TemplateName.cpp b/contrib/llvm-project/clang/lib/AST/TemplateName.cpp index a6dd0fad933..2f0e4181e94 100644 --- a/contrib/llvm-project/clang/lib/AST/TemplateName.cpp +++ b/contrib/llvm-project/clang/lib/AST/TemplateName.cpp @@ -281,6 +281,15 @@ bool TemplateName::containsUnexpandedParameterPack() const { return getDependence() & TemplateNameDependence::UnexpandedPack; } +void TemplateName::Profile(llvm::FoldingSetNodeID &ID) { + if (const auto* USD = getAsUsingShadowDecl()) + ID.AddPointer(USD->getCanonicalDecl()); + else if (const auto *TD = getAsTemplateDecl()) + ID.AddPointer(TD->getCanonicalDecl()); + else + ID.AddPointer(Storage.getOpaqueValue()); +} + void TemplateName::print(raw_ostream &OS, const PrintingPolicy &Policy, Qualified Qual) const { auto Kind = getKind(); diff --git a/contrib/llvm-project/clang/lib/AST/TextNodeDumper.cpp b/contrib/llvm-project/clang/lib/AST/TextNodeDumper.cpp index a5573c117e6..a174faa6635 100644 --- a/contrib/llvm-project/clang/lib/AST/TextNodeDumper.cpp +++ b/contrib/llvm-project/clang/lib/AST/TextNodeDumper.cpp @@ -283,6 +283,8 @@ void TextNodeDumper::Visit(const Decl *D) { OS << " constexpr"; if (FD->isConsteval()) OS << " consteval"; + else if (FD->isImmediateFunction()) + OS << " immediate"; if (FD->isMultiVersion()) OS << " multiversion"; } @@ -1046,6 +1048,8 @@ void TextNodeDumper::VisitDeclRefExpr(const DeclRefExpr *Node) { case NOUR_Constant: OS << " non_odr_use_constant"; break; case NOUR_Discarded: OS << " non_odr_use_discarded"; break; } + if (Node->isImmediateEscalating()) + OS << " immediate-escalating"; } void TextNodeDumper::VisitUnresolvedLookupExpr( @@ -1227,6 +1231,8 @@ void TextNodeDumper::VisitCXXConstructExpr(const CXXConstructExpr *Node) { OS << " std::initializer_list"; if (Node->requiresZeroInitialization()) OS << " zeroing"; + if (Node->isImmediateEscalating()) + OS << " immediate-escalating"; } void TextNodeDumper::VisitCXXBindTemporaryExpr( @@ -1495,6 +1501,9 @@ void TextNodeDumper::VisitVectorType(const VectorType *T) { case VectorType::SveFixedLengthPredicateVector: OS << " fixed-length sve predicate vector"; break; + case VectorType::RVVFixedLengthDataVector: + OS << " fixed-length rvv data vector"; + break; } OS << " " << T->getNumElements(); } @@ -1818,7 +1827,8 @@ void TextNodeDumper::VisitVarDecl(const VarDecl *D) { if (D->hasInit()) { const Expr *E = D->getInit(); // Only dump the value of constexpr VarDecls for now. - if (E && !E->isValueDependent() && D->isConstexpr()) { + if (E && !E->isValueDependent() && D->isConstexpr() && + !D->getType()->isDependentType()) { const APValue *Value = D->evaluateValue(); if (Value) AddChild("value", [=] { Visit(*Value, E->getType()); }); diff --git a/contrib/llvm-project/clang/lib/AST/Type.cpp b/contrib/llvm-project/clang/lib/AST/Type.cpp index 54e62a1939f..99c85903442 100644 --- a/contrib/llvm-project/clang/lib/AST/Type.cpp +++ b/contrib/llvm-project/clang/lib/AST/Type.cpp @@ -18,6 +18,7 @@ #include "clang/AST/Decl.h" #include "clang/AST/DeclBase.h" #include "clang/AST/DeclCXX.h" +#include "clang/AST/DeclFriend.h" #include "clang/AST/DeclObjC.h" #include "clang/AST/DeclTemplate.h" #include "clang/AST/DependenceFlags.h" @@ -46,6 +47,7 @@ #include "llvm/Support/Casting.h" #include "llvm/Support/ErrorHandling.h" #include "llvm/Support/MathExtras.h" +#include "llvm/TargetParser/RISCVTargetParser.h" #include #include #include @@ -158,7 +160,7 @@ unsigned ConstantArrayType::getNumAddressingBits(const ASTContext &Context, if ((ElementSize >> 32) == 0 && NumElements.getBitWidth() <= 64 && (NumElements.getZExtValue() >> 32) == 0) { uint64_t TotalSize = NumElements.getZExtValue() * ElementSize; - return 64 - llvm::countLeadingZeros(TotalSize); + return llvm::bit_width(TotalSize); } // Otherwise, use APSInt to handle arbitrary sized values. @@ -1486,7 +1488,13 @@ struct StripObjCKindOfTypeVisitor bool QualType::UseExcessPrecision(const ASTContext &Ctx) { const BuiltinType *BT = getTypePtr()->getAs(); - if (BT) { + if (!BT) { + const VectorType *VT = getTypePtr()->getAs(); + if (VT) { + QualType ElementType = VT->getElementType(); + return ElementType.UseExcessPrecision(Ctx); + } + } else { switch (BT->getKind()) { case BuiltinType::Kind::Float16: { const TargetInfo &TI = Ctx.getTargetInfo(); @@ -1495,7 +1503,15 @@ bool QualType::UseExcessPrecision(const ASTContext &Ctx) { Ctx.getLangOpts().ExcessPrecisionKind::FPP_None) return true; return false; - } + } break; + case BuiltinType::Kind::BFloat16: { + const TargetInfo &TI = Ctx.getTargetInfo(); + if (TI.hasBFloat16Type() && !TI.hasFullBFloat16Type() && + Ctx.getLangOpts().getBFloat16ExcessPrecision() != + Ctx.getLangOpts().ExcessPrecisionKind::FPP_None) + return true; + return false; + } break; default: return false; } @@ -1928,6 +1944,11 @@ bool Type::hasIntegerRepresentation() const { (VT->getKind() >= BuiltinType::SveInt8 && VT->getKind() <= BuiltinType::SveUint64); } + if (CanonicalType->isRVVVLSBuiltinType()) { + const auto *VT = cast(CanonicalType); + return (VT->getKind() >= BuiltinType::RvvInt8mf8 && + VT->getKind() <= BuiltinType::RvvUint64m8); + } return isIntegerType(); } @@ -2154,8 +2175,9 @@ bool Type::isFloatingType() const { bool Type::hasFloatingRepresentation() const { if (const auto *VT = dyn_cast(CanonicalType)) return VT->getElementType()->isFloatingType(); - else - return isFloatingType(); + if (const auto *MT = dyn_cast(CanonicalType)) + return MT->getElementType()->isFloatingType(); + return isFloatingType(); } bool Type::isRealFloatingType() const { @@ -2176,8 +2198,7 @@ bool Type::isRealType() const { bool Type::isArithmeticType() const { if (const auto *BT = dyn_cast(CanonicalType)) return BT->getKind() >= BuiltinType::Bool && - BT->getKind() <= BuiltinType::Ibm128 && - BT->getKind() != BuiltinType::BFloat16; + BT->getKind() <= BuiltinType::Ibm128; if (const auto *ET = dyn_cast(CanonicalType)) // GCC allows forward declaration of enum types (forbid by C99 6.7.2.3p2). // If a body isn't seen by the time we get here, return false. @@ -2335,6 +2356,10 @@ bool Type::isSizelessBuiltinType() const { #define RVV_TYPE(Name, Id, SingletonId) case BuiltinType::Id: #include "clang/Basic/RISCVVTypes.def" return true; + // WebAssembly reference types +#define WASM_TYPE(Name, Id, SingletonId) case BuiltinType::Id: +#include "clang/Basic/WebAssemblyReferenceTypes.def" + return true; default: return false; } @@ -2342,6 +2367,22 @@ bool Type::isSizelessBuiltinType() const { return false; } +bool Type::isWebAssemblyExternrefType() const { + if (const auto *BT = getAs()) + return BT->getKind() == BuiltinType::WasmExternRef; + return false; +} + +bool Type::isWebAssemblyTableType() const { + if (const auto *ATy = dyn_cast(this)) + return ATy->getElementType().isWebAssemblyReferenceType(); + + if (const auto *PTy = dyn_cast(this)) + return PTy->getPointeeType().isWebAssemblyReferenceType(); + + return false; +} + bool Type::isSizelessType() const { return isSizelessBuiltinType(); } bool Type::isSVESizelessBuiltinType() const { @@ -2358,6 +2399,19 @@ bool Type::isSVESizelessBuiltinType() const { return false; } +bool Type::isRVVSizelessBuiltinType() const { + if (const BuiltinType *BT = getAs()) { + switch (BT->getKind()) { +#define RVV_TYPE(Name, Id, SingletonId) case BuiltinType::Id: +#include "clang/Basic/RISCVVTypes.def" + return true; + default: + return false; + } + } + return false; +} + bool Type::isVLSTBuiltinType() const { if (const BuiltinType *BT = getAs()) { switch (BT->getKind()) { @@ -2374,6 +2428,8 @@ bool Type::isVLSTBuiltinType() const { case BuiltinType::SveFloat64: case BuiltinType::SveBFloat16: case BuiltinType::SveBool: + case BuiltinType::SveBoolx2: + case BuiltinType::SveBoolx4: return true; default: return false; @@ -2385,7 +2441,7 @@ bool Type::isVLSTBuiltinType() const { QualType Type::getSveEltType(const ASTContext &Ctx) const { assert(isVLSTBuiltinType() && "unsupported type!"); - const BuiltinType *BTy = getAs(); + const BuiltinType *BTy = castAs(); if (BTy->getKind() == BuiltinType::SveBool) // Represent predicates as i8 rather than i1 to avoid any layout issues. // The type is bitcasted to a scalable predicate type when casting between @@ -2395,6 +2451,27 @@ QualType Type::getSveEltType(const ASTContext &Ctx) const { return Ctx.getBuiltinVectorTypeInfo(BTy).ElementType; } +bool Type::isRVVVLSBuiltinType() const { + if (const BuiltinType *BT = getAs()) { + switch (BT->getKind()) { +#define RVV_VECTOR_TYPE(Name, Id, SingletonId, NumEls, ElBits, NF, IsSigned, IsFP) \ + case BuiltinType::Id: \ + return NF == 1; +#include "clang/Basic/RISCVVTypes.def" + default: + return false; + } + } + return false; +} + +QualType Type::getRVVEltType(const ASTContext &Ctx) const { + assert(isRVVVLSBuiltinType() && "unsupported type!"); + + const BuiltinType *BTy = castAs(); + return Ctx.getBuiltinVectorTypeInfo(BTy).ElementType; +} + bool QualType::isPODType(const ASTContext &Context) const { // C++11 has a more relaxed definition of POD. if (Context.getLangOpts().CPlusPlus11) @@ -2564,6 +2641,64 @@ bool QualType::isTriviallyRelocatableType(const ASTContext &Context) const { } } +static bool +HasNonDeletedDefaultedEqualityComparison(const CXXRecordDecl *Decl) { + if (Decl->isUnion()) + return false; + + auto IsDefaultedOperatorEqualEqual = [&](const FunctionDecl *Function) { + return Function->getOverloadedOperator() == + OverloadedOperatorKind::OO_EqualEqual && + Function->isDefaulted() && Function->getNumParams() > 0 && + (Function->getParamDecl(0)->getType()->isReferenceType() || + Decl->isTriviallyCopyable()); + }; + + if (llvm::none_of(Decl->methods(), IsDefaultedOperatorEqualEqual) && + llvm::none_of(Decl->friends(), [&](const FriendDecl *Friend) { + if (NamedDecl *ND = Friend->getFriendDecl()) { + return ND->isFunctionOrFunctionTemplate() && + IsDefaultedOperatorEqualEqual(ND->getAsFunction()); + } + return false; + })) + return false; + + return llvm::all_of(Decl->bases(), + [](const CXXBaseSpecifier &BS) { + if (const auto *RD = BS.getType()->getAsCXXRecordDecl()) + return HasNonDeletedDefaultedEqualityComparison(RD); + return true; + }) && + llvm::all_of(Decl->fields(), [](const FieldDecl *FD) { + auto Type = FD->getType(); + if (Type->isArrayType()) + Type = Type->getBaseElementTypeUnsafe()->getCanonicalTypeUnqualified(); + + if (Type->isReferenceType() || Type->isEnumeralType()) + return false; + if (const auto *RD = Type->getAsCXXRecordDecl()) + return HasNonDeletedDefaultedEqualityComparison(RD); + return true; + }); +} + +bool QualType::isTriviallyEqualityComparableType( + const ASTContext &Context) const { + QualType CanonicalType = getCanonicalType(); + if (CanonicalType->isIncompleteType() || CanonicalType->isDependentType() || + CanonicalType->isEnumeralType() || CanonicalType->isArrayType()) + return false; + + if (const auto *RD = CanonicalType->getAsCXXRecordDecl()) { + if (!HasNonDeletedDefaultedEqualityComparison(RD)) + return false; + } + + return Context.hasUniqueObjectRepresentations( + CanonicalType, /*CheckIfTriviallyCopyable=*/false); +} + bool QualType::isNonWeakInMRRWithObjCWeak(const ASTContext &Context) const { return !Context.getLangOpts().ObjCAutoRefCount && Context.getLangOpts().ObjCWeak && @@ -2582,6 +2717,19 @@ bool QualType::hasNonTrivialToPrimitiveCopyCUnion(const RecordDecl *RD) { return RD->hasNonTrivialToPrimitiveCopyCUnion(); } +bool QualType::isWebAssemblyReferenceType() const { + return isWebAssemblyExternrefType() || isWebAssemblyFuncrefType(); +} + +bool QualType::isWebAssemblyExternrefType() const { + return getTypePtr()->isWebAssemblyExternrefType(); +} + +bool QualType::isWebAssemblyFuncrefType() const { + return getTypePtr()->isFunctionPointerType() && + getAddressSpace() == LangAS::wasm_funcref; +} + QualType::PrimitiveDefaultInitializeKind QualType::isNonTrivialToPrimitiveDefaultInitialize() const { if (const auto *RT = @@ -3150,6 +3298,10 @@ StringRef BuiltinType::getName(const PrintingPolicy &Policy) const { case Id: \ return Name; #include "clang/Basic/RISCVVTypes.def" +#define WASM_TYPE(Name, Id, SingletonId) \ + case Id: \ + return Name; +#include "clang/Basic/WebAssemblyReferenceTypes.def" } llvm_unreachable("Invalid builtin type."); @@ -3240,7 +3392,10 @@ FunctionProtoType::FunctionProtoType(QualType result, ArrayRef params, // Fill in the exception type array if present. if (getExceptionSpecType() == EST_Dynamic) { auto &ExtraBits = *getTrailingObjects(); - ExtraBits.NumExceptionType = epi.ExceptionSpec.Exceptions.size(); + size_t NumExceptions = epi.ExceptionSpec.Exceptions.size(); + assert(NumExceptions <= UINT16_MAX && + "Not enough bits to encode exceptions"); + ExtraBits.NumExceptionType = NumExceptions; assert(hasExtraBitfields() && "missing trailing extra bitfields!"); auto *exnSlot = @@ -3640,6 +3795,10 @@ bool AttributedType::isMSTypeSpec() const { llvm_unreachable("invalid attr kind"); } +bool AttributedType::isWebAssemblyFuncrefSpec() const { + return getAttrKind() == attr::WebAssemblyFuncref; +} + bool AttributedType::isCallingConv() const { // FIXME: Generate this with TableGen. switch (getAttrKind()) { @@ -4279,6 +4438,8 @@ bool Type::canHaveNullability(bool ResultIfUnknown) const { #include "clang/Basic/PPCTypes.def" #define RVV_TYPE(Name, Id, SingletonId) case BuiltinType::Id: #include "clang/Basic/RISCVVTypes.def" +#define WASM_TYPE(Name, Id, SingletonId) case BuiltinType::Id: +#include "clang/Basic/WebAssemblyReferenceTypes.def" case BuiltinType::BuiltinFn: case BuiltinType::NullPtr: case BuiltinType::IncompleteMatrixIdx: @@ -4546,10 +4707,13 @@ AutoType::AutoType(QualType DeducedAsType, AutoTypeKeyword Keyword, AutoTypeBits.Keyword = (unsigned)Keyword; AutoTypeBits.NumArgs = TypeConstraintArgs.size(); this->TypeConstraintConcept = TypeConstraintConcept; + assert(TypeConstraintConcept || AutoTypeBits.NumArgs == 0); if (TypeConstraintConcept) { auto *ArgBuffer = const_cast(getTypeConstraintArguments().data()); for (const TemplateArgument &Arg : TypeConstraintArgs) { + // We only syntactically depend on the constraint arguments. They don't + // affect the deduced type, only its validity. addDependence( toSyntacticDependence(toTypeDependence(Arg.getDependence()))); diff --git a/contrib/llvm-project/clang/lib/AST/TypeLoc.cpp b/contrib/llvm-project/clang/lib/AST/TypeLoc.cpp index bcc5a223e6f..69efa6fecbc 100644 --- a/contrib/llvm-project/clang/lib/AST/TypeLoc.cpp +++ b/contrib/llvm-project/clang/lib/AST/TypeLoc.cpp @@ -424,6 +424,8 @@ TypeSpecifierType BuiltinTypeLoc::getWrittenTypeSpec() const { #include "clang/Basic/PPCTypes.def" #define RVV_TYPE(Name, Id, SingletonId) case BuiltinType::Id: #include "clang/Basic/RISCVVTypes.def" +#define WASM_TYPE(Name, Id, SingletonId) case BuiltinType::Id: +#include "clang/Basic/WebAssemblyReferenceTypes.def" case BuiltinType::BuiltinFn: case BuiltinType::IncompleteMatrixIdx: case BuiltinType::OMPArraySection: diff --git a/contrib/llvm-project/clang/lib/AST/TypePrinter.cpp b/contrib/llvm-project/clang/lib/AST/TypePrinter.cpp index 2d06faeca18..1b62f663092 100644 --- a/contrib/llvm-project/clang/lib/AST/TypePrinter.cpp +++ b/contrib/llvm-project/clang/lib/AST/TypePrinter.cpp @@ -692,6 +692,20 @@ void TypePrinter::printVectorBefore(const VectorType *T, raw_ostream &OS) { // Multiply by 8 for the number of bits. OS << ") * 8))) "; printBefore(T->getElementType(), OS); + break; + case VectorType::RVVFixedLengthDataVector: + // FIXME: We prefer to print the size directly here, but have no way + // to get the size of the type. + OS << "__attribute__((__riscv_rvv_vector_bits__("; + + OS << T->getNumElements(); + + OS << " * sizeof("; + print(T->getElementType(), OS, StringRef()); + // Multiply by 8 for the number of bits. + OS << ") * 8))) "; + printBefore(T->getElementType(), OS); + break; } } @@ -757,6 +771,21 @@ void TypePrinter::printDependentVectorBefore( } OS << "))) "; printBefore(T->getElementType(), OS); + break; + case VectorType::RVVFixedLengthDataVector: + // FIXME: We prefer to print the size directly here, but have no way + // to get the size of the type. + OS << "__attribute__((__riscv_rvv_vector_bits__("; + if (T->getSizeExpr()) { + T->getSizeExpr()->printPretty(OS, nullptr, Policy); + OS << " * sizeof("; + print(T->getElementType(), OS, StringRef()); + // Multiply by 8 for the number of bits. + OS << ") * 8"; + } + OS << "))) "; + printBefore(T->getElementType(), OS); + break; } } @@ -1356,11 +1385,20 @@ void TypePrinter::printTag(TagDecl *D, raw_ostream &OS) { if (PLoc.isValid()) { OS << " at "; StringRef File = PLoc.getFilename(); + llvm::SmallString<1024> WrittenFile(File); if (auto *Callbacks = Policy.Callbacks) - OS << Callbacks->remapPath(File); - else - OS << File; - OS << ':' << PLoc.getLine() << ':' << PLoc.getColumn(); + WrittenFile = Callbacks->remapPath(File); + // Fix inconsistent path separator created by + // clang::DirectoryLookup::LookupFile when the file path is relative + // path. + llvm::sys::path::Style Style = + llvm::sys::path::is_absolute(WrittenFile) + ? llvm::sys::path::Style::native + : (Policy.MSVCFormatting + ? llvm::sys::path::Style::windows_backslash + : llvm::sys::path::Style::posix); + llvm::sys::path::native(WrittenFile, Style); + OS << WrittenFile << ':' << PLoc.getLine() << ':' << PLoc.getColumn(); } } @@ -1538,6 +1576,11 @@ void TypePrinter::printElaboratedBefore(const ElaboratedType *T, return; } + if (Policy.SuppressElaboration) { + printBefore(T->getNamedType(), OS); + return; + } + // The tag definition will take care of these. if (!Policy.IncludeTagDefinition) { @@ -1557,6 +1600,12 @@ void TypePrinter::printElaboratedAfter(const ElaboratedType *T, raw_ostream &OS) { if (Policy.IncludeTagDefinition && T->getOwnedTagDecl()) return; + + if (Policy.SuppressElaboration) { + printAfter(T->getNamedType(), OS); + return; + } + ElaboratedTypePolicyRAII PolicyRAII(Policy); printAfter(T->getNamedType(), OS); } @@ -1649,6 +1698,9 @@ void TypePrinter::printAttributedBefore(const AttributedType *T, spaceBeforePlaceHolder(OS); } + if (T->isWebAssemblyFuncrefSpec()) + OS << "__funcref"; + // Print nullability type specifiers. if (T->getImmediateNullability()) { if (T->getAttrKind() == attr::TypeNonNull) @@ -1682,8 +1734,8 @@ void TypePrinter::printAttributedAfter(const AttributedType *T, // Some attributes are printed as qualifiers before the type, so we have // nothing left to do. - if (T->getAttrKind() == attr::ObjCKindOf || - T->isMSTypeSpec() || T->getImmediateNullability()) + if (T->getAttrKind() == attr::ObjCKindOf || T->isMSTypeSpec() || + T->getImmediateNullability() || T->isWebAssemblyFuncrefSpec()) return; // Don't print the inert __unsafe_unretained attribute at all. @@ -1716,6 +1768,11 @@ void TypePrinter::printAttributedAfter(const AttributedType *T, return; } + if (T->getAttrKind() == attr::ArmStreaming) { + OS << "__arm_streaming"; + return; + } + OS << " __attribute__(("; switch (T->getAttrKind()) { #define TYPE_ATTR(NAME) @@ -1755,6 +1812,8 @@ void TypePrinter::printAttributedAfter(const AttributedType *T, case attr::AddressSpace: case attr::CmseNSCall: case attr::AnnotateType: + case attr::WebAssemblyFuncref: + case attr::ArmStreaming: llvm_unreachable("This attribute should have been handled already"); case attr::NSReturnsRetained: @@ -2007,6 +2066,36 @@ static bool isSubstitutedType(ASTContext &Ctx, QualType T, QualType Pattern, return false; } +/// Evaluates the expression template argument 'Pattern' and returns true +/// if 'Arg' evaluates to the same result. +static bool templateArgumentExpressionsEqual(ASTContext const &Ctx, + TemplateArgument const &Pattern, + TemplateArgument const &Arg) { + if (Pattern.getKind() != TemplateArgument::Expression) + return false; + + // Can't evaluate value-dependent expressions so bail early + Expr const *pattern_expr = Pattern.getAsExpr(); + if (pattern_expr->isValueDependent() || + !pattern_expr->isIntegerConstantExpr(Ctx)) + return false; + + if (Arg.getKind() == TemplateArgument::Integral) + return llvm::APSInt::isSameValue(pattern_expr->EvaluateKnownConstInt(Ctx), + Arg.getAsIntegral()); + + if (Arg.getKind() == TemplateArgument::Expression) { + Expr const *args_expr = Arg.getAsExpr(); + if (args_expr->isValueDependent() || !args_expr->isIntegerConstantExpr(Ctx)) + return false; + + return llvm::APSInt::isSameValue(args_expr->EvaluateKnownConstInt(Ctx), + pattern_expr->EvaluateKnownConstInt(Ctx)); + } + + return false; +} + static bool isSubstitutedTemplateArgument(ASTContext &Ctx, TemplateArgument Arg, TemplateArgument Pattern, ArrayRef Args, @@ -2025,15 +2114,8 @@ static bool isSubstitutedTemplateArgument(ASTContext &Ctx, TemplateArgument Arg, } } - if (Arg.getKind() == TemplateArgument::Integral && - Pattern.getKind() == TemplateArgument::Expression) { - Expr const *expr = Pattern.getAsExpr(); - - if (!expr->isValueDependent() && expr->isIntegerConstantExpr(Ctx)) { - return llvm::APSInt::isSameValue(expr->EvaluateKnownConstInt(Ctx), - Arg.getAsIntegral()); - } - } + if (templateArgumentExpressionsEqual(Ctx, Pattern, Arg)) + return true; if (Arg.getKind() != Pattern.getKind()) return false; @@ -2086,14 +2168,10 @@ printTo(raw_ostream &OS, ArrayRef Args, const PrintingPolicy &Policy, if (TPL && Policy.SuppressDefaultTemplateArgs && !Policy.PrintCanonicalTypes && !Args.empty() && !IsPack && Args.size() <= TPL->size()) { - ASTContext &Ctx = TPL->getParam(0)->getASTContext(); llvm::SmallVector OrigArgs; for (const TA &A : Args) OrigArgs.push_back(getArgument(A)); - while (!Args.empty() && - isSubstitutedDefaultArgument(Ctx, getArgument(Args.back()), - TPL->getParam(Args.size() - 1), - OrigArgs, TPL->getDepth())) + while (!Args.empty() && getArgument(Args.back()).getIsDefaulted()) Args = Args.drop_back(); } @@ -2238,6 +2316,8 @@ std::string Qualifiers::getAddrSpaceAsString(LangAS AS) { return "__uptr __ptr32"; case LangAS::ptr64: return "__ptr64"; + case LangAS::wasm_funcref: + return "__funcref"; case LangAS::hlsl_groupshared: return "groupshared"; default: diff --git a/contrib/llvm-project/clang/lib/AST/VTableBuilder.cpp b/contrib/llvm-project/clang/lib/AST/VTableBuilder.cpp index bc9a83bde8a..2a6f1e20202 100644 --- a/contrib/llvm-project/clang/lib/AST/VTableBuilder.cpp +++ b/contrib/llvm-project/clang/lib/AST/VTableBuilder.cpp @@ -2259,7 +2259,7 @@ VTableLayout::VTableLayout(ArrayRef VTableIndices, VTableLayout::~VTableLayout() { } bool VTableContextBase::hasVtableSlot(const CXXMethodDecl *MD) { - return MD->isVirtual() && !MD->isConsteval(); + return MD->isVirtual() && !MD->isImmediateFunction(); } ItaniumVTableContext::ItaniumVTableContext( diff --git a/contrib/llvm-project/clang/lib/ASTMatchers/ASTMatchersInternal.cpp b/contrib/llvm-project/clang/lib/ASTMatchers/ASTMatchersInternal.cpp index f1f73fc4207..3470467112d 100644 --- a/contrib/llvm-project/clang/lib/ASTMatchers/ASTMatchersInternal.cpp +++ b/contrib/llvm-project/clang/lib/ASTMatchers/ASTMatchersInternal.cpp @@ -800,6 +800,7 @@ const internal::VariadicDynCastAllOfMatcher tagDecl; const internal::VariadicDynCastAllOfMatcher cxxMethodDecl; const internal::VariadicDynCastAllOfMatcher cxxConversionDecl; +const internal::VariadicDynCastAllOfMatcher conceptDecl; const internal::VariadicDynCastAllOfMatcher varDecl; const internal::VariadicDynCastAllOfMatcher fieldDecl; const internal::VariadicDynCastAllOfMatcher @@ -882,6 +883,10 @@ const internal::VariadicDynCastAllOfMatcher cxxNoexceptExpr; const internal::VariadicDynCastAllOfMatcher arraySubscriptExpr; +const internal::VariadicDynCastAllOfMatcher + arrayInitIndexExpr; +const internal::VariadicDynCastAllOfMatcher + arrayInitLoopExpr; const internal::VariadicDynCastAllOfMatcher cxxDefaultArgExpr; const internal::VariadicDynCastAllOfMatcher @@ -910,6 +915,8 @@ const internal::VariadicDynCastAllOfMatcher switchCase; const internal::VariadicDynCastAllOfMatcher caseStmt; const internal::VariadicDynCastAllOfMatcher defaultStmt; const internal::VariadicDynCastAllOfMatcher compoundStmt; +const internal::VariadicDynCastAllOfMatcher + coroutineBodyStmt; const internal::VariadicDynCastAllOfMatcher cxxCatchStmt; const internal::VariadicDynCastAllOfMatcher cxxTryStmt; const internal::VariadicDynCastAllOfMatcher cxxThrowExpr; diff --git a/contrib/llvm-project/clang/lib/ASTMatchers/Dynamic/Marshallers.h b/contrib/llvm-project/clang/lib/ASTMatchers/Dynamic/Marshallers.h index 1b099ec3a31..c76ddf17b71 100644 --- a/contrib/llvm-project/clang/lib/ASTMatchers/Dynamic/Marshallers.h +++ b/contrib/llvm-project/clang/lib/ASTMatchers/Dynamic/Marshallers.h @@ -1008,7 +1008,7 @@ public: Diagnostics *) const override { std::vector NodeKinds; - for (auto Arg : Args) { + for (const auto &Arg : Args) { if (!Arg.Value.isNodeKind()) return {}; NodeKinds.push_back(Arg.Value.getNodeKind()); diff --git a/contrib/llvm-project/clang/lib/ASTMatchers/Dynamic/Registry.cpp b/contrib/llvm-project/clang/lib/ASTMatchers/Dynamic/Registry.cpp index 0d436fa29a7..1098df032a6 100644 --- a/contrib/llvm-project/clang/lib/ASTMatchers/Dynamic/Registry.cpp +++ b/contrib/llvm-project/clang/lib/ASTMatchers/Dynamic/Registry.cpp @@ -60,7 +60,7 @@ private: void RegistryMaps::registerMatcher( StringRef MatcherName, std::unique_ptr Callback) { - assert(Constructors.find(MatcherName) == Constructors.end()); + assert(!Constructors.contains(MatcherName)); Constructors[MatcherName] = std::move(Callback); } @@ -134,7 +134,10 @@ RegistryMaps::RegistryMaps() { REGISTER_MATCHER(allOf); REGISTER_MATCHER(anyOf); REGISTER_MATCHER(anything); + REGISTER_MATCHER(arrayInitIndexExpr); + REGISTER_MATCHER(arrayInitLoopExpr); REGISTER_MATCHER(argumentCountIs); + REGISTER_MATCHER(argumentCountAtLeast); REGISTER_MATCHER(arraySubscriptExpr); REGISTER_MATCHER(arrayType); REGISTER_MATCHER(asString); @@ -169,12 +172,14 @@ RegistryMaps::RegistryMaps() { REGISTER_MATCHER(compoundLiteralExpr); REGISTER_MATCHER(compoundStmt); REGISTER_MATCHER(coawaitExpr); + REGISTER_MATCHER(conceptDecl); REGISTER_MATCHER(conditionalOperator); REGISTER_MATCHER(constantArrayType); REGISTER_MATCHER(constantExpr); REGISTER_MATCHER(containsDeclaration); REGISTER_MATCHER(continueStmt); REGISTER_MATCHER(coreturnStmt); + REGISTER_MATCHER(coroutineBodyStmt); REGISTER_MATCHER(coyieldExpr); REGISTER_MATCHER(cudaKernelCallExpr); REGISTER_MATCHER(cxxBaseSpecifier); diff --git a/contrib/llvm-project/clang/lib/Analysis/BodyFarm.cpp b/contrib/llvm-project/clang/lib/Analysis/BodyFarm.cpp index c05534886cb..b989b8422cf 100644 --- a/contrib/llvm-project/clang/lib/Analysis/BodyFarm.cpp +++ b/contrib/llvm-project/clang/lib/Analysis/BodyFarm.cpp @@ -717,6 +717,7 @@ Stmt *BodyFarm::getBody(const FunctionDecl *D) { switch (BuiltinID) { case Builtin::BIas_const: case Builtin::BIforward: + case Builtin::BIforward_like: case Builtin::BImove: case Builtin::BImove_if_noexcept: FF = create_std_move_forward; diff --git a/contrib/llvm-project/clang/lib/Analysis/CFG.cpp b/contrib/llvm-project/clang/lib/Analysis/CFG.cpp index ea8b73e81ea..64a4fffaea5 100644 --- a/contrib/llvm-project/clang/lib/Analysis/CFG.cpp +++ b/contrib/llvm-project/clang/lib/Analysis/CFG.cpp @@ -300,6 +300,7 @@ public: int distance(const_iterator L); const_iterator shared_parent(const_iterator L); bool pointsToFirstDeclaredVar() { return VarIter == 1; } + bool inSameLocalScope(const_iterator rhs) { return Scope == rhs.Scope; } }; private: @@ -349,18 +350,33 @@ int LocalScope::const_iterator::distance(LocalScope::const_iterator L) { /// between this and shared_parent(L) end. LocalScope::const_iterator LocalScope::const_iterator::shared_parent(LocalScope::const_iterator L) { - llvm::SmallPtrSet ScopesOfL; + // one of iterators is not valid (we are not in scope), so common + // parent is const_iterator() (i.e. sentinel). + if ((*this == const_iterator()) || (L == const_iterator())) { + return const_iterator(); + } + + const_iterator F = *this; + if (F.inSameLocalScope(L)) { + // Iterators are in the same scope, get common subset of variables. + F.VarIter = std::min(F.VarIter, L.VarIter); + return F; + } + + llvm::SmallDenseMap ScopesOfL; while (true) { - ScopesOfL.insert(L.Scope); + ScopesOfL.try_emplace(L.Scope, L.VarIter); if (L == const_iterator()) break; L = L.Scope->Prev; } - const_iterator F = *this; while (true) { - if (ScopesOfL.count(F.Scope)) + if (auto LIt = ScopesOfL.find(F.Scope); LIt != ScopesOfL.end()) { + // Get common subset of variables in given scope + F.VarIter = std::min(F.VarIter, LIt->getSecond()); return F; + } assert(F != const_iterator() && "L iterator is not reachable from F iterator."); F = F.Scope->Prev; @@ -513,9 +529,6 @@ class CFGBuilder { llvm::DenseMap ConstructionContextMap; - using DeclsWithEndedScopeSetTy = llvm::SmallSetVector; - DeclsWithEndedScopeSetTy DeclsWithEndedScope; - bool badCFG = false; const CFG::BuildOptions &BuildOpts; @@ -756,18 +769,20 @@ private: CFGBlock *addInitializer(CXXCtorInitializer *I); void addLoopExit(const Stmt *LoopStmt); - void addAutomaticObjDtors(LocalScope::const_iterator B, - LocalScope::const_iterator E, Stmt *S); - void addLifetimeEnds(LocalScope::const_iterator B, - LocalScope::const_iterator E, Stmt *S); void addAutomaticObjHandling(LocalScope::const_iterator B, LocalScope::const_iterator E, Stmt *S); + void addAutomaticObjDestruction(LocalScope::const_iterator B, + LocalScope::const_iterator E, Stmt *S); + void addScopeExitHandling(LocalScope::const_iterator B, + LocalScope::const_iterator E, Stmt *S); void addImplicitDtorsForDestructor(const CXXDestructorDecl *DD); - void addScopesEnd(LocalScope::const_iterator B, LocalScope::const_iterator E, - Stmt *S); - - void getDeclsWithEndedScope(LocalScope::const_iterator B, - LocalScope::const_iterator E, Stmt *S); + void addScopeChangesHandling(LocalScope::const_iterator SrcPos, + LocalScope::const_iterator DstPos, + Stmt *S); + CFGBlock *createScopeChangesHandlingBlock(LocalScope::const_iterator SrcPos, + CFGBlock *SrcBlk, + LocalScope::const_iterator DstPost, + CFGBlock *DstBlk); // Local scopes creation. LocalScope* createOrReuseLocalScope(LocalScope* Scope); @@ -878,18 +893,6 @@ private: B->appendDeleteDtor(RD, DE, cfg->getBumpVectorContext()); } - void prependAutomaticObjDtorsWithTerminator(CFGBlock *Blk, - LocalScope::const_iterator B, LocalScope::const_iterator E); - - void prependAutomaticObjLifetimeWithTerminator(CFGBlock *Blk, - LocalScope::const_iterator B, - LocalScope::const_iterator E); - - const VarDecl * - prependAutomaticObjScopeEndWithTerminator(CFGBlock *Blk, - LocalScope::const_iterator B, - LocalScope::const_iterator E); - void addSuccessor(CFGBlock *B, CFGBlock *S, bool IsReachable = true) { B->addSuccessor(CFGBlock::AdjacentBlock(S, IsReachable), cfg->getBumpVectorContext()); @@ -907,21 +910,11 @@ private: B->appendScopeBegin(VD, S, cfg->getBumpVectorContext()); } - void prependScopeBegin(CFGBlock *B, const VarDecl *VD, const Stmt *S) { - if (BuildOpts.AddScopes) - B->prependScopeBegin(VD, S, cfg->getBumpVectorContext()); - } - void appendScopeEnd(CFGBlock *B, const VarDecl *VD, const Stmt *S) { if (BuildOpts.AddScopes) B->appendScopeEnd(VD, S, cfg->getBumpVectorContext()); } - void prependScopeEnd(CFGBlock *B, const VarDecl *VD, const Stmt *S) { - if (BuildOpts.AddScopes) - B->prependScopeEnd(VD, S, cfg->getBumpVectorContext()); - } - /// Find a relational comparison with an expression evaluating to a /// boolean and a constant other than 0 and 1. /// e.g. if ((x < y) == 10) @@ -1538,7 +1531,6 @@ void CFGBuilder::cleanupConstructionContext(Expr *E) { ConstructionContextMap.erase(E); } - /// BuildCFG - Constructs a CFG from an AST (a Stmt*). The AST can represent an /// arbitrary statement. Examples include a single expression or a function /// body (compound statement). The ownership of the returned CFG is @@ -1556,9 +1548,6 @@ std::unique_ptr CFGBuilder::buildCFG(const Decl *D, Stmt *Statement) { assert(Succ == &cfg->getExit()); Block = nullptr; // the EXIT block is empty. Create all other blocks lazily. - assert(!(BuildOpts.AddImplicitDtors && BuildOpts.AddLifetime) && - "AddImplicitDtors and AddLifetime cannot be used at the same time"); - if (BuildOpts.AddImplicitDtors) if (const CXXDestructorDecl *DD = dyn_cast_or_null(D)) addImplicitDtorsForDestructor(DD); @@ -1622,16 +1611,11 @@ std::unique_ptr CFGBuilder::buildCFG(const Decl *D, Stmt *Statement) { if (LI == LabelMap.end()) continue; JumpTarget JT = LI->second; - prependAutomaticObjLifetimeWithTerminator(B, I->scopePosition, - JT.scopePosition); - prependAutomaticObjDtorsWithTerminator(B, I->scopePosition, - JT.scopePosition); - const VarDecl *VD = prependAutomaticObjScopeEndWithTerminator( - B, I->scopePosition, JT.scopePosition); - appendScopeBegin(JT.block, VD, G); - addSuccessor(B, JT.block); - }; - if (auto *G = dyn_cast(B->getTerminator())) { + + CFGBlock *SuccBlk = createScopeChangesHandlingBlock( + I->scopePosition, B, JT.scopePosition, JT.block); + addSuccessor(B, SuccBlk); + } else if (auto *G = dyn_cast(B->getTerminator())) { CFGBlock *Successor = (I+1)->block; for (auto *L : G->labels()) { LabelMapTy::iterator LI = LabelMap.find(L->getLabel()); @@ -1798,143 +1782,195 @@ void CFGBuilder::addLoopExit(const Stmt *LoopStmt){ appendLoopExit(Block, LoopStmt); } -void CFGBuilder::getDeclsWithEndedScope(LocalScope::const_iterator B, - LocalScope::const_iterator E, Stmt *S) { - if (!BuildOpts.AddScopes) - return; - - if (B == E) - return; - - // To go from B to E, one first goes up the scopes from B to P - // then sideways in one scope from P to P' and then down - // the scopes from P' to E. - // The lifetime of all objects between B and P end. - LocalScope::const_iterator P = B.shared_parent(E); - int Dist = B.distance(P); - if (Dist <= 0) - return; - - for (LocalScope::const_iterator I = B; I != P; ++I) - if (I.pointsToFirstDeclaredVar()) - DeclsWithEndedScope.insert(*I); -} - +/// Adds the CFG elements for leaving the scope of automatic objects in +/// range [B, E). This include following: +/// * AutomaticObjectDtor for variables with non-trivial destructor +/// * LifetimeEnds for all variables +/// * ScopeEnd for each scope left void CFGBuilder::addAutomaticObjHandling(LocalScope::const_iterator B, LocalScope::const_iterator E, Stmt *S) { - getDeclsWithEndedScope(B, E, S); - if (BuildOpts.AddScopes) - addScopesEnd(B, E, S); - if (BuildOpts.AddImplicitDtors) - addAutomaticObjDtors(B, E, S); - if (BuildOpts.AddLifetime) - addLifetimeEnds(B, E, S); -} - -/// Add to current block automatic objects that leave the scope. -void CFGBuilder::addLifetimeEnds(LocalScope::const_iterator B, - LocalScope::const_iterator E, Stmt *S) { - if (!BuildOpts.AddLifetime) + if (!BuildOpts.AddScopes && !BuildOpts.AddImplicitDtors && + !BuildOpts.AddLifetime) return; if (B == E) return; - // To go from B to E, one first goes up the scopes from B to P - // then sideways in one scope from P to P' and then down - // the scopes from P' to E. - // The lifetime of all objects between B and P end. - LocalScope::const_iterator P = B.shared_parent(E); - int dist = B.distance(P); - if (dist <= 0) + // Not leaving the scope, only need to handle destruction and lifetime + if (B.inSameLocalScope(E)) { + addAutomaticObjDestruction(B, E, S); + return; + } + + // Extract information about all local scopes that are left + SmallVector LocalScopeEndMarkers; + LocalScopeEndMarkers.push_back(B); + for (LocalScope::const_iterator I = B; I != E; ++I) { + if (!I.inSameLocalScope(LocalScopeEndMarkers.back())) + LocalScopeEndMarkers.push_back(I); + } + LocalScopeEndMarkers.push_back(E); + + // We need to leave the scope in reverse order, so we reverse the end + // markers + std::reverse(LocalScopeEndMarkers.begin(), LocalScopeEndMarkers.end()); + auto Pairwise = + llvm::zip(LocalScopeEndMarkers, llvm::drop_begin(LocalScopeEndMarkers)); + for (auto [E, B] : Pairwise) { + if (!B.inSameLocalScope(E)) + addScopeExitHandling(B, E, S); + addAutomaticObjDestruction(B, E, S); + } +} + +/// Add CFG elements corresponding to call destructor and end of lifetime +/// of all automatic variables with non-trivial destructor in range [B, E). +/// This include AutomaticObjectDtor and LifetimeEnds elements. +void CFGBuilder::addAutomaticObjDestruction(LocalScope::const_iterator B, + LocalScope::const_iterator E, + Stmt *S) { + if (!BuildOpts.AddImplicitDtors && !BuildOpts.AddLifetime) + return; + + if (B == E) + return; + + SmallVector DeclsNonTrivial; + DeclsNonTrivial.reserve(B.distance(E)); + + for (VarDecl* D : llvm::make_range(B, E)) + if (!hasTrivialDestructor(D)) + DeclsNonTrivial.push_back(D); + + for (VarDecl *VD : llvm::reverse(DeclsNonTrivial)) { + if (BuildOpts.AddImplicitDtors) { + // If this destructor is marked as a no-return destructor, we need to + // create a new block for the destructor which does not have as a + // successor anything built thus far: control won't flow out of this + // block. + QualType Ty = VD->getType(); + if (Ty->isReferenceType()) + Ty = getReferenceInitTemporaryType(VD->getInit()); + Ty = Context->getBaseElementType(Ty); + + if (Ty->getAsCXXRecordDecl()->isAnyDestructorNoReturn()) + Block = createNoReturnBlock(); + } + + autoCreateBlock(); + + // Add LifetimeEnd after automatic obj with non-trivial destructors, + // as they end their lifetime when the destructor returns. For trivial + // objects, we end lifetime with scope end. + if (BuildOpts.AddLifetime) + appendLifetimeEnds(Block, VD, S); + if (BuildOpts.AddImplicitDtors) + appendAutomaticObjDtor(Block, VD, S); + } +} + +/// Add CFG elements corresponding to leaving a scope. +/// Assumes that range [B, E) corresponds to single scope. +/// This add following elements: +/// * LifetimeEnds for all variables with non-trivial destructor +/// * ScopeEnd for each scope left +void CFGBuilder::addScopeExitHandling(LocalScope::const_iterator B, + LocalScope::const_iterator E, Stmt *S) { + assert(!B.inSameLocalScope(E)); + if (!BuildOpts.AddLifetime && !BuildOpts.AddScopes) + return; + + if (BuildOpts.AddScopes) { + autoCreateBlock(); + appendScopeEnd(Block, B.getFirstVarInScope(), S); + } + + if (!BuildOpts.AddLifetime) return; // We need to perform the scope leaving in reverse order SmallVector DeclsTrivial; - SmallVector DeclsNonTrivial; - DeclsTrivial.reserve(dist); - DeclsNonTrivial.reserve(dist); + DeclsTrivial.reserve(B.distance(E)); - for (LocalScope::const_iterator I = B; I != P; ++I) - if (hasTrivialDestructor(*I)) - DeclsTrivial.push_back(*I); - else - DeclsNonTrivial.push_back(*I); + // Objects with trivial destructor ends their lifetime when their storage + // is destroyed, for automatic variables, this happens when the end of the + // scope is added. + for (VarDecl* D : llvm::make_range(B, E)) + if (hasTrivialDestructor(D)) + DeclsTrivial.push_back(D); + + if (DeclsTrivial.empty()) + return; autoCreateBlock(); - // object with trivial destructor end their lifetime last (when storage - // duration ends) for (VarDecl *VD : llvm::reverse(DeclsTrivial)) appendLifetimeEnds(Block, VD, S); - - for (VarDecl *VD : llvm::reverse(DeclsNonTrivial)) - appendLifetimeEnds(Block, VD, S); } -/// Add to current block markers for ending scopes. -void CFGBuilder::addScopesEnd(LocalScope::const_iterator B, - LocalScope::const_iterator E, Stmt *S) { - // If implicit destructors are enabled, we'll add scope ends in - // addAutomaticObjDtors. - if (BuildOpts.AddImplicitDtors) +/// addScopeChangesHandling - appends information about destruction, lifetime +/// and cfgScopeEnd for variables in the scope that was left by the jump, and +/// appends cfgScopeBegin for all scopes that where entered. +/// We insert the cfgScopeBegin at the end of the jump node, as depending on +/// the sourceBlock, each goto, may enter different amount of scopes. +void CFGBuilder::addScopeChangesHandling(LocalScope::const_iterator SrcPos, + LocalScope::const_iterator DstPos, + Stmt *S) { + assert(Block && "Source block should be always crated"); + if (!BuildOpts.AddImplicitDtors && !BuildOpts.AddLifetime && + !BuildOpts.AddScopes) { return; - - autoCreateBlock(); - - for (VarDecl *VD : llvm::reverse(DeclsWithEndedScope)) - appendScopeEnd(Block, VD, S); -} - -/// addAutomaticObjDtors - Add to current block automatic objects destructors -/// for objects in range of local scope positions. Use S as trigger statement -/// for destructors. -void CFGBuilder::addAutomaticObjDtors(LocalScope::const_iterator B, - LocalScope::const_iterator E, Stmt *S) { - if (!BuildOpts.AddImplicitDtors) - return; - - if (B == E) - return; - - // We need to append the destructors in reverse order, but any one of them - // may be a no-return destructor which changes the CFG. As a result, buffer - // this sequence up and replay them in reverse order when appending onto the - // CFGBlock(s). - SmallVector Decls; - Decls.reserve(B.distance(E)); - for (LocalScope::const_iterator I = B; I != E; ++I) - Decls.push_back(*I); - - for (VarDecl *VD : llvm::reverse(Decls)) { - if (hasTrivialDestructor(VD)) { - // If AddScopes is enabled and *I is a first variable in a scope, add a - // ScopeEnd marker in a Block. - if (BuildOpts.AddScopes && DeclsWithEndedScope.count(VD)) { - autoCreateBlock(); - appendScopeEnd(Block, VD, S); - } - continue; - } - // If this destructor is marked as a no-return destructor, we need to - // create a new block for the destructor which does not have as a successor - // anything built thus far: control won't flow out of this block. - QualType Ty = VD->getType(); - if (Ty->isReferenceType()) { - Ty = getReferenceInitTemporaryType(VD->getInit()); - } - Ty = Context->getBaseElementType(Ty); - - if (Ty->getAsCXXRecordDecl()->isAnyDestructorNoReturn()) - Block = createNoReturnBlock(); - else - autoCreateBlock(); - - // Add ScopeEnd just after automatic obj destructor. - if (BuildOpts.AddScopes && DeclsWithEndedScope.count(VD)) - appendScopeEnd(Block, VD, S); - appendAutomaticObjDtor(Block, VD, S); } + + if (SrcPos == DstPos) + return; + + // Get common scope, the jump leaves all scopes [SrcPos, BasePos), and + // enter all scopes between [DstPos, BasePos) + LocalScope::const_iterator BasePos = SrcPos.shared_parent(DstPos); + + // Append scope begins for scopes entered by goto + if (BuildOpts.AddScopes && !DstPos.inSameLocalScope(BasePos)) { + for (LocalScope::const_iterator I = DstPos; I != BasePos; ++I) + if (I.pointsToFirstDeclaredVar()) + appendScopeBegin(Block, *I, S); + } + + // Append scopeEnds, destructor and lifetime with the terminator for + // block left by goto. + addAutomaticObjHandling(SrcPos, BasePos, S); +} + +/// createScopeChangesHandlingBlock - Creates a block with cfgElements +/// corresponding to changing the scope from the source scope of the GotoStmt, +/// to destination scope. Add destructor, lifetime and cfgScopeEnd +/// CFGElements to newly created CFGBlock, that will have the CFG terminator +/// transferred. +CFGBlock *CFGBuilder::createScopeChangesHandlingBlock( + LocalScope::const_iterator SrcPos, CFGBlock *SrcBlk, + LocalScope::const_iterator DstPos, CFGBlock *DstBlk) { + if (SrcPos == DstPos) + return DstBlk; + + if (!BuildOpts.AddImplicitDtors && !BuildOpts.AddLifetime && + (!BuildOpts.AddScopes || SrcPos.inSameLocalScope(DstPos))) + return DstBlk; + + // We will update CFBBuilder when creating new block, restore the + // previous state at exit. + SaveAndRestore save_Block(Block), save_Succ(Succ); + + // Create a new block, and transfer terminator + Block = createBlock(false); + Block->setTerminator(SrcBlk->getTerminator()); + SrcBlk->setTerminator(CFGTerminator()); + addSuccessor(Block, DstBlk); + + // Fill the created Block with the required elements. + addScopeChangesHandling(SrcPos, DstPos, Block->getTerminatorStmt()); + + assert(Block && "There should be at least one scope changing Block"); + return Block; } /// addImplicitDtorsForDestructor - Add implicit destructors generated for @@ -1992,8 +2028,7 @@ LocalScope* CFGBuilder::createOrReuseLocalScope(LocalScope* Scope) { if (Scope) return Scope; llvm::BumpPtrAllocator &alloc = cfg->getAllocator(); - return new (alloc.Allocate()) - LocalScope(BumpVectorContext(alloc), ScopePos); + return new (alloc) LocalScope(BumpVectorContext(alloc), ScopePos); } /// addLocalScopeForStmt - Add LocalScope to local scopes tree for statement @@ -2080,8 +2115,6 @@ bool CFGBuilder::hasTrivialDestructor(VarDecl *VD) { /// const reference. Will reuse Scope if not NULL. LocalScope* CFGBuilder::addLocalScopeForVarDecl(VarDecl *VD, LocalScope* Scope) { - assert(!(BuildOpts.AddImplicitDtors && BuildOpts.AddLifetime) && - "AddImplicitDtors and AddLifetime cannot be used at the same time"); if (!BuildOpts.AddImplicitDtors && !BuildOpts.AddLifetime && !BuildOpts.AddScopes) return Scope; @@ -2090,17 +2123,12 @@ LocalScope* CFGBuilder::addLocalScopeForVarDecl(VarDecl *VD, if (!VD->hasLocalStorage()) return Scope; - if (BuildOpts.AddImplicitDtors) { - if (!hasTrivialDestructor(VD) || BuildOpts.AddScopes) { - // Add the variable to scope - Scope = createOrReuseLocalScope(Scope); - Scope->addVar(VD); - ScopePos = Scope->begin(); - } + if (!BuildOpts.AddLifetime && !BuildOpts.AddScopes && + hasTrivialDestructor(VD)) { + assert(BuildOpts.AddImplicitDtors); return Scope; } - assert(BuildOpts.AddLifetime); // Add the variable to scope Scope = createOrReuseLocalScope(Scope); Scope->addVar(VD); @@ -2116,63 +2144,6 @@ void CFGBuilder::addLocalScopeAndDtors(Stmt *S) { addAutomaticObjHandling(ScopePos, scopeBeginPos, S); } -/// prependAutomaticObjDtorsWithTerminator - Prepend destructor CFGElements for -/// variables with automatic storage duration to CFGBlock's elements vector. -/// Elements will be prepended to physical beginning of the vector which -/// happens to be logical end. Use blocks terminator as statement that specifies -/// destructors call site. -/// FIXME: This mechanism for adding automatic destructors doesn't handle -/// no-return destructors properly. -void CFGBuilder::prependAutomaticObjDtorsWithTerminator(CFGBlock *Blk, - LocalScope::const_iterator B, LocalScope::const_iterator E) { - if (!BuildOpts.AddImplicitDtors) - return; - BumpVectorContext &C = cfg->getBumpVectorContext(); - CFGBlock::iterator InsertPos - = Blk->beginAutomaticObjDtorsInsert(Blk->end(), B.distance(E), C); - for (LocalScope::const_iterator I = B; I != E; ++I) - InsertPos = Blk->insertAutomaticObjDtor(InsertPos, *I, - Blk->getTerminatorStmt()); -} - -/// prependAutomaticObjLifetimeWithTerminator - Prepend lifetime CFGElements for -/// variables with automatic storage duration to CFGBlock's elements vector. -/// Elements will be prepended to physical beginning of the vector which -/// happens to be logical end. Use blocks terminator as statement that specifies -/// where lifetime ends. -void CFGBuilder::prependAutomaticObjLifetimeWithTerminator( - CFGBlock *Blk, LocalScope::const_iterator B, LocalScope::const_iterator E) { - if (!BuildOpts.AddLifetime) - return; - BumpVectorContext &C = cfg->getBumpVectorContext(); - CFGBlock::iterator InsertPos = - Blk->beginLifetimeEndsInsert(Blk->end(), B.distance(E), C); - for (LocalScope::const_iterator I = B; I != E; ++I) { - InsertPos = - Blk->insertLifetimeEnds(InsertPos, *I, Blk->getTerminatorStmt()); - } -} - -/// prependAutomaticObjScopeEndWithTerminator - Prepend scope end CFGElements for -/// variables with automatic storage duration to CFGBlock's elements vector. -/// Elements will be prepended to physical beginning of the vector which -/// happens to be logical end. Use blocks terminator as statement that specifies -/// where scope ends. -const VarDecl * -CFGBuilder::prependAutomaticObjScopeEndWithTerminator( - CFGBlock *Blk, LocalScope::const_iterator B, LocalScope::const_iterator E) { - if (!BuildOpts.AddScopes) - return nullptr; - BumpVectorContext &C = cfg->getBumpVectorContext(); - CFGBlock::iterator InsertPos = - Blk->beginScopeEndInsert(Blk->end(), 1, C); - LocalScope::const_iterator PlaceToInsert = B; - for (LocalScope::const_iterator I = B; I != E; ++I) - PlaceToInsert = I; - Blk->insertScopeEnd(InsertPos, *PlaceToInsert, Blk->getTerminatorStmt()); - return *PlaceToInsert; -} - /// Visit - Walk the subtree of a statement and add extra /// blocks for ternary operators, &&, and ||. We also process "," and /// DeclStmts (which may contain nested control-flow). @@ -3387,8 +3358,7 @@ CFGBlock *CFGBuilder::VisitLabelStmt(LabelStmt *L) { if (!LabelBlock) // This can happen when the body is empty, i.e. LabelBlock = createBlock(); // scopes that only contains NullStmts. - assert(LabelMap.find(L->getDecl()) == LabelMap.end() && - "label already in map"); + assert(!LabelMap.contains(L->getDecl()) && "label already in map"); LabelMap[L->getDecl()] = JumpTarget(LabelBlock, ScopePos); // Labels partition blocks, so this is the end of the basic block we were @@ -3460,8 +3430,8 @@ CFGBlock *CFGBuilder::VisitGotoStmt(GotoStmt *G) { BackpatchBlocks.push_back(JumpSource(Block, ScopePos)); else { JumpTarget JT = I->second; - addAutomaticObjHandling(ScopePos, JT.scopePosition, G); addSuccessor(Block, JT.block); + addScopeChangesHandling(ScopePos, JT.scopePosition, G); } return Block; @@ -3541,6 +3511,11 @@ CFGBlock *CFGBuilder::VisitForStmt(ForStmt *F) { Block = Succ = TransitionBlock = createBlock(false); TransitionBlock->setLoopTarget(F); + + // Loop iteration (after increment) should end with destructor of Condition + // variable (if any). + addAutomaticObjHandling(ScopePos, LoopBeginScopePos, F); + if (Stmt *I = F->getInc()) { // Generate increment code in its own basic block. This is the target of // continue statements. @@ -3560,8 +3535,6 @@ CFGBlock *CFGBuilder::VisitForStmt(ForStmt *F) { ContinueJumpTarget = JumpTarget(Succ, ContinueScopePos); ContinueJumpTarget.block->setLoopTarget(F); - // Loop body should end with destructor of Condition variable (if any). - addAutomaticObjHandling(ScopePos, LoopBeginScopePos, F); // If body is not a compound statement create implicit scope // and add destructors. @@ -4155,7 +4128,7 @@ CFGBlock *CFGBuilder::VisitCXXTypeidExpr(CXXTypeidExpr *S, AddStmtChoice asc) { // operand. [...] // We add only potentially evaluated statements to the block to avoid // CFG generation for unevaluated operands. - if (S && !S->isTypeDependent() && S->isPotentiallyEvaluated()) + if (!S->isTypeDependent() && S->isPotentiallyEvaluated()) return VisitChildren(S); // Return block without CFG for unevaluated operands. @@ -5215,8 +5188,7 @@ CFGBlock *CFG::createBlock() { bool first_block = begin() == end(); // Create the block. - CFGBlock *Mem = getAllocator().Allocate(); - new (Mem) CFGBlock(NumBlockIDs++, BlkBVC, this); + CFGBlock *Mem = new (getAllocator()) CFGBlock(NumBlockIDs++, BlkBVC, this); Blocks.push_back(Mem, BlkBVC); // If this is the first block, set it as the Entry and Exit. @@ -5748,7 +5720,8 @@ static void print_elem(raw_ostream &OS, StmtPrinterHelper &Helper, const CFGElement &E); void CFGElement::dumpToStream(llvm::raw_ostream &OS) const { - StmtPrinterHelper Helper(nullptr, {}); + LangOptions LangOpts; + StmtPrinterHelper Helper(nullptr, LangOpts); print_elem(OS, Helper, *this); } diff --git a/contrib/llvm-project/clang/lib/Analysis/ExprMutationAnalyzer.cpp b/contrib/llvm-project/clang/lib/Analysis/ExprMutationAnalyzer.cpp index c876eaa6358..90803830ff4 100644 --- a/contrib/llvm-project/clang/lib/Analysis/ExprMutationAnalyzer.cpp +++ b/contrib/llvm-project/clang/lib/Analysis/ExprMutationAnalyzer.cpp @@ -102,6 +102,8 @@ AST_MATCHER(CXXTypeidExpr, isPotentiallyEvaluated) { AST_MATCHER_P(GenericSelectionExpr, hasControllingExpr, ast_matchers::internal::Matcher, InnerMatcher) { + if (Node.isTypePredicate()) + return false; return InnerMatcher.matches(*Node.getControllingExpr(), Finder, Builder); } @@ -605,7 +607,7 @@ FunctionParmMutationAnalyzer::FunctionParmMutationAnalyzer( for (const CXXCtorInitializer *Init : Ctor->inits()) { ExprMutationAnalyzer InitAnalyzer(*Init->getInit(), Context); for (const ParmVarDecl *Parm : Ctor->parameters()) { - if (Results.find(Parm) != Results.end()) + if (Results.contains(Parm)) continue; if (const Stmt *S = InitAnalyzer.findMutation(Parm)) Results[Parm] = S; diff --git a/contrib/llvm-project/clang/lib/Analysis/FlowSensitive/Arena.cpp b/contrib/llvm-project/clang/lib/Analysis/FlowSensitive/Arena.cpp new file mode 100644 index 00000000000..a12da2d9b55 --- /dev/null +++ b/contrib/llvm-project/clang/lib/Analysis/FlowSensitive/Arena.cpp @@ -0,0 +1,98 @@ +//===-- Arena.cpp ---------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#include "clang/Analysis/FlowSensitive/Arena.h" +#include "clang/Analysis/FlowSensitive/Value.h" + +namespace clang::dataflow { + +static std::pair +canonicalFormulaPair(const Formula &LHS, const Formula &RHS) { + auto Res = std::make_pair(&LHS, &RHS); + if (&RHS < &LHS) // FIXME: use a deterministic order instead + std::swap(Res.first, Res.second); + return Res; +} + +const Formula &Arena::makeAtomRef(Atom A) { + auto [It, Inserted] = AtomRefs.try_emplace(A); + if (Inserted) + It->second = + &Formula::create(Alloc, Formula::AtomRef, {}, static_cast(A)); + return *It->second; +} + +const Formula &Arena::makeAnd(const Formula &LHS, const Formula &RHS) { + if (&LHS == &RHS) + return LHS; + + auto [It, Inserted] = + Ands.try_emplace(canonicalFormulaPair(LHS, RHS), nullptr); + if (Inserted) + It->second = &Formula::create(Alloc, Formula::And, {&LHS, &RHS}); + return *It->second; +} + +const Formula &Arena::makeOr(const Formula &LHS, const Formula &RHS) { + if (&LHS == &RHS) + return LHS; + + auto [It, Inserted] = + Ors.try_emplace(canonicalFormulaPair(LHS, RHS), nullptr); + if (Inserted) + It->second = &Formula::create(Alloc, Formula::Or, {&LHS, &RHS}); + return *It->second; +} + +const Formula &Arena::makeNot(const Formula &Val) { + auto [It, Inserted] = Nots.try_emplace(&Val, nullptr); + if (Inserted) + It->second = &Formula::create(Alloc, Formula::Not, {&Val}); + return *It->second; +} + +const Formula &Arena::makeImplies(const Formula &LHS, const Formula &RHS) { + if (&LHS == &RHS) + return makeLiteral(true); + + auto [It, Inserted] = + Implies.try_emplace(std::make_pair(&LHS, &RHS), nullptr); + if (Inserted) + It->second = &Formula::create(Alloc, Formula::Implies, {&LHS, &RHS}); + return *It->second; +} + +const Formula &Arena::makeEquals(const Formula &LHS, const Formula &RHS) { + if (&LHS == &RHS) + return makeLiteral(true); + + auto [It, Inserted] = + Equals.try_emplace(canonicalFormulaPair(LHS, RHS), nullptr); + if (Inserted) + It->second = &Formula::create(Alloc, Formula::Equal, {&LHS, &RHS}); + return *It->second; +} + +IntegerValue &Arena::makeIntLiteral(llvm::APInt Value) { + auto [It, Inserted] = IntegerLiterals.try_emplace(Value, nullptr); + + if (Inserted) + It->second = &create(); + return *It->second; +} + +BoolValue &Arena::makeBoolValue(const Formula &F) { + auto [It, Inserted] = FormulaValues.try_emplace(&F); + if (Inserted) + It->second = (F.kind() == Formula::AtomRef) + ? (BoolValue *)&create(F) + : &create(F); + return *It->second; +} + +} // namespace clang::dataflow diff --git a/contrib/llvm-project/clang/lib/Analysis/FlowSensitive/ControlFlowContext.cpp b/contrib/llvm-project/clang/lib/Analysis/FlowSensitive/ControlFlowContext.cpp index 2492b520372..c80525dc4f3 100644 --- a/contrib/llvm-project/clang/lib/Analysis/FlowSensitive/ControlFlowContext.cpp +++ b/contrib/llvm-project/clang/lib/Analysis/FlowSensitive/ControlFlowContext.cpp @@ -16,6 +16,7 @@ #include "clang/AST/Decl.h" #include "clang/AST/Stmt.h" #include "clang/Analysis/CFG.h" +#include "llvm/ADT/BitVector.h" #include "llvm/ADT/DenseMap.h" #include "llvm/Support/Error.h" #include @@ -44,10 +45,47 @@ buildStmtToBasicBlockMap(const CFG &Cfg) { return StmtToBlock; } +static llvm::BitVector findReachableBlocks(const CFG &Cfg) { + llvm::BitVector BlockReachable(Cfg.getNumBlockIDs(), false); + + llvm::SmallVector BlocksToVisit; + BlocksToVisit.push_back(&Cfg.getEntry()); + while (!BlocksToVisit.empty()) { + const CFGBlock *Block = BlocksToVisit.back(); + BlocksToVisit.pop_back(); + + if (BlockReachable[Block->getBlockID()]) + continue; + + BlockReachable[Block->getBlockID()] = true; + + for (const CFGBlock *Succ : Block->succs()) + if (Succ) + BlocksToVisit.push_back(Succ); + } + + return BlockReachable; +} + llvm::Expected -ControlFlowContext::build(const Decl *D, Stmt &S, ASTContext &C) { +ControlFlowContext::build(const FunctionDecl &Func) { + if (!Func.hasBody()) + return llvm::createStringError( + std::make_error_code(std::errc::invalid_argument), + "Cannot analyze function without a body"); + + return build(Func, *Func.getBody(), Func.getASTContext()); +} + +llvm::Expected +ControlFlowContext::build(const Decl &D, Stmt &S, ASTContext &C) { + if (D.isTemplated()) + return llvm::createStringError( + std::make_error_code(std::errc::invalid_argument), + "Cannot analyze templated declarations"); + CFG::BuildOptions Options; - Options.PruneTriviallyFalseEdges = false; + Options.PruneTriviallyFalseEdges = true; Options.AddImplicitDtors = true; Options.AddTemporaryDtors = true; Options.AddInitializers = true; @@ -56,7 +94,7 @@ ControlFlowContext::build(const Decl *D, Stmt &S, ASTContext &C) { // Ensure that all sub-expressions in basic blocks are evaluated. Options.setAllAlwaysAdd(); - auto Cfg = CFG::buildCFG(D, &S, &C, Options); + auto Cfg = CFG::buildCFG(&D, &S, &C, Options); if (Cfg == nullptr) return llvm::createStringError( std::make_error_code(std::errc::invalid_argument), @@ -64,7 +102,21 @@ ControlFlowContext::build(const Decl *D, Stmt &S, ASTContext &C) { llvm::DenseMap StmtToBlock = buildStmtToBasicBlockMap(*Cfg); - return ControlFlowContext(D, std::move(Cfg), std::move(StmtToBlock)); + + llvm::BitVector BlockReachable = findReachableBlocks(*Cfg); + + return ControlFlowContext(&D, std::move(Cfg), std::move(StmtToBlock), + std::move(BlockReachable)); +} + +llvm::Expected +ControlFlowContext::build(const Decl *D, Stmt &S, ASTContext &C) { + if (D == nullptr) + return llvm::createStringError( + std::make_error_code(std::errc::invalid_argument), + "Declaration must not be null"); + + return build(*D, S, C); } } // namespace dataflow diff --git a/contrib/llvm-project/clang/lib/Analysis/FlowSensitive/DataflowAnalysisContext.cpp b/contrib/llvm-project/clang/lib/Analysis/FlowSensitive/DataflowAnalysisContext.cpp index 480606bdac8..9f72dc8f6ab 100644 --- a/contrib/llvm-project/clang/lib/Analysis/FlowSensitive/DataflowAnalysisContext.cpp +++ b/contrib/llvm-project/clang/lib/Analysis/FlowSensitive/DataflowAnalysisContext.cpp @@ -15,54 +15,68 @@ #include "clang/Analysis/FlowSensitive/DataflowAnalysisContext.h" #include "clang/AST/ExprCXX.h" #include "clang/Analysis/FlowSensitive/DebugSupport.h" +#include "clang/Analysis/FlowSensitive/Formula.h" +#include "clang/Analysis/FlowSensitive/Logger.h" #include "clang/Analysis/FlowSensitive/Value.h" #include "llvm/ADT/SetOperations.h" +#include "llvm/ADT/SetVector.h" +#include "llvm/Support/CommandLine.h" #include "llvm/Support/Debug.h" +#include "llvm/Support/FileSystem.h" +#include "llvm/Support/Path.h" +#include "llvm/Support/raw_ostream.h" #include #include +#include #include +#include + +static llvm::cl::opt DataflowLog( + "dataflow-log", llvm::cl::Hidden, llvm::cl::ValueOptional, + llvm::cl::desc("Emit log of dataflow analysis. With no arg, writes textual " + "log to stderr. With an arg, writes HTML logs under the " + "specified directory (one per analyzed function).")); namespace clang { namespace dataflow { -void DataflowAnalysisContext::addModeledFields( - const llvm::DenseSet &Fields) { - llvm::set_union(ModeledFields, Fields); +FieldSet DataflowAnalysisContext::getModeledFields(QualType Type) { + // During context-sensitive analysis, a struct may be allocated in one + // function, but its field accessed in a function lower in the stack than + // the allocation. Since we only collect fields used in the function where + // the allocation occurs, we can't apply that filter when performing + // context-sensitive analysis. But, this only applies to storage locations, + // since field access it not allowed to fail. In contrast, field *values* + // don't need this allowance, since the API allows for uninitialized fields. + if (Opts.ContextSensitiveOpts) + return getObjectFields(Type); + + return llvm::set_intersection(getObjectFields(Type), ModeledFields); } -llvm::DenseSet -DataflowAnalysisContext::getReferencedFields(QualType Type) { - llvm::DenseSet Fields = getObjectFields(Type); - llvm::set_intersect(Fields, ModeledFields); - return Fields; +void DataflowAnalysisContext::addModeledFields(const FieldSet &Fields) { + ModeledFields.set_union(Fields); } StorageLocation &DataflowAnalysisContext::createStorageLocation(QualType Type) { - if (!Type.isNull() && - (Type->isStructureOrClassType() || Type->isUnionType())) { + if (!Type.isNull() && Type->isRecordType()) { llvm::DenseMap FieldLocs; - // During context-sensitive analysis, a struct may be allocated in one - // function, but its field accessed in a function lower in the stack than - // the allocation. Since we only collect fields used in the function where - // the allocation occurs, we can't apply that filter when performing - // context-sensitive analysis. But, this only applies to storage locations, - // since field access it not allowed to fail. In contrast, field *values* - // don't need this allowance, since the API allows for uninitialized fields. - auto Fields = Opts.ContextSensitiveOpts ? getObjectFields(Type) - : getReferencedFields(Type); - for (const FieldDecl *Field : Fields) - FieldLocs.insert({Field, &createStorageLocation(Field->getType())}); - return takeOwnership( - std::make_unique(Type, std::move(FieldLocs))); + for (const FieldDecl *Field : getModeledFields(Type)) + if (Field->getType()->isReferenceType()) + FieldLocs.insert({Field, nullptr}); + else + FieldLocs.insert({Field, &createStorageLocation( + Field->getType().getNonReferenceType())}); + return arena().create(Type, std::move(FieldLocs)); } - return takeOwnership(std::make_unique(Type)); + return arena().create(Type); } StorageLocation & DataflowAnalysisContext::getStableStorageLocation(const VarDecl &D) { if (auto *Loc = getStorageLocation(D)) return *Loc; - auto &Loc = createStorageLocation(D.getType()); + auto &Loc = createStorageLocation(D.getType().getNonReferenceType()); setStorageLocation(D, Loc); return Loc; } @@ -83,275 +97,120 @@ DataflowAnalysisContext::getOrCreateNullPointerValue(QualType PointeeType) { auto Res = NullPointerVals.try_emplace(CanonicalPointeeType, nullptr); if (Res.second) { auto &PointeeLoc = createStorageLocation(CanonicalPointeeType); - Res.first->second = - &takeOwnership(std::make_unique(PointeeLoc)); + Res.first->second = &arena().create(PointeeLoc); } return *Res.first->second; } -static std::pair -makeCanonicalBoolValuePair(BoolValue &LHS, BoolValue &RHS) { - auto Res = std::make_pair(&LHS, &RHS); - if (&RHS < &LHS) - std::swap(Res.first, Res.second); - return Res; -} - -BoolValue &DataflowAnalysisContext::getOrCreateConjunction(BoolValue &LHS, - BoolValue &RHS) { - if (&LHS == &RHS) - return LHS; - - auto Res = ConjunctionVals.try_emplace(makeCanonicalBoolValuePair(LHS, RHS), - nullptr); - if (Res.second) - Res.first->second = - &takeOwnership(std::make_unique(LHS, RHS)); - return *Res.first->second; -} - -BoolValue &DataflowAnalysisContext::getOrCreateDisjunction(BoolValue &LHS, - BoolValue &RHS) { - if (&LHS == &RHS) - return LHS; - - auto Res = DisjunctionVals.try_emplace(makeCanonicalBoolValuePair(LHS, RHS), - nullptr); - if (Res.second) - Res.first->second = - &takeOwnership(std::make_unique(LHS, RHS)); - return *Res.first->second; -} - -BoolValue &DataflowAnalysisContext::getOrCreateNegation(BoolValue &Val) { - auto Res = NegationVals.try_emplace(&Val, nullptr); - if (Res.second) - Res.first->second = &takeOwnership(std::make_unique(Val)); - return *Res.first->second; -} - -BoolValue &DataflowAnalysisContext::getOrCreateImplication(BoolValue &LHS, - BoolValue &RHS) { - if (&LHS == &RHS) - return getBoolLiteralValue(true); - - auto Res = ImplicationVals.try_emplace(std::make_pair(&LHS, &RHS), nullptr); - if (Res.second) - Res.first->second = - &takeOwnership(std::make_unique(LHS, RHS)); - return *Res.first->second; -} - -BoolValue &DataflowAnalysisContext::getOrCreateIff(BoolValue &LHS, - BoolValue &RHS) { - if (&LHS == &RHS) - return getBoolLiteralValue(true); - - auto Res = BiconditionalVals.try_emplace(makeCanonicalBoolValuePair(LHS, RHS), - nullptr); - if (Res.second) - Res.first->second = - &takeOwnership(std::make_unique(LHS, RHS)); - return *Res.first->second; -} - -AtomicBoolValue &DataflowAnalysisContext::makeFlowConditionToken() { - return createAtomicBoolValue(); -} - void DataflowAnalysisContext::addFlowConditionConstraint( - AtomicBoolValue &Token, BoolValue &Constraint) { - auto Res = FlowConditionConstraints.try_emplace(&Token, &Constraint); + Atom Token, const Formula &Constraint) { + auto Res = FlowConditionConstraints.try_emplace(Token, &Constraint); if (!Res.second) { - Res.first->second = &getOrCreateConjunction(*Res.first->second, Constraint); + Res.first->second = + &arena().makeAnd(*Res.first->second, Constraint); } } -AtomicBoolValue & -DataflowAnalysisContext::forkFlowCondition(AtomicBoolValue &Token) { - auto &ForkToken = makeFlowConditionToken(); - FlowConditionDeps[&ForkToken].insert(&Token); - addFlowConditionConstraint(ForkToken, Token); +Atom DataflowAnalysisContext::forkFlowCondition(Atom Token) { + Atom ForkToken = arena().makeFlowConditionToken(); + FlowConditionDeps[ForkToken].insert(Token); + addFlowConditionConstraint(ForkToken, arena().makeAtomRef(Token)); return ForkToken; } -AtomicBoolValue & -DataflowAnalysisContext::joinFlowConditions(AtomicBoolValue &FirstToken, - AtomicBoolValue &SecondToken) { - auto &Token = makeFlowConditionToken(); - FlowConditionDeps[&Token].insert(&FirstToken); - FlowConditionDeps[&Token].insert(&SecondToken); +Atom +DataflowAnalysisContext::joinFlowConditions(Atom FirstToken, + Atom SecondToken) { + Atom Token = arena().makeFlowConditionToken(); + FlowConditionDeps[Token].insert(FirstToken); + FlowConditionDeps[Token].insert(SecondToken); addFlowConditionConstraint(Token, - getOrCreateDisjunction(FirstToken, SecondToken)); + arena().makeOr(arena().makeAtomRef(FirstToken), + arena().makeAtomRef(SecondToken))); return Token; } -Solver::Result -DataflowAnalysisContext::querySolver(llvm::DenseSet Constraints) { - Constraints.insert(&getBoolLiteralValue(true)); - Constraints.insert(&getOrCreateNegation(getBoolLiteralValue(false))); - return S->solve(std::move(Constraints)); +Solver::Result DataflowAnalysisContext::querySolver( + llvm::SetVector Constraints) { + Constraints.insert(&arena().makeLiteral(true)); + Constraints.insert(&arena().makeNot(arena().makeLiteral(false))); + return S->solve(Constraints.getArrayRef()); } -bool DataflowAnalysisContext::flowConditionImplies(AtomicBoolValue &Token, - BoolValue &Val) { +bool DataflowAnalysisContext::flowConditionImplies(Atom Token, + const Formula &Val) { // Returns true if and only if truth assignment of the flow condition implies // that `Val` is also true. We prove whether or not this property holds by // reducing the problem to satisfiability checking. In other words, we attempt // to show that assuming `Val` is false makes the constraints induced by the // flow condition unsatisfiable. - llvm::DenseSet Constraints = {&Token, &getOrCreateNegation(Val)}; - llvm::DenseSet VisitedTokens; + llvm::SetVector Constraints; + Constraints.insert(&arena().makeAtomRef(Token)); + Constraints.insert(&arena().makeNot(Val)); + llvm::DenseSet VisitedTokens; addTransitiveFlowConditionConstraints(Token, Constraints, VisitedTokens); return isUnsatisfiable(std::move(Constraints)); } -bool DataflowAnalysisContext::flowConditionIsTautology(AtomicBoolValue &Token) { +bool DataflowAnalysisContext::flowConditionIsTautology(Atom Token) { // Returns true if and only if we cannot prove that the flow condition can // ever be false. - llvm::DenseSet Constraints = {&getOrCreateNegation(Token)}; - llvm::DenseSet VisitedTokens; + llvm::SetVector Constraints; + Constraints.insert(&arena().makeNot(arena().makeAtomRef(Token))); + llvm::DenseSet VisitedTokens; addTransitiveFlowConditionConstraints(Token, Constraints, VisitedTokens); return isUnsatisfiable(std::move(Constraints)); } -bool DataflowAnalysisContext::equivalentBoolValues(BoolValue &Val1, - BoolValue &Val2) { - llvm::DenseSet Constraints = { - &getOrCreateNegation(getOrCreateIff(Val1, Val2))}; - return isUnsatisfiable(Constraints); +bool DataflowAnalysisContext::equivalentFormulas(const Formula &Val1, + const Formula &Val2) { + llvm::SetVector Constraints; + Constraints.insert(&arena().makeNot(arena().makeEquals(Val1, Val2))); + return isUnsatisfiable(std::move(Constraints)); } void DataflowAnalysisContext::addTransitiveFlowConditionConstraints( - AtomicBoolValue &Token, llvm::DenseSet &Constraints, - llvm::DenseSet &VisitedTokens) { - auto Res = VisitedTokens.insert(&Token); + Atom Token, llvm::SetVector &Constraints, + llvm::DenseSet &VisitedTokens) { + auto Res = VisitedTokens.insert(Token); if (!Res.second) return; - auto ConstraintsIt = FlowConditionConstraints.find(&Token); + auto ConstraintsIt = FlowConditionConstraints.find(Token); if (ConstraintsIt == FlowConditionConstraints.end()) { - Constraints.insert(&Token); + Constraints.insert(&arena().makeAtomRef(Token)); } else { // Bind flow condition token via `iff` to its set of constraints: // FC <=> (C1 ^ C2 ^ ...), where Ci are constraints - Constraints.insert(&getOrCreateIff(Token, *ConstraintsIt->second)); + Constraints.insert(&arena().makeEquals(arena().makeAtomRef(Token), + *ConstraintsIt->second)); } - auto DepsIt = FlowConditionDeps.find(&Token); + auto DepsIt = FlowConditionDeps.find(Token); if (DepsIt != FlowConditionDeps.end()) { - for (AtomicBoolValue *DepToken : DepsIt->second) { - addTransitiveFlowConditionConstraints(*DepToken, Constraints, + for (Atom DepToken : DepsIt->second) { + addTransitiveFlowConditionConstraints(DepToken, Constraints, VisitedTokens); } } } -BoolValue &DataflowAnalysisContext::substituteBoolValue( - BoolValue &Val, - llvm::DenseMap &SubstitutionsCache) { - auto It = SubstitutionsCache.find(&Val); - if (It != SubstitutionsCache.end()) { - // Return memoized result of substituting this boolean value. - return *It->second; - } - - // Handle substitution on the boolean value (and its subvalues), saving the - // result into `SubstitutionsCache`. - BoolValue *Result; - switch (Val.getKind()) { - case Value::Kind::AtomicBool: { - Result = &Val; - break; - } - case Value::Kind::Negation: { - auto &Negation = *cast(&Val); - auto &Sub = substituteBoolValue(Negation.getSubVal(), SubstitutionsCache); - Result = &getOrCreateNegation(Sub); - break; - } - case Value::Kind::Disjunction: { - auto &Disjunct = *cast(&Val); - auto &LeftSub = - substituteBoolValue(Disjunct.getLeftSubValue(), SubstitutionsCache); - auto &RightSub = - substituteBoolValue(Disjunct.getRightSubValue(), SubstitutionsCache); - Result = &getOrCreateDisjunction(LeftSub, RightSub); - break; - } - case Value::Kind::Conjunction: { - auto &Conjunct = *cast(&Val); - auto &LeftSub = - substituteBoolValue(Conjunct.getLeftSubValue(), SubstitutionsCache); - auto &RightSub = - substituteBoolValue(Conjunct.getRightSubValue(), SubstitutionsCache); - Result = &getOrCreateConjunction(LeftSub, RightSub); - break; - } - case Value::Kind::Implication: { - auto &IV = *cast(&Val); - auto &LeftSub = - substituteBoolValue(IV.getLeftSubValue(), SubstitutionsCache); - auto &RightSub = - substituteBoolValue(IV.getRightSubValue(), SubstitutionsCache); - Result = &getOrCreateImplication(LeftSub, RightSub); - break; - } - case Value::Kind::Biconditional: { - auto &BV = *cast(&Val); - auto &LeftSub = - substituteBoolValue(BV.getLeftSubValue(), SubstitutionsCache); - auto &RightSub = - substituteBoolValue(BV.getRightSubValue(), SubstitutionsCache); - Result = &getOrCreateIff(LeftSub, RightSub); - break; - } - default: - llvm_unreachable("Unhandled Value Kind"); - } - SubstitutionsCache[&Val] = Result; - return *Result; -} - -BoolValue &DataflowAnalysisContext::buildAndSubstituteFlowCondition( - AtomicBoolValue &Token, - llvm::DenseMap Substitutions) { - assert( - Substitutions.find(&getBoolLiteralValue(true)) == Substitutions.end() && - Substitutions.find(&getBoolLiteralValue(false)) == Substitutions.end() && - "Do not substitute true/false boolean literals"); - llvm::DenseMap SubstitutionsCache( - Substitutions.begin(), Substitutions.end()); - return buildAndSubstituteFlowConditionWithCache(Token, SubstitutionsCache); -} - -BoolValue &DataflowAnalysisContext::buildAndSubstituteFlowConditionWithCache( - AtomicBoolValue &Token, - llvm::DenseMap &SubstitutionsCache) { - auto ConstraintsIt = FlowConditionConstraints.find(&Token); - if (ConstraintsIt == FlowConditionConstraints.end()) { - return getBoolLiteralValue(true); - } - auto DepsIt = FlowConditionDeps.find(&Token); - if (DepsIt != FlowConditionDeps.end()) { - for (AtomicBoolValue *DepToken : DepsIt->second) { - auto &NewDep = buildAndSubstituteFlowConditionWithCache( - *DepToken, SubstitutionsCache); - SubstitutionsCache[DepToken] = &NewDep; - } - } - return substituteBoolValue(*ConstraintsIt->second, SubstitutionsCache); -} - -void DataflowAnalysisContext::dumpFlowCondition(AtomicBoolValue &Token) { - llvm::DenseSet Constraints = {&Token}; - llvm::DenseSet VisitedTokens; +void DataflowAnalysisContext::dumpFlowCondition(Atom Token, + llvm::raw_ostream &OS) { + llvm::SetVector Constraints; + Constraints.insert(&arena().makeAtomRef(Token)); + llvm::DenseSet VisitedTokens; addTransitiveFlowConditionConstraints(Token, Constraints, VisitedTokens); - llvm::DenseMap AtomNames = { - {&getBoolLiteralValue(false), "False"}, - {&getBoolLiteralValue(true), "True"}}; - llvm::dbgs() << debugString(Constraints, AtomNames); + // TODO: have formulas know about true/false directly instead + Atom True = arena().makeLiteral(true).getAtom(); + Atom False = arena().makeLiteral(false).getAtom(); + Formula::AtomNames Names = {{False, "false"}, {True, "true"}}; + + for (const auto *Constraint : Constraints) { + Constraint->print(OS, &Names); + OS << "\n"; + } } const ControlFlowContext * @@ -364,8 +223,8 @@ DataflowAnalysisContext::getControlFlowContext(const FunctionDecl *F) { if (It != FunctionContexts.end()) return &It->second; - if (Stmt *Body = F->getBody()) { - auto CFCtx = ControlFlowContext::build(F, *Body, F->getASTContext()); + if (F->hasBody()) { + auto CFCtx = ControlFlowContext::build(*F); // FIXME: Handle errors. assert(CFCtx); auto Result = FunctionContexts.insert({F, std::move(*CFCtx)}); @@ -375,6 +234,54 @@ DataflowAnalysisContext::getControlFlowContext(const FunctionDecl *F) { return nullptr; } +static std::unique_ptr makeLoggerFromCommandLine() { + if (DataflowLog.empty()) + return Logger::textual(llvm::errs()); + + llvm::StringRef Dir = DataflowLog; + if (auto EC = llvm::sys::fs::create_directories(Dir)) + llvm::errs() << "Failed to create log dir: " << EC.message() << "\n"; + // All analysis runs within a process will log to the same directory. + // Share a counter so they don't all overwrite each other's 0.html. + // (Don't share a logger, it's not threadsafe). + static std::atomic Counter = {0}; + auto StreamFactory = + [Dir(Dir.str())]() mutable -> std::unique_ptr { + llvm::SmallString<256> File(Dir); + llvm::sys::path::append(File, + std::to_string(Counter.fetch_add(1)) + ".html"); + std::error_code EC; + auto OS = std::make_unique(File, EC); + if (EC) { + llvm::errs() << "Failed to create log " << File << ": " << EC.message() + << "\n"; + return std::make_unique(); + } + return OS; + }; + return Logger::html(std::move(StreamFactory)); +} + +DataflowAnalysisContext::DataflowAnalysisContext(std::unique_ptr S, + Options Opts) + : S(std::move(S)), A(std::make_unique()), Opts(Opts) { + assert(this->S != nullptr); + // If the -dataflow-log command-line flag was set, synthesize a logger. + // This is ugly but provides a uniform method for ad-hoc debugging dataflow- + // based tools. + if (Opts.Log == nullptr) { + if (DataflowLog.getNumOccurrences() > 0) { + LogOwner = makeLoggerFromCommandLine(); + this->Opts.Log = LogOwner.get(); + // FIXME: if the flag is given a value, write an HTML log to a file. + } else { + this->Opts.Log = &Logger::null(); + } + } +} + +DataflowAnalysisContext::~DataflowAnalysisContext() = default; + } // namespace dataflow } // namespace clang @@ -399,9 +306,8 @@ const Stmt &clang::dataflow::ignoreCFGOmittedNodes(const Stmt &S) { // FIXME: Does not precisely handle non-virtual diamond inheritance. A single // field decl will be modeled for all instances of the inherited field. -static void -getFieldsFromClassHierarchy(QualType Type, - llvm::DenseSet &Fields) { +static void getFieldsFromClassHierarchy(QualType Type, + clang::dataflow::FieldSet &Fields) { if (Type->isIncompleteType() || Type->isDependentType() || !Type->isRecordType()) return; @@ -414,9 +320,8 @@ getFieldsFromClassHierarchy(QualType Type, } /// Gets the set of all fields in the type. -llvm::DenseSet -clang::dataflow::getObjectFields(QualType Type) { - llvm::DenseSet Fields; +clang::dataflow::FieldSet clang::dataflow::getObjectFields(QualType Type) { + FieldSet Fields; getFieldsFromClassHierarchy(Type, Fields); return Fields; } diff --git a/contrib/llvm-project/clang/lib/Analysis/FlowSensitive/DataflowEnvironment.cpp b/contrib/llvm-project/clang/lib/Analysis/FlowSensitive/DataflowEnvironment.cpp index cc3992805cc..3a91025df6e 100644 --- a/contrib/llvm-project/clang/lib/Analysis/FlowSensitive/DataflowEnvironment.cpp +++ b/contrib/llvm-project/clang/lib/Analysis/FlowSensitive/DataflowEnvironment.cpp @@ -20,6 +20,7 @@ #include "clang/Analysis/FlowSensitive/Value.h" #include "llvm/ADT/DenseMap.h" #include "llvm/ADT/DenseSet.h" +#include "llvm/ADT/MapVector.h" #include "llvm/ADT/STLExtras.h" #include "llvm/Support/Casting.h" #include "llvm/Support/ErrorHandling.h" @@ -107,22 +108,44 @@ static Value *mergeDistinctValues(QualType Type, Value &Val1, // if (o.has_value()) // x = o.value(); // ``` - auto *Expr1 = cast(&Val1); - auto *Expr2 = cast(&Val2); - auto &MergedVal = MergedEnv.makeAtomicBoolValue(); - MergedEnv.addToFlowCondition(MergedEnv.makeOr( - MergedEnv.makeAnd(Env1.getFlowConditionToken(), - MergedEnv.makeIff(MergedVal, *Expr1)), - MergedEnv.makeAnd(Env2.getFlowConditionToken(), - MergedEnv.makeIff(MergedVal, *Expr2)))); - return &MergedVal; + auto &Expr1 = cast(Val1).formula(); + auto &Expr2 = cast(Val2).formula(); + auto &A = MergedEnv.arena(); + auto &MergedVal = A.makeAtomRef(A.makeAtom()); + MergedEnv.addToFlowCondition( + A.makeOr(A.makeAnd(A.makeAtomRef(Env1.getFlowConditionToken()), + A.makeEquals(MergedVal, Expr1)), + A.makeAnd(A.makeAtomRef(Env2.getFlowConditionToken()), + A.makeEquals(MergedVal, Expr2)))); + return &A.makeBoolValue(MergedVal); + } + + Value *MergedVal = nullptr; + if (auto *StructVal1 = dyn_cast(&Val1)) { + [[maybe_unused]] auto *StructVal2 = cast(&Val2); + + // Values to be merged are always associated with the same location in + // `LocToVal`. The location stored in `StructVal` should therefore also + // be the same. + assert(&StructVal1->getAggregateLoc() == &StructVal2->getAggregateLoc()); + + // `StructVal1` and `StructVal2` may have different properties associated + // with them. Create a new `StructValue` without any properties so that we + // soundly approximate both values. If a particular analysis needs to merge + // properties, it should do so in `DataflowAnalysis::merge()`. + MergedVal = &MergedEnv.create(StructVal1->getAggregateLoc()); + } else { + MergedVal = MergedEnv.createValue(Type); } // FIXME: Consider destroying `MergedValue` immediately if `ValueModel::merge` // returns false to avoid storing unneeded values in `DACtx`. // FIXME: Creating the value based on the type alone creates misshapen values // for lvalues, since the type does not reflect the need for `ReferenceValue`. - if (Value *MergedVal = MergedEnv.createValue(Type)) + // This issue will be resolved when `ReferenceValue` is eliminated as part + // of the ongoing migration to strict handling of value categories (see + // https://discourse.llvm.org/t/70086 for details). + if (MergedVal) if (Model.merge(Type, Val1, Env1, Val2, Env2, *MergedVal, MergedEnv)) return MergedVal; @@ -156,17 +179,24 @@ static Value &widenDistinctValues(QualType Type, Value &Prev, /// Initializes a global storage value. static void insertIfGlobal(const Decl &D, - llvm::DenseSet &Fields, llvm::DenseSet &Vars) { if (auto *V = dyn_cast(&D)) if (V->hasGlobalStorage()) Vars.insert(V); } -static void getFieldsAndGlobalVars(const Decl &D, - llvm::DenseSet &Fields, - llvm::DenseSet &Vars) { - insertIfGlobal(D, Fields, Vars); +static void insertIfFunction(const Decl &D, + llvm::DenseSet &Funcs) { + if (auto *FD = dyn_cast(&D)) + Funcs.insert(FD); +} + +static void +getFieldsGlobalsAndFuncs(const Decl &D, FieldSet &Fields, + llvm::DenseSet &Vars, + llvm::DenseSet &Funcs) { + insertIfGlobal(D, Vars); + insertIfFunction(D, Funcs); if (const auto *Decomp = dyn_cast(&D)) for (const auto *B : Decomp->bindings()) if (auto *ME = dyn_cast_or_null(B->getBinding())) @@ -175,60 +205,99 @@ static void getFieldsAndGlobalVars(const Decl &D, Fields.insert(FD); } -/// Traverses `S` and inserts into `Vars` any global storage values that are -/// declared in or referenced from sub-statements. -static void getFieldsAndGlobalVars(const Stmt &S, - llvm::DenseSet &Fields, - llvm::DenseSet &Vars) { +/// Traverses `S` and inserts into `Fields`, `Vars` and `Funcs` any fields, +/// global variables and functions that are declared in or referenced from +/// sub-statements. +static void +getFieldsGlobalsAndFuncs(const Stmt &S, FieldSet &Fields, + llvm::DenseSet &Vars, + llvm::DenseSet &Funcs) { for (auto *Child : S.children()) if (Child != nullptr) - getFieldsAndGlobalVars(*Child, Fields, Vars); + getFieldsGlobalsAndFuncs(*Child, Fields, Vars, Funcs); + if (const auto *DefaultInit = dyn_cast(&S)) + getFieldsGlobalsAndFuncs(*DefaultInit->getExpr(), Fields, Vars, Funcs); if (auto *DS = dyn_cast(&S)) { if (DS->isSingleDecl()) - getFieldsAndGlobalVars(*DS->getSingleDecl(), Fields, Vars); + getFieldsGlobalsAndFuncs(*DS->getSingleDecl(), Fields, Vars, Funcs); else for (auto *D : DS->getDeclGroup()) - getFieldsAndGlobalVars(*D, Fields, Vars); + getFieldsGlobalsAndFuncs(*D, Fields, Vars, Funcs); } else if (auto *E = dyn_cast(&S)) { - insertIfGlobal(*E->getDecl(), Fields, Vars); + insertIfGlobal(*E->getDecl(), Vars); + insertIfFunction(*E->getDecl(), Funcs); } else if (auto *E = dyn_cast(&S)) { // FIXME: should we be using `E->getFoundDecl()`? const ValueDecl *VD = E->getMemberDecl(); - insertIfGlobal(*VD, Fields, Vars); + insertIfGlobal(*VD, Vars); + insertIfFunction(*VD, Funcs); if (const auto *FD = dyn_cast(VD)) Fields.insert(FD); + } else if (auto *InitList = dyn_cast(&S)) { + if (RecordDecl *RD = InitList->getType()->getAsRecordDecl()) + for (const auto *FD : getFieldsForInitListExpr(RD)) + Fields.insert(FD); } } // FIXME: Add support for resetting globals after function calls to enable // the implementation of sound analyses. -void Environment::initVars(llvm::DenseSet Vars) { +void Environment::initFieldsGlobalsAndFuncs(const FunctionDecl *FuncDecl) { + assert(FuncDecl->getBody() != nullptr); + + FieldSet Fields; + llvm::DenseSet Vars; + llvm::DenseSet Funcs; + + // Look for global variable and field references in the + // constructor-initializers. + if (const auto *CtorDecl = dyn_cast(FuncDecl)) { + for (const auto *Init : CtorDecl->inits()) { + if (Init->isMemberInitializer()) { + Fields.insert(Init->getMember()); + } else if (Init->isIndirectMemberInitializer()) { + for (const auto *I : Init->getIndirectMember()->chain()) + Fields.insert(cast(I)); + } + const Expr *E = Init->getInit(); + assert(E != nullptr); + getFieldsGlobalsAndFuncs(*E, Fields, Vars, Funcs); + } + // Add all fields mentioned in default member initializers. + for (const FieldDecl *F : CtorDecl->getParent()->fields()) + if (const auto *I = F->getInClassInitializer()) + getFieldsGlobalsAndFuncs(*I, Fields, Vars, Funcs); + } + getFieldsGlobalsAndFuncs(*FuncDecl->getBody(), Fields, Vars, Funcs); + + // These have to be added before the lines that follow to ensure that + // `create*` work correctly for structs. + DACtx->addModeledFields(Fields); + for (const VarDecl *D : Vars) { - if (getStorageLocation(*D, SkipPast::None) != nullptr) + if (getStorageLocation(*D) != nullptr) continue; - auto &Loc = createStorageLocation(*D); - setStorageLocation(*D, Loc); - if (auto *Val = createValue(D->getType())) - setValue(Loc, *Val); + + setStorageLocation(*D, createObject(*D)); + } + + for (const FunctionDecl *FD : Funcs) { + if (getStorageLocation(*FD) != nullptr) + continue; + auto &Loc = createStorageLocation(FD->getType()); + setStorageLocation(*FD, Loc); } } Environment::Environment(DataflowAnalysisContext &DACtx) - : DACtx(&DACtx), FlowConditionToken(&DACtx.makeFlowConditionToken()) {} + : DACtx(&DACtx), + FlowConditionToken(DACtx.arena().makeFlowConditionToken()) {} -Environment::Environment(const Environment &Other) - : DACtx(Other.DACtx), CallStack(Other.CallStack), - ReturnLoc(Other.ReturnLoc), ThisPointeeLoc(Other.ThisPointeeLoc), - DeclToLoc(Other.DeclToLoc), ExprToLoc(Other.ExprToLoc), - LocToVal(Other.LocToVal), MemberLocToStruct(Other.MemberLocToStruct), - FlowConditionToken(&DACtx->forkFlowCondition(*Other.FlowConditionToken)) { -} - -Environment &Environment::operator=(const Environment &Other) { - Environment Copy(Other); - *this = std::move(Copy); - return *this; +Environment Environment::fork() const { + Environment Copy(*this); + Copy.FlowConditionToken = DACtx->forkFlowCondition(FlowConditionToken); + return Copy; } Environment::Environment(DataflowAnalysisContext &DACtx, @@ -239,37 +308,12 @@ Environment::Environment(DataflowAnalysisContext &DACtx, if (const auto *FuncDecl = dyn_cast(&DeclCtx)) { assert(FuncDecl->getBody() != nullptr); - llvm::DenseSet Fields; - llvm::DenseSet Vars; - - // Look for global variable references in the constructor-initializers. - if (const auto *CtorDecl = dyn_cast(&DeclCtx)) { - for (const auto *Init : CtorDecl->inits()) { - if (const auto *M = Init->getAnyMember()) - Fields.insert(M); - const Expr *E = Init->getInit(); - assert(E != nullptr); - getFieldsAndGlobalVars(*E, Fields, Vars); - } - } - getFieldsAndGlobalVars(*FuncDecl->getBody(), Fields, Vars); - - // These have to be added before the lines that follow to ensure that - // `create*` work correctly for structs. - DACtx.addModeledFields(Fields); - - initVars(Vars); + initFieldsGlobalsAndFuncs(FuncDecl); for (const auto *ParamDecl : FuncDecl->parameters()) { assert(ParamDecl != nullptr); - auto &ParamLoc = createStorageLocation(*ParamDecl); - setStorageLocation(*ParamDecl, ParamLoc); - if (Value *ParamVal = createValue(ParamDecl->getType())) - setValue(ParamLoc, *ParamVal); + setStorageLocation(*ParamDecl, createObject(*ParamDecl, nullptr)); } - - QualType ReturnType = FuncDecl->getReturnType(); - ReturnLoc = &createStorageLocation(ReturnType); } if (const auto *MethodDecl = dyn_cast(&DeclCtx)) { @@ -281,9 +325,8 @@ Environment::Environment(DataflowAnalysisContext &DACtx, // FIXME: Initialize the ThisPointeeLoc of lambdas too. if (MethodDecl && !MethodDecl->isStatic()) { QualType ThisPointeeType = MethodDecl->getThisObjectType(); - ThisPointeeLoc = &createStorageLocation(ThisPointeeType); - if (Value *ThisPointeeVal = createValue(ThisPointeeType)) - setValue(*ThisPointeeLoc, *ThisPointeeVal); + ThisPointeeLoc = + &cast(createValue(ThisPointeeType))->getAggregateLoc(); } } } @@ -296,13 +339,11 @@ bool Environment::canDescend(unsigned MaxDepth, Environment Environment::pushCall(const CallExpr *Call) const { Environment Env(*this); - // FIXME: Support references here. - Env.ReturnLoc = getStorageLocation(*Call, SkipPast::Reference); - if (const auto *MethodCall = dyn_cast(Call)) { if (const Expr *Arg = MethodCall->getImplicitObjectArgument()) { if (!isa(Arg)) - Env.ThisPointeeLoc = getStorageLocation(*Arg, SkipPast::Reference); + Env.ThisPointeeLoc = cast( + getStorageLocation(*Arg, SkipPast::Reference)); // Otherwise (when the argument is `this`), retain the current // environment's `ThisPointeeLoc`. } @@ -317,10 +358,7 @@ Environment Environment::pushCall(const CallExpr *Call) const { Environment Environment::pushCall(const CXXConstructExpr *Call) const { Environment Env(*this); - // FIXME: Support references here. - Env.ReturnLoc = getStorageLocation(*Call, SkipPast::Reference); - - Env.ThisPointeeLoc = Env.ReturnLoc; + Env.ThisPointeeLoc = &Env.getResultObjectLocation(*Call); Env.pushCallInternal(Call->getConstructor(), llvm::ArrayRef(Call->getArgs(), Call->getNumArgs())); @@ -330,28 +368,15 @@ Environment Environment::pushCall(const CXXConstructExpr *Call) const { void Environment::pushCallInternal(const FunctionDecl *FuncDecl, ArrayRef Args) { + // Canonicalize to the definition of the function. This ensures that we're + // putting arguments into the same `ParamVarDecl`s` that the callee will later + // be retrieving them from. + assert(FuncDecl->getDefinition() != nullptr); + FuncDecl = FuncDecl->getDefinition(); + CallStack.push_back(FuncDecl); - // FIXME: Share this code with the constructor, rather than duplicating it. - llvm::DenseSet Fields; - llvm::DenseSet Vars; - // Look for global variable references in the constructor-initializers. - if (const auto *CtorDecl = dyn_cast(FuncDecl)) { - for (const auto *Init : CtorDecl->inits()) { - if (const auto *M = Init->getAnyMember()) - Fields.insert(M); - const Expr *E = Init->getInit(); - assert(E != nullptr); - getFieldsAndGlobalVars(*E, Fields, Vars); - } - } - getFieldsAndGlobalVars(*FuncDecl->getBody(), Fields, Vars); - - // These have to be added before the lines that follow to ensure that - // `create*` work correctly for structs. - DACtx->addModeledFields(Fields); - - initVars(Vars); + initFieldsGlobalsAndFuncs(FuncDecl); const auto *ParamIt = FuncDecl->param_begin(); @@ -359,45 +384,49 @@ void Environment::pushCallInternal(const FunctionDecl *FuncDecl, // overloaded operators implemented as member functions, and parameter packs. for (unsigned ArgIndex = 0; ArgIndex < Args.size(); ++ParamIt, ++ArgIndex) { assert(ParamIt != FuncDecl->param_end()); - - const Expr *Arg = Args[ArgIndex]; - auto *ArgLoc = getStorageLocation(*Arg, SkipPast::Reference); - if (ArgLoc == nullptr) - continue; - const VarDecl *Param = *ParamIt; - auto &Loc = createStorageLocation(*Param); - setStorageLocation(*Param, Loc); - - QualType ParamType = Param->getType(); - if (ParamType->isReferenceType()) { - auto &Val = takeOwnership(std::make_unique(*ArgLoc)); - setValue(Loc, Val); - } else if (auto *ArgVal = getValue(*ArgLoc)) { - setValue(Loc, *ArgVal); - } else if (Value *Val = createValue(ParamType)) { - setValue(Loc, *Val); - } + setStorageLocation(*Param, createObject(*Param, Args[ArgIndex])); } } -void Environment::popCall(const Environment &CalleeEnv) { +void Environment::popCall(const CallExpr *Call, const Environment &CalleeEnv) { // We ignore `DACtx` because it's already the same in both. We don't want the - // callee's `DeclCtx`, `ReturnLoc` or `ThisPointeeLoc`. We don't bring back - // `DeclToLoc` and `ExprToLoc` because we want to be able to later analyze the - // same callee in a different context, and `setStorageLocation` requires there - // to not already be a storage location assigned. Conceptually, these maps - // capture information from the local scope, so when popping that scope, we do - // not propagate the maps. + // callee's `DeclCtx`, `ReturnVal`, `ReturnLoc` or `ThisPointeeLoc`. We don't + // bring back `DeclToLoc` and `ExprToLoc` because we want to be able to later + // analyze the same callee in a different context, and `setStorageLocation` + // requires there to not already be a storage location assigned. Conceptually, + // these maps capture information from the local scope, so when popping that + // scope, we do not propagate the maps. this->LocToVal = std::move(CalleeEnv.LocToVal); - this->MemberLocToStruct = std::move(CalleeEnv.MemberLocToStruct); this->FlowConditionToken = std::move(CalleeEnv.FlowConditionToken); + + if (Call->isGLValue()) { + if (CalleeEnv.ReturnLoc != nullptr) + setStorageLocationStrict(*Call, *CalleeEnv.ReturnLoc); + } else if (!Call->getType()->isVoidType()) { + if (CalleeEnv.ReturnVal != nullptr) + setValueStrict(*Call, *CalleeEnv.ReturnVal); + } +} + +void Environment::popCall(const CXXConstructExpr *Call, + const Environment &CalleeEnv) { + // See also comment in `popCall(const CallExpr *, const Environment &)` above. + this->LocToVal = std::move(CalleeEnv.LocToVal); + this->FlowConditionToken = std::move(CalleeEnv.FlowConditionToken); + + if (Value *Val = CalleeEnv.getValue(*CalleeEnv.ThisPointeeLoc)) { + setValueStrict(*Call, *Val); + } } bool Environment::equivalentTo(const Environment &Other, Environment::ValueModel &Model) const { assert(DACtx == Other.DACtx); + if (ReturnVal != Other.ReturnVal) + return false; + if (ReturnLoc != Other.ReturnLoc) return false; @@ -435,6 +464,7 @@ bool Environment::equivalentTo(const Environment &Other, LatticeJoinEffect Environment::widen(const Environment &PrevEnv, Environment::ValueModel &Model) { assert(DACtx == PrevEnv.DACtx); + assert(ReturnVal == PrevEnv.ReturnVal); assert(ReturnLoc == PrevEnv.ReturnLoc); assert(ThisPointeeLoc == PrevEnv.ThisPointeeLoc); assert(CallStack == PrevEnv.CallStack); @@ -447,17 +477,10 @@ LatticeJoinEffect Environment::widen(const Environment &PrevEnv, // block. For `DeclToLoc` and `ExprToLoc`, join guarantees that these maps are // subsets of the maps in `PrevEnv`. So, as long as we maintain this property // here, we don't need change their current values to widen. - // - // FIXME: `MemberLocToStruct` does not share the above property, because - // `join` can cause the map size to increase (when we add fresh data in places - // of conflict). Once this issue with join is resolved, re-enable the - // assertion below or replace with something that captures the desired - // invariant. assert(DeclToLoc.size() <= PrevEnv.DeclToLoc.size()); assert(ExprToLoc.size() <= PrevEnv.ExprToLoc.size()); - // assert(MemberLocToStruct.size() <= PrevEnv.MemberLocToStruct.size()); - llvm::DenseMap WidenedLocToVal; + llvm::MapVector WidenedLocToVal; for (auto &Entry : LocToVal) { const StorageLocation *Loc = Entry.first; assert(Loc != nullptr); @@ -482,60 +505,75 @@ LatticeJoinEffect Environment::widen(const Environment &PrevEnv, Effect = LatticeJoinEffect::Changed; } LocToVal = std::move(WidenedLocToVal); - // FIXME: update the equivalence calculation for `MemberLocToStruct`, once we - // have a systematic way of soundly comparing this map. if (DeclToLoc.size() != PrevEnv.DeclToLoc.size() || ExprToLoc.size() != PrevEnv.ExprToLoc.size() || - LocToVal.size() != PrevEnv.LocToVal.size() || - MemberLocToStruct.size() != PrevEnv.MemberLocToStruct.size()) + LocToVal.size() != PrevEnv.LocToVal.size()) Effect = LatticeJoinEffect::Changed; return Effect; } -LatticeJoinEffect Environment::join(const Environment &Other, - Environment::ValueModel &Model) { - assert(DACtx == Other.DACtx); - assert(ReturnLoc == Other.ReturnLoc); - assert(ThisPointeeLoc == Other.ThisPointeeLoc); - assert(CallStack == Other.CallStack); +Environment Environment::join(const Environment &EnvA, const Environment &EnvB, + Environment::ValueModel &Model) { + assert(EnvA.DACtx == EnvB.DACtx); + assert(EnvA.ThisPointeeLoc == EnvB.ThisPointeeLoc); + assert(EnvA.CallStack == EnvB.CallStack); - auto Effect = LatticeJoinEffect::Unchanged; + Environment JoinedEnv(*EnvA.DACtx); - Environment JoinedEnv(*DACtx); + JoinedEnv.CallStack = EnvA.CallStack; + JoinedEnv.ThisPointeeLoc = EnvA.ThisPointeeLoc; - JoinedEnv.CallStack = CallStack; - JoinedEnv.ReturnLoc = ReturnLoc; - JoinedEnv.ThisPointeeLoc = ThisPointeeLoc; + if (EnvA.ReturnVal == nullptr || EnvB.ReturnVal == nullptr) { + // `ReturnVal` might not always get set -- for example if we have a return + // statement of the form `return some_other_func()` and we decide not to + // analyze `some_other_func()`. + // In this case, we can't say anything about the joined return value -- we + // don't simply want to propagate the return value that we do have, because + // it might not be the correct one. + // This occurs for example in the test `ContextSensitiveMutualRecursion`. + JoinedEnv.ReturnVal = nullptr; + } else if (areEquivalentValues(*EnvA.ReturnVal, *EnvB.ReturnVal)) { + JoinedEnv.ReturnVal = EnvA.ReturnVal; + } else { + assert(!EnvA.CallStack.empty()); + // FIXME: Make `CallStack` a vector of `FunctionDecl` so we don't need this + // cast. + auto *Func = dyn_cast(EnvA.CallStack.back()); + assert(Func != nullptr); + if (Value *MergedVal = + mergeDistinctValues(Func->getReturnType(), *EnvA.ReturnVal, EnvA, + *EnvB.ReturnVal, EnvB, JoinedEnv, Model)) + JoinedEnv.ReturnVal = MergedVal; + } - JoinedEnv.DeclToLoc = intersectDenseMaps(DeclToLoc, Other.DeclToLoc); - if (DeclToLoc.size() != JoinedEnv.DeclToLoc.size()) - Effect = LatticeJoinEffect::Changed; + if (EnvA.ReturnLoc == EnvB.ReturnLoc) + JoinedEnv.ReturnLoc = EnvA.ReturnLoc; + else + JoinedEnv.ReturnLoc = nullptr; - JoinedEnv.ExprToLoc = intersectDenseMaps(ExprToLoc, Other.ExprToLoc); - if (ExprToLoc.size() != JoinedEnv.ExprToLoc.size()) - Effect = LatticeJoinEffect::Changed; + // FIXME: Once we're able to remove declarations from `DeclToLoc` when their + // lifetime ends, add an assertion that there aren't any entries in + // `DeclToLoc` and `Other.DeclToLoc` that map the same declaration to + // different storage locations. + JoinedEnv.DeclToLoc = intersectDenseMaps(EnvA.DeclToLoc, EnvB.DeclToLoc); - JoinedEnv.MemberLocToStruct = - intersectDenseMaps(MemberLocToStruct, Other.MemberLocToStruct); - if (MemberLocToStruct.size() != JoinedEnv.MemberLocToStruct.size()) - Effect = LatticeJoinEffect::Changed; + JoinedEnv.ExprToLoc = intersectDenseMaps(EnvA.ExprToLoc, EnvB.ExprToLoc); - // FIXME: set `Effect` as needed. // FIXME: update join to detect backedges and simplify the flow condition // accordingly. - JoinedEnv.FlowConditionToken = &DACtx->joinFlowConditions( - *FlowConditionToken, *Other.FlowConditionToken); + JoinedEnv.FlowConditionToken = EnvA.DACtx->joinFlowConditions( + EnvA.FlowConditionToken, EnvB.FlowConditionToken); - for (auto &Entry : LocToVal) { + for (auto &Entry : EnvA.LocToVal) { const StorageLocation *Loc = Entry.first; assert(Loc != nullptr); Value *Val = Entry.second; assert(Val != nullptr); - auto It = Other.LocToVal.find(Loc); - if (It == Other.LocToVal.end()) + auto It = EnvB.LocToVal.find(Loc); + if (It == EnvB.LocToVal.end()) continue; assert(It->second != nullptr); @@ -544,19 +582,13 @@ LatticeJoinEffect Environment::join(const Environment &Other, continue; } - if (Value *MergedVal = - mergeDistinctValues(Loc->getType(), *Val, *this, *It->second, Other, - JoinedEnv, Model)) { + if (Value *MergedVal = mergeDistinctValues( + Loc->getType(), *Val, EnvA, *It->second, EnvB, JoinedEnv, Model)) { JoinedEnv.LocToVal.insert({Loc, MergedVal}); - Effect = LatticeJoinEffect::Changed; } } - if (LocToVal.size() != JoinedEnv.LocToVal.size()) - Effect = LatticeJoinEffect::Changed; - *this = std::move(JoinedEnv); - - return Effect; + return JoinedEnv; } StorageLocation &Environment::createStorageLocation(QualType Type) { @@ -578,22 +610,39 @@ StorageLocation &Environment::createStorageLocation(const Expr &E) { } void Environment::setStorageLocation(const ValueDecl &D, StorageLocation &Loc) { - assert(DeclToLoc.find(&D) == DeclToLoc.end()); + assert(!DeclToLoc.contains(&D)); + assert(!isa_and_nonnull(getValue(Loc))); DeclToLoc[&D] = &Loc; } -StorageLocation *Environment::getStorageLocation(const ValueDecl &D, - SkipPast SP) const { +StorageLocation *Environment::getStorageLocation(const ValueDecl &D) const { auto It = DeclToLoc.find(&D); - return It == DeclToLoc.end() ? nullptr : &skip(*It->second, SP); + if (It == DeclToLoc.end()) + return nullptr; + + StorageLocation *Loc = It->second; + + assert(!isa_and_nonnull(getValue(*Loc))); + + return Loc; } void Environment::setStorageLocation(const Expr &E, StorageLocation &Loc) { const Expr &CanonE = ignoreCFGOmittedNodes(E); - assert(ExprToLoc.find(&CanonE) == ExprToLoc.end()); + assert(!ExprToLoc.contains(&CanonE)); ExprToLoc[&CanonE] = &Loc; } +void Environment::setStorageLocationStrict(const Expr &E, + StorageLocation &Loc) { + // `DeclRefExpr`s to builtin function types aren't glvalues, for some reason, + // but we still want to be able to associate a `StorageLocation` with them, + // so allow these as an exception. + assert(E.isGLValue() || + E.getType()->isSpecificBuiltinType(BuiltinType::BuiltinFn)); + setStorageLocation(E, Loc); +} + StorageLocation *Environment::getStorageLocation(const Expr &E, SkipPast SP) const { // FIXME: Add a test with parens. @@ -601,12 +650,37 @@ StorageLocation *Environment::getStorageLocation(const Expr &E, return It == ExprToLoc.end() ? nullptr : &skip(*It->second, SP); } -StorageLocation *Environment::getThisPointeeStorageLocation() const { +StorageLocation *Environment::getStorageLocationStrict(const Expr &E) const { + // See comment in `setStorageLocationStrict()`. + assert(E.isGLValue() || + E.getType()->isSpecificBuiltinType(BuiltinType::BuiltinFn)); + StorageLocation *Loc = getStorageLocation(E, SkipPast::None); + + if (Loc == nullptr) + return nullptr; + + if (auto *RefVal = dyn_cast_or_null(getValue(*Loc))) + return &RefVal->getReferentLoc(); + + return Loc; +} + +AggregateStorageLocation *Environment::getThisPointeeStorageLocation() const { return ThisPointeeLoc; } -StorageLocation *Environment::getReturnStorageLocation() const { - return ReturnLoc; +AggregateStorageLocation & +Environment::getResultObjectLocation(const Expr &RecordPRValue) { + assert(RecordPRValue.getType()->isRecordType()); + assert(RecordPRValue.isPRValue()); + + if (StorageLocation *ExistingLoc = + getStorageLocation(RecordPRValue, SkipPast::None)) + return *cast(ExistingLoc); + auto &Loc = cast( + DACtx->getStableStorageLocation(RecordPRValue)); + setStorageLocation(RecordPRValue, Loc); + return Loc; } PointerValue &Environment::getOrCreateNullPointerValue(QualType PointeeType) { @@ -614,45 +688,41 @@ PointerValue &Environment::getOrCreateNullPointerValue(QualType PointeeType) { } void Environment::setValue(const StorageLocation &Loc, Value &Val) { + assert(!isa(&Val) || + &cast(&Val)->getAggregateLoc() == &Loc); + LocToVal[&Loc] = &Val; +} + +void Environment::setValueStrict(const Expr &E, Value &Val) { + assert(E.isPRValue()); + assert(!isa(Val)); if (auto *StructVal = dyn_cast(&Val)) { - auto &AggregateLoc = *cast(&Loc); - - const QualType Type = AggregateLoc.getType(); - assert(Type->isStructureOrClassType() || Type->isUnionType()); - - for (const FieldDecl *Field : DACtx->getReferencedFields(Type)) { - assert(Field != nullptr); - StorageLocation &FieldLoc = AggregateLoc.getChild(*Field); - MemberLocToStruct[&FieldLoc] = std::make_pair(StructVal, Field); - if (auto *FieldVal = StructVal->getChild(*Field)) - setValue(FieldLoc, *FieldVal); - } + if (auto *ExistingVal = cast_or_null(getValueStrict(E))) + assert(&ExistingVal->getAggregateLoc() == &StructVal->getAggregateLoc()); + if (StorageLocation *ExistingLoc = getStorageLocation(E, SkipPast::None)) + assert(ExistingLoc == &StructVal->getAggregateLoc()); + else + setStorageLocation(E, StructVal->getAggregateLoc()); + setValue(StructVal->getAggregateLoc(), Val); + return; } - auto It = MemberLocToStruct.find(&Loc); - if (It != MemberLocToStruct.end()) { - // `Loc` is the location of a struct member so we need to also update the - // value of the member in the corresponding `StructValue`. - - assert(It->second.first != nullptr); - StructValue &StructVal = *It->second.first; - - assert(It->second.second != nullptr); - const ValueDecl &Member = *It->second.second; - - StructVal.setChild(Member, Val); + StorageLocation *Loc = getStorageLocation(E, SkipPast::None); + if (Loc == nullptr) { + Loc = &createStorageLocation(E); + setStorageLocation(E, *Loc); } + setValue(*Loc, Val); } Value *Environment::getValue(const StorageLocation &Loc) const { - auto It = LocToVal.find(&Loc); - return It == LocToVal.end() ? nullptr : It->second; + return LocToVal.lookup(&Loc); } -Value *Environment::getValue(const ValueDecl &D, SkipPast SP) const { - auto *Loc = getStorageLocation(D, SP); +Value *Environment::getValue(const ValueDecl &D) const { + auto *Loc = getStorageLocation(D); if (Loc == nullptr) return nullptr; return getValue(*Loc); @@ -665,6 +735,15 @@ Value *Environment::getValue(const Expr &E, SkipPast SP) const { return getValue(*Loc); } +Value *Environment::getValueStrict(const Expr &E) const { + assert(E.isPRValue()); + Value *Val = getValue(E, SkipPast::None); + + assert(Val == nullptr || !isa(Val)); + + return Val; +} + Value *Environment::createValue(QualType Type) { llvm::DenseSet Visited; int CreatedValuesCount = 0; @@ -697,67 +776,122 @@ Value *Environment::createValueUnlessSelfReferential( // with integers, and so distinguishing them serves no purpose, but could // prevent convergence. CreatedValuesCount++; - return &takeOwnership(std::make_unique()); + return &arena().create(); } - if (Type->isReferenceType()) { + if (Type->isReferenceType() || Type->isPointerType()) { CreatedValuesCount++; - QualType PointeeType = Type->castAs()->getPointeeType(); - auto &PointeeLoc = createStorageLocation(PointeeType); + QualType PointeeType = Type->getPointeeType(); + StorageLocation &PointeeLoc = + createLocAndMaybeValue(PointeeType, Visited, Depth, CreatedValuesCount); - if (Visited.insert(PointeeType.getCanonicalType()).second) { - Value *PointeeVal = createValueUnlessSelfReferential( - PointeeType, Visited, Depth, CreatedValuesCount); - Visited.erase(PointeeType.getCanonicalType()); - - if (PointeeVal != nullptr) - setValue(PointeeLoc, *PointeeVal); - } - - return &takeOwnership(std::make_unique(PointeeLoc)); + if (Type->isReferenceType()) + return &arena().create(PointeeLoc); + else + return &arena().create(PointeeLoc); } - if (Type->isPointerType()) { + if (Type->isRecordType()) { CreatedValuesCount++; - QualType PointeeType = Type->castAs()->getPointeeType(); - auto &PointeeLoc = createStorageLocation(PointeeType); - - if (Visited.insert(PointeeType.getCanonicalType()).second) { - Value *PointeeVal = createValueUnlessSelfReferential( - PointeeType, Visited, Depth, CreatedValuesCount); - Visited.erase(PointeeType.getCanonicalType()); - - if (PointeeVal != nullptr) - setValue(PointeeLoc, *PointeeVal); - } - - return &takeOwnership(std::make_unique(PointeeLoc)); - } - - if (Type->isStructureOrClassType() || Type->isUnionType()) { - CreatedValuesCount++; - llvm::DenseMap FieldValues; - for (const FieldDecl *Field : DACtx->getReferencedFields(Type)) { + llvm::DenseMap FieldLocs; + for (const FieldDecl *Field : DACtx->getModeledFields(Type)) { assert(Field != nullptr); QualType FieldType = Field->getType(); - if (Visited.contains(FieldType.getCanonicalType())) - continue; - Visited.insert(FieldType.getCanonicalType()); - if (auto *FieldValue = createValueUnlessSelfReferential( - FieldType, Visited, Depth + 1, CreatedValuesCount)) - FieldValues.insert({Field, FieldValue}); - Visited.erase(FieldType.getCanonicalType()); + FieldLocs.insert( + {Field, &createLocAndMaybeValue(FieldType, Visited, Depth + 1, + CreatedValuesCount)}); } - return &takeOwnership( - std::make_unique(std::move(FieldValues))); + AggregateStorageLocation &Loc = + arena().create(Type, std::move(FieldLocs)); + StructValue &StructVal = create(Loc); + + // As we already have a storage location for the `StructValue`, we can and + // should associate them in the environment. + setValue(Loc, StructVal); + + return &StructVal; } return nullptr; } +StorageLocation & +Environment::createLocAndMaybeValue(QualType Ty, + llvm::DenseSet &Visited, + int Depth, int &CreatedValuesCount) { + if (!Visited.insert(Ty.getCanonicalType()).second) + return createStorageLocation(Ty.getNonReferenceType()); + Value *Val = createValueUnlessSelfReferential( + Ty.getNonReferenceType(), Visited, Depth, CreatedValuesCount); + Visited.erase(Ty.getCanonicalType()); + + Ty = Ty.getNonReferenceType(); + + if (Val == nullptr) + return createStorageLocation(Ty); + + if (Ty->isRecordType()) + return cast(Val)->getAggregateLoc(); + + StorageLocation &Loc = createStorageLocation(Ty); + setValue(Loc, *Val); + return Loc; +} + +StorageLocation &Environment::createObjectInternal(const VarDecl *D, + QualType Ty, + const Expr *InitExpr) { + if (Ty->isReferenceType()) { + // Although variables of reference type always need to be initialized, it + // can happen that we can't see the initializer, so `InitExpr` may still + // be null. + if (InitExpr) { + if (auto *InitExprLoc = + getStorageLocation(*InitExpr, SkipPast::Reference)) + return *InitExprLoc; + } + + // Even though we have an initializer, we might not get an + // InitExprLoc, for example if the InitExpr is a CallExpr for which we + // don't have a function body. In this case, we just invent a storage + // location and value -- it's the best we can do. + return createObjectInternal(D, Ty.getNonReferenceType(), nullptr); + } + + Value *Val = nullptr; + if (InitExpr) + // In the (few) cases where an expression is intentionally + // "uninterpreted", `InitExpr` is not associated with a value. There are + // two ways to handle this situation: propagate the status, so that + // uninterpreted initializers result in uninterpreted variables, or + // provide a default value. We choose the latter so that later refinements + // of the variable can be used for reasoning about the surrounding code. + // For this reason, we let this case be handled by the `createValue()` + // call below. + // + // FIXME. If and when we interpret all language cases, change this to + // assert that `InitExpr` is interpreted, rather than supplying a + // default value (assuming we don't update the environment API to return + // references). + Val = getValueStrict(*InitExpr); + if (!Val) + Val = createValue(Ty); + + if (Ty->isRecordType()) + return cast(Val)->getAggregateLoc(); + + StorageLocation &Loc = + D ? createStorageLocation(*D) : createStorageLocation(Ty); + + if (Val) + setValue(Loc, *Val); + + return Loc; +} + StorageLocation &Environment::skip(StorageLocation &Loc, SkipPast SP) const { switch (SP) { case SkipPast::None: @@ -768,11 +902,6 @@ StorageLocation &Environment::skip(StorageLocation &Loc, SkipPast SP) const { if (auto *Val = dyn_cast_or_null(getValue(Loc))) return Val->getReferentLoc(); return Loc; - case SkipPast::ReferenceThenPointer: - StorageLocation &LocPastRef = skip(Loc, SkipPast::Reference); - if (auto *Val = dyn_cast_or_null(getValue(LocPastRef))) - return Val->getPointeeLoc(); - return LocPastRef; } llvm_unreachable("bad SkipPast kind"); } @@ -782,12 +911,12 @@ const StorageLocation &Environment::skip(const StorageLocation &Loc, return skip(*const_cast(&Loc), SP); } -void Environment::addToFlowCondition(BoolValue &Val) { - DACtx->addFlowConditionConstraint(*FlowConditionToken, Val); +void Environment::addToFlowCondition(const Formula &Val) { + DACtx->addFlowConditionConstraint(FlowConditionToken, Val); } -bool Environment::flowConditionImplies(BoolValue &Val) const { - return DACtx->flowConditionImplies(*FlowConditionToken, Val); +bool Environment::flowConditionImplies(const Formula &Val) const { + return DACtx->flowConditionImplies(FlowConditionToken, Val); } void Environment::dump(raw_ostream &OS) const { @@ -795,7 +924,7 @@ void Environment::dump(raw_ostream &OS) const { // fields are printed. OS << "DeclToLoc:\n"; for (auto [D, L] : DeclToLoc) - OS << " [" << D->getName() << ", " << L << "]\n"; + OS << " [" << D->getNameAsString() << ", " << L << "]\n"; OS << "ExprToLoc:\n"; for (auto [E, L] : ExprToLoc) @@ -807,12 +936,93 @@ void Environment::dump(raw_ostream &OS) const { } OS << "FlowConditionToken:\n"; - DACtx->dumpFlowCondition(*FlowConditionToken); + DACtx->dumpFlowCondition(FlowConditionToken, OS); } void Environment::dump() const { dump(llvm::dbgs()); } +AggregateStorageLocation * +getImplicitObjectLocation(const CXXMemberCallExpr &MCE, + const Environment &Env) { + Expr *ImplicitObject = MCE.getImplicitObjectArgument(); + if (ImplicitObject == nullptr) + return nullptr; + StorageLocation *Loc = + Env.getStorageLocation(*ImplicitObject, SkipPast::Reference); + if (Loc == nullptr) + return nullptr; + if (ImplicitObject->getType()->isPointerType()) { + if (auto *Val = cast_or_null(Env.getValue(*Loc))) + return &cast(Val->getPointeeLoc()); + return nullptr; + } + return cast(Loc); +} + +AggregateStorageLocation *getBaseObjectLocation(const MemberExpr &ME, + const Environment &Env) { + Expr *Base = ME.getBase(); + if (Base == nullptr) + return nullptr; + StorageLocation *Loc = Env.getStorageLocation(*Base, SkipPast::Reference); + if (Loc == nullptr) + return nullptr; + if (ME.isArrow()) { + if (auto *Val = cast_or_null(Env.getValue(*Loc))) + return &cast(Val->getPointeeLoc()); + return nullptr; + } + return cast(Loc); +} + +std::vector getFieldsForInitListExpr(const RecordDecl *RD) { + // Unnamed bitfields are only used for padding and do not appear in + // `InitListExpr`'s inits. However, those fields do appear in `RecordDecl`'s + // field list, and we thus need to remove them before mapping inits to + // fields to avoid mapping inits to the wrongs fields. + std::vector Fields; + llvm::copy_if( + RD->fields(), std::back_inserter(Fields), + [](const FieldDecl *Field) { return !Field->isUnnamedBitfield(); }); + return Fields; +} + +StructValue &refreshStructValue(AggregateStorageLocation &Loc, + Environment &Env) { + auto &NewVal = Env.create(Loc); + Env.setValue(Loc, NewVal); + return NewVal; +} + +StructValue &refreshStructValue(const Expr &Expr, Environment &Env) { + assert(Expr.getType()->isRecordType()); + + if (Expr.isPRValue()) { + if (auto *ExistingVal = + cast_or_null(Env.getValueStrict(Expr))) { + auto &NewVal = Env.create(ExistingVal->getAggregateLoc()); + Env.setValueStrict(Expr, NewVal); + return NewVal; + } + + auto &NewVal = *cast(Env.createValue(Expr.getType())); + Env.setValueStrict(Expr, NewVal); + return NewVal; + } + + if (auto *Loc = cast_or_null( + Env.getStorageLocationStrict(Expr))) { + auto &NewVal = Env.create(*Loc); + Env.setValue(*Loc, NewVal); + return NewVal; + } + + auto &NewVal = *cast(Env.createValue(Expr.getType())); + Env.setStorageLocationStrict(Expr, NewVal.getAggregateLoc()); + return NewVal; +} + } // namespace dataflow } // namespace clang diff --git a/contrib/llvm-project/clang/lib/Analysis/FlowSensitive/DebugSupport.cpp b/contrib/llvm-project/clang/lib/Analysis/FlowSensitive/DebugSupport.cpp index d4886f154b3..f8a049adea5 100644 --- a/contrib/llvm-project/clang/lib/Analysis/FlowSensitive/DebugSupport.cpp +++ b/contrib/llvm-project/clang/lib/Analysis/FlowSensitive/DebugSupport.cpp @@ -16,22 +16,12 @@ #include "clang/Analysis/FlowSensitive/DebugSupport.h" #include "clang/Analysis/FlowSensitive/Solver.h" #include "clang/Analysis/FlowSensitive/Value.h" -#include "llvm/ADT/DenseMap.h" -#include "llvm/ADT/STLExtras.h" #include "llvm/ADT/StringRef.h" -#include "llvm/ADT/StringSet.h" #include "llvm/Support/ErrorHandling.h" -#include "llvm/Support/FormatAdapters.h" -#include "llvm/Support/FormatCommon.h" -#include "llvm/Support/FormatVariadic.h" namespace clang { namespace dataflow { -using llvm::AlignStyle; -using llvm::fmt_pad; -using llvm::formatv; - llvm::StringRef debugString(Value::Kind Kind) { switch (Kind) { case Value::Kind::Integer: @@ -46,26 +36,19 @@ llvm::StringRef debugString(Value::Kind Kind) { return "AtomicBool"; case Value::Kind::TopBool: return "TopBool"; - case Value::Kind::Conjunction: - return "Conjunction"; - case Value::Kind::Disjunction: - return "Disjunction"; - case Value::Kind::Negation: - return "Negation"; - case Value::Kind::Implication: - return "Implication"; - case Value::Kind::Biconditional: - return "Biconditional"; + case Value::Kind::FormulaBool: + return "FormulaBool"; } llvm_unreachable("Unhandled value kind"); } -llvm::StringRef debugString(Solver::Result::Assignment Assignment) { +llvm::raw_ostream &operator<<(llvm::raw_ostream &OS, + Solver::Result::Assignment Assignment) { switch (Assignment) { case Solver::Result::Assignment::AssignedFalse: - return "False"; + return OS << "False"; case Solver::Result::Assignment::AssignedTrue: - return "True"; + return OS << "True"; } llvm_unreachable("Booleans can only be assigned true/false"); } @@ -82,177 +65,16 @@ llvm::StringRef debugString(Solver::Result::Status Status) { llvm_unreachable("Unhandled SAT check result status"); } -namespace { - -class DebugStringGenerator { -public: - explicit DebugStringGenerator( - llvm::DenseMap AtomNamesArg) - : Counter(0), AtomNames(std::move(AtomNamesArg)) { -#ifndef NDEBUG - llvm::StringSet<> Names; - for (auto &N : AtomNames) { - assert(Names.insert(N.second).second && - "The same name must not assigned to different atoms"); - } -#endif +llvm::raw_ostream &operator<<(llvm::raw_ostream &OS, const Solver::Result &R) { + OS << debugString(R.getStatus()) << "\n"; + if (auto Solution = R.getSolution()) { + std::vector> Sorted = { + Solution->begin(), Solution->end()}; + llvm::sort(Sorted); + for (const auto &Entry : Sorted) + OS << Entry.first << " = " << Entry.second << "\n"; } - - /// Returns a string representation of a boolean value `B`. - std::string debugString(const BoolValue &B, size_t Depth = 0) { - std::string S; - switch (B.getKind()) { - case Value::Kind::AtomicBool: { - S = getAtomName(&cast(B)); - break; - } - case Value::Kind::Conjunction: { - auto &C = cast(B); - auto L = debugString(C.getLeftSubValue(), Depth + 1); - auto R = debugString(C.getRightSubValue(), Depth + 1); - S = formatv("(and\n{0}\n{1})", L, R); - break; - } - case Value::Kind::Disjunction: { - auto &D = cast(B); - auto L = debugString(D.getLeftSubValue(), Depth + 1); - auto R = debugString(D.getRightSubValue(), Depth + 1); - S = formatv("(or\n{0}\n{1})", L, R); - break; - } - case Value::Kind::Negation: { - auto &N = cast(B); - S = formatv("(not\n{0})", debugString(N.getSubVal(), Depth + 1)); - break; - } - case Value::Kind::Implication: { - auto &IV = cast(B); - auto L = debugString(IV.getLeftSubValue(), Depth + 1); - auto R = debugString(IV.getRightSubValue(), Depth + 1); - S = formatv("(=>\n{0}\n{1})", L, R); - break; - } - case Value::Kind::Biconditional: { - auto &BV = cast(B); - auto L = debugString(BV.getLeftSubValue(), Depth + 1); - auto R = debugString(BV.getRightSubValue(), Depth + 1); - S = formatv("(=\n{0}\n{1})", L, R); - break; - } - default: - llvm_unreachable("Unhandled value kind"); - } - auto Indent = Depth * 4; - return formatv("{0}", fmt_pad(S, Indent, 0)); - } - - std::string debugString(const llvm::DenseSet &Constraints) { - std::vector ConstraintsStrings; - ConstraintsStrings.reserve(Constraints.size()); - for (BoolValue *Constraint : Constraints) { - ConstraintsStrings.push_back(debugString(*Constraint)); - } - llvm::sort(ConstraintsStrings); - - std::string Result; - for (const std::string &S : ConstraintsStrings) { - Result += S; - Result += '\n'; - } - return Result; - } - - /// Returns a string representation of a set of boolean `Constraints` and the - /// `Result` of satisfiability checking on the `Constraints`. - std::string debugString(ArrayRef &Constraints, - const Solver::Result &Result) { - auto Template = R"( -Constraints ------------- -{0:$[ - -]} ------------- -{1}. -{2} -)"; - - std::vector ConstraintsStrings; - ConstraintsStrings.reserve(Constraints.size()); - for (auto &Constraint : Constraints) { - ConstraintsStrings.push_back(debugString(*Constraint)); - } - - auto StatusString = clang::dataflow::debugString(Result.getStatus()); - auto Solution = Result.getSolution(); - auto SolutionString = Solution ? "\n" + debugString(*Solution) : ""; - - return formatv( - Template, - llvm::make_range(ConstraintsStrings.begin(), ConstraintsStrings.end()), - StatusString, SolutionString); - } - -private: - /// Returns a string representation of a truth assignment to atom booleans. - std::string debugString( - const llvm::DenseMap - &AtomAssignments) { - size_t MaxNameLength = 0; - for (auto &AtomName : AtomNames) { - MaxNameLength = std::max(MaxNameLength, AtomName.second.size()); - } - - std::vector Lines; - for (auto &AtomAssignment : AtomAssignments) { - auto Line = formatv("{0} = {1}", - fmt_align(getAtomName(AtomAssignment.first), - AlignStyle::Left, MaxNameLength), - clang::dataflow::debugString(AtomAssignment.second)); - Lines.push_back(Line); - } - llvm::sort(Lines); - - return formatv("{0:$[\n]}", llvm::make_range(Lines.begin(), Lines.end())); - } - - /// Returns the name assigned to `Atom`, either user-specified or created by - /// default rules (B0, B1, ...). - std::string getAtomName(const AtomicBoolValue *Atom) { - auto Entry = AtomNames.try_emplace(Atom, formatv("B{0}", Counter)); - if (Entry.second) { - Counter++; - } - return Entry.first->second; - } - - // Keep track of number of atoms without a user-specified name, used to assign - // non-repeating default names to such atoms. - size_t Counter; - - // Keep track of names assigned to atoms. - llvm::DenseMap AtomNames; -}; - -} // namespace - -std::string -debugString(const BoolValue &B, - llvm::DenseMap AtomNames) { - return DebugStringGenerator(std::move(AtomNames)).debugString(B); -} - -std::string -debugString(const llvm::DenseSet &Constraints, - llvm::DenseMap AtomNames) { - return DebugStringGenerator(std::move(AtomNames)).debugString(Constraints); -} - -std::string -debugString(ArrayRef Constraints, const Solver::Result &Result, - llvm::DenseMap AtomNames) { - return DebugStringGenerator(std::move(AtomNames)) - .debugString(Constraints, Result); + return OS; } } // namespace dataflow diff --git a/contrib/llvm-project/clang/lib/Analysis/FlowSensitive/Formula.cpp b/contrib/llvm-project/clang/lib/Analysis/FlowSensitive/Formula.cpp new file mode 100644 index 00000000000..504ad2fb793 --- /dev/null +++ b/contrib/llvm-project/clang/lib/Analysis/FlowSensitive/Formula.cpp @@ -0,0 +1,82 @@ +//===- Formula.cpp ----------------------------------------------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#include "clang/Analysis/FlowSensitive/Formula.h" +#include "clang/Basic/LLVM.h" +#include "llvm/ADT/STLExtras.h" +#include "llvm/ADT/StringRef.h" +#include "llvm/Support/Allocator.h" +#include "llvm/Support/ErrorHandling.h" +#include + +namespace clang::dataflow { + +Formula &Formula::create(llvm::BumpPtrAllocator &Alloc, Kind K, + ArrayRef Operands, unsigned Value) { + assert(Operands.size() == numOperands(K)); + if (Value != 0) // Currently, formulas have values or operands, not both. + assert(numOperands(K) == 0); + void *Mem = Alloc.Allocate(sizeof(Formula) + + Operands.size() * sizeof(Operands.front()), + alignof(Formula)); + Formula *Result = new (Mem) Formula(); + Result->FormulaKind = K; + Result->Value = Value; + // Operands are stored as `const Formula *`s after the formula itself. + // We don't need to construct an object as pointers are trivial types. + // Formula is alignas(const Formula *), so alignment is satisfied. + llvm::copy(Operands, reinterpret_cast(Result + 1)); + return *Result; +} + +static llvm::StringLiteral sigil(Formula::Kind K) { + switch (K) { + case Formula::AtomRef: + return ""; + case Formula::Not: + return "!"; + case Formula::And: + return " & "; + case Formula::Or: + return " | "; + case Formula::Implies: + return " => "; + case Formula::Equal: + return " = "; + } + llvm_unreachable("unhandled formula kind"); +} + +void Formula::print(llvm::raw_ostream &OS, const AtomNames *Names) const { + if (Names && kind() == AtomRef) + if (auto It = Names->find(getAtom()); It != Names->end()) { + OS << It->second; + return; + } + + switch (numOperands(kind())) { + case 0: + OS << getAtom(); + break; + case 1: + OS << sigil(kind()); + operands()[0]->print(OS, Names); + break; + case 2: + OS << '('; + operands()[0]->print(OS, Names); + OS << sigil(kind()); + operands()[1]->print(OS, Names); + OS << ')'; + break; + default: + llvm_unreachable("unhandled formula arity"); + } +} + +} // namespace clang::dataflow \ No newline at end of file diff --git a/contrib/llvm-project/clang/lib/Analysis/FlowSensitive/HTMLLogger.cpp b/contrib/llvm-project/clang/lib/Analysis/FlowSensitive/HTMLLogger.cpp new file mode 100644 index 00000000000..ee89e074f84 --- /dev/null +++ b/contrib/llvm-project/clang/lib/Analysis/FlowSensitive/HTMLLogger.cpp @@ -0,0 +1,536 @@ +//===-- HTMLLogger.cpp ----------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +// +// This file implements the HTML logger. Given a directory dir/, we write +// dir/0.html for the first analysis, etc. +// These files contain a visualization that allows inspecting the CFG and the +// state of the analysis at each point. +// Static assets (HTMLLogger.js, HTMLLogger.css) and SVG graphs etc are embedded +// so each output file is self-contained. +// +// VIEWS +// +// The timeline and function view are always shown. These allow selecting basic +// blocks, statements within them, and processing iterations (BBs are visited +// multiple times when e.g. loops are involved). +// These are written directly into the HTML body. +// +// There are also listings of particular basic blocks, and dumps of the state +// at particular analysis points (i.e. BB2 iteration 3 statement 2). +// These are only shown when the relevant BB/analysis point is *selected*. +// +// DATA AND TEMPLATES +// +// The HTML proper is mostly static. +// The analysis data is in a JSON object HTMLLoggerData which is embedded as +// a \n"; + + writeCode(); + writeCFG(); + + *OS << "\n"; + *OS << llvm::StringRef(HTMLLogger_html).split("").second; + } + + void enterBlock(const CFGBlock &B) override { + Iters.emplace_back(&B, ++BlockIters[&B]); + ElementIndex = 0; + } + void enterElement(const CFGElement &E) override { + ++ElementIndex; + } + + static std::string blockID(unsigned Block) { + return llvm::formatv("B{0}", Block); + } + static std::string eltID(unsigned Block, unsigned Element) { + return llvm::formatv("B{0}.{1}", Block, Element); + } + static std::string iterID(unsigned Block, unsigned Iter) { + return llvm::formatv("B{0}:{1}", Block, Iter); + } + static std::string elementIterID(unsigned Block, unsigned Iter, + unsigned Element) { + return llvm::formatv("B{0}:{1}_B{0}.{2}", Block, Iter, Element); + } + + // Write the analysis state associated with a particular analysis point. + // FIXME: this dump is fairly opaque. We should show: + // - values associated with the current Stmt + // - values associated with its children + // - meaningful names for values + // - which boolean values are implied true/false by the flow condition + void recordState(TypeErasedDataflowAnalysisState &State) override { + unsigned Block = Iters.back().first->getBlockID(); + unsigned Iter = Iters.back().second; + JOS->attributeObject(elementIterID(Block, Iter, ElementIndex), [&] { + JOS->attribute("block", blockID(Block)); + JOS->attribute("iter", Iter); + JOS->attribute("element", ElementIndex); + + // If this state immediately follows an Expr, show its built-in model. + if (ElementIndex > 0) { + auto S = + Iters.back().first->Elements[ElementIndex - 1].getAs(); + if (const Expr *E = S ? llvm::dyn_cast(S->getStmt()) : nullptr) + if (auto *Loc = State.Env.getStorageLocation(*E, SkipPast::None)) + JOS->attributeObject( + "value", [&] { ModelDumper(*JOS, State.Env).dump(*Loc); }); + } + if (!ContextLogs.empty()) { + JOS->attribute("logs", ContextLogs); + ContextLogs.clear(); + } + { + std::string BuiltinLattice; + llvm::raw_string_ostream BuiltinLatticeS(BuiltinLattice); + State.Env.dump(BuiltinLatticeS); + JOS->attribute("builtinLattice", BuiltinLattice); + } + }); + } + void blockConverged() override { logText("Block converged"); } + + void logText(llvm::StringRef S) override { + ContextLogs.append(S.begin(), S.end()); + ContextLogs.push_back('\n'); + } + +private: + // Write the CFG block details. + // Currently this is just the list of elements in execution order. + // FIXME: an AST dump would be a useful view, too. + void writeBlock(const CFGBlock &B, unsigned Iters) { + JOS->attributeObject(blockID(B.getBlockID()), [&] { + JOS->attribute("iters", Iters); + JOS->attributeArray("elements", [&] { + for (const auto &Elt : B.Elements) { + std::string Dump; + llvm::raw_string_ostream DumpS(Dump); + Elt.dumpToStream(DumpS); + JOS->value(Dump); + } + }); + }); + } + + // Write the code of function being examined. + // We want to overlay the code with s that mark which BB particular + // tokens are associated with, and even which BB element (so that clicking + // can select the right element). + void writeCode() { + if (!CFG->getDecl()) + return; + const auto &AST = CFG->getDecl()->getASTContext(); + bool Invalid = false; + + // Extract the source code from the original file. + // Pretty-printing from the AST would probably be nicer (no macros or + // indentation to worry about), but we need the boundaries of particular + // AST nodes and the printer doesn't provide this. + auto Range = clang::Lexer::makeFileCharRange( + CharSourceRange::getTokenRange(CFG->getDecl()->getSourceRange()), + AST.getSourceManager(), AST.getLangOpts()); + if (Range.isInvalid()) + return; + llvm::StringRef Code = clang::Lexer::getSourceText( + Range, AST.getSourceManager(), AST.getLangOpts(), &Invalid); + if (Invalid) + return; + + static constexpr unsigned Missing = -1; + // TokenInfo stores the BB and set of elements that a token is part of. + struct TokenInfo { + // The basic block this is part of. + // This is the BB of the stmt with the smallest containing range. + unsigned BB = Missing; + unsigned BBPriority = 0; + // The most specific stmt this is part of (smallest range). + unsigned Elt = Missing; + unsigned EltPriority = 0; + // All stmts this is part of. + SmallVector Elts; + + // Mark this token as being part of BB.Elt. + // RangeLen is the character length of the element's range, used to + // distinguish inner vs outer statements. + // For example in `a==0`, token "a" is part of the stmts "a" and "a==0". + // However "a" has a smaller range, so is more specific. Clicking on the + // token "a" should select the stmt "a". + void assign(unsigned BB, unsigned Elt, unsigned RangeLen) { + // A worse BB (larger range) => ignore. + if (this->BB != Missing && BB != this->BB && BBPriority <= RangeLen) + return; + if (BB != this->BB) { + this->BB = BB; + Elts.clear(); + BBPriority = RangeLen; + } + BBPriority = std::min(BBPriority, RangeLen); + Elts.push_back(Elt); + if (this->Elt == Missing || EltPriority > RangeLen) + this->Elt = Elt; + } + bool operator==(const TokenInfo &Other) const { + return std::tie(BB, Elt, Elts) == + std::tie(Other.BB, Other.Elt, Other.Elts); + } + // Write the attributes for the on this token. + void write(llvm::raw_ostream &OS) const { + OS << "class='c"; + if (BB != Missing) + OS << " " << blockID(BB); + for (unsigned Elt : Elts) + OS << " " << eltID(BB, Elt); + OS << "'"; + + if (Elt != Missing) + OS << " data-elt='" << eltID(BB, Elt) << "'"; + if (BB != Missing) + OS << " data-bb='" << blockID(BB) << "'"; + } + }; + + // Construct one TokenInfo per character in a flat array. + // This is inefficient (chars in a token all have the same info) but simple. + std::vector State(Code.size()); + for (const auto *Block : CFG->getCFG()) { + unsigned EltIndex = 0; + for (const auto& Elt : *Block) { + ++EltIndex; + if (const auto S = Elt.getAs()) { + auto EltRange = clang::Lexer::makeFileCharRange( + CharSourceRange::getTokenRange(S->getStmt()->getSourceRange()), + AST.getSourceManager(), AST.getLangOpts()); + if (EltRange.isInvalid()) + continue; + if (EltRange.getBegin() < Range.getBegin() || + EltRange.getEnd() >= Range.getEnd() || + EltRange.getEnd() < Range.getBegin() || + EltRange.getEnd() >= Range.getEnd()) + continue; + unsigned Off = EltRange.getBegin().getRawEncoding() - + Range.getBegin().getRawEncoding(); + unsigned Len = EltRange.getEnd().getRawEncoding() - + EltRange.getBegin().getRawEncoding(); + for (unsigned I = 0; I < Len; ++I) + State[Off + I].assign(Block->getBlockID(), EltIndex, Len); + } + } + } + + // Finally, write the code with the correct s. + unsigned Line = + AST.getSourceManager().getSpellingLineNumber(Range.getBegin()); + *OS << ""; + } + + // Write the CFG diagram, a graph of basic blocks. + // Laying out graphs is hard, so we construct a graphviz description and shell + // out to `dot` to turn it into an SVG. + void writeCFG() { + *OS << "\n"; + } + + // Produce a graphviz description of a CFG. + static std::string buildCFGDot(const clang::CFG &CFG) { + std::string Graph; + llvm::raw_string_ostream GraphS(Graph); + // Graphviz likes to add unhelpful tooltips everywhere, " " suppresses. + GraphS << R"(digraph { + tooltip=" " + node[class=bb, shape=square, fontname="sans-serif", tooltip=" "] + edge[tooltip = " "] +)"; + for (unsigned I = 0; I < CFG.getNumBlockIDs(); ++I) + GraphS << " " << blockID(I) << " [id=" << blockID(I) << "]\n"; + for (const auto *Block : CFG) { + for (const auto &Succ : Block->succs()) { + GraphS << " " << blockID(Block->getBlockID()) << " -> " + << blockID(Succ.getReachableBlock()->getBlockID()) << "\n"; + } + } + GraphS << "}\n"; + return Graph; + } +}; + +// Nothing interesting here, just subprocess/temp-file plumbing. +llvm::Expected renderSVG(llvm::StringRef DotGraph) { + std::string DotPath; + if (const auto *FromEnv = ::getenv("GRAPHVIZ_DOT")) + DotPath = FromEnv; + else { + auto FromPath = llvm::sys::findProgramByName("dot"); + if (!FromPath) + return llvm::createStringError(FromPath.getError(), + "'dot' not found on PATH"); + DotPath = FromPath.get(); + } + + // Create input and output files for `dot` subprocess. + // (We create the output file as empty, to reserve the temp filename). + llvm::SmallString<256> Input, Output; + int InputFD; + if (auto EC = llvm::sys::fs::createTemporaryFile("analysis", ".dot", InputFD, + Input)) + return llvm::createStringError(EC, "failed to create `dot` temp input"); + llvm::raw_fd_ostream(InputFD, /*shouldClose=*/true) << DotGraph; + auto DeleteInput = + llvm::make_scope_exit([&] { llvm::sys::fs::remove(Input); }); + if (auto EC = llvm::sys::fs::createTemporaryFile("analysis", ".svg", Output)) + return llvm::createStringError(EC, "failed to create `dot` temp output"); + auto DeleteOutput = + llvm::make_scope_exit([&] { llvm::sys::fs::remove(Output); }); + + std::vector> Redirects = { + Input, Output, + /*stderr=*/std::nullopt}; + std::string ErrMsg; + int Code = llvm::sys::ExecuteAndWait( + DotPath, {"dot", "-Tsvg"}, /*Env=*/std::nullopt, Redirects, + /*SecondsToWait=*/0, /*MemoryLimit=*/0, &ErrMsg); + if (!ErrMsg.empty()) + return llvm::createStringError(llvm::inconvertibleErrorCode(), + "'dot' failed: " + ErrMsg); + if (Code != 0) + return llvm::createStringError(llvm::inconvertibleErrorCode(), + "'dot' failed (" + llvm::Twine(Code) + ")"); + + auto Buf = llvm::MemoryBuffer::getFile(Output); + if (!Buf) + return llvm::createStringError(Buf.getError(), "Can't read `dot` output"); + + // Output has prefix we don't want. Skip to tag. + llvm::StringRef Result = Buf.get()->getBuffer(); + auto Pos = Result.find(" tag in `dot` output"); + return Result.substr(Pos).str(); +} + +} // namespace + +std::unique_ptr +Logger::html(std::function()> Streams) { + return std::make_unique(std::move(Streams)); +} + +} // namespace clang::dataflow diff --git a/contrib/llvm-project/clang/lib/Analysis/FlowSensitive/HTMLLogger.css b/contrib/llvm-project/clang/lib/Analysis/FlowSensitive/HTMLLogger.css new file mode 100644 index 00000000000..c8212df1f94 --- /dev/null +++ b/contrib/llvm-project/clang/lib/Analysis/FlowSensitive/HTMLLogger.css @@ -0,0 +1,142 @@ +/*===-- HTMLLogger.css ----------------------------------------------------=== +* +* Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +* See https://llvm.org/LICENSE.txt for license information. +* SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +* +*===----------------------------------------------------------------------===*/ +html { font-family: sans-serif; } +body { margin: 0; display: flex; justify-content: left; } +body > * { box-sizing: border-box; } +body > section { + border: 1px solid black; + min-width: 20em; + overflow: auto; + max-height: 100vh; +} +section header { + background-color: #008; + color: white; + font-weight: bold; + font-size: large; +} +section h2 { + font-size: medium; + margin-bottom: 0.5em; + padding-top: 0.5em; + border-top: 1px solid #aaa; +} +#timeline { + min-width: 0; +} +#timeline .entry.hover { + background-color: #aaa; +} +#timeline .entry.iter-select { + background-color: #aac; +} + +#bb-elements { + font-family: monospace; + font-size: x-small; + border-collapse: collapse; +} +#bb-elements td:nth-child(1) { + text-align: right; + width: 4em; + border-right: 1px solid #008; + padding: 0.3em 0.5em; + + font-weight: bold; + color: #888; +}; +#bb-elements tr.hover { + background-color: #abc; +} +#bb-elements tr.elt-select { + background-color: #acf; +} +#iterations { + display: flex; +} +#iterations .chooser { + flex-grow: 1; + text-align: center; +} +#iterations .chooser:not(.iter-select).hover { + background-color: #aaa; +} +#iterations .iter-select { + font-weight: bold; + background-color: #ccc; +} +#iterations .chooser:not(.iter-select) { + text-decoration: underline; + color: blue; +} + +code.filename { + font-weight: bold; + color: black; + background-color: #ccc; + display: block; + text-align: center; +} +code.line { + display: block; + white-space: pre; +} +code.line:before { /* line numbers */ + content: attr(data-line); + display: inline-block; + width: 2em; + text-align: right; + padding-right: 2px; + background-color: #ccc; + border-right: 1px solid #888; + margin-right: 8px; +} +code.line:has(.bb-select):before { + border-right: 4px solid black; + margin-right: 5px; +} +.c.hover, .bb.hover { + filter: saturate(200%) brightness(90%); +} +.c.elt-select { + box-shadow: inset 0 -4px 2px -2px #a00; +} +.bb.bb-select polygon { + stroke-width: 4px; + filter: brightness(70%) saturate(150%); +} +.bb { user-select: none; } +.bb polygon { fill: white; } +#cfg { + position: relative; + margin-left: 0.5em; +} + +.value { + border: 1px solid #888; + font-size: x-small; + flex-grow: 1; +} +.value summary { + background-color: #ace; + display: flex; + justify-content: space-between; +} +.value .address { + font-size: xx-small; + font-family: monospace; + color: #888; +} +.value .property { + display: flex; + margin-top: 0.5em; +} +.value .property .key { + font-weight: bold; + min-width: 5em; +} diff --git a/contrib/llvm-project/clang/lib/Analysis/FlowSensitive/HTMLLogger.html b/contrib/llvm-project/clang/lib/Analysis/FlowSensitive/HTMLLogger.html new file mode 100644 index 00000000000..a60259a99cc --- /dev/null +++ b/contrib/llvm-project/clang/lib/Analysis/FlowSensitive/HTMLLogger.html @@ -0,0 +1,107 @@ + + + + + + + + + + + + + +
+
Timeline
+ +
+ +
+
Function
+
+
+
+ +
+
+
+ +
+ + + +
+
+ +
+ +
+ + + + + diff --git a/contrib/llvm-project/clang/lib/Analysis/FlowSensitive/HTMLLogger.js b/contrib/llvm-project/clang/lib/Analysis/FlowSensitive/HTMLLogger.js new file mode 100644 index 00000000000..6e04bc00f66 --- /dev/null +++ b/contrib/llvm-project/clang/lib/Analysis/FlowSensitive/HTMLLogger.js @@ -0,0 +1,219 @@ +//===-- HTMLLogger.js -----------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +// Based on selected objects, hide/show sections & populate data from templates. +// +// For example, if the selection is {bb="BB4", elt="BB4.6" iter="BB4:2"}: +// - show the "block" and "element" sections +// - re-render templates within these sections (if selection changed) +// - apply "bb-select" to items with class class "BB4", etc +let selection = {}; +function updateSelection(changes, data) { + Object.assign(selection, changes); + + data = Object.create(data); + data.selection = selection; + for (root of document.querySelectorAll('[data-selection]')) + updateSection(root, data); + + for (var k in changes) + applyClassIf(k + '-select', classSelector(changes[k])); +} + +// Given
: +// - hide section if selections x or y are null +// - re-render templates if x or y have changed +function updateSection(root, data) { + let changed = root.selection == null; + root.selection ||= {}; + for (key of root.dataset.selection.split(',')) { + if (!key) continue; + if (data.selection[key] != root.selection[key]) { + root.selection[key] = data.selection[key]; + changed = true; + } + if (data.selection[key] == null) { + root.hidden = true; + return; + } + } + if (changed) { + root.hidden = false; + for (tmpl of root.getElementsByTagName('template')) + reinflate(tmpl, data); + } +} + +// Expands template `tmpl` based on input `data`: +// - interpolates {{expressions}} in text and attributes +// -