Merge llvm-project main llvmorg-17-init-19304-gd0b54bb50e51

This updates llvm, clang, compiler-rt, libc++, libunwind, lld, lldb and
openmp to llvm-project main llvmorg-17-init-19304-gd0b54bb50e51, the
last commit before the upstream release/17.x branch was created.

PR:		273753
MFC after:	1 month

(cherry picked from commit 06c3fb2749bda94cb5201f81ffdb8fa6c3161b2e)
This commit is contained in:
Dimitry Andric 2023-09-02 23:17:18 +02:00
parent 2f3b605b2e
commit fe013be447
6358 changed files with 415762 additions and 227707 deletions

View file

@ -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.

View file

@ -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

View file

@ -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

View file

@ -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);
/**
* @}
*/

View file

@ -1,4 +0,0 @@
module Clang_C {
umbrella "."
module * { export * }
}

View file

@ -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 {

View file

@ -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() {}

View file

@ -447,8 +447,8 @@ class ASTContext : public RefCountedBase<ASTContext> {
};
llvm::DenseMap<Module*, PerModuleInitializers*> 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<Decl*> 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) \

View file

@ -34,7 +34,8 @@ namespace clang {
ArrayRef<intptr_t> 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

View file

@ -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.

View file

@ -104,7 +104,8 @@ public:
Visit(Comment, Comment);
// Decls within functions are visited by the body.
if (!isa<FunctionDecl>(*D) && !isa<ObjCMethodDecl>(*D)) {
if (!isa<FunctionDecl>(*D) && !isa<ObjCMethodDecl>(*D) &&
!isa<BlockDecl>(*D)) {
if (Traversal != TK_AsIs) {
if (const auto *CTSD = dyn_cast<ClassTemplateSpecializationDecl>(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);

View file

@ -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<T>() 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

View file

@ -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

View file

@ -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

View file

@ -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,

View file

@ -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<PartialDiagnosticAt> &Notes) const;
private:
APValue *evaluateValueImpl(SmallVectorImpl<PartialDiagnosticAt> &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<FieldDecl> {
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<FieldDecl> {
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<FieldDecl> {
/// 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<void *, 2, InitStorageKind> 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<InitAndBitWidth*>(Ptr)->BitWidth;
return static_cast<Expr*>(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<void*>(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<InitAndBitWidth*>(Ptr)->Init;
return static_cast<Expr*>(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<InitAndBitWidth*>(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<const VariableArrayType *>(
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

View file

@ -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<init_expr> initializtion.
/// function call or omp_priv<init_expr> 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();

View file

@ -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<LambdaDefinitionData &>(*DefinitionData);
DL.MethodTyInfo = TS;
}
void setLambdaIsGeneric(bool IsGeneric) {
assert(DefinitionData && DefinitionData->IsLambda &&
"setting lambda property of non-lambda class");
auto &DL = static_cast<LambdaDefinitionData &>(*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<unsigned char>(K);
}
void setIsCopyDeductionCandidate(bool isCDC = true) {
FunctionDeclBits.IsCopyDeductionCandidate = isCDC;
}
bool isCopyDeductionCandidate() const {
return FunctionDeclBits.IsCopyDeductionCandidate;
DeductionCandidate getDeductionCandidateKind() const {
return static_cast<DeductionCandidate>(
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<Expr *, 1, bool> 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(); }

View file

@ -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);

View file

@ -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<TemplateArgument> 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<TemplateArgument> 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<TemplateArgument> 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<Common *>(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<TemplateArgument> 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<TemplateArgument> TemplateArgs,
TemplateParameterList *TPL, ASTContext &Context);
TemplateParameterList *TPL, const ASTContext &Context);
static bool classof(const Decl *D) { return classofKind(D->getKind()); }

View file

@ -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.

View file

@ -135,8 +135,8 @@ protected:
void setDependence(ExprDependence Deps) {
ExprBits.Dependent = static_cast<unsigned>(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<PartialDiagnosticAt> *Diag;
SmallVectorImpl<PartialDiagnosticAt> *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<PartialDiagnosticAt> &Notes) const;
SmallVectorImpl<PartialDiagnosticAt> &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<Expr *>(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<unsigned>) 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<IdentKind>(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<Expr>(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<Expr>(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<Expr>(SubExprs[RHS]); }
Expr *getLHS() const { return cast<Expr>(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<DesignatedInitExpr>(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<uintptr_t>(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<uintptr_t>(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<FieldDecl *>(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<uintptr_t>(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<FieldDecl *>(FieldInfo.NameOrField);
}
void setFieldDecl(FieldDecl *FD) {
assert(isFieldDesignator() && "Only valid on a field designator");
FieldInfo.NameOrField = reinterpret_cast<uintptr_t>(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<GenericSelectionExpr, Stmt *,
@ -5639,31 +5712,67 @@ class GenericSelectionExpr final
/// expression in the case where the generic selection expression is not
/// result-dependent. The result index is equal to ResultDependentIndex
/// if and only if the generic selection expression is result-dependent.
unsigned NumAssocs, ResultIndex;
unsigned NumAssocs : 15;
unsigned ResultIndex : 15; // NB: ResultDependentIndex is tied to this width.
unsigned IsExprPredicate : 1;
enum : unsigned {
ResultDependentIndex = std::numeric_limits<unsigned>::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<Stmt *>) 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<TypeSourceInfo *>) const {
return getNumAssocs();
// Add one to account for the controlling type predicate, the remainder
// are the associated types.
return getNumAssocs() + (int)isTypePredicate();
}
template <bool Const> 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<TypeSourceInfo *> 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<TypeSourceInfo *> 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<TypeSourceInfo *> AssocTypes,
ArrayRef<Expr *> 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<TypeSourceInfo *> AssocTypes,
ArrayRef<Expr *> 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<TypeSourceInfo *> 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<TypeSourceInfo *> AssocTypes,
ArrayRef<Expr *> 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<TypeSourceInfo *> AssocTypes,
ArrayRef<Expr *> 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<TypeSourceInfo *> AssocTypes,
ArrayRef<Expr *> 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<Expr>(getTrailingObjects<Stmt *>()[ControllingIndex]);
return cast<Expr>(
getTrailingObjects<Stmt *>()[getIndexOfControllingExpression()]);
}
const Expr *getControllingExpr() const {
return cast<Expr>(getTrailingObjects<Stmt *>()[ControllingIndex]);
return cast<Expr>(
getTrailingObjects<Stmt *>()[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<TypeSourceInfo *>()[getIndexOfControllingType()];
}
const TypeSourceInfo* getControllingType() const {
return getTrailingObjects<TypeSourceInfo *>()[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<Expr>(
getTrailingObjects<Stmt *>()[AssocExprStartIndex + getResultIndex()]);
getTrailingObjects<Stmt *>()[getIndexOfStartOfAssociatedExprs() +
getResultIndex()]);
}
const Expr *getResultExpr() const {
return cast<Expr>(
getTrailingObjects<Stmt *>()[AssocExprStartIndex + getResultIndex()]);
getTrailingObjects<Stmt *>()[getIndexOfStartOfAssociatedExprs() +
getResultIndex()]);
}
ArrayRef<Expr *> getAssocExprs() const {
return {reinterpret_cast<Expr *const *>(getTrailingObjects<Stmt *>() +
AssocExprStartIndex),
getIndexOfStartOfAssociatedExprs()),
NumAssocs};
}
ArrayRef<TypeSourceInfo *> getAssocTypeSourceInfos() const {
return {getTrailingObjects<TypeSourceInfo *>(), NumAssocs};
return {getTrailingObjects<TypeSourceInfo *>() +
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<Expr>(getTrailingObjects<Stmt *>()[AssocExprStartIndex + I]),
getTrailingObjects<TypeSourceInfo *>()[I],
cast<Expr>(
getTrailingObjects<Stmt *>()[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<Expr>(getTrailingObjects<Stmt *>()[AssocExprStartIndex + I]),
getTrailingObjects<TypeSourceInfo *>()[I],
cast<Expr>(
getTrailingObjects<Stmt *>()[getIndexOfStartOfAssociatedExprs() +
I]),
getTrailingObjects<
TypeSourceInfo *>()[getIndexOfStartOfAssociatedTypes() + I],
!isResultDependent() && (getResultIndex() == I));
}
association_range associations() {
AssociationIterator Begin(getTrailingObjects<Stmt *>() +
AssocExprStartIndex,
getTrailingObjects<TypeSourceInfo *>(),
getIndexOfStartOfAssociatedExprs(),
getTrailingObjects<TypeSourceInfo *>() +
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<Stmt *>() +
AssocExprStartIndex,
getTrailingObjects<TypeSourceInfo *>(),
getIndexOfStartOfAssociatedExprs(),
getTrailingObjects<TypeSourceInfo *>() +
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_iterator> semantics() {
return llvm::make_range(semantics_begin(), semantics_end());
ArrayRef<Expr*> semantics() {
return ArrayRef(semantics_begin(), semantics_end());
}
llvm::iterator_range<const_semantics_iterator> semantics() const {
return llvm::make_range(semantics_begin(), semantics_end());
ArrayRef<const Expr*> semantics() const {
return ArrayRef(semantics_begin(), semantics_end());
}
Expr *getSemanticExpr(unsigned index) {

View file

@ -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<Expr *> 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<const Expr *> 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<TypeSourceInfo *, 1> TypeAndInitForm;
/// The location of the left parentheses ('(').
SourceLocation LParenLoc;
@ -3515,30 +3524,31 @@ class CXXUnresolvedConstructExpr final
CXXUnresolvedConstructExpr(QualType T, TypeSourceInfo *TSI,
SourceLocation LParenLoc, ArrayRef<Expr *> 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<Expr *> Args,
SourceLocation RParenLoc);
static CXXUnresolvedConstructExpr *
Create(const ASTContext &Context, QualType T, TypeSourceInfo *TSI,
SourceLocation LParenLoc, ArrayRef<Expr *> 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; }

View file

@ -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,

View file

@ -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<T*>(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<T**>(&Ptr);
}
};
/// A lazy value (of type T) that is within an AST node of type Owner,

View file

@ -23,7 +23,8 @@ namespace detail {
inline Expr *IgnoreExprNodesImpl(Expr *E) { return E; }
template <typename FnTy, typename... FnTys>
Expr *IgnoreExprNodesImpl(Expr *E, FnTy &&Fn, FnTys &&... Fns) {
return IgnoreExprNodesImpl(Fn(E), std::forward<FnTys>(Fns)...);
return IgnoreExprNodesImpl(std::forward<FnTy>(Fn)(E),
std::forward<FnTys>(Fns)...);
}
} // namespace detail
@ -165,6 +166,11 @@ inline Expr *IgnoreParensSingleStep(Expr *E) {
return CE->getChosenSubExpr();
}
else if (auto *PE = dyn_cast<PredefinedExpr>(E)) {
if (PE->isTransparent() && PE->getFunctionName())
return PE->getFunctionName();
}
return E;
}

View file

@ -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;
/// @}
};

View file

@ -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

View file

@ -9046,6 +9046,132 @@ public:
Expr *getSize() const { return getStmtAs<Expr>(); }
};
/// 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<OMPDoacrossClause>,
private llvm::TrailingObjects<OMPDoacrossClause, Expr *> {
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<OMPDoacrossClause>(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<OMPDoacrossClause>(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<Expr *> 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<Stmt **>(varlist_begin()),
reinterpret_cast<Stmt **>(varlist_end()));
}
const_child_range children() const {
auto Children = const_cast<OMPDoacrossClause *>(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

View file

@ -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, "++")

View file

@ -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

View file

@ -450,10 +450,13 @@ let Class = PropertyTypeCase<APValue, "LValue"> in {
lvalueBase ? lvalueBase.dyn_cast<const Expr *>() : nullptr;
bool lvalueBaseIsExpr = (bool) expr;
bool lvalueBaseIsTypeInfo = lvalueBase.is<TypeInfoLValue>();
bool lvalueBaseIsDynamicAlloc = lvalueBase.is<DynamicAllocLValue>();
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<APValue, "LValue"> in {
def : Property<"isTypeInfo", Bool> {
let Read = [{ lvalueBaseIsTypeInfo }];
}
def : Property<"isDynamicAlloc", Bool> {
let Read = [{ lvalueBaseIsDynamicAlloc }];
}
def : Property<"hasBase", Bool> {
let Read = [{ static_cast<bool>(lvalueBase) }];
}
@ -485,9 +491,17 @@ let Class = PropertyTypeCase<APValue, "LValue"> in {
QualType(node.getLValueBase().get<TypeInfoLValue>().getType(), 0)
}];
}
def : Property<"dynamicAlloc", UInt32> {
let Conditional = [{ hasBase && isDynamicAlloc }];
let Read = [{ node.getLValueBase().get<DynamicAllocLValue>().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<APValue, "LValue"> in {
let Read = [{ const_cast<Expr *>(expr) }];
}
def : Property<"decl", DeclRef> {
let Conditional = [{ hasBase && !isTypeInfo && !isExpr }];
let Conditional = [{ hasBase && !isTypeInfo && !isDynamicAlloc && !isExpr }];
let Read = [{ lvalueBase.get<const ValueDecl *>() }];
}
def : Property<"offsetQuantity", UInt32> {
@ -521,6 +535,9 @@ let Class = PropertyTypeCase<APValue, "LValue"> 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<Expr>(*stmt),
*callIndex, *version);
@ -745,8 +762,11 @@ let Class = PropertyTypeCase<TemplateArgument, "Type"> 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<TemplateArgument, "Declaration"> in {
@ -756,16 +776,22 @@ let Class = PropertyTypeCase<TemplateArgument, "Declaration"> 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<TemplateArgument, "NullPtr"> 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<TemplateArgument, "Integral"> in {
@ -775,16 +801,22 @@ let Class = PropertyTypeCase<TemplateArgument, "Integral"> 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<TemplateArgument, "Template"> 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<TemplateArgument, "TemplateExpansion"> in {
@ -798,19 +830,25 @@ let Class = PropertyTypeCase<TemplateArgument, "TemplateExpansion"> 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<TemplateArgument, "Expression"> 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<TemplateArgument, "Pack"> in {

View file

@ -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

View file

@ -2553,7 +2553,11 @@ bool RecursiveASTVisitor<Derived>::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<Derived>::VisitOMPXDynCGroupMemClause(
return true;
}
template <typename Derived>
bool RecursiveASTVisitor<Derived>::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

View file

@ -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:

View file

@ -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<Stmt *>()[varOffset()] = CondVar;
}
Stmt *getInit() {
return hasInitStorage() ? getTrailingObjects<Stmt *>()[initOffset()]
: nullptr;
@ -2324,6 +2338,11 @@ public:
: nullptr;
}
void setConditionVariableDeclStmt(DeclStmt *CondVar) {
assert(hasVarStorage());
getTrailingObjects<Stmt *>()[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<Stmt *>()[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<DeclStmt*>(SubExprs[CONDVAR]);
}
const DeclStmt *getConditionVariableDeclStmt() const {
return reinterpret_cast<DeclStmt*>(SubExprs[CONDVAR]);
}
void setConditionVariableDeclStmt(DeclStmt *CondVar) {
SubExprs[CONDVAR] = CondVar;
}
Expr *getCond() { return reinterpret_cast<Expr*>(SubExprs[COND]); }
Expr *getInc() { return reinterpret_cast<Expr*>(SubExprs[INC]); }
Stmt *getBody() { return SubExprs[BODY]; }
@ -3558,8 +3592,11 @@ public:
llvm::PointerIntPair<VarDecl *, 2, VariableCaptureKind> VarAndKind;
SourceLocation Loc;
Capture() = default;
public:
friend class ASTStmtReader;
friend class CapturedStmt;
/// Create a new capture.
///

View file

@ -75,7 +75,8 @@ class CXXTryStmt final : public Stmt,
unsigned NumHandlers;
size_t numTrailingObjects(OverloadToken<Stmt *>) const { return NumHandlers; }
CXXTryStmt(SourceLocation tryLoc, Stmt *tryBlock, ArrayRef<Stmt*> handlers);
CXXTryStmt(SourceLocation tryLoc, CompoundStmt *tryBlock,
ArrayRef<Stmt *> 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<Stmt*> handlers);
CompoundStmt *tryBlock, ArrayRef<Stmt *> 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<CompoundStmt>(getStoredStmts()[SubStmt::Body]);
}
Stmt *getPromiseDeclStmt() const {
@ -404,13 +408,13 @@ public:
Expr *getDeallocate() const {
return cast_or_null<Expr>(getStoredStmts()[SubStmt::Deallocate]);
}
Stmt *getResultDecl() const { return getStoredStmts()[SubStmt::ResultDecl]; }
Expr *getReturnValueInit() const {
return cast<Expr>(getStoredStmts()[SubStmt::ReturnValue]);
}
Expr *getReturnValue() const {
assert(getReturnStmt());
auto *RS = cast<clang::ReturnStmt>(getReturnStmt());
return RS->getRetValue();
auto *RS = dyn_cast_or_null<clang::ReturnStmt>(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;
}

View file

@ -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<uintptr_t>(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<unsigned> NumExpansions) {
///
/// \param IsDefaulted If 'true', implies that this TemplateArgument
/// corresponds to a default template parameter
TemplateArgument(TemplateName Name, std::optional<unsigned> 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<uintptr_t>(E);
}
@ -226,12 +245,11 @@ public:
/// outlives the TemplateArgument itself.
explicit TemplateArgument(ArrayRef<TemplateArgument> 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;

View file

@ -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(); }

View file

@ -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<NullabilityKind> 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<TemplateTypeParmType>(CanonicalType);
}

View file

@ -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;

View file

@ -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<ObjCProtocolDeclRef>> {
let Read = [{ node->getProtocols() }];
}

View file

@ -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); }

View file

@ -563,8 +563,6 @@ private:
llvm::DenseMap<const CXXRecordDecl *, std::unique_ptr<VirtualBaseInfo>>
VBaseInfo;
void enumerateVFPtrs(const CXXRecordDecl *ForClass, VPtrInfoVector &Result);
void computeVTableRelatedInformation(const CXXRecordDecl *RD) override;
void dumpMethodLocations(const CXXRecordDecl *RD,

View file

@ -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<Decl, CXXConversionDecl>
extern const internal::VariadicDynCastAllOfMatcher<Decl, CXXDeductionGuideDecl>
cxxDeductionGuideDecl;
/// Matches concept declarations.
///
/// Example matches integral
/// \code
/// template<typename T>
/// concept integral = std::is_integral_v<T>;
/// \endcode
extern const internal::VariadicDynCastAllOfMatcher<Decl, ConceptDecl>
conceptDecl;
/// Matches variable declarations.
///
/// Note: this does not match declarations of member variables, which are
@ -1970,6 +1981,45 @@ extern const internal::VariadicDynCastAllOfMatcher<Stmt, CXXDeleteExpr>
extern const internal::VariadicDynCastAllOfMatcher<Stmt, CXXNoexceptExpr>
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<Stmt, ArrayInitLoopExpr>
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<Stmt, ArrayInitIndexExpr>
arrayInitIndexExpr;
/// Matches array subscript expressions.
///
/// Given
@ -2450,6 +2500,17 @@ extern const internal::VariadicDynCastAllOfMatcher<Stmt, DependentCoawaitExpr>
extern const internal::VariadicDynCastAllOfMatcher<Stmt, CoyieldExpr>
coyieldExpr;
/// Matches coroutine body statements.
///
/// coroutineBodyStmt() matches the coroutine below
/// \code
/// generator<int> gen() {
/// co_return;
/// }
/// \endcode
extern const internal::VariadicDynCastAllOfMatcher<Stmt, CoroutineBodyStmt>
coroutineBodyStmt;
/// Matches nullptr literal.
extern const internal::VariadicDynCastAllOfMatcher<Stmt, CXXNullPtrLiteralExpr>
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<CXXDefaultArgExpr>(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<Stmt>, InnerMatcher) {
AST_POLYMORPHIC_MATCHER_P(
hasBody,
AST_POLYMORPHIC_SUPPORTED_TYPES(DoStmt, ForStmt, WhileStmt, CXXForRangeStmt,
FunctionDecl, CoroutineBodyStmt),
internal::Matcher<Stmt>, InnerMatcher) {
if (Finder->isTraversalIgnoringImplicitNodes() && isDefaultedHelper(&Node))
return false;
const Stmt *const Statement = internal::GetBodyMatcher<NodeType>::get(Node);

View file

@ -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 {

View file

@ -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

View file

@ -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<ConsumedStateMap> 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);

View file

@ -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 <vector>
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<const CFGBlock *> Blocks;
// Successor blocks of the *interval*: blocks outside the interval for
// reachable (in one edge) from within the interval.
llvm::SmallDenseSet<const CFGBlock *> 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<CFGInterval> partitionIntoIntervals(const CFG &Cfg);
} // namespace clang
#endif // LLVM_CLANG_ANALYSIS_ANALYSES_INTERVALPARTITION_H

View file

@ -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.

View file

@ -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);

View file

@ -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 <class V>
@ -566,6 +571,10 @@ public:
LiteralT(T Dat) : Literal(ValueType::getValueType<T>()), Val(Dat) {}
LiteralT(const LiteralT<T> &L) : Literal(L), Val(L.Val) {}
// The copy assignment operator is defined as deleted pending further
// motivation.
LiteralT &operator=(const LiteralT<T> &) = delete;
T value() const { return Val;}
T& value() { return Val; }

View file

@ -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:

View file

@ -19,6 +19,8 @@
namespace clang {
using DefMapTy = llvm::DenseMap<const VarDecl *, std::vector<const VarDecl *>>;
/// 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<FixItHint> &FixIts,
const SourceManager &SM);
} // namespace internal
} // end namespace clang
#endif /* LLVM_CLANG_ANALYSIS_ANALYSES_UNSAFEBUFFERUSAGE_H */

View file

@ -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

View file

@ -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,

View file

@ -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<const Decl *, std::optional<Stmt *>> BodyMap;

View file

@ -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

View file

@ -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);

View file

@ -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 <vector>
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 <typename T, typename... Args>
std::enable_if_t<std::is_base_of<StorageLocation, T>::value, T &>
create(Args &&...args) {
// Note: If allocation of individual `StorageLocation`s turns out to be
// costly, consider creating specializations of `create<T>` for commonly
// used `StorageLocation` subclasses and make them use a `BumpPtrAllocator`.
return *cast<T>(
Locs.emplace_back(std::make_unique<T>(std::forward<Args>(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 <typename T, typename... Args>
std::enable_if_t<std::is_base_of<Value, T>::value, T &>
create(Args &&...args) {
// Note: If allocation of individual `Value`s turns out to be costly,
// consider creating specializations of `create<T>` for commonly used
// `Value` subclasses and make them use a `BumpPtrAllocator`.
return *cast<T>(
Vals.emplace_back(std::make_unique<T>(std::forward<Args>(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<AtomicBoolValue>(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<TopBoolValue>(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<Atom>(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<std::unique_ptr<StorageLocation>> Locs;
std::vector<std::unique_ptr<Value>> Vals;
// Indices that are used to avoid recreating the same integer literals and
// composite boolean values.
llvm::DenseMap<llvm::APInt, IntegerValue *> IntegerLiterals;
using FormulaPair = std::pair<const Formula *, const Formula *>;
llvm::DenseMap<FormulaPair, const Formula *> Ands;
llvm::DenseMap<FormulaPair, const Formula *> Ors;
llvm::DenseMap<const Formula *, const Formula *> Nots;
llvm::DenseMap<FormulaPair, const Formula *> Implies;
llvm::DenseMap<FormulaPair, const Formula *> Equals;
llvm::DenseMap<Atom, const Formula *> AtomRefs;
llvm::DenseMap<const Formula *, BoolValue *> FormulaValues;
unsigned NextAtom = 0;
Atom True, False;
};
} // namespace clang::dataflow
#endif // LLVM_CLANG_ANALYSIS_FLOWSENSITIVE__ARENA_H

View file

@ -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 <memory>
@ -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<ControlFlowContext> 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<ControlFlowContext> 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<ControlFlowContext> 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> Cfg,
llvm::DenseMap<const Stmt *, const CFGBlock *> StmtToBlock)
llvm::DenseMap<const Stmt *, const CFGBlock *> 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> Cfg;
llvm::DenseMap<const Stmt *, const CFGBlock *> StmtToBlock;
llvm::BitVector BlockReachable;
};
} // namespace dataflow

View file

@ -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<Derived *>(this)->initialElement()};
}
LatticeJoinEffect joinTypeErased(TypeErasedLattice &E1,
TypeErasedLattice joinTypeErased(const TypeErasedLattice &E1,
const TypeErasedLattice &E2) final {
Lattice &L1 = llvm::any_cast<Lattice &>(E1.Value);
// FIXME: change the signature of join() to avoid copying here.
Lattice L1 = llvm::any_cast<const Lattice &>(E1.Value);
const Lattice &L2 = llvm::any_cast<const Lattice &>(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<Lattice &>(E.Value);
static_cast<Derived *>(this)->transfer(Element, L, Env);
@ -205,8 +208,10 @@ runDataflowAnalysis(
const TypeErasedDataflowAnalysisState &State) {
auto *Lattice =
llvm::any_cast<typename AnalysisT::Lattice>(&State.Lattice.Value);
// FIXME: we should not be copying the environment here!
// Ultimately the PostVisitCFG only gets a const reference anyway.
PostVisitCFG(Element, DataflowAnalysisState<typename AnalysisT::Lattice>{
*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<typename AnalysisT::Lattice>{
llvm::any_cast<typename AnalysisT::Lattice>(
std::move(State.Lattice.Value)),
std::move(State.Env)};
});
return llvm::transformOptional(
std::move(OptState), [](TypeErasedDataflowAnalysisState &&State) {
return DataflowAnalysisState<typename AnalysisT::Lattice>{
llvm::any_cast<typename AnalysisT::Lattice>(
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

View file

@ -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 <cassert>
#include <memory>
@ -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<const FieldDecl *, 4>;
/// Returns the set of all fields in the type.
llvm::DenseSet<const FieldDecl *> 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<ContextSensitiveOptions> 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<Solver> 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 <typename T>
std::enable_if_t<std::is_base_of<StorageLocation, T>::value, T &>
takeOwnership(std::unique_ptr<T> Loc) {
assert(Loc != nullptr);
Locs.push_back(std::move(Loc));
return *cast<T>(Locs.back().get());
}
/// Takes ownership of `Val` and returns a reference to it.
///
/// Requirements:
///
/// `Val` must not be null.
template <typename T>
std::enable_if_t<std::is_base_of<Value, T>::value, T &>
takeOwnership(std::unique_ptr<T> Val) {
assert(Val != nullptr);
Vals.push_back(std::move(Val));
return *cast<T>(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<AtomicBoolValue>());
}
/// 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<TopBoolValue>());
}
/// 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<AtomicBoolValue *, BoolValue *> 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<const Formula *> 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<const FieldDecl *> &Fields);
/// Returns the fields of `Type`, limited to the set of fields modeled by this
/// context.
llvm::DenseSet<const FieldDecl *> 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<BoolValue *> &Constraints,
llvm::DenseSet<AtomicBoolValue *> &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<BoolValue *> Constraints);
Atom Token, llvm::SetVector<const Formula *> &Constraints,
llvm::DenseSet<Atom> &VisitedTokens);
/// Returns true if the solver is able to prove that there is no satisfying
/// assignment for `Constraints`
bool isUnsatisfiable(llvm::DenseSet<BoolValue *> Constraints) {
bool isUnsatisfiable(llvm::SetVector<const Formula *> 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<BoolValue *, BoolValue *> &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<BoolValue *, BoolValue *> &SubstitutionsCache);
std::unique_ptr<Solver> S;
// Storage for the state of a program.
std::vector<std::unique_ptr<StorageLocation>> Locs;
std::vector<std::unique_ptr<Value>> Vals;
std::unique_ptr<Arena> 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<QualType, PointerValue *, NullableQualTypeDenseMapInfo>
NullPointerVals;
AtomicBoolValue &TrueVal;
AtomicBoolValue &FalseVal;
Options Opts;
// Indices that are used to avoid recreating the same composite boolean
// values.
llvm::DenseMap<std::pair<BoolValue *, BoolValue *>, ConjunctionValue *>
ConjunctionVals;
llvm::DenseMap<std::pair<BoolValue *, BoolValue *>, DisjunctionValue *>
DisjunctionVals;
llvm::DenseMap<BoolValue *, NegationValue *> NegationVals;
llvm::DenseMap<std::pair<BoolValue *, BoolValue *>, ImplicationValue *>
ImplicationVals;
llvm::DenseMap<std::pair<BoolValue *, BoolValue *>, 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<AtomicBoolValue *, llvm::DenseSet<AtomicBoolValue *>>
FlowConditionDeps;
llvm::DenseMap<AtomicBoolValue *, BoolValue *> FlowConditionConstraints;
llvm::DenseMap<Atom, llvm::DenseSet<Atom>> FlowConditionDeps;
llvm::DenseMap<Atom, const Formula *> FlowConditionConstraints;
llvm::DenseMap<const FunctionDecl *, ControlFlowContext> FunctionContexts;
// Fields modeled by environments covered by this context.
llvm::DenseSet<const FieldDecl *> ModeledFields;
FieldSet ModeledFields;
std::unique_ptr<Logger> LogOwner; // If created via flags.
};
} // namespace dataflow

View file

@ -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 <memory>
#include <type_traits>
@ -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 <typename T>
std::enable_if_t<std::is_base_of<StorageLocation, T>::value, T &>
takeOwnership(std::unique_ptr<T> 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 <typename T, typename... Args>
std::enable_if_t<std::is_base_of<Value, T>::value, T &>
create(Args &&...args) {
return arena().create<T>(std::forward<Args>(args)...);
}
/// Transfers ownership of `Val` to the analysis context and returns a
/// reference to it.
///
/// Requirements:
///
/// `Val` must not be null.
template <typename T>
std::enable_if_t<std::is_base_of<Value, T>::value, T &>
takeOwnership(std::unique_ptr<T> 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<AtomicBoolValue>(
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<AtomicBoolValue *, BoolValue *> 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<FunctionDecl>(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<QualType> &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<QualType> &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<const Expr *> Args);
/// Assigns storage locations and values to all variables in `Vars`.
void initVars(llvm::DenseSet<const VarDecl *> 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<const DeclContext *> 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<const ValueDecl *, StorageLocation *> DeclToLoc;
llvm::DenseMap<const Expr *, StorageLocation *> ExprToLoc;
// We preserve insertion order so that join/widen process values in
// deterministic sequence. This in turn produces deterministic SAT formulas.
llvm::MapVector<const StorageLocation *, Value *> LocToVal;
llvm::DenseMap<const StorageLocation *, Value *> LocToVal;
// Maps locations of struct members to symbolic values of the structs that own
// them and the decls of the struct members.
llvm::DenseMap<const StorageLocation *,
std::pair<StructValue *, const ValueDecl *>>
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<FieldDecl *> 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

View file

@ -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<const AtomicBoolValue *, std::string> 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<BoolValue *> &Constraints,
llvm::DenseMap<const AtomicBoolValue *, std::string> 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<BoolValue *> Constraints, const Solver::Result &Result,
llvm::DenseMap<const AtomicBoolValue *, std::string> AtomNames = {{}});
inline std::string debugString(
const llvm::DenseSet<BoolValue *> &Constraints,
const Solver::Result &Result,
llvm::DenseMap<const AtomicBoolValue *, std::string> AtomNames = {{}}) {
std::vector<BoolValue *> ConstraintsVec(Constraints.begin(),
Constraints.end());
return debugString(ConstraintsVec, Result, std::move(AtomNames));
}
} // namespace dataflow
} // namespace clang

View file

@ -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 <cassert>
#include <string>
#include <type_traits>
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<Atom>(Value);
}
ArrayRef<const Formula *> operands() const {
return ArrayRef(reinterpret_cast<Formula *const *>(this + 1),
numOperands(kind()));
}
using AtomNames = llvm::DenseMap<Atom, std::string>;
// 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<const Formula *> 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<unsigned>(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<clang::dataflow::Atom> {
using Atom = clang::dataflow::Atom;
using Underlying = std::underlying_type_t<Atom>;
static inline Atom getEmptyKey() { return Atom(Underlying(-1)); }
static inline Atom getTombstoneKey() { return Atom(Underlying(-2)); }
static unsigned getHashValue(const Atom &Val) {
return DenseMapInfo<Underlying>::getHashValue(Underlying(Val));
}
static bool isEqual(const Atom &LHS, const Atom &RHS) { return LHS == RHS; }
};
} // namespace llvm
#endif

View file

@ -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 <memory>
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<Logger> 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<Logger>
html(std::function<std::unique_ptr<llvm::raw_ostream>()>);
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<void(llvm::raw_ostream &)> 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

View file

@ -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<Stmt>`
// FIXME: Rename to ASTMatchSwitch.h
#ifndef LLVM_CLANG_ANALYSIS_FLOWSENSITIVE_MATCHSWITCH_H_
#define LLVM_CLANG_ANALYSIS_FLOWSENSITIVE_MATCHSWITCH_H_
@ -69,11 +68,6 @@ template <typename BaseT, typename State, typename Result = void>
using ASTMatchSwitch =
std::function<Result(const BaseT &, ASTContext &, State &)>;
// FIXME: Remove this alias when all usages of `MatchSwitch` are updated to
// `ASTMatchSwitch<Stmt>`.
template <typename State, typename Result = void>
using MatchSwitch = ASTMatchSwitch<Stmt, State, Result>;
/// 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<MatchSwitchAction<BaseT, State, Result>> Actions;
};
// FIXME: Remove this alias when all usages of `MatchSwitchBuilder` are updated
// to `ASTMatchSwitchBuilder<Stmt>`.
template <typename State, typename Result = void>
using MatchSwitchBuilder = ASTMatchSwitchBuilder<Stmt, State, Result>;
} // namespace dataflow
} // namespace clang
#endif // LLVM_CLANG_ANALYSIS_FLOWSENSITIVE_MATCHSWITCH_H_

View file

@ -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.

View file

@ -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,

View file

@ -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

View file

@ -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

View file

@ -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 <optional>
#include <vector>
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<AtomicBoolValue *, Assignment> Solution) {
static Result Satisfiable(llvm::DenseMap<Atom, Assignment> 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<llvm::DenseMap<AtomicBoolValue *, Assignment>>
getSolution() const {
std::optional<llvm::DenseMap<Atom, Assignment>> getSolution() const {
return Solution;
}
private:
Result(
enum Status SATCheckStatus,
std::optional<llvm::DenseMap<AtomicBoolValue *, Assignment>> Solution)
Result(Status SATCheckStatus,
std::optional<llvm::DenseMap<Atom, Assignment>> Solution)
: SATCheckStatus(SATCheckStatus), Solution(std::move(Solution)) {}
Status SATCheckStatus;
std::optional<llvm::DenseMap<AtomicBoolValue *, Assignment>> Solution;
std::optional<llvm::DenseMap<Atom, Assignment>> Solution;
};
virtual ~Solver() = default;
@ -87,9 +86,12 @@ public:
/// Requirements:
///
/// All elements in `Vals` must not be null.
virtual Result solve(llvm::DenseSet<BoolValue *> Vals) = 0;
virtual Result solve(llvm::ArrayRef<const Formula *> 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

View file

@ -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 <cassert>
#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<const ValueDecl *, StorageLocation *>()) {}
using FieldToLoc = llvm::DenseMap<const ValueDecl *, StorageLocation *>;
AggregateStorageLocation(
QualType Type,
llvm::DenseMap<const ValueDecl *, StorageLocation *> 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<FieldToLoc::const_iterator> children() const {
return {Children.begin(), Children.end()};
}
private:
llvm::DenseMap<const ValueDecl *, StorageLocation *> Children;
FieldToLoc Children;
};
} // namespace dataflow
} // namespace clang
#undef DEBUG_TYPE
#endif // LLVM_CLANG_ANALYSIS_FLOWSENSITIVE_STORAGELOCATION_H

View file

@ -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<std::optional<TypeErasedDataflowAnalysisState>>
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<std::optional<TypeErasedDataflowAnalysisState>> BlockToState;
};
/// Evaluates `S` and updates `Env` accordingly.

View file

@ -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

View file

@ -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 <cassert>
#include <utility>
@ -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<llvm::StringMap<Value *>::const_iterator>
properties() const {
return {Properties.begin(), Properties.end()};
}
private:
Kind ValKind;
llvm::StringMap<Value *> 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<const ValueDecl *, Value *>()) {}
explicit StructValue(llvm::DenseMap<const ValueDecl *, Value *> 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<const ValueDecl *, Value *> Children;
AggregateStorageLocation &Loc;
};
raw_ostream &operator<<(raw_ostream &OS, const Value &Val);

View file

@ -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 <limits>
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<std::int64_t>::max();
public:
Result solve(llvm::DenseSet<BoolValue *> 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<const Formula *> Vals) override;
// The solver reached its maximum number of iterations.
bool reachedLimit() const { return MaxIterations == 0; }
};
} // namespace dataflow

View file

@ -95,35 +95,33 @@ private:
llvm::PointerIntPair<const ProgramPointTag *, 2, unsigned> 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<const Decl *>(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;

View file

@ -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.

View file

@ -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

View file

@ -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))).

View file

@ -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 {

View file

@ -168,6 +168,12 @@ def FunctionLike : SubsetSubject<DeclBase,
[{S->getFunctionType(false) != nullptr}],
"functions, function pointers">;
// Function Pointer is a stricter version of FunctionLike that only allows function
// pointers.
def FunctionPointer : SubsetSubject<DeclBase,
[{S->isFunctionPointerType()}],
"functions pointers">;
def OpenCLKernelFunction
: SubsetSubject<Function, [{S->hasAttr<OpenCLKernelAttr>()}],
"kernel functions">;
@ -287,26 +293,38 @@ class VariadicEnumArgument<string name, string type, list<string> values,
}
// This handles one spelling of an attribute.
class Spelling<string name, string variety> {
class Spelling<string name, string variety, int version = 1> {
string Name = name;
string Variety = variety;
int Version = version;
}
class GNU<string name> : Spelling<name, "GNU">;
class Declspec<string name> : Spelling<name, "Declspec">;
class Microsoft<string name> : Spelling<name, "Microsoft">;
class CXX11<string namespace, string name, int version = 1>
: Spelling<name, "CXX11"> {
: Spelling<name, "CXX11", version> {
string Namespace = namespace;
int Version = version;
}
class C2x<string namespace, string name, int version = 1>
: Spelling<name, "C2x"> {
: Spelling<name, "C2x", version> {
string Namespace = namespace;
int Version = version;
}
class Keyword<string name> : Spelling<name, "Keyword">;
class Keyword<string name, bit hasOwnParseRules>
: Spelling<name, "Keyword"> {
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<string name> : Keyword<name, 0> {}
// A keyword that has its own individual parsing rules.
class CustomKeyword<string name> : Keyword<name, 1> {}
class Pragma<string namespace, string name> : Spelling<name, "Pragma"> {
string Namespace = namespace;
}
@ -321,7 +339,8 @@ class GCC<string name, bit allowInC = 1> : Spelling<name, "GCC"> {
// The Clang spelling implies GNU<name>, CXX11<"clang", name>, and optionally,
// C2x<"clang", name>. This spelling should be used for any Clang-specific
// attributes.
class Clang<string name, bit allowInC = 1> : Spelling<name, "Clang"> {
class Clang<string name, bit allowInC = 1, int version = 1>
: Spelling<name, "Clang", version> {
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<TargetAnyArm> {
}
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<TargetArch<
["aarch64", "aarch64_be", "riscv32", "riscv64", "x86", "x86_64"]>> {
["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<TargetAVR> {
}
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<Function, "FunctionDecl">];
let Subjects = SubjectList<[LocalVar]>;
let Documentation = [Undocumented];
let Documentation = [CleanupDocs];
}
def CmseNSEntry : InheritableAttr, TargetSpecificAttr<TargetARM> {
@ -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<TargetNVPTX> {
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<TargetRISCV> {
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<TargetAArch64> {
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<Function, "Function">,
@ -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<TargetWebAssembly> {
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];
}

View file

@ -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 <riscv_vector.h>
#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 <https://docs.microsoft.com/en-us/windows/win32/secbp/pe-metadata>`
@ -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<int> 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<int> 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)
<https://github.com/ARM-software/abi-aa>`_ 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 <https://github.com/ARM-software/acle>`_
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.
}];
}

View file

@ -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:
/// <vardecl> : <semantic>
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;
}

View file

@ -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")

View file

@ -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

View file

@ -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")

View file

@ -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

View file

@ -19,3 +19,4 @@
#undef GET_NEON_BUILTINS
#undef BUILTIN
#undef TARGET_BUILTIN

View file

@ -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")

File diff suppressed because it is too large Load diff

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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")

View file

@ -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)

Some files were not shown because too many files have changed in this diff Show more