Merge llvm-project main llvmorg-15-init-15358-g53dc0f10787

This updates llvm, clang, compiler-rt, libc++, libunwind, lld, lldb and
openmp to llvmorg-15-init-15358-g53dc0f10787.

PR:		265425
MFC after:	2 weeks
This commit is contained in:
Dimitry Andric
2022-07-04 21:20:19 +02:00
6045 changed files with 368606 additions and 154912 deletions
+2 -1
View File
@@ -2353,7 +2353,8 @@ _clang_tblgen= \
usr.bin/clang/llvm-tblgen
.if ${MK_CLANG_BOOTSTRAP} != "no" || ${MK_CLANG} != "no" || \
${MK_LLDB} != "no"
_clang_tblgen+= usr.bin/clang/clang-tblgen
_clang_tblgen+= lib/clang/libclangminimal
_clang_tblgen+= usr.bin/clang/clang-tblgen
.endif
.if ${MK_LLDB} != "no"
_clang_tblgen+= usr.bin/clang/lldb-tblgen
+318
View File
@@ -52,6 +52,324 @@
# xargs -n1 | sort | uniq -d;
# done
# 20230208: new clang import which bumps version from 14.0.5 to 15.0.0
OLD_FILES+=usr/lib/clang/14.0.5/include/cuda_wrappers/algorithm
OLD_FILES+=usr/lib/clang/14.0.5/include/cuda_wrappers/complex
OLD_FILES+=usr/lib/clang/14.0.5/include/cuda_wrappers/new
OLD_DIRS+=usr/lib/clang/14.0.5/include/cuda_wrappers
OLD_FILES+=usr/lib/clang/14.0.5/include/fuzzer/FuzzedDataProvider.h
OLD_DIRS+=usr/lib/clang/14.0.5/include/fuzzer
OLD_FILES+=usr/lib/clang/14.0.5/include/openmp_wrappers/__clang_openmp_device_functions.h
OLD_FILES+=usr/lib/clang/14.0.5/include/openmp_wrappers/cmath
OLD_FILES+=usr/lib/clang/14.0.5/include/openmp_wrappers/complex
OLD_FILES+=usr/lib/clang/14.0.5/include/openmp_wrappers/complex.h
OLD_FILES+=usr/lib/clang/14.0.5/include/openmp_wrappers/complex_cmath.h
OLD_FILES+=usr/lib/clang/14.0.5/include/openmp_wrappers/math.h
OLD_FILES+=usr/lib/clang/14.0.5/include/openmp_wrappers/new
OLD_DIRS+=usr/lib/clang/14.0.5/include/openmp_wrappers
OLD_FILES+=usr/lib/clang/14.0.5/include/ppc_wrappers/emmintrin.h
OLD_FILES+=usr/lib/clang/14.0.5/include/ppc_wrappers/mm_malloc.h
OLD_FILES+=usr/lib/clang/14.0.5/include/ppc_wrappers/mmintrin.h
OLD_FILES+=usr/lib/clang/14.0.5/include/ppc_wrappers/pmmintrin.h
OLD_FILES+=usr/lib/clang/14.0.5/include/ppc_wrappers/smmintrin.h
OLD_FILES+=usr/lib/clang/14.0.5/include/ppc_wrappers/tmmintrin.h
OLD_FILES+=usr/lib/clang/14.0.5/include/ppc_wrappers/xmmintrin.h
OLD_DIRS+=usr/lib/clang/14.0.5/include/ppc_wrappers
OLD_FILES+=usr/lib/clang/14.0.5/include/profile/InstrProfData.inc
OLD_FILES+=usr/lib/clang/14.0.5/include/profile/MemProfData.inc
OLD_DIRS+=usr/lib/clang/14.0.5/include/profile
OLD_FILES+=usr/lib/clang/14.0.5/include/sanitizer/allocator_interface.h
OLD_FILES+=usr/lib/clang/14.0.5/include/sanitizer/asan_interface.h
OLD_FILES+=usr/lib/clang/14.0.5/include/sanitizer/common_interface_defs.h
OLD_FILES+=usr/lib/clang/14.0.5/include/sanitizer/coverage_interface.h
OLD_FILES+=usr/lib/clang/14.0.5/include/sanitizer/dfsan_interface.h
OLD_FILES+=usr/lib/clang/14.0.5/include/sanitizer/hwasan_interface.h
OLD_FILES+=usr/lib/clang/14.0.5/include/sanitizer/linux_syscall_hooks.h
OLD_FILES+=usr/lib/clang/14.0.5/include/sanitizer/lsan_interface.h
OLD_FILES+=usr/lib/clang/14.0.5/include/sanitizer/memprof_interface.h
OLD_FILES+=usr/lib/clang/14.0.5/include/sanitizer/msan_interface.h
OLD_FILES+=usr/lib/clang/14.0.5/include/sanitizer/netbsd_syscall_hooks.h
OLD_FILES+=usr/lib/clang/14.0.5/include/sanitizer/scudo_interface.h
OLD_FILES+=usr/lib/clang/14.0.5/include/sanitizer/tsan_interface.h
OLD_FILES+=usr/lib/clang/14.0.5/include/sanitizer/tsan_interface_atomic.h
OLD_FILES+=usr/lib/clang/14.0.5/include/sanitizer/ubsan_interface.h
OLD_DIRS+=usr/lib/clang/14.0.5/include/sanitizer
OLD_FILES+=usr/lib/clang/14.0.5/include/xray/xray_interface.h
OLD_FILES+=usr/lib/clang/14.0.5/include/xray/xray_log_interface.h
OLD_FILES+=usr/lib/clang/14.0.5/include/xray/xray_records.h
OLD_DIRS+=usr/lib/clang/14.0.5/include/xray
OLD_FILES+=usr/lib/clang/14.0.5/include/__clang_cuda_builtin_vars.h
OLD_FILES+=usr/lib/clang/14.0.5/include/__clang_cuda_cmath.h
OLD_FILES+=usr/lib/clang/14.0.5/include/__clang_cuda_complex_builtins.h
OLD_FILES+=usr/lib/clang/14.0.5/include/__clang_cuda_device_functions.h
OLD_FILES+=usr/lib/clang/14.0.5/include/__clang_cuda_intrinsics.h
OLD_FILES+=usr/lib/clang/14.0.5/include/__clang_cuda_libdevice_declares.h
OLD_FILES+=usr/lib/clang/14.0.5/include/__clang_cuda_math.h
OLD_FILES+=usr/lib/clang/14.0.5/include/__clang_cuda_math_forward_declares.h
OLD_FILES+=usr/lib/clang/14.0.5/include/__clang_cuda_runtime_wrapper.h
OLD_FILES+=usr/lib/clang/14.0.5/include/__clang_cuda_texture_intrinsics.h
OLD_FILES+=usr/lib/clang/14.0.5/include/__clang_hip_cmath.h
OLD_FILES+=usr/lib/clang/14.0.5/include/__clang_hip_libdevice_declares.h
OLD_FILES+=usr/lib/clang/14.0.5/include/__clang_hip_math.h
OLD_FILES+=usr/lib/clang/14.0.5/include/__clang_hip_runtime_wrapper.h
OLD_FILES+=usr/lib/clang/14.0.5/include/__stddef_max_align_t.h
OLD_FILES+=usr/lib/clang/14.0.5/include/__wmmintrin_aes.h
OLD_FILES+=usr/lib/clang/14.0.5/include/__wmmintrin_pclmul.h
OLD_FILES+=usr/lib/clang/14.0.5/include/adxintrin.h
OLD_FILES+=usr/lib/clang/14.0.5/include/altivec.h
OLD_FILES+=usr/lib/clang/14.0.5/include/ammintrin.h
OLD_FILES+=usr/lib/clang/14.0.5/include/amxintrin.h
OLD_FILES+=usr/lib/clang/14.0.5/include/arm64intr.h
OLD_FILES+=usr/lib/clang/14.0.5/include/arm_acle.h
OLD_FILES+=usr/lib/clang/14.0.5/include/arm_bf16.h
OLD_FILES+=usr/lib/clang/14.0.5/include/arm_cde.h
OLD_FILES+=usr/lib/clang/14.0.5/include/arm_cmse.h
OLD_FILES+=usr/lib/clang/14.0.5/include/arm_fp16.h
OLD_FILES+=usr/lib/clang/14.0.5/include/arm_mve.h
OLD_FILES+=usr/lib/clang/14.0.5/include/arm_neon.h
OLD_FILES+=usr/lib/clang/14.0.5/include/arm_neon_sve_bridge.h
OLD_FILES+=usr/lib/clang/14.0.5/include/arm_sve.h
OLD_FILES+=usr/lib/clang/14.0.5/include/armintr.h
OLD_FILES+=usr/lib/clang/14.0.5/include/avx2intrin.h
OLD_FILES+=usr/lib/clang/14.0.5/include/avx512bf16intrin.h
OLD_FILES+=usr/lib/clang/14.0.5/include/avx512bitalgintrin.h
OLD_FILES+=usr/lib/clang/14.0.5/include/avx512bwintrin.h
OLD_FILES+=usr/lib/clang/14.0.5/include/avx512cdintrin.h
OLD_FILES+=usr/lib/clang/14.0.5/include/avx512dqintrin.h
OLD_FILES+=usr/lib/clang/14.0.5/include/avx512erintrin.h
OLD_FILES+=usr/lib/clang/14.0.5/include/avx512fintrin.h
OLD_FILES+=usr/lib/clang/14.0.5/include/avx512fp16intrin.h
OLD_FILES+=usr/lib/clang/14.0.5/include/avx512ifmaintrin.h
OLD_FILES+=usr/lib/clang/14.0.5/include/avx512ifmavlintrin.h
OLD_FILES+=usr/lib/clang/14.0.5/include/avx512pfintrin.h
OLD_FILES+=usr/lib/clang/14.0.5/include/avx512vbmi2intrin.h
OLD_FILES+=usr/lib/clang/14.0.5/include/avx512vbmiintrin.h
OLD_FILES+=usr/lib/clang/14.0.5/include/avx512vbmivlintrin.h
OLD_FILES+=usr/lib/clang/14.0.5/include/avx512vlbf16intrin.h
OLD_FILES+=usr/lib/clang/14.0.5/include/avx512vlbitalgintrin.h
OLD_FILES+=usr/lib/clang/14.0.5/include/avx512vlbwintrin.h
OLD_FILES+=usr/lib/clang/14.0.5/include/avx512vlcdintrin.h
OLD_FILES+=usr/lib/clang/14.0.5/include/avx512vldqintrin.h
OLD_FILES+=usr/lib/clang/14.0.5/include/avx512vlfp16intrin.h
OLD_FILES+=usr/lib/clang/14.0.5/include/avx512vlintrin.h
OLD_FILES+=usr/lib/clang/14.0.5/include/avx512vlvbmi2intrin.h
OLD_FILES+=usr/lib/clang/14.0.5/include/avx512vlvnniintrin.h
OLD_FILES+=usr/lib/clang/14.0.5/include/avx512vlvp2intersectintrin.h
OLD_FILES+=usr/lib/clang/14.0.5/include/avx512vnniintrin.h
OLD_FILES+=usr/lib/clang/14.0.5/include/avx512vp2intersectintrin.h
OLD_FILES+=usr/lib/clang/14.0.5/include/avx512vpopcntdqintrin.h
OLD_FILES+=usr/lib/clang/14.0.5/include/avx512vpopcntdqvlintrin.h
OLD_FILES+=usr/lib/clang/14.0.5/include/avxintrin.h
OLD_FILES+=usr/lib/clang/14.0.5/include/avxvnniintrin.h
OLD_FILES+=usr/lib/clang/14.0.5/include/bmi2intrin.h
OLD_FILES+=usr/lib/clang/14.0.5/include/bmiintrin.h
OLD_FILES+=usr/lib/clang/14.0.5/include/builtins.h
OLD_FILES+=usr/lib/clang/14.0.5/include/cet.h
OLD_FILES+=usr/lib/clang/14.0.5/include/cetintrin.h
OLD_FILES+=usr/lib/clang/14.0.5/include/cldemoteintrin.h
OLD_FILES+=usr/lib/clang/14.0.5/include/clflushoptintrin.h
OLD_FILES+=usr/lib/clang/14.0.5/include/clwbintrin.h
OLD_FILES+=usr/lib/clang/14.0.5/include/clzerointrin.h
OLD_FILES+=usr/lib/clang/14.0.5/include/cpuid.h
OLD_FILES+=usr/lib/clang/14.0.5/include/crc32intrin.h
OLD_FILES+=usr/lib/clang/14.0.5/include/emmintrin.h
OLD_FILES+=usr/lib/clang/14.0.5/include/enqcmdintrin.h
OLD_FILES+=usr/lib/clang/14.0.5/include/f16cintrin.h
OLD_FILES+=usr/lib/clang/14.0.5/include/float.h
OLD_FILES+=usr/lib/clang/14.0.5/include/fma4intrin.h
OLD_FILES+=usr/lib/clang/14.0.5/include/fmaintrin.h
OLD_FILES+=usr/lib/clang/14.0.5/include/fxsrintrin.h
OLD_FILES+=usr/lib/clang/14.0.5/include/gfniintrin.h
OLD_FILES+=usr/lib/clang/14.0.5/include/hexagon_circ_brev_intrinsics.h
OLD_FILES+=usr/lib/clang/14.0.5/include/hexagon_protos.h
OLD_FILES+=usr/lib/clang/14.0.5/include/hexagon_types.h
OLD_FILES+=usr/lib/clang/14.0.5/include/hresetintrin.h
OLD_FILES+=usr/lib/clang/14.0.5/include/htmintrin.h
OLD_FILES+=usr/lib/clang/14.0.5/include/htmxlintrin.h
OLD_FILES+=usr/lib/clang/14.0.5/include/hvx_hexagon_protos.h
OLD_FILES+=usr/lib/clang/14.0.5/include/ia32intrin.h
OLD_FILES+=usr/lib/clang/14.0.5/include/immintrin.h
OLD_FILES+=usr/lib/clang/14.0.5/include/intrin.h
OLD_FILES+=usr/lib/clang/14.0.5/include/inttypes.h
OLD_FILES+=usr/lib/clang/14.0.5/include/invpcidintrin.h
OLD_FILES+=usr/lib/clang/14.0.5/include/iso646.h
OLD_FILES+=usr/lib/clang/14.0.5/include/keylockerintrin.h
OLD_FILES+=usr/lib/clang/14.0.5/include/limits.h
OLD_FILES+=usr/lib/clang/14.0.5/include/lwpintrin.h
OLD_FILES+=usr/lib/clang/14.0.5/include/lzcntintrin.h
OLD_FILES+=usr/lib/clang/14.0.5/include/mm3dnow.h
OLD_FILES+=usr/lib/clang/14.0.5/include/mm_malloc.h
OLD_FILES+=usr/lib/clang/14.0.5/include/mmintrin.h
OLD_FILES+=usr/lib/clang/14.0.5/include/module.modulemap
OLD_FILES+=usr/lib/clang/14.0.5/include/movdirintrin.h
OLD_FILES+=usr/lib/clang/14.0.5/include/msa.h
OLD_FILES+=usr/lib/clang/14.0.5/include/mwaitxintrin.h
OLD_FILES+=usr/lib/clang/14.0.5/include/nmmintrin.h
OLD_FILES+=usr/lib/clang/14.0.5/include/omp-tools.h
OLD_FILES+=usr/lib/clang/14.0.5/include/omp.h
OLD_FILES+=usr/lib/clang/14.0.5/include/ompt.h
OLD_FILES+=usr/lib/clang/14.0.5/include/opencl-c-base.h
OLD_FILES+=usr/lib/clang/14.0.5/include/opencl-c.h
OLD_FILES+=usr/lib/clang/14.0.5/include/pconfigintrin.h
OLD_FILES+=usr/lib/clang/14.0.5/include/pkuintrin.h
OLD_FILES+=usr/lib/clang/14.0.5/include/pmmintrin.h
OLD_FILES+=usr/lib/clang/14.0.5/include/popcntintrin.h
OLD_FILES+=usr/lib/clang/14.0.5/include/prfchwintrin.h
OLD_FILES+=usr/lib/clang/14.0.5/include/ptwriteintrin.h
OLD_FILES+=usr/lib/clang/14.0.5/include/rdseedintrin.h
OLD_FILES+=usr/lib/clang/14.0.5/include/riscv_vector.h
OLD_FILES+=usr/lib/clang/14.0.5/include/rtmintrin.h
OLD_FILES+=usr/lib/clang/14.0.5/include/s390intrin.h
OLD_FILES+=usr/lib/clang/14.0.5/include/serializeintrin.h
OLD_FILES+=usr/lib/clang/14.0.5/include/sgxintrin.h
OLD_FILES+=usr/lib/clang/14.0.5/include/shaintrin.h
OLD_FILES+=usr/lib/clang/14.0.5/include/smmintrin.h
OLD_FILES+=usr/lib/clang/14.0.5/include/stdalign.h
OLD_FILES+=usr/lib/clang/14.0.5/include/stdarg.h
OLD_FILES+=usr/lib/clang/14.0.5/include/stdatomic.h
OLD_FILES+=usr/lib/clang/14.0.5/include/stdbool.h
OLD_FILES+=usr/lib/clang/14.0.5/include/stddef.h
OLD_FILES+=usr/lib/clang/14.0.5/include/stdint.h
OLD_FILES+=usr/lib/clang/14.0.5/include/stdnoreturn.h
OLD_FILES+=usr/lib/clang/14.0.5/include/tbmintrin.h
OLD_FILES+=usr/lib/clang/14.0.5/include/tgmath.h
OLD_FILES+=usr/lib/clang/14.0.5/include/tmmintrin.h
OLD_FILES+=usr/lib/clang/14.0.5/include/tsxldtrkintrin.h
OLD_FILES+=usr/lib/clang/14.0.5/include/uintrintrin.h
OLD_FILES+=usr/lib/clang/14.0.5/include/unwind.h
OLD_FILES+=usr/lib/clang/14.0.5/include/vadefs.h
OLD_FILES+=usr/lib/clang/14.0.5/include/vaesintrin.h
OLD_FILES+=usr/lib/clang/14.0.5/include/varargs.h
OLD_FILES+=usr/lib/clang/14.0.5/include/vecintrin.h
OLD_FILES+=usr/lib/clang/14.0.5/include/vpclmulqdqintrin.h
OLD_FILES+=usr/lib/clang/14.0.5/include/waitpkgintrin.h
OLD_FILES+=usr/lib/clang/14.0.5/include/wasm_simd128.h
OLD_FILES+=usr/lib/clang/14.0.5/include/wbnoinvdintrin.h
OLD_FILES+=usr/lib/clang/14.0.5/include/wmmintrin.h
OLD_FILES+=usr/lib/clang/14.0.5/include/x86gprintrin.h
OLD_FILES+=usr/lib/clang/14.0.5/include/x86intrin.h
OLD_FILES+=usr/lib/clang/14.0.5/include/xmmintrin.h
OLD_FILES+=usr/lib/clang/14.0.5/include/xopintrin.h
OLD_FILES+=usr/lib/clang/14.0.5/include/xsavecintrin.h
OLD_FILES+=usr/lib/clang/14.0.5/include/xsaveintrin.h
OLD_FILES+=usr/lib/clang/14.0.5/include/xsaveoptintrin.h
OLD_FILES+=usr/lib/clang/14.0.5/include/xsavesintrin.h
OLD_FILES+=usr/lib/clang/14.0.5/include/xtestintrin.h
OLD_DIRS+=usr/lib/clang/14.0.5/include
OLD_FILES+=usr/lib/clang/14.0.5/lib/freebsd/libclang_rt.asan-aarch64.a
OLD_FILES+=usr/lib/clang/14.0.5/lib/freebsd/libclang_rt.asan-aarch64.so
OLD_FILES+=usr/lib/clang/14.0.5/lib/freebsd/libclang_rt.asan-arm.a
OLD_FILES+=usr/lib/clang/14.0.5/lib/freebsd/libclang_rt.asan-arm.so
OLD_FILES+=usr/lib/clang/14.0.5/lib/freebsd/libclang_rt.asan-armhf.a
OLD_FILES+=usr/lib/clang/14.0.5/lib/freebsd/libclang_rt.asan-armhf.so
OLD_FILES+=usr/lib/clang/14.0.5/lib/freebsd/libclang_rt.asan-i386.a
OLD_FILES+=usr/lib/clang/14.0.5/lib/freebsd/libclang_rt.asan-i386.so
OLD_FILES+=usr/lib/clang/14.0.5/lib/freebsd/libclang_rt.asan-preinit-aarch64.a
OLD_FILES+=usr/lib/clang/14.0.5/lib/freebsd/libclang_rt.asan-preinit-arm.a
OLD_FILES+=usr/lib/clang/14.0.5/lib/freebsd/libclang_rt.asan-preinit-armhf.a
OLD_FILES+=usr/lib/clang/14.0.5/lib/freebsd/libclang_rt.asan-preinit-i386.a
OLD_FILES+=usr/lib/clang/14.0.5/lib/freebsd/libclang_rt.asan-preinit-x86_64.a
OLD_FILES+=usr/lib/clang/14.0.5/lib/freebsd/libclang_rt.asan-x86_64.a
OLD_FILES+=usr/lib/clang/14.0.5/lib/freebsd/libclang_rt.asan-x86_64.so
OLD_FILES+=usr/lib/clang/14.0.5/lib/freebsd/libclang_rt.asan_cxx-aarch64.a
OLD_FILES+=usr/lib/clang/14.0.5/lib/freebsd/libclang_rt.asan_cxx-arm.a
OLD_FILES+=usr/lib/clang/14.0.5/lib/freebsd/libclang_rt.asan_cxx-armhf.a
OLD_FILES+=usr/lib/clang/14.0.5/lib/freebsd/libclang_rt.asan_cxx-i386.a
OLD_FILES+=usr/lib/clang/14.0.5/lib/freebsd/libclang_rt.asan_cxx-x86_64.a
OLD_FILES+=usr/lib/clang/14.0.5/lib/freebsd/libclang_rt.asan_static-i386.a
OLD_FILES+=usr/lib/clang/14.0.5/lib/freebsd/libclang_rt.asan_static-x86_64.a
OLD_FILES+=usr/lib/clang/14.0.5/lib/freebsd/libclang_rt.cfi-aarch64.a
OLD_FILES+=usr/lib/clang/14.0.5/lib/freebsd/libclang_rt.cfi-arm.a
OLD_FILES+=usr/lib/clang/14.0.5/lib/freebsd/libclang_rt.cfi-armhf.a
OLD_FILES+=usr/lib/clang/14.0.5/lib/freebsd/libclang_rt.cfi-i386.a
OLD_FILES+=usr/lib/clang/14.0.5/lib/freebsd/libclang_rt.cfi-x86_64.a
OLD_FILES+=usr/lib/clang/14.0.5/lib/freebsd/libclang_rt.cfi_diag-aarch64.a
OLD_FILES+=usr/lib/clang/14.0.5/lib/freebsd/libclang_rt.cfi_diag-arm.a
OLD_FILES+=usr/lib/clang/14.0.5/lib/freebsd/libclang_rt.cfi_diag-armhf.a
OLD_FILES+=usr/lib/clang/14.0.5/lib/freebsd/libclang_rt.cfi_diag-i386.a
OLD_FILES+=usr/lib/clang/14.0.5/lib/freebsd/libclang_rt.cfi_diag-x86_64.a
OLD_FILES+=usr/lib/clang/14.0.5/lib/freebsd/libclang_rt.dd-aarch64.a
OLD_FILES+=usr/lib/clang/14.0.5/lib/freebsd/libclang_rt.dd-x86_64.a
OLD_FILES+=usr/lib/clang/14.0.5/lib/freebsd/libclang_rt.fuzzer-aarch64.a
OLD_FILES+=usr/lib/clang/14.0.5/lib/freebsd/libclang_rt.fuzzer-x86_64.a
OLD_FILES+=usr/lib/clang/14.0.5/lib/freebsd/libclang_rt.fuzzer_interceptors-x86_64.a
OLD_FILES+=usr/lib/clang/14.0.5/lib/freebsd/libclang_rt.fuzzer_no_main-aarch64.a
OLD_FILES+=usr/lib/clang/14.0.5/lib/freebsd/libclang_rt.fuzzer_no_main-x86_64.a
OLD_FILES+=usr/lib/clang/14.0.5/lib/freebsd/libclang_rt.msan-aarch64.a
OLD_FILES+=usr/lib/clang/14.0.5/lib/freebsd/libclang_rt.msan-x86_64.a
OLD_FILES+=usr/lib/clang/14.0.5/lib/freebsd/libclang_rt.msan_cxx-aarch64.a
OLD_FILES+=usr/lib/clang/14.0.5/lib/freebsd/libclang_rt.msan_cxx-x86_64.a
OLD_FILES+=usr/lib/clang/14.0.5/lib/freebsd/libclang_rt.profile-aarch64.a
OLD_FILES+=usr/lib/clang/14.0.5/lib/freebsd/libclang_rt.profile-arm.a
OLD_FILES+=usr/lib/clang/14.0.5/lib/freebsd/libclang_rt.profile-armhf.a
OLD_FILES+=usr/lib/clang/14.0.5/lib/freebsd/libclang_rt.profile-i386.a
OLD_FILES+=usr/lib/clang/14.0.5/lib/freebsd/libclang_rt.profile-powerpc.a
OLD_FILES+=usr/lib/clang/14.0.5/lib/freebsd/libclang_rt.profile-powerpc64.a
OLD_FILES+=usr/lib/clang/14.0.5/lib/freebsd/libclang_rt.profile-powerpc64le.a
OLD_FILES+=usr/lib/clang/14.0.5/lib/freebsd/libclang_rt.profile-x86_64.a
OLD_FILES+=usr/lib/clang/14.0.5/lib/freebsd/libclang_rt.safestack-aarch64.a
OLD_FILES+=usr/lib/clang/14.0.5/lib/freebsd/libclang_rt.safestack-i386.a
OLD_FILES+=usr/lib/clang/14.0.5/lib/freebsd/libclang_rt.safestack-x86_64.a
OLD_FILES+=usr/lib/clang/14.0.5/lib/freebsd/libclang_rt.stats-aarch64.a
OLD_FILES+=usr/lib/clang/14.0.5/lib/freebsd/libclang_rt.stats-arm.a
OLD_FILES+=usr/lib/clang/14.0.5/lib/freebsd/libclang_rt.stats-armhf.a
OLD_FILES+=usr/lib/clang/14.0.5/lib/freebsd/libclang_rt.stats-i386.a
OLD_FILES+=usr/lib/clang/14.0.5/lib/freebsd/libclang_rt.stats-x86_64.a
OLD_FILES+=usr/lib/clang/14.0.5/lib/freebsd/libclang_rt.stats_client-aarch64.a
OLD_FILES+=usr/lib/clang/14.0.5/lib/freebsd/libclang_rt.stats_client-arm.a
OLD_FILES+=usr/lib/clang/14.0.5/lib/freebsd/libclang_rt.stats_client-armhf.a
OLD_FILES+=usr/lib/clang/14.0.5/lib/freebsd/libclang_rt.stats_client-i386.a
OLD_FILES+=usr/lib/clang/14.0.5/lib/freebsd/libclang_rt.stats_client-x86_64.a
OLD_FILES+=usr/lib/clang/14.0.5/lib/freebsd/libclang_rt.tsan-aarch64.a
OLD_FILES+=usr/lib/clang/14.0.5/lib/freebsd/libclang_rt.tsan-x86_64.a
OLD_FILES+=usr/lib/clang/14.0.5/lib/freebsd/libclang_rt.tsan_cxx-aarch64.a
OLD_FILES+=usr/lib/clang/14.0.5/lib/freebsd/libclang_rt.tsan_cxx-x86_64.a
OLD_FILES+=usr/lib/clang/14.0.5/lib/freebsd/libclang_rt.ubsan_minimal-aarch64.a
OLD_FILES+=usr/lib/clang/14.0.5/lib/freebsd/libclang_rt.ubsan_minimal-arm.a
OLD_FILES+=usr/lib/clang/14.0.5/lib/freebsd/libclang_rt.ubsan_minimal-armhf.a
OLD_FILES+=usr/lib/clang/14.0.5/lib/freebsd/libclang_rt.ubsan_minimal-i386.a
OLD_FILES+=usr/lib/clang/14.0.5/lib/freebsd/libclang_rt.ubsan_minimal-x86_64.a
OLD_FILES+=usr/lib/clang/14.0.5/lib/freebsd/libclang_rt.ubsan_standalone-aarch64.a
OLD_FILES+=usr/lib/clang/14.0.5/lib/freebsd/libclang_rt.ubsan_standalone-arm.a
OLD_FILES+=usr/lib/clang/14.0.5/lib/freebsd/libclang_rt.ubsan_standalone-armhf.a
OLD_FILES+=usr/lib/clang/14.0.5/lib/freebsd/libclang_rt.ubsan_standalone-i386.a
OLD_FILES+=usr/lib/clang/14.0.5/lib/freebsd/libclang_rt.ubsan_standalone-x86_64.a
OLD_FILES+=usr/lib/clang/14.0.5/lib/freebsd/libclang_rt.ubsan_standalone_cxx-aarch64.a
OLD_FILES+=usr/lib/clang/14.0.5/lib/freebsd/libclang_rt.ubsan_standalone_cxx-arm.a
OLD_FILES+=usr/lib/clang/14.0.5/lib/freebsd/libclang_rt.ubsan_standalone_cxx-armhf.a
OLD_FILES+=usr/lib/clang/14.0.5/lib/freebsd/libclang_rt.ubsan_standalone_cxx-i386.a
OLD_FILES+=usr/lib/clang/14.0.5/lib/freebsd/libclang_rt.ubsan_standalone_cxx-x86_64.a
OLD_FILES+=usr/lib/clang/14.0.5/lib/freebsd/libclang_rt.xray-aarch64.a
OLD_FILES+=usr/lib/clang/14.0.5/lib/freebsd/libclang_rt.xray-arm.a
OLD_FILES+=usr/lib/clang/14.0.5/lib/freebsd/libclang_rt.xray-armhf.a
OLD_FILES+=usr/lib/clang/14.0.5/lib/freebsd/libclang_rt.xray-basic-aarch64.a
OLD_FILES+=usr/lib/clang/14.0.5/lib/freebsd/libclang_rt.xray-basic-arm.a
OLD_FILES+=usr/lib/clang/14.0.5/lib/freebsd/libclang_rt.xray-basic-armhf.a
OLD_FILES+=usr/lib/clang/14.0.5/lib/freebsd/libclang_rt.xray-basic-x86_64.a
OLD_FILES+=usr/lib/clang/14.0.5/lib/freebsd/libclang_rt.xray-fdr-aarch64.a
OLD_FILES+=usr/lib/clang/14.0.5/lib/freebsd/libclang_rt.xray-fdr-arm.a
OLD_FILES+=usr/lib/clang/14.0.5/lib/freebsd/libclang_rt.xray-fdr-armhf.a
OLD_FILES+=usr/lib/clang/14.0.5/lib/freebsd/libclang_rt.xray-fdr-x86_64.a
OLD_FILES+=usr/lib/clang/14.0.5/lib/freebsd/libclang_rt.xray-profiling-aarch64.a
OLD_FILES+=usr/lib/clang/14.0.5/lib/freebsd/libclang_rt.xray-profiling-arm.a
OLD_FILES+=usr/lib/clang/14.0.5/lib/freebsd/libclang_rt.xray-profiling-armhf.a
OLD_FILES+=usr/lib/clang/14.0.5/lib/freebsd/libclang_rt.xray-profiling-x86_64.a
OLD_FILES+=usr/lib/clang/14.0.5/lib/freebsd/libclang_rt.xray-x86_64.a
OLD_DIRS+=usr/lib/clang/14.0.5/lib/freebsd
OLD_DIRS+=usr/lib/clang/14.0.5/lib
OLD_FILES+=usr/lib/clang/14.0.5/share/asan_ignorelist.txt
OLD_FILES+=usr/lib/clang/14.0.5/share/cfi_ignorelist.txt
OLD_FILES+=usr/lib/clang/14.0.5/share/msan_ignorelist.txt
OLD_DIRS+=usr/lib/clang/14.0.5/share
OLD_DIRS+=usr/lib/clang/14.0.5
# 20230208: new libc++ import which bumps version from 14.0.5 to 15.0.0
OLD_FILES+=usr/include/c++/v1/__functional_base
OLD_FILES+=usr/include/c++/v1/__libcpp_version
OLD_FILES+=usr/include/c++/v1/__nullptr
OLD_FILES+=usr/include/c++/v1/__string
OLD_FILES+=usr/include/c++/v1/experimental/filesystem
# 20230203: loader help files renamed
OLD_FILES+=boot/loader.help
+38 -10
View File
@@ -10,12 +10,12 @@ CONTRIBUTING.md
README.md
SECURITY.md
bolt/
clang-tools-extra/
clang/.clang-format
clang/.clang-tidy
clang/.gitignore
clang/CMakeLists.txt
clang/CODE_OWNERS.TXT
clang/INPUTS/
clang/INSTALL.txt
clang/ModuleInfo.txt
clang/NOTES.txt
@@ -43,6 +43,7 @@ clang/lib/ASTMatchers/CMakeLists.txt
clang/lib/ASTMatchers/Dynamic/CMakeLists.txt
clang/lib/Analysis/CMakeLists.txt
clang/lib/Analysis/FlowSensitive/CMakeLists.txt
clang/lib/Analysis/FlowSensitive/Models/CMakeLists.txt
clang/lib/Analysis/plugins/CMakeLists.txt
clang/lib/Analysis/plugins/CheckerDependencyHandling/CMakeLists.txt
clang/lib/Analysis/plugins/CheckerOptionHandling/CMakeLists.txt
@@ -55,6 +56,7 @@ clang/lib/CrossTU/CMakeLists.txt
clang/lib/DirectoryWatcher/CMakeLists.txt
clang/lib/Driver/CMakeLists.txt
clang/lib/Edit/CMakeLists.txt
clang/lib/ExtractAPI/CMakeLists.txt
clang/lib/Format/CMakeLists.txt
clang/lib/Frontend/CMakeLists.txt
clang/lib/Frontend/Rewrite/CMakeLists.txt
@@ -73,6 +75,7 @@ clang/lib/StaticAnalyzer/Checkers/CMakeLists.txt
clang/lib/StaticAnalyzer/Core/CMakeLists.txt
clang/lib/StaticAnalyzer/Frontend/CMakeLists.txt
clang/lib/StaticAnalyzer/README.txt
clang/lib/Support/CMakeLists.txt
clang/lib/Testing/CMakeLists.txt
clang/lib/Tooling/ASTDiff/CMakeLists.txt
clang/lib/Tooling/CMakeLists.txt
@@ -95,6 +98,7 @@ 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/CMakeLists.txt
clang/tools/clang-format/clang-format-bbedit.applescript
clang/tools/clang-format/clang-format-diff.py
@@ -104,12 +108,12 @@ 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/
clang/tools/clang-nvlink-wrapper/
clang/tools/clang-offload-bundler/
clang/tools/clang-offload-packager/
clang/tools/clang-offload-wrapper/
clang/tools/clang-refactor/
clang/tools/clang-rename/
@@ -120,9 +124,10 @@ clang/tools/diag-build/
clang/tools/diagtool/
clang/tools/driver/CMakeLists.txt
clang/tools/driver/Info.plist.in
clang/tools/include-mapping/
clang/tools/libclang/
clang/tools/scan-build/
clang/tools/scan-build-py/
clang/tools/scan-build/
clang/tools/scan-view/
clang/unittests/
clang/utils/ABITest/
@@ -152,7 +157,6 @@ 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
@@ -220,8 +224,8 @@ compiler-rt/lib/tsan/check_cmake.sh
compiler-rt/lib/tsan/dd/CMakeLists.txt
compiler-rt/lib/tsan/go/build.bat
compiler-rt/lib/tsan/go/buildgo.sh
compiler-rt/lib/tsan/rtl/CMakeLists.txt
compiler-rt/lib/tsan/rtl-old/CMakeLists.txt
compiler-rt/lib/tsan/rtl/CMakeLists.txt
compiler-rt/lib/tsan/tests/
compiler-rt/lib/ubsan/CMakeLists.txt
compiler-rt/lib/ubsan_minimal/CMakeLists.txt
@@ -431,6 +435,7 @@ lldb/source/Plugins/SymbolFile/Symtab/CMakeLists.txt
lldb/source/Plugins/SymbolVendor/CMakeLists.txt
lldb/source/Plugins/SymbolVendor/ELF/CMakeLists.txt
lldb/source/Plugins/SymbolVendor/MacOSX/
lldb/source/Plugins/SymbolVendor/PECOFF/CMakeLists.txt
lldb/source/Plugins/SymbolVendor/wasm/CMakeLists.txt
lldb/source/Plugins/SystemRuntime/
lldb/source/Plugins/Trace/CMakeLists.txt
@@ -458,6 +463,7 @@ lldb/tools/debugserver/
lldb/tools/driver/CMakeLists.txt
lldb/tools/driver/lldb-Info.plist.in
lldb/tools/intel-features/
lldb/tools/lldb-fuzzer/
lldb/tools/lldb-instr/CMakeLists.txt
lldb/tools/lldb-server/CMakeLists.txt
lldb/tools/lldb-test/
@@ -470,6 +476,7 @@ 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
@@ -549,6 +556,7 @@ llvm/lib/MC/CMakeLists.txt
llvm/lib/MC/MCDisassembler/CMakeLists.txt
llvm/lib/MC/MCParser/CMakeLists.txt
llvm/lib/MCA/CMakeLists.txt
llvm/lib/ObjCopy/CMakeLists.txt
llvm/lib/Object/CMakeLists.txt
llvm/lib/ObjectYAML/CMakeLists.txt
llvm/lib/Option/CMakeLists.txt
@@ -556,6 +564,8 @@ llvm/lib/Passes/CMakeLists.txt
llvm/lib/ProfileData/CMakeLists.txt
llvm/lib/ProfileData/Coverage/CMakeLists.txt
llvm/lib/Remarks/CMakeLists.txt
llvm/lib/Support/BLAKE3/.clang-format
llvm/lib/Support/BLAKE3/CMakeLists.txt
llvm/lib/Support/CMakeLists.txt
llvm/lib/TableGen/CMakeLists.txt
llvm/lib/Target/AArch64/AsmParser/CMakeLists.txt
@@ -597,8 +607,13 @@ llvm/lib/Target/BPF/TargetInfo/CMakeLists.txt
llvm/lib/Target/CMakeLists.txt
llvm/lib/Target/CSKY/AsmParser/CMakeLists.txt
llvm/lib/Target/CSKY/CMakeLists.txt
llvm/lib/Target/CSKY/Disassembler/CMakeLists.txt
llvm/lib/Target/CSKY/MCTargetDesc/CMakeLists.txt
llvm/lib/Target/CSKY/TargetInfo/CMakeLists.txt
llvm/lib/Target/DirectX/CMakeLists.txt
llvm/lib/Target/DirectX/DXILWriter/CMakeLists.txt
llvm/lib/Target/DirectX/MCTargetDesc/CMakeLists.txt
llvm/lib/Target/DirectX/TargetInfo/CMakeLists.txt
llvm/lib/Target/Hexagon/AsmParser/CMakeLists.txt
llvm/lib/Target/Hexagon/CMakeLists.txt
llvm/lib/Target/Hexagon/Disassembler/CMakeLists.txt
@@ -609,6 +624,11 @@ llvm/lib/Target/Lanai/CMakeLists.txt
llvm/lib/Target/Lanai/Disassembler/CMakeLists.txt
llvm/lib/Target/Lanai/MCTargetDesc/CMakeLists.txt
llvm/lib/Target/Lanai/TargetInfo/CMakeLists.txt
llvm/lib/Target/LoongArch/AsmParser/CMakeLists.txt
llvm/lib/Target/LoongArch/CMakeLists.txt
llvm/lib/Target/LoongArch/Disassembler/CMakeLists.txt
llvm/lib/Target/LoongArch/MCTargetDesc/CMakeLists.txt
llvm/lib/Target/LoongArch/TargetInfo/CMakeLists.txt
llvm/lib/Target/M68k/AsmParser/CMakeLists.txt
llvm/lib/Target/M68k/CMakeLists.txt
llvm/lib/Target/M68k/Disassembler/CMakeLists.txt
@@ -641,6 +661,9 @@ llvm/lib/Target/RISCV/CMakeLists.txt
llvm/lib/Target/RISCV/Disassembler/CMakeLists.txt
llvm/lib/Target/RISCV/MCTargetDesc/CMakeLists.txt
llvm/lib/Target/RISCV/TargetInfo/CMakeLists.txt
llvm/lib/Target/SPIRV/CMakeLists.txt
llvm/lib/Target/SPIRV/MCTargetDesc/CMakeLists.txt
llvm/lib/Target/SPIRV/TargetInfo/CMakeLists.txt
llvm/lib/Target/Sparc/AsmParser/CMakeLists.txt
llvm/lib/Target/Sparc/CMakeLists.txt
llvm/lib/Target/Sparc/Disassembler/CMakeLists.txt
@@ -696,6 +719,7 @@ llvm/lib/Transforms/ObjCARC/CMakeLists.txt
llvm/lib/Transforms/Scalar/CMakeLists.txt
llvm/lib/Transforms/Utils/CMakeLists.txt
llvm/lib/Transforms/Vectorize/CMakeLists.txt
llvm/lib/WindowsDriver/CMakeLists.txt
llvm/lib/WindowsManifest/CMakeLists.txt
llvm/lib/XRay/CMakeLists.txt
llvm/llvm.spec.in
@@ -704,16 +728,17 @@ llvm/resources/
llvm/runtimes/
llvm/test/
llvm/tools/CMakeLists.txt
llvm/tools/bugpoint/CMakeLists.txt
llvm/tools/bugpoint-passes/
llvm/tools/bugpoint/CMakeLists.txt
llvm/tools/dsymutil/
llvm/tools/dxil-dis/
llvm/tools/gold/
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/CMakeLists.txt
llvm/tools/llvm-as-fuzzer/
llvm/tools/llvm-as/CMakeLists.txt
llvm/tools/llvm-bcanalyzer/CMakeLists.txt
llvm/tools/llvm-c-test/
llvm/tools/llvm-cat/
@@ -727,8 +752,10 @@ llvm/tools/llvm-cxxmap/CMakeLists.txt
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-dlang-demangle-fuzzer/
llvm/tools/llvm-driver/
llvm/tools/llvm-dwarfdump/CMakeLists.txt
llvm/tools/llvm-dwarfdump/fuzzer/
llvm/tools/llvm-dwp/CMakeLists.txt
@@ -746,9 +773,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/
@@ -765,6 +792,7 @@ llvm/tools/llvm-profgen/
llvm/tools/llvm-rc/
llvm/tools/llvm-readobj/CMakeLists.txt
llvm/tools/llvm-reduce/
llvm/tools/llvm-remark-size-diff/
llvm/tools/llvm-rtdyld/CMakeLists.txt
llvm/tools/llvm-rust-demangle-fuzzer/
llvm/tools/llvm-shlib/
@@ -782,10 +810,9 @@ llvm/tools/llvm-xray/CMakeLists.txt
llvm/tools/llvm-yaml-numeric-parser-fuzzer/
llvm/tools/llvm-yaml-parser-fuzzer/
llvm/tools/lto/
llvm/tools/msbuild/
llvm/tools/obj2yaml/
llvm/tools/opt/CMakeLists.txt
llvm/tools/opt-viewer/
llvm/tools/opt/CMakeLists.txt
llvm/tools/remarks-shlib/
llvm/tools/sancov/
llvm/tools/sanstats/
@@ -809,6 +836,7 @@ llvm/utils/TableGen/CMakeLists.txt
llvm/utils/TableGen/GlobalISel/CMakeLists.txt
llvm/utils/TableGen/tdtags
llvm/utils/Target/
llvm/utils/UnicodeData/
llvm/utils/UpdateCMakeLists.pl
llvm/utils/UpdateTestChecks/
llvm/utils/abtest.py
@@ -2189,7 +2189,17 @@ enum CXCursorKind {
*/
CXCursor_CXXAddrspaceCastExpr = 152,
CXCursor_LastExpr = CXCursor_CXXAddrspaceCastExpr,
/**
* Expression that references a C++20 concept.
*/
CXCursor_ConceptSpecializationExpr = 153,
/**
* Expression that references a C++20 concept.
*/
CXCursor_RequiresExpr = 154,
CXCursor_LastExpr = CXCursor_RequiresExpr,
/* Statements */
CXCursor_FirstStmt = 200,
@@ -2600,7 +2610,43 @@ enum CXCursorKind {
*/
CXCursor_OMPGenericLoopDirective = 295,
CXCursor_LastStmt = CXCursor_OMPGenericLoopDirective,
/** OpenMP teams loop directive.
*/
CXCursor_OMPTeamsGenericLoopDirective = 296,
/** OpenMP target teams loop directive.
*/
CXCursor_OMPTargetTeamsGenericLoopDirective = 297,
/** OpenMP parallel loop directive.
*/
CXCursor_OMPParallelGenericLoopDirective = 298,
/** OpenMP target parallel loop directive.
*/
CXCursor_OMPTargetParallelGenericLoopDirective = 299,
/** OpenMP parallel masked directive.
*/
CXCursor_OMPParallelMaskedDirective = 300,
/** OpenMP masked taskloop directive.
*/
CXCursor_OMPMaskedTaskLoopDirective = 301,
/** OpenMP masked taskloop simd directive.
*/
CXCursor_OMPMaskedTaskLoopSimdDirective = 302,
/** OpenMP parallel masked taskloop directive.
*/
CXCursor_OMPParallelMaskedTaskLoopDirective = 303,
/** OpenMP parallel masked taskloop simd directive.
*/
CXCursor_OMPParallelMaskedTaskLoopSimdDirective = 304,
CXCursor_LastStmt = CXCursor_OMPParallelMaskedTaskLoopSimdDirective,
/**
* Cursor that represents the translation unit itself.
@@ -2608,7 +2654,7 @@ enum CXCursorKind {
* The translation unit cursor exists primarily to act as the root
* cursor for traversing the contents of a translation unit.
*/
CXCursor_TranslationUnit = 300,
CXCursor_TranslationUnit = 350,
/* Attributes */
CXCursor_FirstAttr = 400,
@@ -2684,8 +2730,13 @@ enum CXCursorKind {
* a friend declaration.
*/
CXCursor_FriendDecl = 603,
/**
* a concept declaration.
*/
CXCursor_ConceptDecl = 604,
CXCursor_FirstExtraDecl = CXCursor_ModuleImportDecl,
CXCursor_LastExtraDecl = CXCursor_FriendDecl,
CXCursor_LastExtraDecl = CXCursor_ConceptDecl,
/**
* A code completion overload candidate.
@@ -3401,7 +3452,8 @@ enum CXTypeKind {
CXType_OCLIntelSubgroupAVCImeDualRefStreamin = 175,
CXType_ExtVector = 176,
CXType_Atomic = 177
CXType_Atomic = 177,
CXType_BTFTagAttributed = 178
};
/**
@@ -3428,6 +3480,7 @@ enum CXCallingConv {
CXCallingConv_PreserveAll = 15,
CXCallingConv_AArch64VectorCall = 16,
CXCallingConv_SwiftAsync = 17,
CXCallingConv_AArch64SVEPCS = 18,
CXCallingConv_Invalid = 100,
CXCallingConv_Unexposed = 200
@@ -3900,7 +3953,7 @@ enum CXTypeNullabilityKind {
/**
* Generally behaves like Nullable, except when used in a block parameter that
* was imported into a swift async method. There, swift will assume that the
* parameter can get null even if no error occured. _Nullable parameters are
* parameter can get null even if no error occurred. _Nullable parameters are
* assumed to only get null on error.
*/
CXTypeNullability_NullableResult = 4
@@ -6301,7 +6354,8 @@ typedef enum {
CXIdxEntity_CXXDestructor = 23,
CXIdxEntity_CXXConversionFunction = 24,
CXIdxEntity_CXXTypeAlias = 25,
CXIdxEntity_CXXInterface = 26
CXIdxEntity_CXXInterface = 26,
CXIdxEntity_CXXConcept = 27
} CXIdxEntityKind;
@@ -77,7 +77,7 @@ class CommonEntityInfo {
void setSwiftPrivate(llvm::Optional<bool> Private) {
SwiftPrivateSpecified = Private.hasValue();
SwiftPrivate = Private.hasValue() ? *Private : 0;
SwiftPrivate = Private ? *Private : 0;
}
friend bool operator==(const CommonEntityInfo &, const CommonEntityInfo &);
@@ -238,8 +238,8 @@ class ObjCContextInfo : public CommonTypeInfo {
: llvm::None;
}
void setSwiftImportAsNonGeneric(llvm::Optional<bool> Value) {
SwiftImportAsNonGenericSpecified = Value.hasValue();
SwiftImportAsNonGeneric = Value.getValueOr(false);
SwiftImportAsNonGenericSpecified = Value.has_value();
SwiftImportAsNonGeneric = Value.value_or(false);
}
llvm::Optional<bool> getSwiftObjCMembers() const {
@@ -247,8 +247,8 @@ class ObjCContextInfo : public CommonTypeInfo {
: llvm::None;
}
void setSwiftObjCMembers(llvm::Optional<bool> Value) {
SwiftObjCMembersSpecified = Value.hasValue();
SwiftObjCMembers = Value.getValueOr(false);
SwiftObjCMembersSpecified = Value.has_value();
SwiftObjCMembers = Value.value_or(false);
}
/// Strip off any information within the class information structure that is
@@ -365,8 +365,8 @@ class ObjCPropertyInfo : public VariableInfo {
: llvm::None;
}
void setSwiftImportAsAccessors(llvm::Optional<bool> Value) {
SwiftImportAsAccessorsSpecified = Value.hasValue();
SwiftImportAsAccessors = Value.getValueOr(false);
SwiftImportAsAccessorsSpecified = Value.has_value();
SwiftImportAsAccessors = Value.value_or(false);
}
friend bool operator==(const ObjCPropertyInfo &, const ObjCPropertyInfo &);
@@ -429,8 +429,8 @@ class ParamInfo : public VariableInfo {
return NoEscape;
}
void setNoEscape(llvm::Optional<bool> Value) {
NoEscapeSpecified = Value.hasValue();
NoEscape = Value.getValueOr(false);
NoEscapeSpecified = Value.has_value();
NoEscape = Value.value_or(false);
}
llvm::Optional<RetainCountConventionKind> getRetainCountConvention() const {
@@ -440,8 +440,7 @@ class ParamInfo : public VariableInfo {
}
void
setRetainCountConvention(llvm::Optional<RetainCountConventionKind> Value) {
RawRetainCountConvention =
Value.hasValue() ? static_cast<unsigned>(Value.getValue()) + 1 : 0;
RawRetainCountConvention = Value ? static_cast<unsigned>(*Value) + 1 : 0;
assert(getRetainCountConvention() == Value && "bitfield too small");
}
@@ -559,8 +558,7 @@ class FunctionInfo : public CommonEntityInfo {
}
void
setRetainCountConvention(llvm::Optional<RetainCountConventionKind> Value) {
RawRetainCountConvention =
Value.hasValue() ? static_cast<unsigned>(Value.getValue()) + 1 : 0;
RawRetainCountConvention = Value ? static_cast<unsigned>(*Value) + 1 : 0;
assert(getRetainCountConvention() == Value && "bitfield too small");
}
@@ -666,17 +664,17 @@ class TagInfo : public CommonTypeInfo {
return llvm::None;
}
void setFlagEnum(llvm::Optional<bool> Value) {
HasFlagEnum = Value.hasValue();
IsFlagEnum = Value.getValueOr(false);
HasFlagEnum = Value.has_value();
IsFlagEnum = Value.value_or(false);
}
TagInfo &operator|=(const TagInfo &RHS) {
static_cast<CommonTypeInfo &>(*this) |= RHS;
if (!HasFlagEnum && HasFlagEnum)
if (!HasFlagEnum)
setFlagEnum(RHS.isFlagEnum());
if (!EnumExtensibility.hasValue())
if (!EnumExtensibility)
EnumExtensibility = RHS.EnumExtensibility;
return *this;
@@ -706,7 +704,7 @@ class TypedefInfo : public CommonTypeInfo {
TypedefInfo &operator|=(const TypedefInfo &RHS) {
static_cast<CommonTypeInfo &>(*this) |= RHS;
if (!SwiftWrapper.hasValue())
if (!SwiftWrapper)
SwiftWrapper = RHS.SwiftWrapper;
return *this;
}
@@ -211,7 +211,7 @@ class ASTContext : public RefCountedBase<ASTContext> {
mutable SmallVector<Type *, 0> Types;
mutable llvm::FoldingSet<ExtQuals> ExtQualNodes;
mutable llvm::FoldingSet<ComplexType> ComplexTypes;
mutable llvm::FoldingSet<PointerType> PointerTypes;
mutable llvm::FoldingSet<PointerType> PointerTypes{GeneralTypesLog2InitSize};
mutable llvm::FoldingSet<AdjustedType> AdjustedTypes;
mutable llvm::FoldingSet<BlockPointerType> BlockPointerTypes;
mutable llvm::FoldingSet<LValueReferenceType> LValueReferenceTypes;
@@ -243,9 +243,10 @@ class ASTContext : public RefCountedBase<ASTContext> {
SubstTemplateTypeParmPackTypes;
mutable llvm::ContextualFoldingSet<TemplateSpecializationType, ASTContext&>
TemplateSpecializationTypes;
mutable llvm::FoldingSet<ParenType> ParenTypes;
mutable llvm::FoldingSet<ParenType> ParenTypes{GeneralTypesLog2InitSize};
mutable llvm::FoldingSet<UsingType> UsingTypes;
mutable llvm::FoldingSet<ElaboratedType> ElaboratedTypes;
mutable llvm::FoldingSet<ElaboratedType> ElaboratedTypes{
GeneralTypesLog2InitSize};
mutable llvm::FoldingSet<DependentNameType> DependentNameTypes;
mutable llvm::ContextualFoldingSet<DependentTemplateSpecializationType,
ASTContext&>
@@ -263,6 +264,7 @@ class ASTContext : public RefCountedBase<ASTContext> {
mutable llvm::FoldingSet<PipeType> PipeTypes;
mutable llvm::FoldingSet<BitIntType> BitIntTypes;
mutable llvm::FoldingSet<DependentBitIntType> DependentBitIntTypes;
llvm::FoldingSet<BTFTagAttributedType> BTFTagAttributedTypes;
mutable llvm::FoldingSet<QualifiedTemplateName> QualifiedTemplateNames;
mutable llvm::FoldingSet<DependentTemplateName> DependentTemplateNames;
@@ -312,6 +314,10 @@ class ASTContext : public RefCountedBase<ASTContext> {
/// Mapping from GUIDs to the corresponding MSGuidDecl.
mutable llvm::FoldingSet<MSGuidDecl> MSGuidDecls;
/// Mapping from APValues to the corresponding UnnamedGlobalConstantDecl.
mutable llvm::FoldingSet<UnnamedGlobalConstantDecl>
UnnamedGlobalConstantDecls;
/// Mapping from APValues to the corresponding TemplateParamObjects.
mutable llvm::FoldingSet<TemplateParamObjectDecl> TemplateParamObjectDecls;
@@ -466,6 +472,10 @@ class ASTContext : public RefCountedBase<ASTContext> {
};
llvm::DenseMap<Module*, PerModuleInitializers*> ModuleInitializers;
static constexpr unsigned ConstantArrayTypesLog2InitSize = 8;
static constexpr unsigned GeneralTypesLog2InitSize = 9;
static constexpr unsigned FunctionProtoTypesLog2InitSize = 12;
ASTContext &this_() { return *this; }
public:
@@ -1150,6 +1160,10 @@ class ASTContext : public RefCountedBase<ASTContext> {
/// Keep track of CUDA/HIP device-side variables ODR-used by host code.
llvm::DenseSet<const VarDecl *> CUDADeviceVarODRUsedByHost;
/// Keep track of CUDA/HIP external kernels or device variables ODR-used by
/// host code.
llvm::DenseSet<const ValueDecl *> CUDAExternalDeviceDeclODRUsedByHost;
ASTContext(LangOptions &LOpts, SourceManager &SM, IdentifierTable &idents,
SelectorTable &sels, Builtin::Context &builtins,
TranslationUnitKind TUKind);
@@ -1587,6 +1601,9 @@ class ASTContext : public RefCountedBase<ASTContext> {
QualType modifiedType,
QualType equivalentType);
QualType getBTFTagAttributedType(const BTFTypeTagAttr *BTFAttr,
QualType Wrapped);
QualType getSubstTemplateTypeParmType(const TemplateTypeParmType *Replaced,
QualType Replacement) const;
QualType getSubstTemplateTypeParmPackType(
@@ -2165,7 +2182,7 @@ class ASTContext : public RefCountedBase<ASTContext> {
TemplateName getQualifiedTemplateName(NestedNameSpecifier *NNS,
bool TemplateKeyword,
TemplateDecl *Template) const;
TemplateName Template) const;
TemplateName getDependentTemplateName(NestedNameSpecifier *NNS,
const IdentifierInfo *Name) const;
@@ -2537,7 +2554,7 @@ class ASTContext : public RefCountedBase<ASTContext> {
bool IsParam) const {
auto SubTnullability = SubT->getNullability(*this);
auto SuperTnullability = SuperT->getNullability(*this);
if (SubTnullability.hasValue() == SuperTnullability.hasValue()) {
if (SubTnullability.has_value() == SuperTnullability.has_value()) {
// Neither has nullability; return true
if (!SubTnullability)
return true;
@@ -2753,14 +2770,6 @@ class ASTContext : public RefCountedBase<ASTContext> {
/// long double and double on AArch64 will return 0).
int getFloatingTypeSemanticOrder(QualType LHS, QualType RHS) const;
/// Return a real floating point or a complex type (based on
/// \p typeDomain/\p typeSize).
///
/// \param typeDomain a real floating point or complex type.
/// \param typeSize a real floating point or complex type.
QualType getFloatingTypeOfSizeWithinDomain(QualType typeSize,
QualType typeDomain) const;
unsigned getTargetAddressSpace(QualType T) const;
unsigned getTargetAddressSpace(Qualifiers Q) const;
@@ -3032,7 +3041,8 @@ class ASTContext : public RefCountedBase<ASTContext> {
DeclaratorDecl *getDeclaratorForUnnamedTagDecl(const TagDecl *TD);
void setManglingNumber(const NamedDecl *ND, unsigned Number);
unsigned getManglingNumber(const NamedDecl *ND) const;
unsigned getManglingNumber(const NamedDecl *ND,
bool ForAuxTarget = false) const;
void setStaticLocalNumber(const VarDecl *VD, unsigned Number);
unsigned getStaticLocalNumber(const VarDecl *VD) const;
@@ -3063,6 +3073,11 @@ class ASTContext : public RefCountedBase<ASTContext> {
/// GUID value.
MSGuidDecl *getMSGuidDecl(MSGuidDeclParts Parts) const;
/// Return a declaration for a uniquified anonymous global constant
/// corresponding to a given APValue.
UnnamedGlobalConstantDecl *
getUnnamedGlobalConstantDecl(QualType Ty, const APValue &Value) const;
/// Return the template parameter object of the given type with the given
/// value.
TemplateParamObjectDecl *getTemplateParamObjectDecl(QualType T,
@@ -3280,10 +3295,10 @@ OPT_LIST(V)
OMPTraitInfo &getNewOMPTraitInfo();
/// Whether a C++ static variable or CUDA/HIP kernel may be externalized.
bool mayExternalizeStaticVar(const Decl *D) const;
bool mayExternalize(const Decl *D) const;
/// Whether a C++ static variable or CUDA/HIP kernel should be externalized.
bool shouldExternalizeStaticVar(const Decl *D) const;
bool shouldExternalize(const Decl *D) const;
StringRef getCUIDHash() const;
@@ -33,6 +33,7 @@ class OMPClause;
class Attr;
#define ATTR(A) class A##Attr;
#include "clang/Basic/AttrList.inc"
class ObjCProtocolLoc;
} // end namespace clang
@@ -0,0 +1,51 @@
//===- ASTImportError.h - Define errors while importing AST -----*- 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 ASTImportError class which basically defines the kind
// of error while importing AST .
//
//===----------------------------------------------------------------------===//
#ifndef LLVM_CLANG_AST_ASTIMPORTERROR_H
#define LLVM_CLANG_AST_ASTIMPORTERROR_H
#include "llvm/Support/Error.h"
namespace clang {
class ASTImportError : public llvm::ErrorInfo<ASTImportError> {
public:
/// \brief Kind of error when importing an AST component.
enum ErrorKind {
NameConflict, /// Naming ambiguity (likely ODR violation).
UnsupportedConstruct, /// Not supported node or case.
Unknown /// Other error.
};
ErrorKind Error;
static char ID;
ASTImportError() : Error(Unknown) {}
ASTImportError(const ASTImportError &Other) : Error(Other.Error) {}
ASTImportError &operator=(const ASTImportError &Other) {
Error = Other.Error;
return *this;
}
ASTImportError(ErrorKind Error) : Error(Error) {}
std::string toString() const;
void log(llvm::raw_ostream &OS) const override;
std::error_code convertToErrorCode() const override;
};
} // namespace clang
#endif // LLVM_CLANG_AST_ASTIMPORTERROR_H
@@ -14,7 +14,7 @@
#ifndef LLVM_CLANG_AST_ASTIMPORTER_H
#define LLVM_CLANG_AST_ASTIMPORTER_H
#include "clang/AST/APValue.h"
#include "clang/AST/ASTImportError.h"
#include "clang/AST/DeclBase.h"
#include "clang/AST/DeclarationName.h"
#include "clang/AST/ExprCXX.h"
@@ -29,7 +29,6 @@
#include "llvm/ADT/DenseSet.h"
#include "llvm/ADT/Optional.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/Support/Error.h"
#include <utility>
namespace clang {
@@ -49,33 +48,6 @@ class TagDecl;
class TranslationUnitDecl;
class TypeSourceInfo;
class ImportError : public llvm::ErrorInfo<ImportError> {
public:
/// \brief Kind of error when importing an AST component.
enum ErrorKind {
NameConflict, /// Naming ambiguity (likely ODR violation).
UnsupportedConstruct, /// Not supported node or case.
Unknown /// Other error.
};
ErrorKind Error;
static char ID;
ImportError() : Error(Unknown) {}
ImportError(const ImportError &Other) : Error(Other.Error) {}
ImportError &operator=(const ImportError &Other) {
Error = Other.Error;
return *this;
}
ImportError(ErrorKind Error) : Error(Error) { }
std::string toString() const;
void log(raw_ostream &OS) const override;
std::error_code convertToErrorCode() const override;
};
// \brief Returns with a list of declarations started from the canonical decl
// then followed by subsequent decls in the translation unit.
// This gives a canonical list for each entry in the redecl chain.
@@ -259,7 +231,7 @@ class TypeSourceInfo;
/// imported. The same declaration may or may not be included in
/// ImportedDecls. This map is updated continuously during imports and never
/// cleared (like ImportedDecls).
llvm::DenseMap<Decl *, ImportError> ImportDeclErrors;
llvm::DenseMap<Decl *, ASTImportError> ImportDeclErrors;
/// Mapping from the already-imported declarations in the "to"
/// context to the corresponding declarations in the "from" context.
@@ -592,10 +564,10 @@ class TypeSourceInfo;
/// Return if import of the given declaration has failed and if yes
/// the kind of the problem. This gives the first error encountered with
/// the node.
llvm::Optional<ImportError> getImportDeclErrorIfAny(Decl *FromD) const;
llvm::Optional<ASTImportError> getImportDeclErrorIfAny(Decl *FromD) const;
/// Mark (newly) imported declaration with error.
void setImportDeclError(Decl *From, ImportError Error);
void setImportDeclError(Decl *From, ASTImportError Error);
/// Determine whether the given types are structurally
/// equivalent.
@@ -14,11 +14,10 @@
#ifndef LLVM_CLANG_AST_ASTIMPORTERSHAREDSTATE_H
#define LLVM_CLANG_AST_ASTIMPORTERSHAREDSTATE_H
#include "clang/AST/ASTImportError.h"
#include "clang/AST/ASTImporterLookupTable.h"
#include "clang/AST/Decl.h"
#include "llvm/ADT/DenseMap.h"
// FIXME We need this because of ImportError.
#include "clang/AST/ASTImporter.h"
namespace clang {
@@ -37,7 +36,10 @@ class ASTImporterSharedState {
/// imported. The same declaration may or may not be included in
/// ImportedFromDecls. This map is updated continuously during imports and
/// never cleared (like ImportedFromDecls).
llvm::DenseMap<Decl *, ImportError> ImportErrors;
llvm::DenseMap<Decl *, ASTImportError> ImportErrors;
/// Set of the newly created declarations.
llvm::DenseSet<Decl *> NewDecls;
// FIXME put ImportedFromDecls here!
// And from that point we can better encapsulate the lookup table.
@@ -63,17 +65,21 @@ class ASTImporterSharedState {
LookupTable->remove(ND);
}
llvm::Optional<ImportError> getImportDeclErrorIfAny(Decl *ToD) const {
llvm::Optional<ASTImportError> getImportDeclErrorIfAny(Decl *ToD) const {
auto Pos = ImportErrors.find(ToD);
if (Pos != ImportErrors.end())
return Pos->second;
else
return Optional<ImportError>();
return Optional<ASTImportError>();
}
void setImportDeclError(Decl *To, ImportError Error) {
void setImportDeclError(Decl *To, ASTImportError Error) {
ImportErrors[To] = Error;
}
bool isNewDecl(const Decl *ToD) const { return NewDecls.count(ToD); }
void markAsNewDecl(Decl *ToD) { NewDecls.insert(ToD); }
};
} // namespace clang
@@ -65,8 +65,8 @@ inline bool isGenericLambdaCallOperatorSpecialization(DeclContext *DC) {
}
inline bool isGenericLambdaCallOperatorOrStaticInvokerSpecialization(
DeclContext *DC) {
CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(DC);
const DeclContext *DC) {
const auto *MD = dyn_cast<CXXMethodDecl>(DC);
if (!MD) return false;
const CXXRecordDecl *LambdaClass = MD->getParent();
if (LambdaClass && LambdaClass->isGenericLambda())
@@ -75,7 +75,6 @@ inline bool isGenericLambdaCallOperatorOrStaticInvokerSpecialization(
return false;
}
// This returns the parent DeclContext ensuring that the correct
// parent DeclContext is returned for Lambdas
inline DeclContext *getLambdaAwareParentOfDeclContext(DeclContext *DC) {
@@ -386,6 +386,9 @@ class ASTNodeTraverser
// FIXME: AttrKind
Visit(T->getModifiedType());
}
void VisitBTFTagAttributedType(const BTFTagAttributedType *T) {
Visit(T->getWrappedType());
}
void VisitSubstTemplateTypeParmType(const SubstTemplateTypeParmType *T) {
Visit(T->getReplacedParameter());
}
@@ -464,6 +467,10 @@ class ASTNodeTraverser
void VisitBindingDecl(const BindingDecl *D) {
if (Traversal == TK_IgnoreUnlessSpelledInSource)
return;
if (const auto *V = D->getHoldingVar())
Visit(V);
if (const auto *E = D->getBinding())
Visit(E);
}
@@ -160,6 +160,7 @@ class ASTNodeKind {
NKI_Attr,
#define ATTR(A) NKI_##A##Attr,
#include "clang/Basic/AttrList.inc"
NKI_ObjCProtocolLoc,
NKI_NumberOfKinds
};
@@ -213,6 +214,7 @@ KIND_TO_KIND_ID(Stmt)
KIND_TO_KIND_ID(Type)
KIND_TO_KIND_ID(OMPClause)
KIND_TO_KIND_ID(Attr)
KIND_TO_KIND_ID(ObjCProtocolLoc)
KIND_TO_KIND_ID(CXXBaseSpecifier)
#define DECL(DERIVED, BASE) KIND_TO_KIND_ID(DERIVED##Decl)
#include "clang/AST/DeclNodes.inc"
@@ -499,7 +501,7 @@ class DynTypedNode {
/// have storage or unique pointers and thus need to be stored by value.
llvm::AlignedCharArrayUnion<const void *, TemplateArgument,
TemplateArgumentLoc, NestedNameSpecifierLoc,
QualType, TypeLoc>
QualType, TypeLoc, ObjCProtocolLoc>
Storage;
};
@@ -570,6 +572,10 @@ template <>
struct DynTypedNode::BaseConverter<CXXBaseSpecifier, void>
: public PtrConverter<CXXBaseSpecifier> {};
template <>
struct DynTypedNode::BaseConverter<ObjCProtocolLoc, void>
: public ValueConverter<ObjCProtocolLoc> {};
// The only operation we allow on unsupported types is \c get.
// This allows to conveniently use \c DynTypedNode when having an arbitrary
// AST node that is not supported, but prevents misuse - a user cannot create
@@ -21,7 +21,7 @@ inline T makeNullableFromOptional(const Optional<T> &value) {
template <class T>
inline T *makePointerFromOptional(Optional<T *> value) {
return value.getValueOr(nullptr);
return value.value_or(nullptr);
}
// PropertyReader is a class concept that requires the following method:
@@ -9,8 +9,9 @@
#ifndef LLVM_CLANG_AST_ABSTRACTTYPEREADER_H
#define LLVM_CLANG_AST_ABSTRACTTYPEREADER_H
#include "clang/AST/Type.h"
#include "clang/AST/AbstractBasicReader.h"
#include "clang/AST/DeclObjC.h"
#include "clang/AST/Type.h"
namespace clang {
namespace serialization {
@@ -182,6 +182,12 @@ namespace clang {
/// Beware llvm::Align assumes power of two 8-bit bytes.
llvm::Align getAsAlign() const { return llvm::Align(Quantity); }
/// getAsMaybeAlign - Returns Quantity as a valid llvm::Align or
/// llvm::None, Beware llvm::MaybeAlign assumes power of two 8-bit bytes.
llvm::MaybeAlign getAsMaybeAlign() const {
return llvm::MaybeAlign(Quantity);
}
/// alignTo - Returns the next integer (mod 2**64) that is
/// greater than or equal to this quantity and is a multiple of \p Align.
/// Align must be non-zero.
@@ -194,6 +194,11 @@ class Comment {
#include "clang/AST/CommentNodes.inc"
};
struct Argument {
SourceRange Range;
StringRef Text;
};
Comment(CommentKind K,
SourceLocation LocBegin,
SourceLocation LocEnd) :
@@ -296,13 +301,6 @@ class TextComment : public InlineContentComment {
/// A command with word-like arguments that is considered inline content.
class InlineCommandComment : public InlineContentComment {
public:
struct Argument {
SourceRange Range;
StringRef Text;
Argument(SourceRange Range, StringRef Text) : Range(Range), Text(Text) { }
};
/// The most appropriate rendering mode for this command, chosen on command
/// semantics in Doxygen.
enum RenderKind {
@@ -588,15 +586,6 @@ class ParagraphComment : public BlockContentComment {
/// arguments depends on command name) and a paragraph as an argument
/// (e. g., \\brief).
class BlockCommandComment : public BlockContentComment {
public:
struct Argument {
SourceRange Range;
StringRef Text;
Argument() { }
Argument(SourceRange Range, StringRef Text) : Range(Range), Text(Text) { }
};
protected:
/// Word-like arguments.
ArrayRef<Argument> Args;
@@ -31,6 +31,7 @@ class Command<string name> {
}
class InlineCommand<string name> : Command<name> {
let NumArgs = 1;
let IsInlineCommand = 1;
}
@@ -62,6 +63,11 @@ class VerbatimLineCommand<string name> : Command<name> {
let IsVerbatimLineCommand = 1;
}
class PropertyCommand<string name> : Command<name> {
let NumArgs = 0;
let IsInlineCommand = 1;
}
class DeclarationVerbatimLineCommand<string name> :
VerbatimLineCommand<name> {
let IsDeclarationCommand = 1;
@@ -86,6 +92,7 @@ def C : InlineCommand<"c">;
def P : InlineCommand<"p">;
def A : InlineCommand<"a">;
def E : InlineCommand<"e">;
def N : InlineCommand<"n"> { let NumArgs = 0; }
def Em : InlineCommand<"em">;
def Emoji : InlineCommand<"emoji">;
@@ -154,7 +161,7 @@ def Post : BlockCommand<"post">;
def Pre : BlockCommand<"pre">;
def Remark : BlockCommand<"remark">;
def Remarks : BlockCommand<"remarks">;
def Retval : BlockCommand<"retval">;
def Retval : BlockCommand<"retval"> { let NumArgs = 1; }
def Sa : BlockCommand<"sa">;
def See : BlockCommand<"see">;
def Since : BlockCommand<"since">;
@@ -162,7 +169,7 @@ def Test : BlockCommand<"test">;
def Todo : BlockCommand<"todo">;
def Version : BlockCommand<"version">;
def Warning : BlockCommand<"warning">;
def XRefItem : BlockCommand<"xrefitem">;
def XRefItem : BlockCommand<"xrefitem"> { let NumArgs = 3; }
// HeaderDoc commands
def Abstract : BlockCommand<"abstract"> { let IsBriefCommand = 1; }
def ClassDesign : RecordLikeDetailCommand<"classdesign">;
@@ -273,31 +280,6 @@ def Until : VerbatimLineCommand<"until">;
def NoOp : VerbatimLineCommand<"noop">;
// These have actually no arguments, but we can treat them as line commands.
def CallGraph : VerbatimLineCommand<"callgraph">;
def HideCallGraph : VerbatimLineCommand<"hidecallgraph">;
def CallerGraph : VerbatimLineCommand<"callergraph">;
def HideCallerGraph : VerbatimLineCommand<"hidecallergraph">;
def ShowInitializer : VerbatimLineCommand<"showinitializer">;
def HideInitializer : VerbatimLineCommand<"hideinitializer">;
def ShowRefBy : VerbatimLineCommand<"showrefby">;
def HideRefBy : VerbatimLineCommand<"hiderefby">;
def ShowRefs : VerbatimLineCommand<"showrefs">;
def HideRefs : VerbatimLineCommand<"hiderefs">;
// These also have no argument.
def Private : VerbatimLineCommand<"private">;
def Protected : VerbatimLineCommand<"protected">;
def Public : VerbatimLineCommand<"public">;
def Pure : VerbatimLineCommand<"pure">;
def Static : VerbatimLineCommand<"static">;
// These also have no argument.
def NoSubgrouping : VerbatimLineCommand<"nosubgrouping">;
def PrivateSection : VerbatimLineCommand<"privatesection">;
def ProtectedSection : VerbatimLineCommand<"protectedsection">;
def PublicSection : VerbatimLineCommand<"publicsection">;
// We might also build proper support for if/ifnot/else/elseif/endif.
def If : VerbatimLineCommand<"if">;
def IfNot : VerbatimLineCommand<"ifnot">;
@@ -309,6 +291,32 @@ def Endif : VerbatimLineCommand<"endif">;
def Cond : VerbatimLineCommand<"cond">;
def EndCond : VerbatimLineCommand<"endcond">;
//===----------------------------------------------------------------------===//
// PropertyCommand
//===----------------------------------------------------------------------===//
def CallGraph : PropertyCommand<"callgraph">;
def HideCallGraph : PropertyCommand<"hidecallgraph">;
def CallerGraph : PropertyCommand<"callergraph">;
def HideCallerGraph : PropertyCommand<"hidecallergraph">;
def ShowInitializer : PropertyCommand<"showinitializer">;
def HideInitializer : PropertyCommand<"hideinitializer">;
def ShowRefBy : PropertyCommand<"showrefby">;
def HideRefBy : PropertyCommand<"hiderefby">;
def ShowRefs : PropertyCommand<"showrefs">;
def HideRefs : PropertyCommand<"hiderefs">;
def Private : PropertyCommand<"private">;
def Protected : PropertyCommand<"protected">;
def Public : PropertyCommand<"public">;
def Pure : PropertyCommand<"pure">;
def Static : PropertyCommand<"static">;
def NoSubgrouping : PropertyCommand<"nosubgrouping">;
def PrivateSection : PropertyCommand<"privatesection">;
def ProtectedSection : PropertyCommand<"protectedsection">;
def PublicSection : PropertyCommand<"publicsection">;
//===----------------------------------------------------------------------===//
// DeclarationVerbatimLineCommand
//===----------------------------------------------------------------------===//
@@ -97,9 +97,8 @@ class Parser {
void parseTParamCommandArgs(TParamCommandComment *TPC,
TextTokenRetokenizer &Retokenizer);
void parseBlockCommandArgs(BlockCommandComment *BC,
TextTokenRetokenizer &Retokenizer,
unsigned NumArgs);
ArrayRef<Comment::Argument>
parseCommandArgs(TextTokenRetokenizer &Retokenizer, unsigned NumArgs);
BlockCommandComment *parseBlockCommand();
InlineCommandComment *parseInlineCommand();
@@ -128,16 +128,10 @@ class Sema {
void actOnTParamCommandFinish(TParamCommandComment *Command,
ParagraphComment *Paragraph);
InlineCommandComment *actOnInlineCommand(SourceLocation CommandLocBegin,
SourceLocation CommandLocEnd,
unsigned CommandID);
InlineCommandComment *actOnInlineCommand(SourceLocation CommandLocBegin,
SourceLocation CommandLocEnd,
unsigned CommandID,
SourceLocation ArgLocBegin,
SourceLocation ArgLocEnd,
StringRef Arg);
ArrayRef<Comment::Argument> Args);
InlineContentComment *actOnUnknownCommand(SourceLocation LocBegin,
SourceLocation LocEnd,
@@ -1041,7 +1041,7 @@ class VarDecl : public DeclaratorDecl, public Redeclarable<VarDecl> {
};
VarDecl(Kind DK, ASTContext &C, DeclContext *DC, SourceLocation StartLoc,
SourceLocation IdLoc, IdentifierInfo *Id, QualType T,
SourceLocation IdLoc, const IdentifierInfo *Id, QualType T,
TypeSourceInfo *TInfo, StorageClass SC);
using redeclarable_base = Redeclarable<VarDecl>;
@@ -1071,8 +1071,8 @@ class VarDecl : public DeclaratorDecl, public Redeclarable<VarDecl> {
static VarDecl *Create(ASTContext &C, DeclContext *DC,
SourceLocation StartLoc, SourceLocation IdLoc,
IdentifierInfo *Id, QualType T, TypeSourceInfo *TInfo,
StorageClass S);
const IdentifierInfo *Id, QualType T,
TypeSourceInfo *TInfo, StorageClass S);
static VarDecl *CreateDeserialized(ASTContext &C, unsigned ID);
@@ -1588,6 +1588,20 @@ class VarDecl : public DeclaratorDecl, public Redeclarable<VarDecl> {
/// kind?
QualType::DestructionKind needsDestruction(const ASTContext &Ctx) const;
/// Whether this variable has a flexible array member initialized with one
/// or more elements. This can only be called for declarations where
/// hasInit() is true.
///
/// (The standard doesn't allow initializing flexible array members; this is
/// a gcc/msvc extension.)
bool hasFlexibleArrayInit(const ASTContext &Ctx) const;
/// If hasFlexibleArrayInit is true, compute the number of additional bytes
/// necessary to store those elements. Otherwise, returns zero.
///
/// This can only be called for declarations where hasInit() is true.
CharUnits getFlexibleArrayInitChars(const ASTContext &Ctx) const;
// Implement isa/cast/dyncast/etc.
static bool classof(const Decl *D) { return classofKind(D->getKind()); }
static bool classofKind(Kind K) { return K >= firstVar && K <= lastVar; }
@@ -1616,6 +1630,9 @@ class ImplicitParamDecl : public VarDecl {
/// Parameter for captured context
CapturedContext,
/// Parameter for Thread private variable
ThreadPrivateVar,
/// Other implicit parameter
Other,
};
@@ -2231,6 +2248,13 @@ class FunctionDecl : public DeclaratorDecl,
DeclAsWritten->getCanonicalDecl()->isDefaulted());
}
bool isIneligibleOrNotSelected() const {
return FunctionDeclBits.IsIneligibleOrNotSelected;
}
void setIneligibleOrNotSelected(bool II) {
FunctionDeclBits.IsIneligibleOrNotSelected = II;
}
/// Whether falling off this function implicitly returns null/zero.
/// If a more specific implicit return value is required, front-ends
/// should synthesize the appropriate return statements.
@@ -3483,6 +3507,24 @@ class TagDecl : public TypeDecl,
/// parameters.
bool isDependentType() const { return isDependentContext(); }
/// Whether this declaration was a definition in some module but was forced
/// to be a declaration.
///
/// Useful for clients checking if a module has a definition of a specific
/// symbol and not interested in the final AST with deduplicated definitions.
bool isThisDeclarationADemotedDefinition() const {
return TagDeclBits.IsThisDeclarationADemotedDefinition;
}
/// Mark a definition as a declaration and maintain information it _was_
/// a definition.
void demoteThisDefinitionToDeclaration() {
assert(isCompleteDefinition() &&
"Should demote definitions only, not forward declarations");
setCompleteDefinition(false);
TagDeclBits.IsThisDeclarationADemotedDefinition = true;
}
/// Starts the definition of this tag declaration.
///
/// This method should be invoked at the beginning of the definition
@@ -4030,6 +4072,12 @@ class RecordDecl : public TagDecl {
RecordDeclBits.ParamDestroyedInCallee = V;
}
bool isRandomized() const { return RecordDeclBits.IsRandomized; }
void setIsRandomized(bool V) { RecordDeclBits.IsRandomized = V; }
void reorderDecls(const SmallVectorImpl<Decl *> &Decls);
/// Determines whether this declaration represents the
/// injected class name.
///
@@ -4446,6 +4494,16 @@ class CapturedDecl final
/// @import std.vector;
/// \endcode
///
/// A C++20 module import declaration imports the named module or partition.
/// Periods are permitted in C++20 module names, but have no semantic meaning.
/// For example:
/// \code
/// import NamedModule;
/// import :SomePartition; // Must be a partition of the current module.
/// import Names.Like.this; // Allowed.
/// import :and.Also.Partition.names;
/// \endcode
///
/// Import declarations can also be implicitly generated from
/// \#include/\#import directives.
class ImportDecl final : public Decl,
@@ -225,8 +225,15 @@ class alignas(8) Decl {
/// module is imported.
VisibleWhenImported,
/// This declaration has an owning module, and is visible to lookups
/// that occurs within that module. And it is reachable in other module
/// when the owning module is transitively imported.
ReachableWhenImported,
/// This declaration has an owning module, but is only visible to
/// lookups that occur within that module.
/// The discarded declarations in global module fragment belongs
/// to this group too.
ModulePrivate
};
@@ -235,8 +242,8 @@ class alignas(8) Decl {
/// DeclContext. These pointers form the linked list that is
/// traversed via DeclContext's decls_begin()/decls_end().
///
/// The extra two bits are used for the ModuleOwnershipKind.
llvm::PointerIntPair<Decl *, 2, ModuleOwnershipKind> NextInContextAndBits;
/// The extra three bits are used for the ModuleOwnershipKind.
llvm::PointerIntPair<Decl *, 3, ModuleOwnershipKind> NextInContextAndBits;
private:
friend class DeclContext;
@@ -313,6 +320,7 @@ class alignas(8) Decl {
friend class ASTReader;
friend class CXXClassMemberWrapper;
friend class LinkageComputer;
friend class RecordDecl;
template<typename decl_type> friend class Redeclarable;
/// Access - Used by C++ decls for the access specifier.
@@ -621,6 +629,14 @@ class alignas(8) Decl {
/// export void B::f2(); // isInExportDeclContext() == true
bool isInExportDeclContext() const;
bool isInvisibleOutsideTheOwningModule() const {
return getModuleOwnershipKind() > ModuleOwnershipKind::VisibleWhenImported;
}
/// FIXME: Implement discarding declarations actually in global module
/// fragment. See [module.global.frag]p3,4 for details.
bool isDiscardedInGlobalModuleFragment() const { return false; }
/// Return true if this declaration has an attribute which acts as
/// definition of the entity, such as 'alias' or 'ifunc'.
bool hasDefiningAttr() const;
@@ -798,6 +814,11 @@ class alignas(8) Decl {
return (int)getModuleOwnershipKind() <= (int)ModuleOwnershipKind::Visible;
}
bool isReachable() const {
return (int)getModuleOwnershipKind() <=
(int)ModuleOwnershipKind::ReachableWhenImported;
}
/// Set that this declaration is globally visible, even if it came from a
/// module that is not visible.
void setVisibleDespiteOwningModule() {
@@ -1443,10 +1464,14 @@ class DeclContext {
/// Has the full definition of this type been required by a use somewhere in
/// the TU.
uint64_t IsCompleteDefinitionRequired : 1;
/// Whether this tag is a definition which was demoted due to
/// a module merge.
uint64_t IsThisDeclarationADemotedDefinition : 1;
};
/// Number of non-inherited bits in TagDeclBitfields.
enum { NumTagDeclBits = 9 };
enum { NumTagDeclBits = 10 };
/// Stores the bits used by EnumDecl.
/// If modified NumEnumDeclBit and the accessor
@@ -1536,10 +1561,13 @@ class DeclContext {
/// Represents the way this type is passed to a function.
uint64_t ArgPassingRestrictions : 2;
/// Indicates whether this struct has had its field layout randomized.
uint64_t IsRandomized : 1;
};
/// Number of non-inherited bits in RecordDeclBitfields.
enum { NumRecordDeclBits = 14 };
enum { NumRecordDeclBits = 15 };
/// Stores the bits used by OMPDeclareReductionDecl.
/// If modified NumOMPDeclareReductionDeclBits and the accessor
@@ -1588,6 +1616,12 @@ class DeclContext {
uint64_t IsDefaulted : 1;
uint64_t IsExplicitlyDefaulted : 1;
uint64_t HasDefaultedFunctionInfo : 1;
/// For member functions of complete types, whether this is an ineligible
/// special member function or an unselected destructor. See
/// [class.mem.special].
uint64_t IsIneligibleOrNotSelected : 1;
uint64_t HasImplicitReturnZero : 1;
uint64_t IsLateTemplateParsed : 1;
@@ -1623,7 +1657,7 @@ class DeclContext {
};
/// Number of non-inherited bits in FunctionDeclBitfields.
enum { NumFunctionDeclBits = 27 };
enum { NumFunctionDeclBits = 28 };
/// Stores the bits used by CXXConstructorDecl. If modified
/// NumCXXConstructorDeclBits and the accessor
@@ -1635,12 +1669,12 @@ class DeclContext {
/// For the bits in FunctionDeclBitfields.
uint64_t : NumFunctionDeclBits;
/// 24 bits to fit in the remaining available space.
/// 23 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 : 21;
uint64_t NumCtorInitializers : 20;
uint64_t IsInheritingConstructor : 1;
/// Whether this constructor has a trail-allocated explicit specifier.
@@ -275,6 +275,14 @@ class CXXRecordDecl : public RecordDecl {
SMF_All = 0x3f
};
public:
enum LambdaDependencyKind {
LDK_Unknown = 0,
LDK_AlwaysDependent,
LDK_NeverDependent,
};
private:
struct DefinitionData {
#define FIELD(Name, Width, Merge) \
unsigned Name : Width;
@@ -374,7 +382,7 @@ class CXXRecordDecl : public RecordDecl {
/// lambda will have been created with the enclosing context as its
/// declaration context, rather than function. This is an unfortunate
/// artifact of having to parse the default arguments before.
unsigned Dependent : 1;
unsigned DependencyKind : 2;
/// Whether this lambda is a generic lambda.
unsigned IsGenericLambda : 1;
@@ -408,9 +416,9 @@ class CXXRecordDecl : public RecordDecl {
/// The type of the call method.
TypeSourceInfo *MethodTyInfo;
LambdaDefinitionData(CXXRecordDecl *D, TypeSourceInfo *Info, bool Dependent,
LambdaDefinitionData(CXXRecordDecl *D, TypeSourceInfo *Info, unsigned DK,
bool IsGeneric, LambdaCaptureDefault CaptureDefault)
: DefinitionData(D), Dependent(Dependent), IsGenericLambda(IsGeneric),
: DefinitionData(D), DependencyKind(DK), IsGenericLambda(IsGeneric),
CaptureDefault(CaptureDefault), NumCaptures(0),
NumExplicitCaptures(0), HasKnownInternalLinkage(0), ManglingNumber(0),
MethodTyInfo(Info) {
@@ -547,7 +555,7 @@ class CXXRecordDecl : public RecordDecl {
bool DelayTypeCreation = false);
static CXXRecordDecl *CreateLambda(const ASTContext &C, DeclContext *DC,
TypeSourceInfo *Info, SourceLocation Loc,
bool DependentLambda, bool IsGeneric,
unsigned DependencyKind, bool IsGeneric,
LambdaCaptureDefault CaptureDefault);
static CXXRecordDecl *CreateDeserialized(const ASTContext &C, unsigned ID);
@@ -1414,6 +1422,19 @@ class CXXRecordDecl : public RecordDecl {
return isLiteral() && data().StructuralIfLiteral;
}
/// 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.
/// This is called separately from addedMember because it has to be deferred
/// to the completion of the class.
void addedSelectedDestructor(CXXDestructorDecl *DD);
/// Notify the class that an eligible SMF has been added.
/// This updates triviality and destructor based properties of the class accordingly.
void addedEligibleSpecialMemberFunction(const CXXMethodDecl *MD, unsigned SMKind);
/// If this record is an instantiation of a member class,
/// retrieves the member class from which it was instantiated.
///
@@ -1774,7 +1795,17 @@ class CXXRecordDecl : public RecordDecl {
/// function declaration itself is dependent. This flag indicates when we
/// know that the lambda is dependent despite that.
bool isDependentLambda() const {
return isLambda() && getLambdaData().Dependent;
return isLambda() && getLambdaData().DependencyKind == LDK_AlwaysDependent;
}
bool isNeverDependentLambda() const {
return isLambda() && getLambdaData().DependencyKind == LDK_NeverDependent;
}
unsigned getLambdaDependencyKind() const {
if (!isLambda())
return LDK_Unknown;
return getLambdaData().DependencyKind;
}
TypeSourceInfo *getLambdaTypeInfo() const {
@@ -4188,6 +4219,54 @@ class MSGuidDecl : public ValueDecl,
static bool classofKind(Kind K) { return K == Decl::MSGuid; }
};
/// An artificial decl, representing a global anonymous constant value which is
/// uniquified by value within a translation unit.
///
/// These is currently only used to back the LValue returned by
/// __builtin_source_location, but could potentially be used for other similar
/// situations in the future.
class UnnamedGlobalConstantDecl : public ValueDecl,
public Mergeable<UnnamedGlobalConstantDecl>,
public llvm::FoldingSetNode {
// The constant value of this global.
APValue Value;
void anchor() override;
UnnamedGlobalConstantDecl(const ASTContext &C, DeclContext *DC, QualType T,
const APValue &Val);
static UnnamedGlobalConstantDecl *Create(const ASTContext &C, QualType T,
const APValue &APVal);
static UnnamedGlobalConstantDecl *CreateDeserialized(ASTContext &C,
unsigned ID);
// Only ASTContext::getUnnamedGlobalConstantDecl and deserialization create
// these.
friend class ASTContext;
friend class ASTReader;
friend class ASTDeclReader;
public:
/// Print this in a human-readable format.
void printName(llvm::raw_ostream &OS) const override;
const APValue &getValue() const { return Value; }
static void Profile(llvm::FoldingSetNodeID &ID, QualType Ty,
const APValue &APVal) {
Ty.Profile(ID);
APVal.Profile(ID);
}
void Profile(llvm::FoldingSetNodeID &ID) {
Profile(ID, getType(), getValue());
}
static bool classof(const Decl *D) { return classofKind(D->getKind()); }
static bool classofKind(Kind K) { return K == Decl::UnnamedGlobalConstant; }
};
/// Insertion operator for diagnostics. This allows sending an AccessSpecifier
/// into a diagnostic with <<.
const StreamingDiagnostic &operator<<(const StreamingDiagnostic &DB,
@@ -1951,7 +1951,10 @@ class ObjCIvarDecl : public FieldDecl {
/// in; this is either the interface where the ivar was declared, or the
/// interface the ivar is conceptually a part of in the case of synthesized
/// ivars.
const ObjCInterfaceDecl *getContainingInterface() const;
ObjCInterfaceDecl *getContainingInterface();
const ObjCInterfaceDecl *getContainingInterface() const {
return const_cast<ObjCIvarDecl *>(this)->getContainingInterface();
}
ObjCIvarDecl *getNextIvar() { return NextIvar; }
const ObjCIvarDecl *getNextIvar() const { return NextIvar; }
@@ -2885,15 +2888,16 @@ ObjCInterfaceDecl::filtered_category_iterator<Filter>::operator++() {
}
inline bool ObjCInterfaceDecl::isVisibleCategory(ObjCCategoryDecl *Cat) {
return Cat->isUnconditionallyVisible();
return !Cat->isInvalidDecl() && Cat->isUnconditionallyVisible();
}
inline bool ObjCInterfaceDecl::isVisibleExtension(ObjCCategoryDecl *Cat) {
return Cat->IsClassExtension() && Cat->isUnconditionallyVisible();
return !Cat->isInvalidDecl() && Cat->IsClassExtension() &&
Cat->isUnconditionallyVisible();
}
inline bool ObjCInterfaceDecl::isKnownExtension(ObjCCategoryDecl *Cat) {
return Cat->IsClassExtension();
return !Cat->isInvalidDecl() && Cat->IsClassExtension();
}
} // namespace clang
@@ -1109,7 +1109,7 @@ class FunctionTemplateDecl : public RedeclarableTemplateDecl {
bool isAbbreviated() const {
// Since the invented template parameters generated from 'auto' parameters
// are either appended to the end of the explicit template parameter list or
// form a new template paramter list, we can simply observe the last
// form a new template parameter list, we can simply observe the last
// parameter to determine if such a thing happened.
const TemplateParameterList *TPL = getTemplateParameters();
return TPL->getParam(TPL->size() - 1)->isImplicit();
@@ -1148,23 +1148,40 @@ class FunctionTemplateDecl : public RedeclarableTemplateDecl {
/// parameters and is not part of the Decl hierarchy. Just a facility.
class TemplateParmPosition {
protected:
// FIXME: These probably don't need to be ints. int:5 for depth, int:8 for
// position? Maybe?
unsigned Depth;
unsigned Position;
enum { DepthWidth = 20, PositionWidth = 12 };
unsigned Depth : DepthWidth;
unsigned Position : PositionWidth;
TemplateParmPosition(unsigned D, unsigned P) : Depth(D), Position(P) {}
static constexpr unsigned MaxDepth = (1U << DepthWidth) - 1;
static constexpr unsigned MaxPosition = (1U << PositionWidth) - 1;
TemplateParmPosition(unsigned D, unsigned P) : Depth(D), Position(P) {
// The input may fill maximum values to show that it is invalid.
// Add one here to convert it to zero.
assert((D + 1) <= MaxDepth &&
"The depth of template parmeter position is more than 2^20!");
assert((P + 1) <= MaxPosition &&
"The position of template parmeter position is more than 2^12!");
}
public:
TemplateParmPosition() = delete;
/// Get the nesting depth of the template parameter.
unsigned getDepth() const { return Depth; }
void setDepth(unsigned D) { Depth = D; }
void setDepth(unsigned D) {
assert((D + 1) <= MaxDepth &&
"The depth of template parmeter position is more than 2^20!");
Depth = D;
}
/// Get the position of the template parameter within its parameter list.
unsigned getPosition() const { return Position; }
void setPosition(unsigned P) { Position = P; }
void setPosition(unsigned P) {
assert((P + 1) <= MaxPosition &&
"The position of template parmeter position is more than 2^12!");
Position = P;
}
/// Get the index of the template parameter within its parameter list.
unsigned getIndex() const { return Position; }
@@ -1216,7 +1233,7 @@ class TemplateTypeParmDecl final : public TypeDecl,
: TypeDecl(TemplateTypeParm, DC, IdLoc, Id, KeyLoc), Typename(Typename),
HasTypeConstraint(HasTypeConstraint), TypeConstraintInitialized(false),
ExpandedParameterPack(NumExpanded),
NumExpanded(NumExpanded.getValueOr(0)) {}
NumExpanded(NumExpanded.value_or(0)) {}
public:
static TemplateTypeParmDecl *Create(const ASTContext &C, DeclContext *DC,
@@ -2701,7 +2718,7 @@ class VarTemplateSpecializationDecl : public VarDecl,
/// The template arguments used to describe this specialization.
const TemplateArgumentList *TemplateArgs;
TemplateArgumentListInfo TemplateArgsInfo;
const ASTTemplateArgumentListInfo *TemplateArgsInfo = nullptr;
/// The point where this template was instantiated (if any).
SourceLocation PointOfInstantiation;
@@ -2756,8 +2773,9 @@ class VarTemplateSpecializationDecl : public VarDecl,
// TODO: Always set this when creating the new specialization?
void setTemplateArgsInfo(const TemplateArgumentListInfo &ArgsInfo);
void setTemplateArgsInfo(const ASTTemplateArgumentListInfo *ArgsInfo);
const TemplateArgumentListInfo &getTemplateArgsInfo() const {
const ASTTemplateArgumentListInfo *getTemplateArgsInfo() const {
return TemplateArgsInfo;
}
@@ -3313,10 +3331,12 @@ class TemplateParamObjectDecl : public ValueDecl,
/// Print this object as an equivalent expression.
void printAsExpr(llvm::raw_ostream &OS) const;
void printAsExpr(llvm::raw_ostream &OS, const PrintingPolicy &Policy) const;
/// Print this object as an initializer suitable for a variable of the
/// object's type.
void printAsInit(llvm::raw_ostream &OS) const;
void printAsInit(llvm::raw_ostream &OS, const PrintingPolicy &Policy) const;
const APValue &getValue() const { return Value; }
@@ -21,6 +21,7 @@
#include "clang/Basic/SourceLocation.h"
#include "llvm/ADT/DenseMapInfo.h"
#include "llvm/ADT/FoldingSet.h"
#include "llvm/ADT/STLExtras.h"
#include "llvm/Support/Compiler.h"
#include "llvm/Support/type_traits.h"
#include <cassert>
@@ -192,6 +193,13 @@ class DeclarationName {
"The various classes that DeclarationName::Ptr can point to"
" must be at least aligned to 8 bytes!");
static_assert(
std::is_same<std::underlying_type_t<StoredNameKind>,
std::underlying_type_t<
detail::DeclarationNameExtra::ExtraKind>>::value,
"The various enums used to compute values for NameKind should "
"all have the same underlying type");
public:
/// The kind of the name stored in this DeclarationName.
/// The first 7 enumeration values are stored inline and correspond
@@ -205,15 +213,18 @@ class DeclarationName {
CXXDestructorName = StoredCXXDestructorName,
CXXConversionFunctionName = StoredCXXConversionFunctionName,
CXXOperatorName = StoredCXXOperatorName,
CXXDeductionGuideName = UncommonNameKindOffset +
detail::DeclarationNameExtra::CXXDeductionGuideName,
CXXLiteralOperatorName =
UncommonNameKindOffset +
detail::DeclarationNameExtra::CXXLiteralOperatorName,
CXXUsingDirective = UncommonNameKindOffset +
detail::DeclarationNameExtra::CXXUsingDirective,
ObjCMultiArgSelector = UncommonNameKindOffset +
detail::DeclarationNameExtra::ObjCMultiArgSelector
CXXDeductionGuideName = llvm::addEnumValues(
UncommonNameKindOffset,
detail::DeclarationNameExtra::CXXDeductionGuideName),
CXXLiteralOperatorName = llvm::addEnumValues(
UncommonNameKindOffset,
detail::DeclarationNameExtra::CXXLiteralOperatorName),
CXXUsingDirective =
llvm::addEnumValues(UncommonNameKindOffset,
detail::DeclarationNameExtra::CXXUsingDirective),
ObjCMultiArgSelector =
llvm::addEnumValues(UncommonNameKindOffset,
detail::DeclarationNameExtra::ObjCMultiArgSelector),
};
private:
@@ -1785,7 +1785,7 @@ class StringLiteral final
/// * An array of getByteLength() char used to store the string data.
public:
enum StringKind { Ascii, Wide, UTF8, UTF16, UTF32 };
enum StringKind { Ordinary, Wide, UTF8, UTF16, UTF32 };
private:
unsigned numTrailingObjects(OverloadToken<unsigned>) const { return 1; }
@@ -1882,7 +1882,7 @@ class StringLiteral final
return static_cast<StringKind>(StringLiteralBits.Kind);
}
bool isAscii() const { return getKind() == Ascii; }
bool isOrdinary() const { return getKind() == Ordinary; }
bool isWide() const { return getKind() == Wide; }
bool isUTF8() const { return getKind() == UTF8; }
bool isUTF16() const { return getKind() == UTF16; }
@@ -3127,11 +3127,7 @@ class CallExpr : public Expr {
setDependence(getDependence() | ExprDependence::TypeValueInstantiation);
}
bool isCallToStdMove() const {
const FunctionDecl *FD = getDirectCallee();
return getNumArgs() == 1 && FD && FD->isInStdNamespace() &&
FD->getIdentifier() && FD->getIdentifier()->isStr("move");
}
bool isCallToStdMove() const;
static bool classof(const Stmt *T) {
return T->getStmtClass() >= firstCallExprConstant &&
@@ -4681,16 +4677,17 @@ class VAArgExpr : public Expr {
};
/// Represents a function call to one of __builtin_LINE(), __builtin_COLUMN(),
/// __builtin_FUNCTION(), or __builtin_FILE().
/// __builtin_FUNCTION(), __builtin_FILE(), or __builtin_source_location().
class SourceLocExpr final : public Expr {
SourceLocation BuiltinLoc, RParenLoc;
DeclContext *ParentContext;
public:
enum IdentKind { Function, File, Line, Column };
enum IdentKind { Function, File, Line, Column, SourceLocStruct };
SourceLocExpr(const ASTContext &Ctx, IdentKind Type, SourceLocation BLoc,
SourceLocation RParenLoc, DeclContext *Context);
SourceLocExpr(const ASTContext &Ctx, IdentKind Type, QualType ResultTy,
SourceLocation BLoc, SourceLocation RParenLoc,
DeclContext *Context);
/// Build an empty call expression.
explicit SourceLocExpr(EmptyShell Empty) : Expr(SourceLocExprClass, Empty) {}
@@ -4707,18 +4704,18 @@ class SourceLocExpr final : public Expr {
return static_cast<IdentKind>(SourceLocExprBits.Kind);
}
bool isStringType() const {
bool isIntType() const {
switch (getIdentKind()) {
case File:
case Function:
return true;
case SourceLocStruct:
return false;
case Line:
case Column:
return false;
return true;
}
llvm_unreachable("unknown source location expression kind");
}
bool isIntType() const LLVM_READONLY { return !isStringType(); }
/// If the SourceLocExpr has been resolved return the subexpression
/// representing the resolved value. Otherwise return null.
@@ -2261,15 +2261,32 @@ class CXXNewExpr final
bool isArray() const { return CXXNewExprBits.IsArray; }
/// This might return None 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.
Optional<Expr *> getArraySize() {
if (!isArray())
return None;
return cast_or_null<Expr>(getTrailingObjects<Stmt *>()[arraySizeOffset()]);
if (auto *Result =
cast_or_null<Expr>(getTrailingObjects<Stmt *>()[arraySizeOffset()]))
return Result;
return None;
}
/// This might return None 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.
Optional<const Expr *> getArraySize() const {
if (!isArray())
return None;
return cast_or_null<Expr>(getTrailingObjects<Stmt *>()[arraySizeOffset()]);
if (auto *Result =
cast_or_null<Expr>(getTrailingObjects<Stmt *>()[arraySizeOffset()]))
return Result;
return None;
}
unsigned getNumPlacementArgs() const {
@@ -4681,18 +4698,19 @@ class CoroutineSuspendExpr : public Expr {
SourceLocation KeywordLoc;
enum SubExpr { Common, Ready, Suspend, Resume, Count };
enum SubExpr { Operand, Common, Ready, Suspend, Resume, Count };
Stmt *SubExprs[SubExpr::Count];
OpaqueValueExpr *OpaqueValue = nullptr;
public:
CoroutineSuspendExpr(StmtClass SC, SourceLocation KeywordLoc, Expr *Common,
Expr *Ready, Expr *Suspend, Expr *Resume,
CoroutineSuspendExpr(StmtClass SC, SourceLocation KeywordLoc, Expr *Operand,
Expr *Common, Expr *Ready, Expr *Suspend, Expr *Resume,
OpaqueValueExpr *OpaqueValue)
: Expr(SC, Resume->getType(), Resume->getValueKind(),
Resume->getObjectKind()),
KeywordLoc(KeywordLoc), OpaqueValue(OpaqueValue) {
SubExprs[SubExpr::Operand] = Operand;
SubExprs[SubExpr::Common] = Common;
SubExprs[SubExpr::Ready] = Ready;
SubExprs[SubExpr::Suspend] = Suspend;
@@ -4701,10 +4719,11 @@ class CoroutineSuspendExpr : public Expr {
}
CoroutineSuspendExpr(StmtClass SC, SourceLocation KeywordLoc, QualType Ty,
Expr *Common)
Expr *Operand, Expr *Common)
: Expr(SC, Ty, VK_PRValue, OK_Ordinary), KeywordLoc(KeywordLoc) {
assert(Common->isTypeDependent() && Ty->isDependentType() &&
"wrong constructor for non-dependent co_await/co_yield expression");
SubExprs[SubExpr::Operand] = Operand;
SubExprs[SubExpr::Common] = Common;
SubExprs[SubExpr::Ready] = nullptr;
SubExprs[SubExpr::Suspend] = nullptr;
@@ -4713,14 +4732,13 @@ class CoroutineSuspendExpr : public Expr {
}
CoroutineSuspendExpr(StmtClass SC, EmptyShell Empty) : Expr(SC, Empty) {
SubExprs[SubExpr::Operand] = nullptr;
SubExprs[SubExpr::Common] = nullptr;
SubExprs[SubExpr::Ready] = nullptr;
SubExprs[SubExpr::Suspend] = nullptr;
SubExprs[SubExpr::Resume] = nullptr;
}
SourceLocation getKeywordLoc() const { return KeywordLoc; }
Expr *getCommonExpr() const {
return static_cast<Expr*>(SubExprs[SubExpr::Common]);
}
@@ -4740,10 +4758,17 @@ class CoroutineSuspendExpr : public Expr {
return static_cast<Expr*>(SubExprs[SubExpr::Resume]);
}
// The syntactic operand written in the code
Expr *getOperand() const {
return static_cast<Expr *>(SubExprs[SubExpr::Operand]);
}
SourceLocation getKeywordLoc() const { return KeywordLoc; }
SourceLocation getBeginLoc() const LLVM_READONLY { return KeywordLoc; }
SourceLocation getEndLoc() const LLVM_READONLY {
return getCommonExpr()->getEndLoc();
return getOperand()->getEndLoc();
}
child_range children() {
@@ -4765,28 +4790,24 @@ class CoawaitExpr : public CoroutineSuspendExpr {
friend class ASTStmtReader;
public:
CoawaitExpr(SourceLocation CoawaitLoc, Expr *Operand, Expr *Ready,
Expr *Suspend, Expr *Resume, OpaqueValueExpr *OpaqueValue,
bool IsImplicit = false)
: CoroutineSuspendExpr(CoawaitExprClass, CoawaitLoc, Operand, Ready,
Suspend, Resume, OpaqueValue) {
CoawaitExpr(SourceLocation CoawaitLoc, Expr *Operand, Expr *Common,
Expr *Ready, Expr *Suspend, Expr *Resume,
OpaqueValueExpr *OpaqueValue, bool IsImplicit = false)
: CoroutineSuspendExpr(CoawaitExprClass, CoawaitLoc, Operand, Common,
Ready, Suspend, Resume, OpaqueValue) {
CoawaitBits.IsImplicit = IsImplicit;
}
CoawaitExpr(SourceLocation CoawaitLoc, QualType Ty, Expr *Operand,
bool IsImplicit = false)
: CoroutineSuspendExpr(CoawaitExprClass, CoawaitLoc, Ty, Operand) {
Expr *Common, bool IsImplicit = false)
: CoroutineSuspendExpr(CoawaitExprClass, CoawaitLoc, Ty, Operand,
Common) {
CoawaitBits.IsImplicit = IsImplicit;
}
CoawaitExpr(EmptyShell Empty)
: CoroutineSuspendExpr(CoawaitExprClass, Empty) {}
Expr *getOperand() const {
// FIXME: Dig out the actual operand or store it.
return getCommonExpr();
}
bool isImplicit() const { return CoawaitBits.IsImplicit; }
void setIsImplicit(bool value = true) { CoawaitBits.IsImplicit = value; }
@@ -4850,20 +4871,18 @@ class CoyieldExpr : public CoroutineSuspendExpr {
friend class ASTStmtReader;
public:
CoyieldExpr(SourceLocation CoyieldLoc, Expr *Operand, Expr *Ready,
Expr *Suspend, Expr *Resume, OpaqueValueExpr *OpaqueValue)
: CoroutineSuspendExpr(CoyieldExprClass, CoyieldLoc, Operand, Ready,
Suspend, Resume, OpaqueValue) {}
CoyieldExpr(SourceLocation CoyieldLoc, QualType Ty, Expr *Operand)
: CoroutineSuspendExpr(CoyieldExprClass, CoyieldLoc, Ty, Operand) {}
CoyieldExpr(SourceLocation CoyieldLoc, Expr *Operand, Expr *Common,
Expr *Ready, Expr *Suspend, Expr *Resume,
OpaqueValueExpr *OpaqueValue)
: CoroutineSuspendExpr(CoyieldExprClass, CoyieldLoc, Operand, Common,
Ready, Suspend, Resume, OpaqueValue) {}
CoyieldExpr(SourceLocation CoyieldLoc, QualType Ty, Expr *Operand,
Expr *Common)
: CoroutineSuspendExpr(CoyieldExprClass, CoyieldLoc, Ty, Operand,
Common) {}
CoyieldExpr(EmptyShell Empty)
: CoroutineSuspendExpr(CoyieldExprClass, Empty) {}
Expr *getOperand() const {
// FIXME: Dig out the actual operand or store it.
return getCommonExpr();
}
static bool classof(const Stmt *T) {
return T->getStmtClass() == CoyieldExprClass;
}
@@ -122,6 +122,8 @@ class ConceptSpecializationExpr final : public Expr, public ConceptReference,
}
SourceLocation getBeginLoc() const LLVM_READONLY {
if (auto QualifierLoc = getNestedNameSpecifierLoc())
return QualifierLoc.getBeginLoc();
return ConceptName.getBeginLoc();
}
@@ -160,6 +160,7 @@ class JSONNodeDumper
std::string createPointerRepresentation(const void *Ptr);
llvm::json::Object createQualType(QualType QT, bool Desugar = true);
llvm::json::Object createBareDeclRef(const Decl *D);
llvm::json::Object createFPOptions(FPOptionsOverride FPO);
void writeBareDeclRef(const Decl *D);
llvm::json::Object createCXXRecordDefinitionData(const CXXRecordDecl *RD);
llvm::json::Object createCXXBaseSpecifier(const CXXBaseSpecifier &BS);
@@ -317,6 +318,7 @@ class JSONNodeDumper
void VisitGotoStmt(const GotoStmt *GS);
void VisitWhileStmt(const WhileStmt *WS);
void VisitObjCAtCatchStmt(const ObjCAtCatchStmt *OACS);
void VisitCompoundStmt(const CompoundStmt *IS);
void VisitNullTemplateArgument(const TemplateArgument &TA);
void VisitTypeTemplateArgument(const TemplateArgument &TA);
@@ -54,6 +54,9 @@ class MangleContext {
ASTContext &Context;
DiagnosticsEngine &Diags;
const ManglerKind Kind;
/// For aux target. If true, uses mangling number for aux target from
/// ASTContext.
bool IsAux = false;
llvm::DenseMap<const BlockDecl*, unsigned> GlobalBlockIds;
llvm::DenseMap<const BlockDecl*, unsigned> LocalBlockIds;
@@ -62,10 +65,11 @@ class MangleContext {
public:
ManglerKind getKind() const { return Kind; }
explicit MangleContext(ASTContext &Context,
DiagnosticsEngine &Diags,
ManglerKind Kind)
: Context(Context), Diags(Diags), Kind(Kind) {}
bool isAux() const { return IsAux; }
explicit MangleContext(ASTContext &Context, DiagnosticsEngine &Diags,
ManglerKind Kind, bool IsAux = false)
: Context(Context), Diags(Diags), Kind(Kind), IsAux(IsAux) {}
virtual ~MangleContext() { }
@@ -172,8 +176,9 @@ class ItaniumMangleContext : public MangleContext {
public:
using DiscriminatorOverrideTy =
llvm::Optional<unsigned> (*)(ASTContext &, const NamedDecl *);
explicit ItaniumMangleContext(ASTContext &C, DiagnosticsEngine &D)
: MangleContext(C, D, MK_Itanium) {}
explicit ItaniumMangleContext(ASTContext &C, DiagnosticsEngine &D,
bool IsAux = false)
: MangleContext(C, D, MK_Itanium, IsAux) {}
virtual void mangleCXXVTable(const CXXRecordDecl *RD, raw_ostream &) = 0;
virtual void mangleCXXVTT(const CXXRecordDecl *RD, raw_ostream &) = 0;
@@ -194,6 +199,8 @@ class ItaniumMangleContext : public MangleContext {
virtual void mangleDynamicStermFinalizer(const VarDecl *D, raw_ostream &) = 0;
virtual void mangleModuleInitializer(const Module *Module, raw_ostream &) = 0;
// This has to live here, otherwise the CXXNameMangler won't have access to
// it.
virtual DiscriminatorOverrideTy getDiscriminatorOverride() const = 0;
@@ -201,17 +208,19 @@ class ItaniumMangleContext : public MangleContext {
return C->getKind() == MK_Itanium;
}
static ItaniumMangleContext *create(ASTContext &Context,
DiagnosticsEngine &Diags);
static ItaniumMangleContext *
create(ASTContext &Context, DiagnosticsEngine &Diags, bool IsAux = false);
static ItaniumMangleContext *create(ASTContext &Context,
DiagnosticsEngine &Diags,
DiscriminatorOverrideTy Discriminator);
DiscriminatorOverrideTy Discriminator,
bool IsAux = false);
};
class MicrosoftMangleContext : public MangleContext {
public:
explicit MicrosoftMangleContext(ASTContext &C, DiagnosticsEngine &D)
: MangleContext(C, D, MK_Microsoft) {}
explicit MicrosoftMangleContext(ASTContext &C, DiagnosticsEngine &D,
bool IsAux = false)
: MangleContext(C, D, MK_Microsoft, IsAux) {}
/// Mangle vftable symbols. Only a subset of the bases along the path
/// to the vftable are included in the name. It's up to the caller to pick
@@ -270,8 +279,8 @@ class MicrosoftMangleContext : public MangleContext {
return C->getKind() == MK_Microsoft;
}
static MicrosoftMangleContext *create(ASTContext &Context,
DiagnosticsEngine &Diags);
static MicrosoftMangleContext *
create(ASTContext &Context, DiagnosticsEngine &Diags, bool IsAux = false);
};
class ASTNameGenerator {
@@ -162,7 +162,7 @@ class NestedNameSpecifier : public llvm::FoldingSetNode {
/// Return the prefix of this nested name specifier.
///
/// The prefix contains all of the parts of the nested name
/// specifier that preced this current specifier. For example, for a
/// specifier that precede this current specifier. For example, for a
/// nested name specifier that represents "foo::bar::", the current
/// specifier will contain "bar::" and the prefix will contain
/// "foo::".
@@ -4746,14 +4746,24 @@ class OMPDependClause final
friend OMPVarListClause;
friend TrailingObjects;
/// Dependency type (one of in, out, inout).
OpenMPDependClauseKind DepKind = OMPC_DEPEND_unknown;
public:
struct DependDataTy final {
/// Dependency type (one of in, out, inout).
OpenMPDependClauseKind DepKind = OMPC_DEPEND_unknown;
/// Dependency type location.
SourceLocation DepLoc;
/// Dependency type location.
SourceLocation DepLoc;
/// Colon location.
SourceLocation ColonLoc;
/// Colon location.
SourceLocation ColonLoc;
/// Location of 'omp_all_memory'.
SourceLocation OmpAllMemoryLoc;
};
private:
/// Dependency type and source locations.
DependDataTy Data;
/// Number of loops, associated with the depend clause.
unsigned NumLoops = 0;
@@ -4784,13 +4794,16 @@ class OMPDependClause final
NumLoops(NumLoops) {}
/// Set dependency kind.
void setDependencyKind(OpenMPDependClauseKind K) { DepKind = K; }
void setDependencyKind(OpenMPDependClauseKind K) { Data.DepKind = K; }
/// Set dependency kind and its location.
void setDependencyLoc(SourceLocation Loc) { DepLoc = Loc; }
void setDependencyLoc(SourceLocation Loc) { Data.DepLoc = Loc; }
/// Set colon location.
void setColonLoc(SourceLocation Loc) { ColonLoc = Loc; }
void setColonLoc(SourceLocation Loc) { Data.ColonLoc = Loc; }
/// Set the 'omp_all_memory' location.
void setOmpAllMemoryLoc(SourceLocation Loc) { Data.OmpAllMemoryLoc = Loc; }
/// Sets optional dependency modifier.
void setModifier(Expr *DepModifier);
@@ -4802,18 +4815,15 @@ class OMPDependClause final
/// \param StartLoc Starting location of the clause.
/// \param LParenLoc Location of '('.
/// \param EndLoc Ending location of the clause.
/// \param DepKind Dependency type.
/// \param DepLoc Location of the dependency type.
/// \param ColonLoc Colon location.
/// \param Data Dependency type and source locations.
/// \param VL List of references to the variables.
/// \param NumLoops Number of loops that is associated with this depend
/// clause.
static OMPDependClause *Create(const ASTContext &C, SourceLocation StartLoc,
SourceLocation LParenLoc,
SourceLocation EndLoc, Expr *DepModifier,
OpenMPDependClauseKind DepKind,
SourceLocation DepLoc, SourceLocation ColonLoc,
ArrayRef<Expr *> VL, unsigned NumLoops);
SourceLocation EndLoc, DependDataTy Data,
Expr *DepModifier, ArrayRef<Expr *> VL,
unsigned NumLoops);
/// Creates an empty clause with \a N variables.
///
@@ -4825,7 +4835,16 @@ class OMPDependClause final
unsigned NumLoops);
/// Get dependency type.
OpenMPDependClauseKind getDependencyKind() const { return DepKind; }
OpenMPDependClauseKind getDependencyKind() const { return Data.DepKind; }
/// Get dependency type location.
SourceLocation getDependencyLoc() const { return Data.DepLoc; }
/// Get colon location.
SourceLocation getColonLoc() const { return Data.ColonLoc; }
/// Get 'omp_all_memory' location.
SourceLocation getOmpAllMemoryLoc() const { return Data.OmpAllMemoryLoc; }
/// Return optional depend modifier.
Expr *getModifier();
@@ -4833,12 +4852,6 @@ class OMPDependClause final
return const_cast<OMPDependClause *>(this)->getModifier();
}
/// Get dependency type location.
SourceLocation getDependencyLoc() const { return DepLoc; }
/// Get colon location.
SourceLocation getColonLoc() const { return ColonLoc; }
/// Get number of loops associated with the clause.
unsigned getNumLoops() const { return NumLoops; }
@@ -7416,6 +7429,110 @@ class OMPIsDevicePtrClause final
}
};
/// This represents clause 'has_device_ptr' in the '#pragma omp ...'
/// directives.
///
/// \code
/// #pragma omp target has_device_addr(a,b)
/// \endcode
/// In this example directive '#pragma omp target' has clause
/// 'has_device_ptr' with the variables 'a' and 'b'.
class OMPHasDeviceAddrClause final
: public OMPMappableExprListClause<OMPHasDeviceAddrClause>,
private llvm::TrailingObjects<
OMPHasDeviceAddrClause, Expr *, ValueDecl *, unsigned,
OMPClauseMappableExprCommon::MappableComponent> {
friend class OMPClauseReader;
friend OMPMappableExprListClause;
friend OMPVarListClause;
friend TrailingObjects;
/// Build clause with number of variables \a NumVars.
///
/// \param Locs Locations needed to build a mappable clause. It includes 1)
/// StartLoc: starting location of the clause (the clause keyword); 2)
/// LParenLoc: location of '('; 3) EndLoc: ending location of the clause.
/// \param Sizes All required sizes to build a mappable clause. It includes 1)
/// NumVars: number of expressions listed in this clause; 2)
/// NumUniqueDeclarations: number of unique base declarations in this clause;
/// 3) NumComponentLists: number of component lists in this clause; and 4)
/// NumComponents: total number of expression components in the clause.
explicit OMPHasDeviceAddrClause(const OMPVarListLocTy &Locs,
const OMPMappableExprListSizeTy &Sizes)
: OMPMappableExprListClause(llvm::omp::OMPC_has_device_addr, Locs,
Sizes) {}
/// Build an empty clause.
///
/// \param Sizes All required sizes to build a mappable clause. It includes 1)
/// NumVars: number of expressions listed in this clause; 2)
/// NumUniqueDeclarations: number of unique base declarations in this clause;
/// 3) NumComponentLists: number of component lists in this clause; and 4)
/// NumComponents: total number of expression components in the clause.
explicit OMPHasDeviceAddrClause(const OMPMappableExprListSizeTy &Sizes)
: OMPMappableExprListClause(llvm::omp::OMPC_has_device_addr,
OMPVarListLocTy(), Sizes) {}
/// Define the sizes of each trailing object array except the last one. This
/// is required for TrailingObjects to work properly.
size_t numTrailingObjects(OverloadToken<Expr *>) const {
return varlist_size();
}
size_t numTrailingObjects(OverloadToken<ValueDecl *>) const {
return getUniqueDeclarationsNum();
}
size_t numTrailingObjects(OverloadToken<unsigned>) const {
return getUniqueDeclarationsNum() + getTotalComponentListNum();
}
public:
/// Creates clause with a list of variables \a Vars.
///
/// \param C AST context.
/// \param Locs Locations needed to build a mappable clause. It includes 1)
/// StartLoc: starting location of the clause (the clause keyword); 2)
/// LParenLoc: location of '('; 3) EndLoc: ending location of the clause.
/// \param Vars The original expression used in the clause.
/// \param Declarations Declarations used in the clause.
/// \param ComponentLists Component lists used in the clause.
static OMPHasDeviceAddrClause *
Create(const ASTContext &C, const OMPVarListLocTy &Locs,
ArrayRef<Expr *> Vars, ArrayRef<ValueDecl *> Declarations,
MappableExprComponentListsRef ComponentLists);
/// Creates an empty clause with the place for \a NumVars variables.
///
/// \param C AST context.
/// \param Sizes All required sizes to build a mappable clause. It includes 1)
/// NumVars: number of expressions listed in this clause; 2)
/// NumUniqueDeclarations: number of unique base declarations in this clause;
/// 3) NumComponentLists: number of component lists in this clause; and 4)
/// NumComponents: total number of expression components in the clause.
static OMPHasDeviceAddrClause *
CreateEmpty(const ASTContext &C, const OMPMappableExprListSizeTy &Sizes);
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<OMPHasDeviceAddrClause *>(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_has_device_addr;
}
};
/// This represents clause 'nontemporal' in the '#pragma omp ...' directives.
///
/// \code
@@ -90,29 +90,27 @@ class TraversalKindScope {
/// Container for either a single DynTypedNode or for an ArrayRef to
/// DynTypedNode. For use with ParentMap.
class DynTypedNodeList {
llvm::AlignedCharArrayUnion<DynTypedNode, ArrayRef<DynTypedNode>> Storage;
union {
DynTypedNode SingleNode;
ArrayRef<DynTypedNode> Nodes;
};
bool IsSingleNode;
public:
DynTypedNodeList(const DynTypedNode &N) : IsSingleNode(true) {
new (&Storage) DynTypedNode(N);
new (&SingleNode) DynTypedNode(N);
}
DynTypedNodeList(ArrayRef<DynTypedNode> A) : IsSingleNode(false) {
new (&Storage) ArrayRef<DynTypedNode>(A);
new (&Nodes) ArrayRef<DynTypedNode>(A);
}
const DynTypedNode *begin() const {
if (!IsSingleNode)
return reinterpret_cast<const ArrayRef<DynTypedNode> *>(&Storage)
->begin();
return reinterpret_cast<const DynTypedNode *>(&Storage);
return !IsSingleNode ? Nodes.begin() : &SingleNode;
}
const DynTypedNode *end() const {
if (!IsSingleNode)
return reinterpret_cast<const ArrayRef<DynTypedNode> *>(&Storage)->end();
return reinterpret_cast<const DynTypedNode *>(&Storage) + 1;
return !IsSingleNode ? Nodes.end() : &SingleNode + 1;
}
size_t size() const { return end() - begin(); }
@@ -74,7 +74,8 @@ struct PrintingPolicy {
SuppressImplicitBase(false), FullyQualifiedName(false),
PrintCanonicalTypes(false), PrintInjectedClassNameWithArguments(true),
UsePreferredNames(true), AlwaysIncludeTypeForTemplateArgument(false),
CleanUglifiedParameters(false) {}
CleanUglifiedParameters(false), EntireContentsOfLargeArray(true),
UseEnumerators(true) {}
/// Adjust this printing policy for cases where it's known that we're
/// printing C++ code (for instance, if AST dumping reaches a C++-only
@@ -286,6 +287,14 @@ struct PrintingPolicy {
/// This only affects parameter names, and so describes a compatible API.
unsigned CleanUglifiedParameters : 1;
/// Whether to print the entire array initializers, especially on non-type
/// template parameters, no matter how many elements there are.
unsigned EntireContentsOfLargeArray : 1;
/// Whether to print enumerator non-type template parameters with a matching
/// enumerator name or via cast of an integer.
unsigned UseEnumerators : 1;
/// Callbacks to use to allow the behavior of printing to be customized.
const PrintingCallbacks *Callbacks = nullptr;
};
@@ -79,6 +79,7 @@ def AttrKind : EnumPropertyType<"attr::Kind">;
def AutoTypeKeyword : EnumPropertyType;
def Bool : PropertyType<"bool">;
def BuiltinTypeKind : EnumPropertyType<"BuiltinType::Kind">;
def BTFTypeTagAttr : PropertyType<"const BTFTypeTagAttr *">;
def CallingConv : EnumPropertyType;
def DeclarationName : PropertyType;
def DeclarationNameKind : EnumPropertyType<"DeclarationName::NameKind">;
@@ -619,6 +620,16 @@ let Class = PropertyTypeCase<TemplateName, "Template"> in {
return TemplateName(declaration);
}]>;
}
let Class = PropertyTypeCase<TemplateName, "UsingTemplate"> in {
def : Property<"foundDecl", UsingShadowDeclRef> {
let Read = [{ node.getAsUsingShadowDecl() }];
}
def : Creator<[{
return TemplateName(foundDecl);
}]>;
}
let Class = PropertyTypeCase<TemplateName, "OverloadedTemplate"> in {
def : Property<"overloads", Array<NamedDeclRef>> {
let Read = [{ node.getAsOverloadedTemplate()->decls() }];
@@ -652,12 +663,12 @@ let Class = PropertyTypeCase<TemplateName, "QualifiedTemplate"> in {
def : Property<"hasTemplateKeyword", Bool> {
let Read = [{ qtn->hasTemplateKeyword() }];
}
def : Property<"declaration", TemplateDeclRef> {
let Read = [{ qtn->getTemplateDecl() }];
def : Property<"underlyingTemplateName", TemplateName> {
let Read = [{ qtn->getUnderlyingTemplate() }];
}
def : Creator<[{
return ctx.getQualifiedTemplateName(qualifier, hasTemplateKeyword,
declaration);
underlyingTemplateName);
}]>;
}
let Class = PropertyTypeCase<TemplateName, "DependentTemplate"> in {
@@ -0,0 +1,35 @@
//===- Randstruct.h - Interfact for structure randomization -------*- 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 contains the interface for Clang's structure field layout
// randomization.
//
//===----------------------------------------------------------------------===//
#ifndef LLVM_CLANG_AST_RANDSTRUCT_H
#define LLVM_CLANG_AST_RANDSTRUCT_H
namespace llvm {
template <typename T> class SmallVectorImpl;
} // end namespace llvm
namespace clang {
class ASTContext;
class Decl;
class RecordDecl;
namespace randstruct {
bool randomizeStructureLayout(const ASTContext &Context, RecordDecl *RD,
llvm::SmallVectorImpl<Decl *> &FinalOrdering);
} // namespace randstruct
} // namespace clang
#endif // LLVM_CLANG_AST_RANDSTRUCT_H
@@ -139,6 +139,21 @@ class RawComment {
std::string getFormattedText(const SourceManager &SourceMgr,
DiagnosticsEngine &Diags) const;
struct CommentLine {
std::string Text;
PresumedLoc Begin;
PresumedLoc End;
CommentLine(StringRef Text, PresumedLoc Begin, PresumedLoc End)
: Text(Text), Begin(Begin), End(End) {}
};
/// Returns sanitized comment text as separated lines with locations in
/// source, suitable for further processing and rendering requiring source
/// locations.
std::vector<CommentLine> getFormattedLines(const SourceManager &SourceMgr,
DiagnosticsEngine &Diags) const;
/// Parse the comment, assuming it is attached to decl \c D.
comments::FullComment *parse(const ASTContext &Context,
const Preprocessor *PP, const Decl *D) const;
@@ -13,18 +13,19 @@
#ifndef LLVM_CLANG_AST_RECURSIVEASTVISITOR_H
#define LLVM_CLANG_AST_RECURSIVEASTVISITOR_H
#include "clang/AST/ASTConcept.h"
#include "clang/AST/Attr.h"
#include "clang/AST/Decl.h"
#include "clang/AST/DeclarationName.h"
#include "clang/AST/DeclBase.h"
#include "clang/AST/DeclCXX.h"
#include "clang/AST/DeclFriend.h"
#include "clang/AST/DeclObjC.h"
#include "clang/AST/DeclOpenMP.h"
#include "clang/AST/DeclTemplate.h"
#include "clang/AST/DeclarationName.h"
#include "clang/AST/Expr.h"
#include "clang/AST/ExprConcepts.h"
#include "clang/AST/ExprCXX.h"
#include "clang/AST/ExprConcepts.h"
#include "clang/AST/ExprObjC.h"
#include "clang/AST/ExprOpenMP.h"
#include "clang/AST/LambdaCapture.h"
@@ -319,10 +320,11 @@ template <typename Derived> class RecursiveASTVisitor {
bool TraverseSynOrSemInitListExpr(InitListExpr *S,
DataRecursionQueue *Queue = nullptr);
/// Recursively visit a reference to a concept with potential arguments.
/// Recursively visit an Objective-C protocol reference with location
/// information.
///
/// \returns false if the visitation was terminated early, true otherwise.
bool TraverseConceptReference(const ConceptReference &C);
bool TraverseObjCProtocolLoc(ObjCProtocolLoc ProtocolLoc);
// ---- Methods on Attrs ----
@@ -469,11 +471,21 @@ template <typename Derived> class RecursiveASTVisitor {
DEF_TRAVERSE_TMPL_INST(Function)
#undef DEF_TRAVERSE_TMPL_INST
bool TraverseTypeConstraint(const TypeConstraint *C);
bool TraverseConceptRequirement(concepts::Requirement *R);
bool TraverseConceptTypeRequirement(concepts::TypeRequirement *R);
bool TraverseConceptExprRequirement(concepts::ExprRequirement *R);
bool TraverseConceptNestedRequirement(concepts::NestedRequirement *R);
bool dataTraverseNode(Stmt *S, DataRecursionQueue *Queue);
private:
// These are helper methods used by more than one Traverse* method.
bool TraverseTemplateParameterListHelper(TemplateParameterList *TPL);
/// Traverses the qualifier, name and template arguments of a concept
/// reference.
bool TraverseConceptReferenceHelper(const ConceptReference &C);
// Traverses template parameter lists of either a DeclaratorDecl or TagDecl.
template <typename T>
@@ -505,6 +517,55 @@ template <typename Derived> class RecursiveASTVisitor {
bool PostVisitStmt(Stmt *S);
};
template <typename Derived>
bool RecursiveASTVisitor<Derived>::TraverseTypeConstraint(
const TypeConstraint *C) {
if (!getDerived().shouldVisitImplicitCode()) {
TRY_TO(TraverseConceptReferenceHelper(*C));
return true;
}
if (Expr *IDC = C->getImmediatelyDeclaredConstraint()) {
TRY_TO(TraverseStmt(IDC));
} else {
// Avoid traversing the ConceptReference in the TypeConstraint
// if we have an immediately-declared-constraint, otherwise
// we'll end up visiting the concept and the arguments in
// the TC twice.
TRY_TO(TraverseConceptReferenceHelper(*C));
}
return true;
}
template <typename Derived>
bool RecursiveASTVisitor<Derived>::TraverseConceptRequirement(
concepts::Requirement *R) {
switch (R->getKind()) {
case concepts::Requirement::RK_Type:
return getDerived().TraverseConceptTypeRequirement(
cast<concepts::TypeRequirement>(R));
case concepts::Requirement::RK_Simple:
case concepts::Requirement::RK_Compound:
return getDerived().TraverseConceptExprRequirement(
cast<concepts::ExprRequirement>(R));
case concepts::Requirement::RK_Nested:
return getDerived().TraverseConceptNestedRequirement(
cast<concepts::NestedRequirement>(R));
}
llvm_unreachable("unexpected case");
}
template <typename Derived>
bool RecursiveASTVisitor<Derived>::TraverseConceptReferenceHelper(
const ConceptReference &C) {
TRY_TO(TraverseNestedNameSpecifierLoc(C.getNestedNameSpecifierLoc()));
TRY_TO(TraverseDeclarationNameInfo(C.getConceptNameInfo()));
if (C.hasExplicitTemplateArgs())
TRY_TO(TraverseTemplateArgumentLocsHelper(
C.getTemplateArgsAsWritten()->getTemplateArgs(),
C.getTemplateArgsAsWritten()->NumTemplateArgs));
return true;
}
template <typename Derived>
bool RecursiveASTVisitor<Derived>::dataTraverseNode(Stmt *S,
DataRecursionQueue *Queue) {
@@ -524,6 +585,40 @@ bool RecursiveASTVisitor<Derived>::dataTraverseNode(Stmt *S,
#undef DISPATCH_STMT
template <typename Derived>
bool RecursiveASTVisitor<Derived>::TraverseConceptTypeRequirement(
concepts::TypeRequirement *R) {
if (R->isSubstitutionFailure())
return true;
return getDerived().TraverseTypeLoc(R->getType()->getTypeLoc());
}
template <typename Derived>
bool RecursiveASTVisitor<Derived>::TraverseConceptExprRequirement(
concepts::ExprRequirement *R) {
if (!R->isExprSubstitutionFailure())
TRY_TO(TraverseStmt(R->getExpr()));
auto &RetReq = R->getReturnTypeRequirement();
if (RetReq.isTypeConstraint()) {
if (getDerived().shouldVisitImplicitCode()) {
TRY_TO(TraverseTemplateParameterListHelper(
RetReq.getTypeConstraintTemplateParameterList()));
} else {
// Template parameter list is implicit, visit constraint directly.
TRY_TO(TraverseTypeConstraint(RetReq.getTypeConstraint()));
}
}
return true;
}
template <typename Derived>
bool RecursiveASTVisitor<Derived>::TraverseConceptNestedRequirement(
concepts::NestedRequirement *R) {
if (!R->isSubstitutionFailure())
return getDerived().TraverseStmt(R->getConstraintExpr());
return true;
}
template <typename Derived>
bool RecursiveASTVisitor<Derived>::PostVisitStmt(Stmt *S) {
// In pre-order traversal mode, each Traverse##STMT method is responsible for
@@ -1001,7 +1096,6 @@ DEF_TRAVERSE_TYPE(UnaryTransformType, {
DEF_TRAVERSE_TYPE(AutoType, {
TRY_TO(TraverseType(T->getDeducedType()));
if (T->isConstrained()) {
TRY_TO(TraverseDecl(T->getTypeConstraintConcept()));
TRY_TO(TraverseTemplateArguments(T->getArgs(), T->getNumArgs()));
}
})
@@ -1030,6 +1124,9 @@ DEF_TRAVERSE_TYPE(InjectedClassNameType, {})
DEF_TRAVERSE_TYPE(AttributedType,
{ TRY_TO(TraverseType(T->getModifiedType())); })
DEF_TRAVERSE_TYPE(BTFTagAttributedType,
{ TRY_TO(TraverseType(T->getWrappedType())); })
DEF_TRAVERSE_TYPE(ParenType, { TRY_TO(TraverseType(T->getInnerType())); })
DEF_TRAVERSE_TYPE(MacroQualifiedType,
@@ -1316,6 +1413,9 @@ DEF_TRAVERSE_TYPELOC(MacroQualifiedType,
DEF_TRAVERSE_TYPELOC(AttributedType,
{ TRY_TO(TraverseTypeLoc(TL.getModifiedLoc())); })
DEF_TRAVERSE_TYPELOC(BTFTagAttributedType,
{ TRY_TO(TraverseTypeLoc(TL.getWrappedLoc())); })
DEF_TRAVERSE_TYPELOC(ElaboratedType, {
if (TL.getQualifierLoc()) {
TRY_TO(TraverseNestedNameSpecifierLoc(TL.getQualifierLoc()));
@@ -1340,7 +1440,12 @@ DEF_TRAVERSE_TYPELOC(DependentTemplateSpecializationType, {
DEF_TRAVERSE_TYPELOC(PackExpansionType,
{ TRY_TO(TraverseTypeLoc(TL.getPatternLoc())); })
DEF_TRAVERSE_TYPELOC(ObjCTypeParamType, {})
DEF_TRAVERSE_TYPELOC(ObjCTypeParamType, {
for (unsigned I = 0, N = TL.getNumProtocols(); I != N; ++I) {
ObjCProtocolLoc ProtocolLoc(TL.getProtocol(I), TL.getProtocolLoc(I));
TRY_TO(TraverseObjCProtocolLoc(ProtocolLoc));
}
})
DEF_TRAVERSE_TYPELOC(ObjCInterfaceType, {})
@@ -1351,6 +1456,10 @@ DEF_TRAVERSE_TYPELOC(ObjCObjectType, {
TRY_TO(TraverseTypeLoc(TL.getBaseLoc()));
for (unsigned i = 0, n = TL.getNumTypeArgs(); i != n; ++i)
TRY_TO(TraverseTypeLoc(TL.getTypeArgTInfo(i)->getTypeLoc()));
for (unsigned I = 0, N = TL.getNumProtocols(); I != N; ++I) {
ObjCProtocolLoc ProtocolLoc(TL.getProtocol(I), TL.getProtocolLoc(I));
TRY_TO(TraverseObjCProtocolLoc(ProtocolLoc));
}
})
DEF_TRAVERSE_TYPELOC(ObjCObjectPointerType,
@@ -1541,12 +1650,16 @@ DEF_TRAVERSE_DECL(
DEF_TRAVERSE_DECL(ObjCCompatibleAliasDecl, {// FIXME: implement
})
DEF_TRAVERSE_DECL(ObjCCategoryDecl, {// FIXME: implement
DEF_TRAVERSE_DECL(ObjCCategoryDecl, {
if (ObjCTypeParamList *typeParamList = D->getTypeParamList()) {
for (auto typeParam : *typeParamList) {
TRY_TO(TraverseObjCTypeParamDecl(typeParam));
}
}
for (auto It : llvm::zip(D->protocols(), D->protocol_locs())) {
ObjCProtocolLoc ProtocolLoc(std::get<0>(It), std::get<1>(It));
TRY_TO(TraverseObjCProtocolLoc(ProtocolLoc));
}
})
DEF_TRAVERSE_DECL(ObjCCategoryImplDecl, {// FIXME: implement
@@ -1555,7 +1668,7 @@ DEF_TRAVERSE_DECL(ObjCCategoryImplDecl, {// FIXME: implement
DEF_TRAVERSE_DECL(ObjCImplementationDecl, {// FIXME: implement
})
DEF_TRAVERSE_DECL(ObjCInterfaceDecl, {// FIXME: implement
DEF_TRAVERSE_DECL(ObjCInterfaceDecl, {
if (ObjCTypeParamList *typeParamList = D->getTypeParamListAsWritten()) {
for (auto typeParam : *typeParamList) {
TRY_TO(TraverseObjCTypeParamDecl(typeParam));
@@ -1565,10 +1678,22 @@ DEF_TRAVERSE_DECL(ObjCInterfaceDecl, {// FIXME: implement
if (TypeSourceInfo *superTInfo = D->getSuperClassTInfo()) {
TRY_TO(TraverseTypeLoc(superTInfo->getTypeLoc()));
}
if (D->isThisDeclarationADefinition()) {
for (auto It : llvm::zip(D->protocols(), D->protocol_locs())) {
ObjCProtocolLoc ProtocolLoc(std::get<0>(It), std::get<1>(It));
TRY_TO(TraverseObjCProtocolLoc(ProtocolLoc));
}
}
})
DEF_TRAVERSE_DECL(ObjCProtocolDecl, {// FIXME: implement
})
DEF_TRAVERSE_DECL(ObjCProtocolDecl, {
if (D->isThisDeclarationADefinition()) {
for (auto It : llvm::zip(D->protocols(), D->protocol_locs())) {
ObjCProtocolLoc ProtocolLoc(std::get<0>(It), std::get<1>(It));
TRY_TO(TraverseObjCProtocolLoc(ProtocolLoc));
}
}
})
DEF_TRAVERSE_DECL(ObjCMethodDecl, {
if (D->getReturnTypeSourceInfo()) {
@@ -1801,17 +1926,8 @@ DEF_TRAVERSE_DECL(BuiltinTemplateDecl, {
template <typename Derived>
bool RecursiveASTVisitor<Derived>::TraverseTemplateTypeParamDeclConstraints(
const TemplateTypeParmDecl *D) {
if (const auto *TC = D->getTypeConstraint()) {
if (Expr *IDC = TC->getImmediatelyDeclaredConstraint()) {
TRY_TO(TraverseStmt(IDC));
} else {
// Avoid traversing the ConceptReference in the TypeCosntraint
// if we have an immediately-declared-constraint, otherwise
// we'll end up visiting the concept and the arguments in
// the TC twice.
TRY_TO(TraverseConceptReference(*TC));
}
}
if (const auto *TC = D->getTypeConstraint())
TRY_TO(TraverseTypeConstraint(TC));
return true;
}
@@ -1905,7 +2021,7 @@ DEF_TRAVERSE_DECL(RecordDecl, { TRY_TO(TraverseRecordHelper(D)); })
DEF_TRAVERSE_DECL(CXXRecordDecl, { TRY_TO(TraverseCXXRecordHelper(D)); })
#define DEF_TRAVERSE_TMPL_SPEC_DECL(TMPLDECLKIND) \
#define DEF_TRAVERSE_TMPL_SPEC_DECL(TMPLDECLKIND, DECLKIND) \
DEF_TRAVERSE_DECL(TMPLDECLKIND##TemplateSpecializationDecl, { \
/* For implicit instantiations ("set<int> x;"), we don't want to \
recurse at all, since the instatiated template isn't written in \
@@ -1918,18 +2034,23 @@ DEF_TRAVERSE_DECL(CXXRecordDecl, { TRY_TO(TraverseCXXRecordHelper(D)); })
if (TypeSourceInfo *TSI = D->getTypeAsWritten()) \
TRY_TO(TraverseTypeLoc(TSI->getTypeLoc())); \
\
TRY_TO(TraverseNestedNameSpecifierLoc(D->getQualifierLoc())); \
if (!getDerived().shouldVisitTemplateInstantiations() && \
D->getTemplateSpecializationKind() != TSK_ExplicitSpecialization) \
if (getDerived().shouldVisitTemplateInstantiations() || \
D->getTemplateSpecializationKind() == TSK_ExplicitSpecialization) { \
/* Traverse base definition for explicit specializations */ \
TRY_TO(Traverse##DECLKIND##Helper(D)); \
} else { \
TRY_TO(TraverseNestedNameSpecifierLoc(D->getQualifierLoc())); \
\
/* Returning from here skips traversing the \
declaration context of the *TemplateSpecializationDecl \
(embedded in the DEF_TRAVERSE_DECL() macro) \
which contains the instantiated members of the template. */ \
return true; \
} \
})
DEF_TRAVERSE_TMPL_SPEC_DECL(Class)
DEF_TRAVERSE_TMPL_SPEC_DECL(Var)
DEF_TRAVERSE_TMPL_SPEC_DECL(Class, CXXRecord)
DEF_TRAVERSE_TMPL_SPEC_DECL(Var, Var)
template <typename Derived>
bool RecursiveASTVisitor<Derived>::TraverseTemplateArgumentLocsHelper(
@@ -2002,6 +2123,7 @@ DEF_TRAVERSE_DECL(BindingDecl, {
DEF_TRAVERSE_DECL(MSPropertyDecl, { TRY_TO(TraverseDeclaratorHelper(D)); })
DEF_TRAVERSE_DECL(MSGuidDecl, {})
DEF_TRAVERSE_DECL(UnnamedGlobalConstantDecl, {})
DEF_TRAVERSE_DECL(TemplateParamObjectDecl, {})
@@ -2397,15 +2519,9 @@ bool RecursiveASTVisitor<Derived>::TraverseSynOrSemInitListExpr(
return true;
}
template<typename Derived>
bool RecursiveASTVisitor<Derived>::TraverseConceptReference(
const ConceptReference &C) {
TRY_TO(TraverseNestedNameSpecifierLoc(C.getNestedNameSpecifierLoc()));
TRY_TO(TraverseDeclarationNameInfo(C.getConceptNameInfo()));
if (C.hasExplicitTemplateArgs())
TRY_TO(TraverseTemplateArgumentLocsHelper(
C.getTemplateArgsAsWritten()->getTemplateArgs(),
C.getTemplateArgsAsWritten()->NumTemplateArgs));
template <typename Derived>
bool RecursiveASTVisitor<Derived>::TraverseObjCProtocolLoc(
ObjCProtocolLoc ProtocolLoc) {
return true;
}
@@ -2781,30 +2897,15 @@ DEF_TRAVERSE_STMT(CoyieldExpr, {
}
})
DEF_TRAVERSE_STMT(ConceptSpecializationExpr, {
TRY_TO(TraverseConceptReference(*S));
})
DEF_TRAVERSE_STMT(ConceptSpecializationExpr,
{ TRY_TO(TraverseConceptReferenceHelper(*S)); })
DEF_TRAVERSE_STMT(RequiresExpr, {
TRY_TO(TraverseDecl(S->getBody()));
for (ParmVarDecl *Parm : S->getLocalParameters())
TRY_TO(TraverseDecl(Parm));
for (concepts::Requirement *Req : S->getRequirements())
if (auto *TypeReq = dyn_cast<concepts::TypeRequirement>(Req)) {
if (!TypeReq->isSubstitutionFailure())
TRY_TO(TraverseTypeLoc(TypeReq->getType()->getTypeLoc()));
} else if (auto *ExprReq = dyn_cast<concepts::ExprRequirement>(Req)) {
if (!ExprReq->isExprSubstitutionFailure())
TRY_TO(TraverseStmt(ExprReq->getExpr()));
auto &RetReq = ExprReq->getReturnTypeRequirement();
if (RetReq.isTypeConstraint())
TRY_TO(TraverseTemplateParameterListHelper(
RetReq.getTypeConstraintTemplateParameterList()));
} else {
auto *NestedReq = cast<concepts::NestedRequirement>(Req);
if (!NestedReq->isSubstitutionFailure())
TRY_TO(TraverseStmt(NestedReq->getConstraintExpr()));
}
TRY_TO(TraverseConceptRequirement(Req));
})
// These literals (all of them) do not need any action.
@@ -2893,6 +2994,9 @@ DEF_TRAVERSE_STMT(OMPParallelForSimdDirective,
DEF_TRAVERSE_STMT(OMPParallelMasterDirective,
{ TRY_TO(TraverseOMPExecutableDirective(S)); })
DEF_TRAVERSE_STMT(OMPParallelMaskedDirective,
{ TRY_TO(TraverseOMPExecutableDirective(S)); })
DEF_TRAVERSE_STMT(OMPParallelSectionsDirective,
{ TRY_TO(TraverseOMPExecutableDirective(S)); })
@@ -2974,6 +3078,18 @@ DEF_TRAVERSE_STMT(OMPParallelMasterTaskLoopDirective,
DEF_TRAVERSE_STMT(OMPParallelMasterTaskLoopSimdDirective,
{ TRY_TO(TraverseOMPExecutableDirective(S)); })
DEF_TRAVERSE_STMT(OMPMaskedTaskLoopDirective,
{ TRY_TO(TraverseOMPExecutableDirective(S)); })
DEF_TRAVERSE_STMT(OMPMaskedTaskLoopSimdDirective,
{ TRY_TO(TraverseOMPExecutableDirective(S)); })
DEF_TRAVERSE_STMT(OMPParallelMaskedTaskLoopDirective,
{ TRY_TO(TraverseOMPExecutableDirective(S)); })
DEF_TRAVERSE_STMT(OMPParallelMaskedTaskLoopSimdDirective,
{ TRY_TO(TraverseOMPExecutableDirective(S)); })
DEF_TRAVERSE_STMT(OMPDistributeDirective,
{ TRY_TO(TraverseOMPExecutableDirective(S)); })
@@ -3031,6 +3147,17 @@ DEF_TRAVERSE_STMT(OMPMaskedDirective,
DEF_TRAVERSE_STMT(OMPGenericLoopDirective,
{ TRY_TO(TraverseOMPExecutableDirective(S)); })
DEF_TRAVERSE_STMT(OMPTeamsGenericLoopDirective,
{ TRY_TO(TraverseOMPExecutableDirective(S)); })
DEF_TRAVERSE_STMT(OMPTargetTeamsGenericLoopDirective,
{ TRY_TO(TraverseOMPExecutableDirective(S)); })
DEF_TRAVERSE_STMT(OMPParallelGenericLoopDirective,
{ TRY_TO(TraverseOMPExecutableDirective(S)); })
DEF_TRAVERSE_STMT(OMPTargetParallelGenericLoopDirective,
{ TRY_TO(TraverseOMPExecutableDirective(S)); })
// OpenMP clauses.
template <typename Derived>
bool RecursiveASTVisitor<Derived>::TraverseOMPClause(OMPClause *C) {
@@ -3647,6 +3774,13 @@ bool RecursiveASTVisitor<Derived>::VisitOMPIsDevicePtrClause(
return true;
}
template <typename Derived>
bool RecursiveASTVisitor<Derived>::VisitOMPHasDeviceAddrClause(
OMPHasDeviceAddrClause *C) {
TRY_TO(VisitOMPClauseList(C));
return true;
}
template <typename Derived>
bool RecursiveASTVisitor<Derived>::VisitOMPNontemporalClause(
OMPNontemporalClause *C) {
@@ -19,6 +19,7 @@
#include "clang/Basic/CapturedStmt.h"
#include "clang/Basic/IdentifierTable.h"
#include "clang/Basic/LLVM.h"
#include "clang/Basic/LangOptions.h"
#include "clang/Basic/SourceLocation.h"
#include "clang/Basic/Specifiers.h"
#include "llvm/ADT/ArrayRef.h"
@@ -128,10 +129,11 @@ class alignas(void *) Stmt {
unsigned : NumStmtBits;
unsigned NumStmts : 32 - NumStmtBits;
/// True if the compound statement has one or more pragmas that set some
/// floating-point features.
unsigned HasFPFeatures : 1;
/// The location of the opening "{".
SourceLocation LBraceLoc;
unsigned NumStmts;
};
class LabelStmtBitfields {
@@ -594,8 +596,8 @@ class alignas(void *) Stmt {
unsigned : NumExprBits;
/// The kind of source location builtin represented by the SourceLocExpr.
/// Ex. __builtin_LINE, __builtin_FUNCTION, ect.
unsigned Kind : 2;
/// Ex. __builtin_LINE, __builtin_FUNCTION, etc.
unsigned Kind : 3;
};
class StmtExprBitfields {
@@ -1244,7 +1246,7 @@ class alignas(void *) Stmt {
}
/// Child Iterators: All subclasses must implement 'children'
/// to permit easy iteration over the substatements/subexpessions of an
/// to permit easy iteration over the substatements/subexpressions of an
/// AST node. This permits easy iteration over all nodes in the AST.
using child_iterator = StmtIterator;
using const_child_iterator = ConstStmtIterator;
@@ -1401,36 +1403,61 @@ class NullStmt : public Stmt {
};
/// CompoundStmt - This represents a group of statements like { stmt stmt }.
class CompoundStmt final : public Stmt,
private llvm::TrailingObjects<CompoundStmt, Stmt *> {
class CompoundStmt final
: public Stmt,
private llvm::TrailingObjects<CompoundStmt, Stmt *, FPOptionsOverride> {
friend class ASTStmtReader;
friend TrailingObjects;
/// The location of the closing "}". LBraceLoc is stored in CompoundStmtBits.
/// The location of the opening "{".
SourceLocation LBraceLoc;
/// The location of the closing "}".
SourceLocation RBraceLoc;
CompoundStmt(ArrayRef<Stmt *> Stmts, SourceLocation LB, SourceLocation RB);
CompoundStmt(ArrayRef<Stmt *> Stmts, FPOptionsOverride FPFeatures,
SourceLocation LB, SourceLocation RB);
explicit CompoundStmt(EmptyShell Empty) : Stmt(CompoundStmtClass, Empty) {}
void setStmts(ArrayRef<Stmt *> Stmts);
/// Set FPOptionsOverride in trailing storage. Used only by Serialization.
void setStoredFPFeatures(FPOptionsOverride F) {
assert(hasStoredFPFeatures());
*getTrailingObjects<FPOptionsOverride>() = F;
}
size_t numTrailingObjects(OverloadToken<Stmt *>) const {
return CompoundStmtBits.NumStmts;
}
public:
static CompoundStmt *Create(const ASTContext &C, ArrayRef<Stmt *> Stmts,
SourceLocation LB, SourceLocation RB);
FPOptionsOverride FPFeatures, SourceLocation LB,
SourceLocation RB);
// Build an empty compound statement with a location.
explicit CompoundStmt(SourceLocation Loc)
: Stmt(CompoundStmtClass), RBraceLoc(Loc) {
: Stmt(CompoundStmtClass), LBraceLoc(Loc), RBraceLoc(Loc) {
CompoundStmtBits.NumStmts = 0;
CompoundStmtBits.LBraceLoc = Loc;
CompoundStmtBits.HasFPFeatures = 0;
}
// Build an empty compound statement.
static CompoundStmt *CreateEmpty(const ASTContext &C, unsigned NumStmts);
static CompoundStmt *CreateEmpty(const ASTContext &C, unsigned NumStmts,
bool HasFPFeatures);
bool body_empty() const { return CompoundStmtBits.NumStmts == 0; }
unsigned size() const { return CompoundStmtBits.NumStmts; }
bool hasStoredFPFeatures() const { return CompoundStmtBits.HasFPFeatures; }
/// Get FPOptionsOverride from trailing storage.
FPOptionsOverride getStoredFPFeatures() const {
assert(hasStoredFPFeatures());
return *getTrailingObjects<FPOptionsOverride>();
}
using body_iterator = Stmt **;
using body_range = llvm::iterator_range<body_iterator>;
@@ -1505,10 +1532,10 @@ class CompoundStmt final : public Stmt,
return const_cast<CompoundStmt *>(this)->getStmtExprResult();
}
SourceLocation getBeginLoc() const { return CompoundStmtBits.LBraceLoc; }
SourceLocation getBeginLoc() const { return LBraceLoc; }
SourceLocation getEndLoc() const { return RBraceLoc; }
SourceLocation getLBracLoc() const { return CompoundStmtBits.LBraceLoc; }
SourceLocation getLBracLoc() const { return LBraceLoc; }
SourceLocation getRBracLoc() const { return RBraceLoc; }
static bool classof(const Stmt *T) {
@@ -327,7 +327,6 @@ class CoroutineBodyStmt final
Allocate, ///< Coroutine frame memory allocation.
Deallocate, ///< Coroutine frame memory deallocation.
ReturnValue, ///< Return value for thunk function: p.get_return_object().
ResultDecl, ///< Declaration holding the result of get_return_object.
ReturnStmt, ///< Return statement for the thunk function.
ReturnStmtOnAllocFailure, ///< Return statement if allocation failed.
FirstParamMove ///< First offset for move construction of parameter copies.
@@ -354,7 +353,6 @@ class CoroutineBodyStmt final
Expr *Allocate = nullptr;
Expr *Deallocate = nullptr;
Expr *ReturnValue = nullptr;
Stmt *ResultDecl = nullptr;
Stmt *ReturnStmt = nullptr;
Stmt *ReturnStmtOnAllocFailure = nullptr;
ArrayRef<Stmt *> ParamMoves;
@@ -409,7 +407,11 @@ class CoroutineBodyStmt final
Expr *getReturnValueInit() const {
return cast<Expr>(getStoredStmts()[SubStmt::ReturnValue]);
}
Stmt *getResultDecl() const { return getStoredStmts()[SubStmt::ResultDecl]; }
Expr *getReturnValue() const {
assert(getReturnStmt());
auto *RS = cast<clang::ReturnStmt>(getReturnStmt());
return RS->getRetValue();
}
Stmt *getReturnStmt() const { return getStoredStmts()[SubStmt::ReturnStmt]; }
Stmt *getReturnStmtOnAllocFailure() const {
return getStoredStmts()[SubStmt::ReturnStmtOnAllocFailure];
@@ -495,16 +497,10 @@ class CoreturnStmt : public Stmt {
}
child_range children() {
if (!getOperand())
return child_range(SubStmts + SubStmt::PromiseCall,
SubStmts + SubStmt::Count);
return child_range(SubStmts, SubStmts + SubStmt::Count);
}
const_child_range children() const {
if (!getOperand())
return const_child_range(SubStmts + SubStmt::PromiseCall,
SubStmts + SubStmt::Count);
return const_child_range(SubStmts, SubStmts + SubStmt::Count);
}
@@ -1523,9 +1523,17 @@ class OMPLoopDirective : public OMPLoopBasedDirective {
T->getStmtClass() == OMPParallelForSimdDirectiveClass ||
T->getStmtClass() == OMPTaskLoopDirectiveClass ||
T->getStmtClass() == OMPTaskLoopSimdDirectiveClass ||
T->getStmtClass() == OMPMaskedTaskLoopDirectiveClass ||
T->getStmtClass() == OMPMaskedTaskLoopSimdDirectiveClass ||
T->getStmtClass() == OMPMasterTaskLoopDirectiveClass ||
T->getStmtClass() == OMPMasterTaskLoopSimdDirectiveClass ||
T->getStmtClass() == OMPGenericLoopDirectiveClass ||
T->getStmtClass() == OMPTeamsGenericLoopDirectiveClass ||
T->getStmtClass() == OMPTargetTeamsGenericLoopDirectiveClass ||
T->getStmtClass() == OMPParallelGenericLoopDirectiveClass ||
T->getStmtClass() == OMPTargetParallelGenericLoopDirectiveClass ||
T->getStmtClass() == OMPParallelMaskedTaskLoopDirectiveClass ||
T->getStmtClass() == OMPParallelMaskedTaskLoopSimdDirectiveClass ||
T->getStmtClass() == OMPParallelMasterTaskLoopDirectiveClass ||
T->getStmtClass() == OMPParallelMasterTaskLoopSimdDirectiveClass ||
T->getStmtClass() == OMPDistributeDirectiveClass ||
@@ -2300,6 +2308,69 @@ class OMPParallelMasterDirective : public OMPExecutableDirective {
}
};
/// This represents '#pragma omp parallel masked' directive.
///
/// \code
/// #pragma omp parallel masked filter(tid)
/// \endcode
/// In this example directive '#pragma omp parallel masked' has a clause
/// 'filter' with the variable tid
///
class OMPParallelMaskedDirective final : public OMPExecutableDirective {
friend class ASTStmtReader;
friend class OMPExecutableDirective;
OMPParallelMaskedDirective(SourceLocation StartLoc, SourceLocation EndLoc)
: OMPExecutableDirective(OMPParallelMaskedDirectiveClass,
llvm::omp::OMPD_parallel_masked, StartLoc,
EndLoc) {}
explicit OMPParallelMaskedDirective()
: OMPExecutableDirective(OMPParallelMaskedDirectiveClass,
llvm::omp::OMPD_parallel_masked,
SourceLocation(), SourceLocation()) {}
/// Sets special task reduction descriptor.
void setTaskReductionRefExpr(Expr *E) { Data->getChildren()[0] = E; }
public:
/// Creates directive with a list of \a Clauses.
///
/// \param C AST context.
/// \param StartLoc Starting location of the directive kind.
/// \param EndLoc Ending Location of the directive.
/// \param Clauses List of clauses.
/// \param AssociatedStmt Statement, associated with the directive.
/// \param TaskRedRef Task reduction special reference expression to handle
/// taskgroup descriptor.
///
static OMPParallelMaskedDirective *
Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc,
ArrayRef<OMPClause *> Clauses, Stmt *AssociatedStmt, Expr *TaskRedRef);
/// Creates an empty directive with the place for \a NumClauses
/// clauses.
///
/// \param C AST context.
/// \param NumClauses Number of clauses.
///
static OMPParallelMaskedDirective *
CreateEmpty(const ASTContext &C, unsigned NumClauses, EmptyShell);
/// Returns special task reduction reference expression.
Expr *getTaskReductionRefExpr() {
return cast_or_null<Expr>(Data->getChildren()[0]);
}
const Expr *getTaskReductionRefExpr() const {
return const_cast<OMPParallelMaskedDirective *>(this)
->getTaskReductionRefExpr();
}
static bool classof(const Stmt *T) {
return T->getStmtClass() == OMPParallelMaskedDirectiveClass;
}
};
/// This represents '#pragma omp parallel sections' directive.
///
/// \code
@@ -2823,25 +2894,31 @@ class OMPOrderedDirective : public OMPExecutableDirective {
class OMPAtomicDirective : public OMPExecutableDirective {
friend class ASTStmtReader;
friend class OMPExecutableDirective;
/// Used for 'atomic update' or 'atomic capture' constructs. They may
/// have atomic expressions of forms
/// \code
/// x = x binop expr;
/// x = expr binop x;
/// \endcode
/// This field is true for the first form of the expression and false for the
/// second. Required for correct codegen of non-associative operations (like
/// << or >>).
bool IsXLHSInRHSPart = false;
/// Used for 'atomic update' or 'atomic capture' constructs. They may
/// have atomic expressions of forms
/// \code
/// v = x; <update x>;
/// <update x>; v = x;
/// \endcode
/// This field is true for the first(postfix) form of the expression and false
/// otherwise.
bool IsPostfixUpdate = false;
struct FlagTy {
/// Used for 'atomic update' or 'atomic capture' constructs. They may
/// have atomic expressions of forms:
/// \code
/// x = x binop expr;
/// x = expr binop x;
/// \endcode
/// This field is 1 for the first form of the expression and 0 for the
/// second. Required for correct codegen of non-associative operations (like
/// << or >>).
uint8_t IsXLHSInRHSPart : 1;
/// Used for 'atomic update' or 'atomic capture' constructs. They may
/// have atomic expressions of forms:
/// \code
/// v = x; <update x>;
/// <update x>; v = x;
/// \endcode
/// This field is 1 for the first(postfix) form of the expression and 0
/// otherwise.
uint8_t IsPostfixUpdate : 1;
/// 1 if 'v' is updated only when the condition is false (compare capture
/// only).
uint8_t IsFailOnly : 1;
} Flags;
/// Build directive with the given start and end location.
///
@@ -2863,6 +2940,9 @@ class OMPAtomicDirective : public OMPExecutableDirective {
POS_V,
POS_E,
POS_UpdateExpr,
POS_D,
POS_Cond,
POS_R,
};
/// Set 'x' part of the associated expression/statement.
@@ -2875,10 +2955,42 @@ class OMPAtomicDirective : public OMPExecutableDirective {
}
/// Set 'v' part of the associated expression/statement.
void setV(Expr *V) { Data->getChildren()[DataPositionTy::POS_V] = V; }
/// Set 'r' part of the associated expression/statement.
void setR(Expr *R) { Data->getChildren()[DataPositionTy::POS_R] = R; }
/// Set 'expr' part of the associated expression/statement.
void setExpr(Expr *E) { Data->getChildren()[DataPositionTy::POS_E] = E; }
/// Set 'd' part of the associated expression/statement.
void setD(Expr *D) { Data->getChildren()[DataPositionTy::POS_D] = D; }
/// Set conditional expression in `atomic compare`.
void setCond(Expr *C) { Data->getChildren()[DataPositionTy::POS_Cond] = C; }
public:
struct Expressions {
/// 'x' part of the associated expression/statement.
Expr *X = nullptr;
/// 'v' part of the associated expression/statement.
Expr *V = nullptr;
// 'r' part of the associated expression/statement.
Expr *R = nullptr;
/// 'expr' part of the associated expression/statement.
Expr *E = nullptr;
/// UE Helper expression of the form:
/// 'OpaqueValueExpr(x) binop OpaqueValueExpr(expr)' or
/// 'OpaqueValueExpr(expr) binop OpaqueValueExpr(x)'.
Expr *UE = nullptr;
/// 'd' part of the associated expression/statement.
Expr *D = nullptr;
/// Conditional expression in `atomic compare` construct.
Expr *Cond = nullptr;
/// True if UE has the first form and false if the second.
bool IsXLHSInRHSPart;
/// True if original value of 'x' must be stored in 'v', not an updated one.
bool IsPostfixUpdate;
/// True if 'v' is updated only when the condition is false (compare capture
/// only).
bool IsFailOnly;
};
/// Creates directive with a list of \a Clauses and 'x', 'v' and 'expr'
/// parts of the atomic construct (see Section 2.12.6, atomic Construct, for
/// detailed description of 'x', 'v' and 'expr').
@@ -2888,20 +3000,12 @@ class OMPAtomicDirective : public OMPExecutableDirective {
/// \param EndLoc Ending Location of the directive.
/// \param Clauses List of clauses.
/// \param AssociatedStmt Statement, associated with the directive.
/// \param X 'x' part of the associated expression/statement.
/// \param V 'v' part of the associated expression/statement.
/// \param E 'expr' part of the associated expression/statement.
/// \param UE Helper expression of the form
/// 'OpaqueValueExpr(x) binop OpaqueValueExpr(expr)' or
/// 'OpaqueValueExpr(expr) binop OpaqueValueExpr(x)'.
/// \param IsXLHSInRHSPart true if \a UE has the first form and false if the
/// second.
/// \param IsPostfixUpdate true if original value of 'x' must be stored in
/// 'v', not an updated one.
static OMPAtomicDirective *
Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc,
ArrayRef<OMPClause *> Clauses, Stmt *AssociatedStmt, Expr *X, Expr *V,
Expr *E, Expr *UE, bool IsXLHSInRHSPart, bool IsPostfixUpdate);
/// \param Exprs Associated expressions or statements.
static OMPAtomicDirective *Create(const ASTContext &C,
SourceLocation StartLoc,
SourceLocation EndLoc,
ArrayRef<OMPClause *> Clauses,
Stmt *AssociatedStmt, Expressions Exprs);
/// Creates an empty directive with the place for \a NumClauses
/// clauses.
@@ -2933,10 +3037,13 @@ class OMPAtomicDirective : public OMPExecutableDirective {
/// Return true if helper update expression has form
/// 'OpaqueValueExpr(x) binop OpaqueValueExpr(expr)' and false if it has form
/// 'OpaqueValueExpr(expr) binop OpaqueValueExpr(x)'.
bool isXLHSInRHSPart() const { return IsXLHSInRHSPart; }
bool isXLHSInRHSPart() const { return Flags.IsXLHSInRHSPart; }
/// Return true if 'v' expression must be updated to original value of
/// 'x', false if 'v' must be updated to the new value of 'x'.
bool isPostfixUpdate() const { return IsPostfixUpdate; }
bool isPostfixUpdate() const { return Flags.IsPostfixUpdate; }
/// Return true if 'v' is updated only when the condition is evaluated false
/// (compare capture only).
bool isFailOnly() const { return Flags.IsFailOnly; }
/// Get 'v' part of the associated expression/statement.
Expr *getV() {
return cast_or_null<Expr>(Data->getChildren()[DataPositionTy::POS_V]);
@@ -2944,6 +3051,13 @@ class OMPAtomicDirective : public OMPExecutableDirective {
const Expr *getV() const {
return cast_or_null<Expr>(Data->getChildren()[DataPositionTy::POS_V]);
}
/// Get 'r' part of the associated expression/statement.
Expr *getR() {
return cast_or_null<Expr>(Data->getChildren()[DataPositionTy::POS_R]);
}
const Expr *getR() const {
return cast_or_null<Expr>(Data->getChildren()[DataPositionTy::POS_R]);
}
/// Get 'expr' part of the associated expression/statement.
Expr *getExpr() {
return cast_or_null<Expr>(Data->getChildren()[DataPositionTy::POS_E]);
@@ -2951,6 +3065,20 @@ class OMPAtomicDirective : public OMPExecutableDirective {
const Expr *getExpr() const {
return cast_or_null<Expr>(Data->getChildren()[DataPositionTy::POS_E]);
}
/// Get 'd' part of the associated expression/statement.
Expr *getD() {
return cast_or_null<Expr>(Data->getChildren()[DataPositionTy::POS_D]);
}
Expr *getD() const {
return cast_or_null<Expr>(Data->getChildren()[DataPositionTy::POS_D]);
}
/// Get the 'cond' part of the source atomic expression.
Expr *getCondExpr() {
return cast_or_null<Expr>(Data->getChildren()[DataPositionTy::POS_Cond]);
}
Expr *getCondExpr() const {
return cast_or_null<Expr>(Data->getChildren()[DataPositionTy::POS_Cond]);
}
static bool classof(const Stmt *T) {
return T->getStmtClass() == OMPAtomicDirectiveClass;
@@ -3734,6 +3862,82 @@ class OMPMasterTaskLoopDirective : public OMPLoopDirective {
}
};
/// This represents '#pragma omp masked taskloop' directive.
///
/// \code
/// #pragma omp masked taskloop private(a,b) grainsize(val) num_tasks(num)
/// \endcode
/// In this example directive '#pragma omp masked taskloop' has clauses
/// 'private' with the variables 'a' and 'b', 'grainsize' with expression 'val'
/// and 'num_tasks' with expression 'num'.
///
class OMPMaskedTaskLoopDirective final : public OMPLoopDirective {
friend class ASTStmtReader;
friend class OMPExecutableDirective;
/// true if the construct has inner cancel directive.
bool HasCancel = false;
/// Build directive with the given start and end location.
///
/// \param StartLoc Starting location of the directive kind.
/// \param EndLoc Ending location of the directive.
/// \param CollapsedNum Number of collapsed nested loops.
///
OMPMaskedTaskLoopDirective(SourceLocation StartLoc, SourceLocation EndLoc,
unsigned CollapsedNum)
: OMPLoopDirective(OMPMaskedTaskLoopDirectiveClass,
llvm::omp::OMPD_masked_taskloop, StartLoc, EndLoc,
CollapsedNum) {}
/// Build an empty directive.
///
/// \param CollapsedNum Number of collapsed nested loops.
///
explicit OMPMaskedTaskLoopDirective(unsigned CollapsedNum)
: OMPLoopDirective(OMPMaskedTaskLoopDirectiveClass,
llvm::omp::OMPD_masked_taskloop, SourceLocation(),
SourceLocation(), CollapsedNum) {}
/// Set cancel state.
void setHasCancel(bool Has) { HasCancel = Has; }
public:
/// Creates directive with a list of \a Clauses.
///
/// \param C AST context.
/// \param StartLoc Starting location of the directive kind.
/// \param EndLoc Ending Location of the directive.
/// \param CollapsedNum Number of collapsed loops.
/// \param Clauses List of clauses.
/// \param AssociatedStmt Statement, associated with the directive.
/// \param Exprs Helper expressions for CodeGen.
/// \param HasCancel true if this directive has inner cancel directive.
///
static OMPMaskedTaskLoopDirective *
Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc,
unsigned CollapsedNum, ArrayRef<OMPClause *> Clauses,
Stmt *AssociatedStmt, const HelperExprs &Exprs, bool HasCancel);
/// Creates an empty directive with the place
/// for \a NumClauses clauses.
///
/// \param C AST context.
/// \param CollapsedNum Number of collapsed nested loops.
/// \param NumClauses Number of clauses.
///
static OMPMaskedTaskLoopDirective *CreateEmpty(const ASTContext &C,
unsigned NumClauses,
unsigned CollapsedNum,
EmptyShell);
/// Return true if current directive has inner cancel directive.
bool hasCancel() const { return HasCancel; }
static bool classof(const Stmt *T) {
return T->getStmtClass() == OMPMaskedTaskLoopDirectiveClass;
}
};
/// This represents '#pragma omp master taskloop simd' directive.
///
/// \code
@@ -3799,6 +4003,71 @@ class OMPMasterTaskLoopSimdDirective : public OMPLoopDirective {
}
};
/// This represents '#pragma omp masked taskloop simd' directive.
///
/// \code
/// #pragma omp masked taskloop simd private(a,b) grainsize(val) num_tasks(num)
/// \endcode
/// In this example directive '#pragma omp masked taskloop simd' has clauses
/// 'private' with the variables 'a' and 'b', 'grainsize' with expression 'val'
/// and 'num_tasks' with expression 'num'.
///
class OMPMaskedTaskLoopSimdDirective final : public OMPLoopDirective {
friend class ASTStmtReader;
friend class OMPExecutableDirective;
/// Build directive with the given start and end location.
///
/// \param StartLoc Starting location of the directive kind.
/// \param EndLoc Ending location of the directive.
/// \param CollapsedNum Number of collapsed nested loops.
///
OMPMaskedTaskLoopSimdDirective(SourceLocation StartLoc, SourceLocation EndLoc,
unsigned CollapsedNum)
: OMPLoopDirective(OMPMaskedTaskLoopSimdDirectiveClass,
llvm::omp::OMPD_masked_taskloop_simd, StartLoc, EndLoc,
CollapsedNum) {}
/// Build an empty directive.
///
/// \param CollapsedNum Number of collapsed nested loops.
///
explicit OMPMaskedTaskLoopSimdDirective(unsigned CollapsedNum)
: OMPLoopDirective(OMPMaskedTaskLoopSimdDirectiveClass,
llvm::omp::OMPD_masked_taskloop_simd, SourceLocation(),
SourceLocation(), CollapsedNum) {}
public:
/// Creates directive with a list of \p Clauses.
///
/// \param C AST context.
/// \param StartLoc Starting location of the directive kind.
/// \param EndLoc Ending Location of the directive.
/// \param CollapsedNum Number of collapsed loops.
/// \param Clauses List of clauses.
/// \param AssociatedStmt Statement, associated with the directive.
/// \param Exprs Helper expressions for CodeGen.
///
static OMPMaskedTaskLoopSimdDirective *
Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc,
unsigned CollapsedNum, ArrayRef<OMPClause *> Clauses,
Stmt *AssociatedStmt, const HelperExprs &Exprs);
/// Creates an empty directive with the place for \p NumClauses clauses.
///
/// \param C AST context.
/// \param CollapsedNum Number of collapsed nested loops.
/// \param NumClauses Number of clauses.
///
static OMPMaskedTaskLoopSimdDirective *CreateEmpty(const ASTContext &C,
unsigned NumClauses,
unsigned CollapsedNum,
EmptyShell);
static bool classof(const Stmt *T) {
return T->getStmtClass() == OMPMaskedTaskLoopSimdDirectiveClass;
}
};
/// This represents '#pragma omp parallel master taskloop' directive.
///
/// \code
@@ -3877,6 +4146,84 @@ class OMPParallelMasterTaskLoopDirective : public OMPLoopDirective {
}
};
/// This represents '#pragma omp parallel masked taskloop' directive.
///
/// \code
/// #pragma omp parallel masked taskloop private(a,b) grainsize(val)
/// num_tasks(num)
/// \endcode
/// In this example directive '#pragma omp parallel masked taskloop' has clauses
/// 'private' with the variables 'a' and 'b', 'grainsize' with expression 'val'
/// and 'num_tasks' with expression 'num'.
///
class OMPParallelMaskedTaskLoopDirective final : public OMPLoopDirective {
friend class ASTStmtReader;
friend class OMPExecutableDirective;
/// true if the construct has inner cancel directive.
bool HasCancel = false;
/// Build directive with the given start and end location.
///
/// \param StartLoc Starting location of the directive kind.
/// \param EndLoc Ending location of the directive.
/// \param CollapsedNum Number of collapsed nested loops.
///
OMPParallelMaskedTaskLoopDirective(SourceLocation StartLoc,
SourceLocation EndLoc,
unsigned CollapsedNum)
: OMPLoopDirective(OMPParallelMaskedTaskLoopDirectiveClass,
llvm::omp::OMPD_parallel_masked_taskloop, StartLoc,
EndLoc, CollapsedNum) {}
/// Build an empty directive.
///
/// \param CollapsedNum Number of collapsed nested loops.
///
explicit OMPParallelMaskedTaskLoopDirective(unsigned CollapsedNum)
: OMPLoopDirective(OMPParallelMaskedTaskLoopDirectiveClass,
llvm::omp::OMPD_parallel_masked_taskloop,
SourceLocation(), SourceLocation(), CollapsedNum) {}
/// Set cancel state.
void setHasCancel(bool Has) { HasCancel = Has; }
public:
/// Creates directive with a list of \a Clauses.
///
/// \param C AST context.
/// \param StartLoc Starting location of the directive kind.
/// \param EndLoc Ending Location of the directive.
/// \param CollapsedNum Number of collapsed loops.
/// \param Clauses List of clauses.
/// \param AssociatedStmt Statement, associated with the directive.
/// \param Exprs Helper expressions for CodeGen.
/// \param HasCancel true if this directive has inner cancel directive.
///
static OMPParallelMaskedTaskLoopDirective *
Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc,
unsigned CollapsedNum, ArrayRef<OMPClause *> Clauses,
Stmt *AssociatedStmt, const HelperExprs &Exprs, bool HasCancel);
/// Creates an empty directive with the place
/// for \a NumClauses clauses.
///
/// \param C AST context.
/// \param CollapsedNum Number of collapsed nested loops.
/// \param NumClauses Number of clauses.
///
static OMPParallelMaskedTaskLoopDirective *CreateEmpty(const ASTContext &C,
unsigned NumClauses,
unsigned CollapsedNum,
EmptyShell);
/// Return true if current directive has inner cancel directive.
bool hasCancel() const { return HasCancel; }
static bool classof(const Stmt *T) {
return T->getStmtClass() == OMPParallelMaskedTaskLoopDirectiveClass;
}
};
/// This represents '#pragma omp parallel master taskloop simd' directive.
///
/// \code
@@ -3944,6 +4291,73 @@ class OMPParallelMasterTaskLoopSimdDirective : public OMPLoopDirective {
}
};
/// This represents '#pragma omp parallel masked taskloop simd' directive.
///
/// \code
/// #pragma omp parallel masked taskloop simd private(a,b) grainsize(val)
/// num_tasks(num)
/// \endcode
/// In this example directive '#pragma omp parallel masked taskloop simd' has
/// clauses 'private' with the variables 'a' and 'b', 'grainsize' with
/// expression 'val' and 'num_tasks' with expression 'num'.
///
class OMPParallelMaskedTaskLoopSimdDirective final : public OMPLoopDirective {
friend class ASTStmtReader;
friend class OMPExecutableDirective;
/// Build directive with the given start and end location.
///
/// \param StartLoc Starting location of the directive kind.
/// \param EndLoc Ending location of the directive.
/// \param CollapsedNum Number of collapsed nested loops.
///
OMPParallelMaskedTaskLoopSimdDirective(SourceLocation StartLoc,
SourceLocation EndLoc,
unsigned CollapsedNum)
: OMPLoopDirective(OMPParallelMaskedTaskLoopSimdDirectiveClass,
llvm::omp::OMPD_parallel_masked_taskloop_simd,
StartLoc, EndLoc, CollapsedNum) {}
/// Build an empty directive.
///
/// \param CollapsedNum Number of collapsed nested loops.
///
explicit OMPParallelMaskedTaskLoopSimdDirective(unsigned CollapsedNum)
: OMPLoopDirective(OMPParallelMaskedTaskLoopSimdDirectiveClass,
llvm::omp::OMPD_parallel_masked_taskloop_simd,
SourceLocation(), SourceLocation(), CollapsedNum) {}
public:
/// Creates directive with a list of \p Clauses.
///
/// \param C AST context.
/// \param StartLoc Starting location of the directive kind.
/// \param EndLoc Ending Location of the directive.
/// \param CollapsedNum Number of collapsed loops.
/// \param Clauses List of clauses.
/// \param AssociatedStmt Statement, associated with the directive.
/// \param Exprs Helper expressions for CodeGen.
///
static OMPParallelMaskedTaskLoopSimdDirective *
Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc,
unsigned CollapsedNum, ArrayRef<OMPClause *> Clauses,
Stmt *AssociatedStmt, const HelperExprs &Exprs);
/// Creates an empty directive with the place
/// for \a NumClauses clauses.
///
/// \param C AST context.
/// \param CollapsedNum Number of collapsed nested loops.
/// \param NumClauses Number of clauses.
///
static OMPParallelMaskedTaskLoopSimdDirective *
CreateEmpty(const ASTContext &C, unsigned NumClauses, unsigned CollapsedNum,
EmptyShell);
static bool classof(const Stmt *T) {
return T->getStmtClass() == OMPParallelMaskedTaskLoopSimdDirectiveClass;
}
};
/// This represents '#pragma omp distribute' directive.
///
/// \code
@@ -5546,6 +5960,266 @@ class OMPGenericLoopDirective final : public OMPLoopDirective {
}
};
/// This represents '#pragma omp teams loop' directive.
///
/// \code
/// #pragma omp teams loop private(a,b) order(concurrent)
/// \endcode
/// In this example directive '#pragma omp teams loop' has
/// clauses 'private' with the variables 'a' and 'b', and order(concurrent).
///
class OMPTeamsGenericLoopDirective final : public OMPLoopDirective {
friend class ASTStmtReader;
friend class OMPExecutableDirective;
/// Build directive with the given start and end location.
///
/// \param StartLoc Starting location of the directive kind.
/// \param EndLoc Ending location of the directive.
/// \param CollapsedNum Number of collapsed nested loops.
///
OMPTeamsGenericLoopDirective(SourceLocation StartLoc, SourceLocation EndLoc,
unsigned CollapsedNum)
: OMPLoopDirective(OMPTeamsGenericLoopDirectiveClass,
llvm::omp::OMPD_teams_loop, StartLoc, EndLoc,
CollapsedNum) {}
/// Build an empty directive.
///
/// \param CollapsedNum Number of collapsed nested loops.
///
explicit OMPTeamsGenericLoopDirective(unsigned CollapsedNum)
: OMPLoopDirective(OMPTeamsGenericLoopDirectiveClass,
llvm::omp::OMPD_teams_loop, SourceLocation(),
SourceLocation(), CollapsedNum) {}
public:
/// Creates directive with a list of \p Clauses.
///
/// \param C AST context.
/// \param StartLoc Starting location of the directive kind.
/// \param EndLoc Ending Location of the directive.
/// \param CollapsedNum Number of collapsed loops.
/// \param Clauses List of clauses.
/// \param AssociatedStmt Statement, associated with the directive.
/// \param Exprs Helper expressions for CodeGen.
///
static OMPTeamsGenericLoopDirective *
Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc,
unsigned CollapsedNum, ArrayRef<OMPClause *> Clauses,
Stmt *AssociatedStmt, const HelperExprs &Exprs);
/// Creates an empty directive with the place
/// for \a NumClauses clauses.
///
/// \param C AST context.
/// \param CollapsedNum Number of collapsed nested loops.
/// \param NumClauses Number of clauses.
///
static OMPTeamsGenericLoopDirective *CreateEmpty(const ASTContext &C,
unsigned NumClauses,
unsigned CollapsedNum,
EmptyShell);
static bool classof(const Stmt *T) {
return T->getStmtClass() == OMPTeamsGenericLoopDirectiveClass;
}
};
/// This represents '#pragma omp target teams loop' directive.
///
/// \code
/// #pragma omp target teams loop private(a,b) order(concurrent)
/// \endcode
/// In this example directive '#pragma omp target teams loop' has
/// clauses 'private' with the variables 'a' and 'b', and order(concurrent).
///
class OMPTargetTeamsGenericLoopDirective final : public OMPLoopDirective {
friend class ASTStmtReader;
friend class OMPExecutableDirective;
/// Build directive with the given start and end location.
///
/// \param StartLoc Starting location of the directive kind.
/// \param EndLoc Ending location of the directive.
/// \param CollapsedNum Number of collapsed nested loops.
///
OMPTargetTeamsGenericLoopDirective(SourceLocation StartLoc,
SourceLocation EndLoc,
unsigned CollapsedNum)
: OMPLoopDirective(OMPTargetTeamsGenericLoopDirectiveClass,
llvm::omp::OMPD_target_teams_loop, StartLoc, EndLoc,
CollapsedNum) {}
/// Build an empty directive.
///
/// \param CollapsedNum Number of collapsed nested loops.
///
explicit OMPTargetTeamsGenericLoopDirective(unsigned CollapsedNum)
: OMPLoopDirective(OMPTargetTeamsGenericLoopDirectiveClass,
llvm::omp::OMPD_target_teams_loop, SourceLocation(),
SourceLocation(), CollapsedNum) {}
public:
/// Creates directive with a list of \p Clauses.
///
/// \param C AST context.
/// \param StartLoc Starting location of the directive kind.
/// \param EndLoc Ending Location of the directive.
/// \param CollapsedNum Number of collapsed loops.
/// \param Clauses List of clauses.
/// \param AssociatedStmt Statement, associated with the directive.
/// \param Exprs Helper expressions for CodeGen.
///
static OMPTargetTeamsGenericLoopDirective *
Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc,
unsigned CollapsedNum, ArrayRef<OMPClause *> Clauses,
Stmt *AssociatedStmt, const HelperExprs &Exprs);
/// Creates an empty directive with the place
/// for \a NumClauses clauses.
///
/// \param C AST context.
/// \param CollapsedNum Number of collapsed nested loops.
/// \param NumClauses Number of clauses.
///
static OMPTargetTeamsGenericLoopDirective *CreateEmpty(const ASTContext &C,
unsigned NumClauses,
unsigned CollapsedNum,
EmptyShell);
static bool classof(const Stmt *T) {
return T->getStmtClass() == OMPTargetTeamsGenericLoopDirectiveClass;
}
};
/// This represents '#pragma omp parallel loop' directive.
///
/// \code
/// #pragma omp parallel loop private(a,b) order(concurrent)
/// \endcode
/// In this example directive '#pragma omp parallel loop' has
/// clauses 'private' with the variables 'a' and 'b', and order(concurrent).
///
class OMPParallelGenericLoopDirective final : public OMPLoopDirective {
friend class ASTStmtReader;
friend class OMPExecutableDirective;
/// Build directive with the given start and end location.
///
/// \param StartLoc Starting location of the directive kind.
/// \param EndLoc Ending location of the directive.
/// \param CollapsedNum Number of collapsed nested loops.
///
OMPParallelGenericLoopDirective(SourceLocation StartLoc,
SourceLocation EndLoc, unsigned CollapsedNum)
: OMPLoopDirective(OMPParallelGenericLoopDirectiveClass,
llvm::omp::OMPD_parallel_loop, StartLoc, EndLoc,
CollapsedNum) {}
/// Build an empty directive.
///
/// \param CollapsedNum Number of collapsed nested loops.
///
explicit OMPParallelGenericLoopDirective(unsigned CollapsedNum)
: OMPLoopDirective(OMPParallelGenericLoopDirectiveClass,
llvm::omp::OMPD_parallel_loop, SourceLocation(),
SourceLocation(), CollapsedNum) {}
public:
/// Creates directive with a list of \p Clauses.
///
/// \param C AST context.
/// \param StartLoc Starting location of the directive kind.
/// \param EndLoc Ending Location of the directive.
/// \param CollapsedNum Number of collapsed loops.
/// \param Clauses List of clauses.
/// \param AssociatedStmt Statement, associated with the directive.
/// \param Exprs Helper expressions for CodeGen.
///
static OMPParallelGenericLoopDirective *
Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc,
unsigned CollapsedNum, ArrayRef<OMPClause *> Clauses,
Stmt *AssociatedStmt, const HelperExprs &Exprs);
/// Creates an empty directive with the place
/// for \a NumClauses clauses.
///
/// \param C AST context.
/// \param CollapsedNum Number of collapsed nested loops.
/// \param NumClauses Number of clauses.
///
static OMPParallelGenericLoopDirective *CreateEmpty(const ASTContext &C,
unsigned NumClauses,
unsigned CollapsedNum,
EmptyShell);
static bool classof(const Stmt *T) {
return T->getStmtClass() == OMPParallelGenericLoopDirectiveClass;
}
};
/// This represents '#pragma omp target parallel loop' directive.
///
/// \code
/// #pragma omp target parallel loop private(a,b) order(concurrent)
/// \endcode
/// In this example directive '#pragma omp target parallel loop' has
/// clauses 'private' with the variables 'a' and 'b', and order(concurrent).
///
class OMPTargetParallelGenericLoopDirective final : public OMPLoopDirective {
friend class ASTStmtReader;
friend class OMPExecutableDirective;
/// Build directive with the given start and end location.
///
/// \param StartLoc Starting location of the directive kind.
/// \param EndLoc Ending location of the directive.
/// \param CollapsedNum Number of collapsed nested loops.
///
OMPTargetParallelGenericLoopDirective(SourceLocation StartLoc,
SourceLocation EndLoc,
unsigned CollapsedNum)
: OMPLoopDirective(OMPTargetParallelGenericLoopDirectiveClass,
llvm::omp::OMPD_target_parallel_loop, StartLoc, EndLoc,
CollapsedNum) {}
/// Build an empty directive.
///
/// \param CollapsedNum Number of collapsed nested loops.
///
explicit OMPTargetParallelGenericLoopDirective(unsigned CollapsedNum)
: OMPLoopDirective(OMPTargetParallelGenericLoopDirectiveClass,
llvm::omp::OMPD_target_parallel_loop, SourceLocation(),
SourceLocation(), CollapsedNum) {}
public:
/// Creates directive with a list of \p Clauses.
///
/// \param C AST context.
/// \param StartLoc Starting location of the directive kind.
/// \param EndLoc Ending Location of the directive.
/// \param CollapsedNum Number of collapsed loops.
/// \param Clauses List of clauses.
/// \param AssociatedStmt Statement, associated with the directive.
/// \param Exprs Helper expressions for CodeGen.
///
static OMPTargetParallelGenericLoopDirective *
Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc,
unsigned CollapsedNum, ArrayRef<OMPClause *> Clauses,
Stmt *AssociatedStmt, const HelperExprs &Exprs);
/// Creates an empty directive with the place
/// for \a NumClauses clauses.
///
/// \param C AST context.
/// \param CollapsedNum Number of collapsed nested loops.
/// \param NumClauses Number of clauses.
///
static OMPTargetParallelGenericLoopDirective *
CreateEmpty(const ASTContext &C, unsigned NumClauses, unsigned CollapsedNum,
EmptyShell);
static bool classof(const Stmt *T) {
return T->getStmtClass() == OMPTargetParallelGenericLoopDirectiveClass;
}
};
} // end namespace clang
#endif
@@ -618,6 +618,9 @@ struct ASTTemplateArgumentListInfo final
ASTTemplateArgumentListInfo(const TemplateArgumentListInfo &List);
// FIXME: Is it ever necessary to copy to another context?
ASTTemplateArgumentListInfo(const ASTTemplateArgumentListInfo *List);
public:
/// The source location of the left angle bracket ('<').
SourceLocation LAngleLoc;
@@ -647,6 +650,10 @@ struct ASTTemplateArgumentListInfo final
static const ASTTemplateArgumentListInfo *
Create(const ASTContext &C, const TemplateArgumentListInfo &List);
// FIXME: Is it ever necessary to copy to another context?
static const ASTTemplateArgumentListInfo *
Create(const ASTContext &C, const ASTTemplateArgumentListInfo *List);
};
/// Represents an explicit template argument list in C++, e.g.,
@@ -25,6 +25,7 @@
namespace clang {
class ASTContext;
class Decl;
class DependentTemplateName;
class IdentifierInfo;
class NamedDecl;
@@ -39,6 +40,7 @@ class SubstTemplateTemplateParmStorage;
class TemplateArgument;
class TemplateDecl;
class TemplateTemplateParmDecl;
class UsingShadowDecl;
/// Implementation class used to describe either a set of overloaded
/// template names or an already-substituted template template parameter pack.
@@ -188,8 +190,12 @@ class SubstTemplateTemplateParmPackStorage
/// specifier in the typedef. "apply" is a nested template, and can
/// only be understood in the context of
class TemplateName {
// NameDecl is either a TemplateDecl or a UsingShadowDecl depending on the
// NameKind.
// !! There is no free low bits in 32-bit builds to discriminate more than 4
// pointer types in PointerUnion.
using StorageType =
llvm::PointerUnion<TemplateDecl *, UncommonTemplateNameStorage *,
llvm::PointerUnion<Decl *, UncommonTemplateNameStorage *,
QualifiedTemplateName *, DependentTemplateName *>;
StorageType Storage;
@@ -224,7 +230,11 @@ class TemplateName {
/// A template template parameter pack that has been substituted for
/// a template template argument pack, but has not yet been expanded into
/// individual arguments.
SubstTemplateTemplateParmPack
SubstTemplateTemplateParmPack,
/// A template name that refers to a template declaration found through a
/// specific using shadow declaration.
UsingTemplate,
};
TemplateName() = default;
@@ -235,6 +245,7 @@ class TemplateName {
explicit TemplateName(SubstTemplateTemplateParmPackStorage *Storage);
explicit TemplateName(QualifiedTemplateName *Qual);
explicit TemplateName(DependentTemplateName *Dep);
explicit TemplateName(UsingShadowDecl *Using);
/// Determine whether this template name is NULL.
bool isNull() const;
@@ -287,6 +298,10 @@ class TemplateName {
/// structure, if any.
DependentTemplateName *getAsDependentTemplateName() const;
/// Retrieve the using shadow declaration through which the underlying
/// template declaration is introduced, if any.
UsingShadowDecl *getAsUsingShadowDecl() const;
TemplateName getUnderlying() const;
/// Get the template name to substitute when this template name is used as a
@@ -399,13 +414,19 @@ class QualifiedTemplateName : public llvm::FoldingSetNode {
/// this name with DependentTemplateName).
llvm::PointerIntPair<NestedNameSpecifier *, 1> Qualifier;
/// The template declaration or set of overloaded function templates
/// that this qualified name refers to.
TemplateDecl *Template;
/// The underlying template name, it is either
/// 1) a Template -- a template declaration that this qualified name refers
/// to.
/// 2) or a UsingTemplate -- a template declaration introduced by a
/// using-shadow declaration.
TemplateName UnderlyingTemplate;
QualifiedTemplateName(NestedNameSpecifier *NNS, bool TemplateKeyword,
TemplateDecl *Template)
: Qualifier(NNS, TemplateKeyword? 1 : 0), Template(Template) {}
TemplateName Template)
: Qualifier(NNS, TemplateKeyword ? 1 : 0), UnderlyingTemplate(Template) {
assert(UnderlyingTemplate.getKind() == TemplateName::Template ||
UnderlyingTemplate.getKind() == TemplateName::UsingTemplate);
}
public:
/// Return the nested name specifier that qualifies this name.
@@ -415,23 +436,18 @@ class QualifiedTemplateName : public llvm::FoldingSetNode {
/// keyword.
bool hasTemplateKeyword() const { return Qualifier.getInt(); }
/// The template declaration that this qualified name refers
/// to.
TemplateDecl *getDecl() const { return Template; }
/// The template declaration to which this qualified name
/// refers.
TemplateDecl *getTemplateDecl() const { return Template; }
/// Return the underlying template name.
TemplateName getUnderlyingTemplate() const { return UnderlyingTemplate; }
void Profile(llvm::FoldingSetNodeID &ID) {
Profile(ID, getQualifier(), hasTemplateKeyword(), getTemplateDecl());
Profile(ID, getQualifier(), hasTemplateKeyword(), UnderlyingTemplate);
}
static void Profile(llvm::FoldingSetNodeID &ID, NestedNameSpecifier *NNS,
bool TemplateKeyword, TemplateDecl *Template) {
bool TemplateKeyword, TemplateName TN) {
ID.AddPointer(NNS);
ID.AddBoolean(TemplateKeyword);
ID.AddPointer(Template);
ID.AddPointer(TN.getAsVoidPointer());
}
};
@@ -246,6 +246,7 @@ class TextNodeDumper
void VisitLabelStmt(const LabelStmt *Node);
void VisitGotoStmt(const GotoStmt *Node);
void VisitCaseStmt(const CaseStmt *Node);
void VisitCompoundStmt(const CompoundStmt *Node);
void VisitConstantExpr(const ConstantExpr *Node);
void VisitCallExpr(const CallExpr *Node);
void VisitCXXOperatorCallExpr(const CXXOperatorCallExpr *Node);
@@ -317,6 +318,8 @@ class TextNodeDumper
void VisitTagType(const TagType *T);
void VisitTemplateTypeParmType(const TemplateTypeParmType *T);
void VisitAutoType(const AutoType *T);
void VisitDeducedTemplateSpecializationType(
const DeducedTemplateSpecializationType *T);
void VisitTemplateSpecializationType(const TemplateSpecializationType *T);
void VisitInjectedClassNameType(const InjectedClassNameType *T);
void VisitObjCInterfaceType(const ObjCInterfaceType *T);
@@ -57,6 +57,7 @@
namespace clang {
class BTFTypeTagAttr;
class ExtQuals;
class QualType;
class ConceptDecl;
@@ -264,16 +265,31 @@ class Qualifiers {
bool hasOnlyConst() const { return Mask == Const; }
void removeConst() { Mask &= ~Const; }
void addConst() { Mask |= Const; }
Qualifiers withConst() const {
Qualifiers Qs = *this;
Qs.addConst();
return Qs;
}
bool hasVolatile() const { return Mask & Volatile; }
bool hasOnlyVolatile() const { return Mask == Volatile; }
void removeVolatile() { Mask &= ~Volatile; }
void addVolatile() { Mask |= Volatile; }
Qualifiers withVolatile() const {
Qualifiers Qs = *this;
Qs.addVolatile();
return Qs;
}
bool hasRestrict() const { return Mask & Restrict; }
bool hasOnlyRestrict() const { return Mask == Restrict; }
void removeRestrict() { Mask &= ~Restrict; }
void addRestrict() { Mask |= Restrict; }
Qualifiers withRestrict() const {
Qualifiers Qs = *this;
Qs.addRestrict();
return Qs;
}
bool hasCVRQualifiers() const { return getCVRQualifiers(); }
unsigned getCVRQualifiers() const { return Mask & CVRMask; }
@@ -608,6 +624,47 @@ class Qualifiers {
static const uint32_t AddressSpaceShift = 9;
};
class QualifiersAndAtomic {
Qualifiers Quals;
bool HasAtomic;
public:
QualifiersAndAtomic() : HasAtomic(false) {}
QualifiersAndAtomic(Qualifiers Quals, bool HasAtomic)
: Quals(Quals), HasAtomic(HasAtomic) {}
operator Qualifiers() const { return Quals; }
bool hasVolatile() const { return Quals.hasVolatile(); }
bool hasConst() const { return Quals.hasConst(); }
bool hasRestrict() const { return Quals.hasRestrict(); }
bool hasAtomic() const { return HasAtomic; }
void addVolatile() { Quals.addVolatile(); }
void addConst() { Quals.addConst(); }
void addRestrict() { Quals.addRestrict(); }
void addAtomic() { HasAtomic = true; }
void removeVolatile() { Quals.removeVolatile(); }
void removeConst() { Quals.removeConst(); }
void removeRestrict() { Quals.removeRestrict(); }
void removeAtomic() { HasAtomic = false; }
QualifiersAndAtomic withVolatile() {
return {Quals.withVolatile(), HasAtomic};
}
QualifiersAndAtomic withConst() { return {Quals.withConst(), HasAtomic}; }
QualifiersAndAtomic withRestrict() {
return {Quals.withRestrict(), HasAtomic};
}
QualifiersAndAtomic withAtomic() { return {Quals, true}; }
QualifiersAndAtomic &operator+=(Qualifiers RHS) {
Quals += RHS;
return *this;
}
};
/// A std::pair-like structure for storing a qualified type split
/// into its local qualifiers and its locally-unqualified type.
struct SplitQualType {
@@ -829,6 +886,8 @@ class QualType {
/// Return true if this is a trivially copyable type (C++0x [basic.types]p9)
bool isTriviallyCopyableType(const ASTContext &Context) const;
/// Return true if this is a trivially relocatable type.
bool isTriviallyRelocatableType(const ASTContext &Context) const;
/// Returns true if it is a class and it might be dynamic.
bool mayBeDynamicClass() const;
@@ -930,6 +989,10 @@ class QualType {
/// The resulting type might still be qualified if it's sugar for an array
/// type. To strip qualifiers even from within a sugared array type, use
/// ASTContext::getUnqualifiedArrayType.
///
/// Note: In C, the _Atomic qualifier is special (see C2x 6.2.5p29 for
/// details), and it is not stripped by this function. Use
/// getAtomicUnqualifiedType() to strip qualifiers including _Atomic.
inline QualType getUnqualifiedType() const;
/// Retrieve the unqualified variant of the given type, removing as little
@@ -1311,6 +1374,8 @@ class QualType {
static bool hasNonTrivialToPrimitiveCopyCUnion(const RecordDecl *RD);
};
raw_ostream &operator<<(raw_ostream &OS, QualType QT);
} // namespace clang
namespace llvm {
@@ -1615,6 +1680,9 @@ class alignas(8) Type : public ExtQualsTypeCommonBase {
/// Whether this function has extended parameter information.
unsigned HasExtParameterInfos : 1;
/// Whether this function has extra bitfields for the prototype.
unsigned HasExtraBitfields : 1;
/// Whether the function is variadic.
unsigned Variadic : 1;
@@ -2046,6 +2114,7 @@ class alignas(8) Type : public ExtQualsTypeCommonBase {
bool isComplexIntegerType() const; // GCC _Complex integer type.
bool isVectorType() const; // GCC vector type.
bool isExtVectorType() const; // Extended vector type.
bool isExtVectorBoolType() const; // Extended vector type with bool element.
bool isMatrixType() const; // Matrix type.
bool isConstantMatrixType() const; // Constant matrix type.
bool isDependentAddressSpaceType() const; // value-dependent address space qualifier
@@ -2555,6 +2624,8 @@ class BuiltinType : public Type {
return getKind() >= Half && getKind() <= Ibm128;
}
bool isSVEBool() const { return getKind() == Kind::SveBool; }
/// Determines whether the given kind corresponds to a placeholder type.
static bool isPlaceholderTypeKind(Kind K) {
return K >= Overload;
@@ -3786,13 +3857,12 @@ class FunctionType : public Type {
/// A simple holder for various uncommon bits which do not fit in
/// FunctionTypeBitfields. Aligned to alignof(void *) to maintain the
/// alignment of subsequent objects in TrailingObjects. You must update
/// hasExtraBitfields in FunctionProtoType after adding extra data here.
/// alignment of subsequent objects in TrailingObjects.
struct alignas(void *) FunctionTypeExtraBitfields {
/// 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;
unsigned NumExceptionType = 0;
};
protected:
@@ -3986,6 +4056,10 @@ class FunctionProtoType final
Result.ExceptionSpec = ESI;
return Result;
}
bool requiresFunctionProtoTypeExtraBitfields() const {
return ExceptionSpec.Type == EST_Dynamic;
}
};
private:
@@ -4076,16 +4150,13 @@ class FunctionProtoType final
return getExceptionSpecSize(getExceptionSpecType(), getNumExceptions());
}
/// Whether the trailing FunctionTypeExtraBitfields is present.
static bool hasExtraBitfields(ExceptionSpecificationType EST) {
// If the exception spec type is EST_Dynamic then we have > 0 exception
// types and the exact number is stored in FunctionTypeExtraBitfields.
return EST == EST_Dynamic;
}
/// Whether the trailing FunctionTypeExtraBitfields is present.
bool hasExtraBitfields() const {
return hasExtraBitfields(getExceptionSpecType());
assert((getExceptionSpecType() != EST_Dynamic ||
FunctionTypeBits.HasExtraBitfields) &&
"ExtraBitfields are required for given ExceptionSpecType");
return FunctionTypeBits.HasExtraBitfields;
}
bool hasExtQualifiers() const {
@@ -4784,6 +4855,40 @@ class AttributedType : public Type, public llvm::FoldingSetNode {
}
};
class BTFTagAttributedType : public Type, public llvm::FoldingSetNode {
private:
friend class ASTContext; // ASTContext creates these
QualType WrappedType;
const BTFTypeTagAttr *BTFAttr;
BTFTagAttributedType(QualType Canon, QualType Wrapped,
const BTFTypeTagAttr *BTFAttr)
: Type(BTFTagAttributed, Canon, Wrapped->getDependence()),
WrappedType(Wrapped), BTFAttr(BTFAttr) {}
public:
QualType getWrappedType() const { return WrappedType; }
const BTFTypeTagAttr *getAttr() const { return BTFAttr; }
bool isSugared() const { return true; }
QualType desugar() const { return getWrappedType(); }
void Profile(llvm::FoldingSetNodeID &ID) {
Profile(ID, WrappedType, BTFAttr);
}
static void Profile(llvm::FoldingSetNodeID &ID, QualType Wrapped,
const BTFTypeTagAttr *BTFAttr) {
ID.AddPointer(Wrapped.getAsOpaquePtr());
ID.AddPointer(BTFAttr);
}
static bool classof(const Type *T) {
return T->getTypeClass() == BTFTagAttributed;
}
};
class TemplateTypeParmType : public Type, public llvm::FoldingSetNode {
friend class ASTContext; // ASTContext creates these
@@ -5045,6 +5150,10 @@ class alignas(8) AutoType : public DeducedType, public llvm::FoldingSetNode {
return getKeyword() == AutoTypeKeyword::DecltypeAuto;
}
bool isGNUAutoType() const {
return getKeyword() == AutoTypeKeyword::GNUAutoType;
}
AutoTypeKeyword getKeyword() const {
return (AutoTypeKeyword)AutoTypeBits.Keyword;
}
@@ -5696,7 +5805,7 @@ class PackExpansionType : public Type, public llvm::FoldingSetNode {
static void Profile(llvm::FoldingSetNodeID &ID, QualType Pattern,
Optional<unsigned> NumExpansions) {
ID.AddPointer(Pattern.getAsOpaquePtr());
ID.AddBoolean(NumExpansions.hasValue());
ID.AddBoolean(NumExpansions.has_value());
if (NumExpansions)
ID.AddInteger(*NumExpansions);
}
@@ -6805,6 +6914,12 @@ inline bool Type::isExtVectorType() const {
return isa<ExtVectorType>(CanonicalType);
}
inline bool Type::isExtVectorBoolType() const {
if (!isExtVectorType())
return false;
return cast<ExtVectorType>(CanonicalType)->getElementType()->isBooleanType();
}
inline bool Type::isMatrixType() const {
return isa<MatrixType>(CanonicalType);
}
@@ -7218,6 +7333,8 @@ template <typename T> const T *Type::getAsAdjusted() const {
while (Ty) {
if (const auto *A = dyn_cast<AttributedType>(Ty))
Ty = A->getModifiedType().getTypePtr();
else if (const auto *A = dyn_cast<BTFTagAttributedType>(Ty))
Ty = A->getWrappedType().getTypePtr();
else if (const auto *E = dyn_cast<ElaboratedType>(Ty))
Ty = E->desugar().getTypePtr();
else if (const auto *P = dyn_cast<ParenType>(Ty))
@@ -901,6 +901,29 @@ class AttributedTypeLoc : public ConcreteTypeLoc<UnqualTypeLoc,
}
};
struct BTFTagAttributedLocInfo {}; // Nothing.
/// Type source information for an btf_tag attributed type.
class BTFTagAttributedTypeLoc
: public ConcreteTypeLoc<UnqualTypeLoc, BTFTagAttributedTypeLoc,
BTFTagAttributedType, BTFTagAttributedLocInfo> {
public:
TypeLoc getWrappedLoc() const { return getInnerTypeLoc(); }
/// The btf_type_tag attribute.
const BTFTypeTagAttr *getAttr() const { return getTypePtr()->getAttr(); }
template <typename T> T *getAttrAs() {
return dyn_cast_or_null<T>(getAttr());
}
SourceRange getLocalSourceRange() const;
void initializeLocal(ASTContext &Context, SourceLocation loc) {}
QualType getInnerType() const { return getTypePtr()->getWrappedType(); }
};
struct ObjCObjectTypeLocInfo {
SourceLocation TypeArgsLAngleLoc;
SourceLocation TypeArgsRAngleLoc;
@@ -2589,6 +2612,8 @@ inline T TypeLoc::getAsAdjusted() const {
Cur = PTL.getInnerLoc();
else if (auto ATL = Cur.getAs<AttributedTypeLoc>())
Cur = ATL.getModifiedLoc();
else if (auto ATL = Cur.getAs<BTFTagAttributedTypeLoc>())
Cur = ATL.getWrappedLoc();
else if (auto ETL = Cur.getAs<ElaboratedTypeLoc>())
Cur = ETL.getNamedTypeLoc();
else if (auto ATL = Cur.getAs<AdjustedTypeLoc>())
@@ -2607,6 +2632,22 @@ class DependentBitIntTypeLoc final
: public InheritingConcreteTypeLoc<TypeSpecTypeLoc, DependentBitIntTypeLoc,
DependentBitIntType> {};
class ObjCProtocolLoc {
ObjCProtocolDecl *Protocol = nullptr;
SourceLocation Loc = SourceLocation();
public:
ObjCProtocolLoc(ObjCProtocolDecl *protocol, SourceLocation loc)
: Protocol(protocol), Loc(loc) {}
ObjCProtocolDecl *getProtocol() const { return Protocol; }
SourceLocation getLocation() const { return Loc; }
/// The source range is just the protocol name.
SourceRange getSourceRange() const LLVM_READONLY {
return SourceRange(Loc, Loc);
}
};
} // namespace clang
#endif // LLVM_CLANG_AST_TYPELOC_H
@@ -619,6 +619,19 @@ let Class = AttributedType in {
}]>;
}
let Class = BTFTagAttributedType in {
def : Property<"attr", BTFTypeTagAttr> {
let Read = [{ node->getAttr() }];
}
def : Property<"wrappedType", QualType> {
let Read = [{ node->getWrappedType() }];
}
def : Creator<[{
return ctx.getBTFTagAttributedType(attr, wrappedType);
}]>;
}
let Class = DependentAddressSpaceType in {
def : Property<"pointeeType", QualType> {
let Read = [{ node->getPointeeType() }];
@@ -658,7 +671,7 @@ let Class = TemplateSpecializationType in {
def : Creator<[{
QualType result;
if (!underlyingType.hasValue()) {
if (!underlyingType) {
result = ctx.getCanonicalTemplateSpecializationType(templateName,
templateArguments);
} else {
@@ -1515,6 +1515,15 @@ extern const internal::VariadicDynCastAllOfMatcher<Stmt, CXXMemberCallExpr>
extern const internal::VariadicDynCastAllOfMatcher<Stmt, ObjCMessageExpr>
objcMessageExpr;
/// Matches ObjectiveC String literal expressions.
///
/// Example matches @"abcd"
/// \code
/// NSString *s = @"abcd";
/// \endcode
extern const internal::VariadicDynCastAllOfMatcher<Stmt, ObjCStringLiteral>
objcStringLiteral;
/// Matches Objective-C interface declarations.
///
/// Example matches Foo
@@ -2523,7 +2532,7 @@ extern const internal::VariadicDynCastAllOfMatcher<Stmt, OpaqueValueExpr>
/// Matches a C++ static_assert declaration.
///
/// Example:
/// staticAssertExpr()
/// staticAssertDecl()
/// matches
/// static_assert(sizeof(S) == sizeof(int))
/// in
@@ -5011,6 +5020,49 @@ AST_POLYMORPHIC_MATCHER_P(parameterCountIs,
return Node.getNumParams() == N;
}
/// Matches classTemplateSpecialization, templateSpecializationType and
/// functionDecl nodes where the template argument matches the inner matcher.
/// This matcher may produce multiple matches.
///
/// Given
/// \code
/// template <typename T, unsigned N, unsigned M>
/// struct Matrix {};
///
/// constexpr unsigned R = 2;
/// Matrix<int, R * 2, R * 4> M;
///
/// template <typename T, typename U>
/// void f(T&& t, U&& u) {}
///
/// bool B = false;
/// f(R, B);
/// \endcode
/// templateSpecializationType(forEachTemplateArgument(isExpr(expr())))
/// matches twice, with expr() matching 'R * 2' and 'R * 4'
/// functionDecl(forEachTemplateArgument(refersToType(builtinType())))
/// matches the specialization f<unsigned, bool> twice, for 'unsigned'
/// and 'bool'
AST_POLYMORPHIC_MATCHER_P(
forEachTemplateArgument,
AST_POLYMORPHIC_SUPPORTED_TYPES(ClassTemplateSpecializationDecl,
TemplateSpecializationType, FunctionDecl),
clang::ast_matchers::internal::Matcher<TemplateArgument>, InnerMatcher) {
ArrayRef<TemplateArgument> TemplateArgs =
clang::ast_matchers::internal::getTemplateSpecializationArgs(Node);
clang::ast_matchers::internal::BoundNodesTreeBuilder Result;
bool Matched = false;
for (const auto &Arg : TemplateArgs) {
clang::ast_matchers::internal::BoundNodesTreeBuilder ArgBuilder(*Builder);
if (InnerMatcher.matches(Arg, Finder, &ArgBuilder)) {
Matched = true;
Result.addMatch(ArgBuilder);
}
}
*Builder = std::move(Result);
return Matched;
}
/// Matches \c FunctionDecls that have a noreturn attribute.
///
/// Given
@@ -7673,7 +7725,7 @@ AST_MATCHER_P(FunctionDecl, hasExplicitSpecifier, internal::Matcher<Expr>,
return InnerMatcher.matches(*ES.getExpr(), Finder, Builder);
}
/// Matches function and namespace declarations that are marked with
/// Matches functions, variables and namespace declarations that are marked with
/// the inline keyword.
///
/// Given
@@ -7683,18 +7735,22 @@ AST_MATCHER_P(FunctionDecl, hasExplicitSpecifier, internal::Matcher<Expr>,
/// namespace n {
/// inline namespace m {}
/// }
/// inline int Foo = 5;
/// \endcode
/// functionDecl(isInline()) will match ::f().
/// namespaceDecl(isInline()) will match n::m.
AST_POLYMORPHIC_MATCHER(isInline,
AST_POLYMORPHIC_SUPPORTED_TYPES(NamespaceDecl,
FunctionDecl)) {
/// varDecl(isInline()) will match Foo;
AST_POLYMORPHIC_MATCHER(isInline, AST_POLYMORPHIC_SUPPORTED_TYPES(NamespaceDecl,
FunctionDecl,
VarDecl)) {
// This is required because the spelling of the function used to determine
// whether inline is specified or not differs between the polymorphic types.
if (const auto *FD = dyn_cast<FunctionDecl>(&Node))
return FD->isInlineSpecified();
else if (const auto *NSD = dyn_cast<NamespaceDecl>(&Node))
if (const auto *NSD = dyn_cast<NamespaceDecl>(&Node))
return NSD->isInline();
if (const auto *VD = dyn_cast<VarDecl>(&Node))
return VD->isInline();
llvm_unreachable("Not a valid polymorphic type");
}
@@ -7924,8 +7980,7 @@ AST_MATCHER_P(Stmt, forFunction, internal::Matcher<FunctionDecl>,
return true;
}
} else {
for (const auto &Parent : Finder->getASTContext().getParents(CurNode))
Stack.push_back(Parent);
llvm::append_range(Stack, Finder->getASTContext().getParents(CurNode));
}
}
return false;
@@ -7983,8 +8038,7 @@ AST_MATCHER_P(Stmt, forCallable, internal::Matcher<Decl>, InnerMatcher) {
return true;
}
} else {
for (const auto &Parent : Finder->getASTContext().getParents(CurNode))
Stack.push_back(Parent);
llvm::append_range(Stack, Finder->getASTContext().getParents(CurNode));
}
}
return false;
@@ -8258,12 +8312,13 @@ AST_MATCHER_P(OMPExecutableDirective, hasAnyClause,
/// \code
/// #pragma omp parallel default(none)
/// #pragma omp parallel default(shared)
/// #pragma omp parallel default(private)
/// #pragma omp parallel default(firstprivate)
/// #pragma omp parallel
/// \endcode
///
/// ``ompDefaultClause()`` matches ``default(none)``, ``default(shared)``, and
/// ``default(firstprivate)``
/// ``ompDefaultClause()`` matches ``default(none)``, ``default(shared)``,
/// `` default(private)`` and ``default(firstprivate)``
extern const internal::VariadicDynCastAllOfMatcher<OMPClause, OMPDefaultClause>
ompDefaultClause;
@@ -8275,6 +8330,7 @@ extern const internal::VariadicDynCastAllOfMatcher<OMPClause, OMPDefaultClause>
/// #pragma omp parallel
/// #pragma omp parallel default(none)
/// #pragma omp parallel default(shared)
/// #pragma omp parallel default(private)
/// #pragma omp parallel default(firstprivate)
/// \endcode
///
@@ -8291,6 +8347,7 @@ AST_MATCHER(OMPDefaultClause, isNoneKind) {
/// #pragma omp parallel
/// #pragma omp parallel default(none)
/// #pragma omp parallel default(shared)
/// #pragma omp parallel default(private)
/// #pragma omp parallel default(firstprivate)
/// \endcode
///
@@ -8299,6 +8356,25 @@ AST_MATCHER(OMPDefaultClause, isSharedKind) {
return Node.getDefaultKind() == llvm::omp::OMP_DEFAULT_shared;
}
/// Matches if the OpenMP ``default`` clause has ``private`` kind
/// specified.
///
/// Given
///
/// \code
/// #pragma omp parallel
/// #pragma omp parallel default(none)
/// #pragma omp parallel default(shared)
/// #pragma omp parallel default(private)
/// #pragma omp parallel default(firstprivate)
/// \endcode
///
/// ``ompDefaultClause(isPrivateKind())`` matches only
/// ``default(private)``.
AST_MATCHER(OMPDefaultClause, isPrivateKind) {
return Node.getDefaultKind() == llvm::omp::OMP_DEFAULT_private;
}
/// Matches if the OpenMP ``default`` clause has ``firstprivate`` kind
/// specified.
///
@@ -8308,6 +8384,7 @@ AST_MATCHER(OMPDefaultClause, isSharedKind) {
/// #pragma omp parallel
/// #pragma omp parallel default(none)
/// #pragma omp parallel default(shared)
/// #pragma omp parallel default(private)
/// #pragma omp parallel default(firstprivate)
/// \endcode
///
@@ -132,10 +132,7 @@ struct VariadicFunction {
// We also allow calls with an already created array, in case the caller
// already had it.
ResultT operator()(ArrayRef<ArgT> Args) const {
SmallVector<const ArgT*, 8> InnerArgs;
for (const ArgT &Arg : Args)
InnerArgs.push_back(&Arg);
return Func(InnerArgs);
return Func(llvm::to_vector<8>(llvm::make_pointer_range(Args)));
}
private:
@@ -600,17 +597,15 @@ class Matcher {
/// Convert \c this into a \c Matcher<T> by applying dyn_cast<> to the
/// argument.
/// \c To must be a base class of \c T.
template <typename To> Matcher<To> dynCastTo() const LLVM_LVALUE_FUNCTION {
template <typename To> Matcher<To> dynCastTo() const & {
static_assert(std::is_base_of<To, T>::value, "Invalid dynCast call.");
return Matcher<To>(Implementation);
}
#if LLVM_HAS_RVALUE_REFERENCE_THIS
template <typename To> Matcher<To> dynCastTo() && {
static_assert(std::is_base_of<To, T>::value, "Invalid dynCast call.");
return Matcher<To>(std::move(Implementation));
}
#endif
/// Forwards the call to the underlying MatcherInterface<T> pointer.
bool matches(const T &Node,
@@ -628,13 +623,9 @@ class Matcher {
///
/// The returned matcher keeps the same restrictions as \c this and remembers
/// that it is meant to support nodes of type \c T.
operator DynTypedMatcher() const LLVM_LVALUE_FUNCTION {
return Implementation;
}
operator DynTypedMatcher() const & { return Implementation; }
#if LLVM_HAS_RVALUE_REFERENCE_THIS
operator DynTypedMatcher() && { return std::move(Implementation); }
#endif
/// Allows the conversion of a \c Matcher<Type> to a \c
/// Matcher<QualType>.
@@ -1361,35 +1352,31 @@ template <typename... Ps> class VariadicOperatorMatcher {
VariadicOperatorMatcher(DynTypedMatcher::VariadicOperator Op, Ps &&... Params)
: Op(Op), Params(std::forward<Ps>(Params)...) {}
template <typename T> operator Matcher<T>() const LLVM_LVALUE_FUNCTION {
template <typename T> operator Matcher<T>() const & {
return DynTypedMatcher::constructVariadic(
Op, ASTNodeKind::getFromNodeKind<T>(),
getMatchers<T>(std::index_sequence_for<Ps...>()))
.template unconditionalConvertTo<T>();
}
#if LLVM_HAS_RVALUE_REFERENCE_THIS
template <typename T> operator Matcher<T>() && {
return DynTypedMatcher::constructVariadic(
Op, ASTNodeKind::getFromNodeKind<T>(),
getMatchers<T>(std::index_sequence_for<Ps...>()))
.template unconditionalConvertTo<T>();
}
#endif
private:
// Helper method to unpack the tuple into a vector.
template <typename T, std::size_t... Is>
std::vector<DynTypedMatcher>
getMatchers(std::index_sequence<Is...>) const LLVM_LVALUE_FUNCTION {
std::vector<DynTypedMatcher> getMatchers(std::index_sequence<Is...>) const & {
return {Matcher<T>(std::get<Is>(Params))...};
}
#if LLVM_HAS_RVALUE_REFERENCE_THIS
template <typename T, std::size_t... Is>
std::vector<DynTypedMatcher> getMatchers(std::index_sequence<Is...>) && {
return {Matcher<T>(std::get<Is>(std::move(Params)))...};
}
#endif
const DynTypedMatcher::VariadicOperator Op;
std::tuple<Ps...> Params;
@@ -1479,15 +1466,13 @@ class ArgumentAdaptingMatcherFuncAdaptor {
using ReturnTypes = ToTypes;
template <typename To> operator Matcher<To>() const LLVM_LVALUE_FUNCTION {
template <typename To> operator Matcher<To>() const & {
return Matcher<To>(new ArgumentAdapterT<To, T>(InnerMatcher));
}
#if LLVM_HAS_RVALUE_REFERENCE_THIS
template <typename To> operator Matcher<To>() && {
return Matcher<To>(new ArgumentAdapterT<To, T>(std::move(InnerMatcher)));
}
#endif
private:
Matcher<T> InnerMatcher;
@@ -1558,21 +1543,19 @@ template <typename MatcherType> class TraversalWrapper {
TraversalWrapper(TraversalKind TK, const MatcherType &InnerMatcher)
: TK(TK), InnerMatcher(InnerMatcher) {}
template <typename T> operator Matcher<T>() const LLVM_LVALUE_FUNCTION {
template <typename T> operator Matcher<T>() const & {
return internal::DynTypedMatcher::constructRestrictedWrapper(
new internal::TraversalMatcher<T>(TK, InnerMatcher),
ASTNodeKind::getFromNodeKind<T>())
.template unconditionalConvertTo<T>();
}
#if LLVM_HAS_RVALUE_REFERENCE_THIS
template <typename T> operator Matcher<T>() && {
return internal::DynTypedMatcher::constructRestrictedWrapper(
new internal::TraversalMatcher<T>(TK, std::move(InnerMatcher)),
ASTNodeKind::getFromNodeKind<T>())
.template unconditionalConvertTo<T>();
}
#endif
private:
TraversalKind TK;
@@ -1599,20 +1582,18 @@ class PolymorphicMatcher {
using ReturnTypes = typename ExtractFunctionArgMeta<ReturnTypesF>::type;
template <typename T> operator Matcher<T>() const LLVM_LVALUE_FUNCTION {
template <typename T> operator Matcher<T>() const & {
static_assert(TypeListContainsSuperOf<ReturnTypes, T>::value,
"right polymorphic conversion");
return Matcher<T>(new_from_tuple<MatcherT<T, ParamTypes...>>(Params));
}
#if LLVM_HAS_RVALUE_REFERENCE_THIS
template <typename T> operator Matcher<T>() && {
static_assert(TypeListContainsSuperOf<ReturnTypes, T>::value,
"right polymorphic conversion");
return Matcher<T>(
new_from_tuple<MatcherT<T, ParamTypes...>>(std::move(Params)));
}
#endif
private:
std::tuple<ParamTypes...> Params;
@@ -188,7 +188,7 @@ class VariantMatcher {
bool hasTypedMatcher(ASTNodeKind NK) const {
if (!Value) return false;
return Value->getTypedMatcher(MatcherOps(NK)).hasValue();
return Value->getTypedMatcher(MatcherOps(NK)).has_value();
}
/// Determines if the contained matcher can be converted to \p Kind.
@@ -79,7 +79,7 @@ class CalledOnceCheckHandler {
/// the path containing the call and not containing the call. This helps us
/// to pinpoint a bad path for the user.
/// \param Parameter -- parameter that should be called once.
/// \param Function -- function declaration where the problem occured.
/// \param Function -- function declaration where the problem occurred.
/// \param Where -- the least common ancestor statement.
/// \param Reason -- a reason describing the path without a call.
/// \param IsCalledDirectly -- true, if parameter actually gets called on
@@ -38,6 +38,8 @@ class ExprMutationAnalyzer {
}
const Stmt *findPointeeMutation(const Expr *Exp);
const Stmt *findPointeeMutation(const Decl *Dec);
static bool isUnevaluated(const Stmt *Smt, const Stmt &Stm,
ASTContext &Context);
private:
using MutationFinder = const Stmt *(ExprMutationAnalyzer::*)(const Expr *);
@@ -98,9 +98,8 @@ class ThreadSafetyHandler {
virtual ~ThreadSafetyHandler();
/// Warn about lock expressions which fail to resolve to lockable objects.
/// \param Kind -- the capability's name parameter (role, mutex, etc).
/// \param Loc -- the SourceLocation of the unresolved expression.
virtual void handleInvalidLockExp(StringRef Kind, SourceLocation Loc) {}
virtual void handleInvalidLockExp(SourceLocation Loc) {}
/// Warn about unlock function calls that do not have a prior matching lock
/// expression.
@@ -169,14 +168,12 @@ class ThreadSafetyHandler {
SourceLocation Loc2) {}
/// Warn when a protected operation occurs while no locks are held.
/// \param Kind -- the capability's name parameter (role, mutex, etc).
/// \param D -- The decl for the protected variable or function
/// \param POK -- The kind of protected operation (e.g. variable access)
/// \param AK -- The kind of access (i.e. read or write) that occurred
/// \param Loc -- The location of the protected operation.
virtual void handleNoMutexHeld(StringRef Kind, const NamedDecl *D,
ProtectedOperationKind POK, AccessKind AK,
SourceLocation Loc) {}
virtual void handleNoMutexHeld(const NamedDecl *D, ProtectedOperationKind POK,
AccessKind AK, SourceLocation Loc) {}
/// Warn when a protected operation occurs while the specific mutex protecting
/// the operation is not locked.
@@ -30,6 +30,7 @@
#include "clang/Analysis/CFG.h"
#include "clang/Basic/LLVM.h"
#include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/PointerIntPair.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/Support/Casting.h"
#include <sstream>
@@ -269,28 +270,36 @@ class CFGWalker {
// translateAttrExpr needs it, but that should be moved too.
class CapabilityExpr {
private:
/// The capability expression.
const til::SExpr* CapExpr;
/// The capability expression and whether it's negated.
llvm::PointerIntPair<const til::SExpr *, 1, bool> CapExpr;
/// True if this is a negative capability.
bool Negated;
/// The kind of capability as specified by @ref CapabilityAttr::getName.
StringRef CapKind;
public:
CapabilityExpr(const til::SExpr *E, bool Neg) : CapExpr(E), Negated(Neg) {}
CapabilityExpr() : CapExpr(nullptr, false) {}
CapabilityExpr(const til::SExpr *E, StringRef Kind, bool Neg)
: CapExpr(E, Neg), CapKind(Kind) {}
const til::SExpr* sexpr() const { return CapExpr; }
bool negative() const { return Negated; }
// Don't allow implicitly-constructed StringRefs since we'll capture them.
template <typename T> CapabilityExpr(const til::SExpr *, T, bool) = delete;
const til::SExpr *sexpr() const { return CapExpr.getPointer(); }
StringRef getKind() const { return CapKind; }
bool negative() const { return CapExpr.getInt(); }
CapabilityExpr operator!() const {
return CapabilityExpr(CapExpr, !Negated);
return CapabilityExpr(CapExpr.getPointer(), CapKind, !CapExpr.getInt());
}
bool equals(const CapabilityExpr &other) const {
return (Negated == other.Negated) && sx::equals(CapExpr, other.CapExpr);
return (negative() == other.negative()) &&
sx::equals(sexpr(), other.sexpr());
}
bool matches(const CapabilityExpr &other) const {
return (Negated == other.Negated) && sx::matches(CapExpr, other.CapExpr);
return (negative() == other.negative()) &&
sx::matches(sexpr(), other.sexpr());
}
bool matchesUniv(const CapabilityExpr &CapE) const {
@@ -298,27 +307,27 @@ class CapabilityExpr {
}
bool partiallyMatches(const CapabilityExpr &other) const {
return (Negated == other.Negated) &&
sx::partiallyMatches(CapExpr, other.CapExpr);
return (negative() == other.negative()) &&
sx::partiallyMatches(sexpr(), other.sexpr());
}
const ValueDecl* valueDecl() const {
if (Negated || CapExpr == nullptr)
if (negative() || sexpr() == nullptr)
return nullptr;
if (const auto *P = dyn_cast<til::Project>(CapExpr))
if (const auto *P = dyn_cast<til::Project>(sexpr()))
return P->clangDecl();
if (const auto *P = dyn_cast<til::LiteralPtr>(CapExpr))
if (const auto *P = dyn_cast<til::LiteralPtr>(sexpr()))
return P->clangDecl();
return nullptr;
}
std::string toString() const {
if (Negated)
return "!" + sx::toString(CapExpr);
return sx::toString(CapExpr);
if (negative())
return "!" + sx::toString(sexpr());
return sx::toString(sexpr());
}
bool shouldIgnore() const { return CapExpr == nullptr; }
bool shouldIgnore() const { return sexpr() == nullptr; }
bool isInvalid() const { return sexpr() && isa<til::Undefined>(sexpr()); }
@@ -229,7 +229,9 @@ class LocationContext : public llvm::FoldingSetNode {
protected:
LocationContext(ContextKind k, AnalysisDeclContext *ctx,
const LocationContext *parent, int64_t ID)
: Kind(k), Ctx(ctx), Parent(parent), ID(ID) {}
: Kind(k), Ctx(ctx), Parent(parent), ID(ID) {
assert(ctx);
}
public:
virtual ~LocationContext();
@@ -238,8 +240,10 @@ class LocationContext : public llvm::FoldingSetNode {
int64_t getID() const { return ID; }
LLVM_ATTRIBUTE_RETURNS_NONNULL
AnalysisDeclContext *getAnalysisDeclContext() const { return Ctx; }
/// It might return null.
const LocationContext *getParent() const { return Parent; }
bool isParentOf(const LocationContext *LC) const;
@@ -208,13 +208,7 @@ class CloneDetector {
// The initial assumption is that there is only one clone group and every
// statement is a clone of the others. This clone group will then be
// split up with the help of the constraints.
CloneGroup AllClones;
AllClones.reserve(Sequences.size());
for (const auto &C : Sequences) {
AllClones.push_back(C);
}
Result.push_back(AllClones);
Result.push_back(Sequences);
constrainClones(Result, ConstraintList...);
}
@@ -120,7 +120,8 @@ class ConstructionContextItem {
ConstructionContextItem(const Expr *E, unsigned Index)
: Data(E), Kind(ArgumentKind), Index(Index) {
assert(isa<CallExpr>(E) || isa<CXXConstructExpr>(E) ||
isa<CXXInheritedCtorInitExpr>(E) || isa<ObjCMessageExpr>(E));
isa<CXXDeleteExpr>(E) || isa<CXXInheritedCtorInitExpr>(E) ||
isa<ObjCMessageExpr>(E));
}
ConstructionContextItem(const CXXCtorInitializer *Init)
@@ -106,16 +106,36 @@ template <typename LatticeT> struct DataflowAnalysisState {
};
/// Performs dataflow analysis and returns a mapping from basic block IDs to
/// dataflow analysis states that model the respective basic blocks. Indices
/// of the returned vector correspond to basic block IDs. Returns an error if
/// the dataflow analysis cannot be performed successfully.
/// dataflow analysis states that model the respective basic blocks. The
/// returned vector, if any, will have the same size as the number of CFG
/// blocks, with indices corresponding to basic block IDs. Returns an error if
/// the dataflow analysis cannot be performed successfully. Otherwise, calls
/// `PostVisitStmt` on each statement with the final analysis results at that
/// program point.
template <typename AnalysisT>
llvm::Expected<std::vector<
llvm::Optional<DataflowAnalysisState<typename AnalysisT::Lattice>>>>
runDataflowAnalysis(const ControlFlowContext &CFCtx, AnalysisT &Analysis,
const Environment &InitEnv) {
auto TypeErasedBlockStates =
runTypeErasedDataflowAnalysis(CFCtx, Analysis, InitEnv);
runDataflowAnalysis(
const ControlFlowContext &CFCtx, AnalysisT &Analysis,
const Environment &InitEnv,
std::function<void(const Stmt *, const DataflowAnalysisState<
typename AnalysisT::Lattice> &)>
PostVisitStmt = nullptr) {
std::function<void(const Stmt *, const TypeErasedDataflowAnalysisState &)>
PostVisitStmtClosure = nullptr;
if (PostVisitStmt != nullptr) {
PostVisitStmtClosure = [&PostVisitStmt](
const Stmt *Stmt,
const TypeErasedDataflowAnalysisState &State) {
auto *Lattice =
llvm::any_cast<typename AnalysisT::Lattice>(&State.Lattice.Value);
PostVisitStmt(Stmt, DataflowAnalysisState<typename AnalysisT::Lattice>{
*Lattice, State.Env});
};
}
auto TypeErasedBlockStates = runTypeErasedDataflowAnalysis(
CFCtx, Analysis, InitEnv, PostVisitStmtClosure);
if (!TypeErasedBlockStates)
return TypeErasedBlockStates.takeError();
@@ -136,6 +156,15 @@ runDataflowAnalysis(const ControlFlowContext &CFCtx, AnalysisT &Analysis,
return BlockStates;
}
/// Abstract base class for dataflow "models": reusable analysis components that
/// model a particular aspect of program semantics in the `Environment`. For
/// example, a model may capture a type and its related functions.
class DataflowModel : public Environment::ValueModel {
public:
/// Return value indicates whether the model processed the `Stmt`.
virtual bool transfer(const Stmt *Stmt, Environment &Env) = 0;
};
} // namespace dataflow
} // namespace clang
@@ -17,9 +17,12 @@
#include "clang/AST/Decl.h"
#include "clang/AST/Expr.h"
#include "clang/AST/TypeOrdering.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 <cassert>
#include <memory>
#include <type_traits>
@@ -29,13 +32,36 @@
namespace clang {
namespace dataflow {
/// 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
/// exist.
///
/// * `ParenExpr` - The CFG takes the operator precedence into account, but
/// otherwise omits the node afterwards.
///
/// * `ExprWithCleanups` - The CFG will generate the appropriate calls to
/// destructors and then omit the node.
///
const Expr &ignoreCFGOmittedNodes(const Expr &E);
const Stmt &ignoreCFGOmittedNodes(const Stmt &S);
/// Returns the set of all fields in the type.
llvm::DenseSet<const FieldDecl *> getObjectFields(QualType Type);
/// Owns objects that encompass the state of a program and stores context that
/// is used during dataflow analysis.
class DataflowAnalysisContext {
public:
DataflowAnalysisContext()
: TrueVal(&takeOwnership(std::make_unique<BoolValue>())),
FalseVal(&takeOwnership(std::make_unique<BoolValue>())) {}
/// Constructs a dataflow analysis context.
///
/// Requirements:
///
/// `S` must not be null.
DataflowAnalysisContext(std::unique_ptr<Solver> S)
: S(std::move(S)), TrueVal(createAtomicBoolValue()),
FalseVal(createAtomicBoolValue()) {
assert(this->S != nullptr);
}
/// Takes ownership of `Loc` and returns a reference to it.
///
@@ -63,6 +89,19 @@ class DataflowAnalysisContext {
return *cast<T>(Vals.back().get());
}
/// Returns a stable storage location appropriate for `Type`.
///
/// Requirements:
///
/// `Type` must not be null.
StorageLocation &getStableStorageLocation(QualType Type);
/// Returns a stable storage location for `D`.
StorageLocation &getStableStorageLocation(const VarDecl &D);
/// Returns a stable storage location for `E`.
StorageLocation &getStableStorageLocation(const Expr &E);
/// Assigns `Loc` as the storage location of `D`.
///
/// Requirements:
@@ -86,14 +125,15 @@ class DataflowAnalysisContext {
///
/// `E` must not be assigned a storage location.
void setStorageLocation(const Expr &E, StorageLocation &Loc) {
assert(ExprToLoc.find(&E) == ExprToLoc.end());
ExprToLoc[&E] = &Loc;
const Expr &CanonE = ignoreCFGOmittedNodes(E);
assert(ExprToLoc.find(&CanonE) == ExprToLoc.end());
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(&E);
auto It = ExprToLoc.find(&ignoreCFGOmittedNodes(E));
return It == ExprToLoc.end() ? nullptr : It->second;
}
@@ -113,13 +153,144 @@ class DataflowAnalysisContext {
return ThisPointeeLoc;
}
/// 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);
/// Returns a symbolic boolean value that models a boolean literal equal to
/// `Value`.
BoolValue &getBoolLiteralValue(bool Value) const {
return Value ? *TrueVal : *FalseVal;
AtomicBoolValue &getBoolLiteralValue(bool Value) const {
return Value ? TrueVal : FalseVal;
}
/// Creates an atomic boolean value.
AtomicBoolValue &createAtomicBoolValue() {
return takeOwnership(std::make_unique<AtomicBoolValue>());
}
/// 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);
/// Creates a new flow condition with the same constraints as the flow
/// condition identified by `Token` and returns its token.
AtomicBoolValue &forkFlowCondition(AtomicBoolValue &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);
/// 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);
/// Returns true if and only if the constraints of the flow condition
/// identified by `Token` are always true.
bool flowConditionIsTautology(AtomicBoolValue &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);
private:
/// 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 result of satisfiability checking on `Constraints`.
/// Possible return values are:
/// - `Satisfiable`: There exists a satisfying assignment for `Constraints`.
/// - `Unsatisfiable`: There is no satisfying assignment for `Constraints`.
/// - `TimedOut`: The solver gives up on finding a satisfying assignment.
Solver::Result querySolver(llvm::DenseSet<BoolValue *> Constraints);
/// Returns true if the solver is able to prove that there is no satisfying
/// assignment for `Constraints`
bool isUnsatisfiable(llvm::DenseSet<BoolValue *> Constraints) {
return querySolver(std::move(Constraints)) == Solver::Result::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;
@@ -134,9 +305,40 @@ class DataflowAnalysisContext {
StorageLocation *ThisPointeeLoc = nullptr;
// FIXME: Add support for boolean expressions.
BoolValue *TrueVal;
BoolValue *FalseVal;
// Null pointer values, keyed by the canonical pointee type.
//
// FIXME: The pointer values are indexed by the pointee types which are
// required to initialize the `PointeeLoc` field in `PointerValue`. Consider
// creating a type-independent `NullPointerValue` without a `PointeeLoc`
// field.
llvm::DenseMap<QualType, PointerValue *> NullPointerVals;
AtomicBoolValue &TrueVal;
AtomicBoolValue &FalseVal;
// 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;
// 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
// "iff" of the form `FC <=> (C1 ^ C2 ^ ...)` where `FC` is a flow condition
// token (an atomic boolean) and `Ci`s are the set of constraints in the flow
// flow condition clause. The set of constraints (C1 ^ C2 ^ ...) are stored in
// the `FlowConditionConstraints` map, keyed by the token of the flow
// condition.
//
// 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;
};
} // namespace dataflow
@@ -49,6 +49,11 @@ enum class SkipPast {
};
/// Holds the state of the program (store and heap) at a given program point.
///
/// WARNING: Symbolic values that are created by the environment for static
/// local and global variables are not currently invalidated on function calls.
/// This is unsound and should be taken into account when designing dataflow
/// analyses.
class Environment {
public:
/// Supplements `Environment` with non-standard comparison and join
@@ -64,32 +69,55 @@ class Environment {
/// `Val1` and `Val2` must be distinct.
///
/// `Val1` and `Val2` must model values of type `Type`.
///
/// `Val1` and `Val2` must be assigned to the same storage location in
/// `Env1` and `Env2` respectively.
virtual bool compareEquivalent(QualType Type, const Value &Val1,
const Value &Val2) {
const Environment &Env1, const Value &Val2,
const Environment &Env2) {
// FIXME: Consider adding QualType to StructValue and removing the Type
// argument here.
return false;
//
// FIXME: default to a sound comparison and/or expand the comparison logic
// built into the framework to support broader forms of equivalence than
// strict pointer equality.
return true;
}
/// Modifies `MergedVal` to approximate both `Val1` and `Val2`. This could
/// be a strict lattice join or a more general widening operation. If this
/// function returns true, `MergedVal` will be assigned to a storage
/// location of type `Type` in `Env`.
/// be a strict lattice join or a more general widening operation.
///
/// If this function returns true, `MergedVal` will be assigned to a storage
/// location of type `Type` in `MergedEnv`.
///
/// `Env1` and `Env2` can be used to query child values and path condition
/// implications of `Val1` and `Val2` respectively.
///
/// Requirements:
///
/// `Val1` and `Val2` must be distinct.
///
/// `Val1`, `Val2`, and `MergedVal` must model values of type `Type`.
virtual bool merge(QualType Type, const Value &Val1, const Value &Val2,
Value &MergedVal, Environment &Env) {
return false;
///
/// `Val1` and `Val2` must be assigned to the same storage location in
/// `Env1` and `Env2` respectively.
virtual bool merge(QualType Type, const Value &Val1,
const Environment &Env1, const Value &Val2,
const Environment &Env2, Value &MergedVal,
Environment &MergedEnv) {
return true;
}
};
/// Creates an environment that uses `DACtx` to store objects that encompass
/// the state of a program.
explicit Environment(DataflowAnalysisContext &DACtx) : DACtx(&DACtx) {}
explicit Environment(DataflowAnalysisContext &DACtx);
Environment(const Environment &Other);
Environment &operator=(const Environment &Other);
Environment(Environment &&Other) = default;
Environment &operator=(Environment &&Other) = default;
/// Creates an environment that uses `DACtx` to store objects that encompass
/// the state of a program.
@@ -175,6 +203,10 @@ class Environment {
/// in the environment.
StorageLocation *getThisPointeeStorageLocation() const;
/// 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
@@ -226,10 +258,73 @@ class Environment {
/// Returns a symbolic boolean value that models a boolean literal equal to
/// `Value`
BoolValue &getBoolLiteralValue(bool Value) const {
AtomicBoolValue &getBoolLiteralValue(bool Value) const {
return DACtx->getBoolLiteralValue(Value);
}
/// Returns an atomic boolean value.
BoolValue &makeAtomicBoolValue() const {
return DACtx->createAtomicBoolValue();
}
/// 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 &makeAnd(BoolValue &LHS, BoolValue &RHS) const {
return DACtx->getOrCreateConjunction(LHS, 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 &makeOr(BoolValue &LHS, BoolValue &RHS) const {
return DACtx->getOrCreateDisjunction(LHS, RHS);
}
/// 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);
}
/// Returns a boolean value 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 &makeImplication(BoolValue &LHS, BoolValue &RHS) const {
return DACtx->getOrCreateImplication(LHS, RHS);
}
/// Returns a boolean value 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 &makeIff(BoolValue &LHS, BoolValue &RHS) const {
return DACtx->getOrCreateIff(LHS, RHS);
}
/// Returns the token that identifies the flow condition of the environment.
AtomicBoolValue &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));
}
/// 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;
private:
/// Creates a value appropriate for `Type`, if `Type` is supported, otherwise
/// return null.
@@ -243,7 +338,8 @@ class Environment {
///
/// `Type` must not be null.
Value *createValueUnlessSelfReferential(QualType Type,
llvm::DenseSet<QualType> &Visited);
llvm::DenseSet<QualType> &Visited,
int Depth, int &CreatedValuesCount);
StorageLocation &skip(StorageLocation &Loc, SkipPast SP) const;
const StorageLocation &skip(const StorageLocation &Loc, SkipPast SP) const;
@@ -260,7 +356,13 @@ class Environment {
llvm::DenseMap<const StorageLocation *, Value *> LocToVal;
// FIXME: Add flow condition constraints.
// 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;
};
} // namespace dataflow
@@ -0,0 +1,151 @@
//===---- MatchSwitch.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
//
//===----------------------------------------------------------------------===//
//
// This file defines the `MatchSwitch` 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.
//
// Currently, the design is catered towards simplifying the implementation of
// `DataflowAnalysis` transfer functions. Based on experience here, this
// library may be generalized and moved to ASTMatchers.
//
//===----------------------------------------------------------------------===//
#ifndef LLVM_CLANG_ANALYSIS_FLOWSENSITIVE_MATCHSWITCH_H_
#define LLVM_CLANG_ANALYSIS_FLOWSENSITIVE_MATCHSWITCH_H_
#include "clang/AST/ASTContext.h"
#include "clang/AST/Stmt.h"
#include "clang/ASTMatchers/ASTMatchFinder.h"
#include "clang/ASTMatchers/ASTMatchers.h"
#include "clang/Analysis/FlowSensitive/DataflowEnvironment.h"
#include "llvm/ADT/StringRef.h"
#include <functional>
#include <string>
#include <utility>
#include <vector>
namespace clang {
namespace dataflow {
/// A common form of state shared between the cases of a transfer function.
template <typename LatticeT> struct TransferState {
TransferState(LatticeT &Lattice, Environment &Env)
: Lattice(Lattice), Env(Env) {}
/// Current lattice element.
LatticeT &Lattice;
Environment &Env;
};
/// Matches against `Stmt` and, based on its structure, dispatches to an
/// appropriate handler.
template <typename State, typename Result = void>
using MatchSwitch = std::function<Result(const Stmt &, ASTContext &, State &)>;
/// Collects cases of a "match switch": a collection of matchers paired with
/// callbacks, which together define a switch that can be applied to a
/// `Stmt`. This structure can simplify the definition of `transfer` functions
/// that rely on pattern-matching.
///
/// For example, consider an analysis that handles particular function calls. It
/// can define the `MatchSwitch` once, in the constructor of the analysis, and
/// then reuse it each time that `transfer` is called, with a fresh state value.
///
/// \code
/// MatchSwitch<TransferState<MyLattice> BuildSwitch() {
/// return MatchSwitchBuilder<TransferState<MyLattice>>()
/// .CaseOf(callExpr(callee(functionDecl(hasName("foo")))), TransferFooCall)
/// .CaseOf(callExpr(argumentCountIs(2),
/// callee(functionDecl(hasName("bar")))),
/// TransferBarCall)
/// .Build();
/// }
/// \endcode
template <typename State, typename Result = void> class MatchSwitchBuilder {
public:
/// Registers an action that will be triggered by the match of a pattern
/// against the input statement.
///
/// Requirements:
///
/// `Node` should be a subclass of `Stmt`.
template <typename Node>
MatchSwitchBuilder &&
CaseOf(ast_matchers::internal::Matcher<Stmt> M,
std::function<Result(const Node *,
const ast_matchers::MatchFinder::MatchResult &,
State &)>
A) && {
Matchers.push_back(std::move(M));
Actions.push_back(
[A = std::move(A)](const Stmt *Stmt,
const ast_matchers::MatchFinder::MatchResult &R,
State &S) { return A(cast<Node>(Stmt), R, S); });
return std::move(*this);
}
MatchSwitch<State, Result> Build() && {
return [Matcher = BuildMatcher(), Actions = std::move(Actions)](
const Stmt &Stmt, ASTContext &Context, State &S) -> Result {
auto Results = ast_matchers::matchDynamic(Matcher, Stmt, Context);
if (Results.empty())
return Result();
// Look through the map for the first binding of the form "TagN..." use
// that to select the action.
for (const auto &Element : Results[0].getMap()) {
llvm::StringRef ID(Element.first);
size_t Index = 0;
if (ID.consume_front("Tag") && !ID.getAsInteger(10, Index) &&
Index < Actions.size()) {
return Actions[Index](
&Stmt,
ast_matchers::MatchFinder::MatchResult(Results[0], &Context), S);
}
}
return Result();
};
}
private:
ast_matchers::internal::DynTypedMatcher BuildMatcher() {
using ast_matchers::anything;
using ast_matchers::stmt;
using ast_matchers::unless;
using ast_matchers::internal::DynTypedMatcher;
if (Matchers.empty())
return stmt(unless(anything()));
for (int I = 0, N = Matchers.size(); I < N; ++I) {
std::string Tag = ("Tag" + llvm::Twine(I)).str();
// Many matchers are not bindable, so ensure that tryBind will work.
Matchers[I].setAllowBind(true);
auto M = *Matchers[I].tryBind(Tag);
// Each anyOf explicitly controls the traversal kind. The anyOf itself is
// set to `TK_AsIs` to ensure no nodes are skipped, thereby deferring to
// the kind of the branches. Then, each branch is either left as is, if
// the kind is already set, or explicitly set to `TK_AsIs`. We choose this
// setting because it is the default interpretation of matchers.
Matchers[I] =
!M.getTraversalKind() ? M.withTraversalKind(TK_AsIs) : std::move(M);
}
// The matcher type on the cases ensures that `Expr` kind is compatible with
// all of the matchers.
return DynTypedMatcher::constructVariadic(
DynTypedMatcher::VO_AnyOf, ASTNodeKind::getFromNodeKind<Stmt>(),
std::move(Matchers));
}
std::vector<ast_matchers::internal::DynTypedMatcher> Matchers;
std::vector<std::function<Result(
const Stmt *, const ast_matchers::MatchFinder::MatchResult &, State &)>>
Actions;
};
} // namespace dataflow
} // namespace clang
#endif // LLVM_CLANG_ANALYSIS_FLOWSENSITIVE_MATCHSWITCH_H_
@@ -0,0 +1,39 @@
//===-- ChromiumCheckModel.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
//
//===----------------------------------------------------------------------===//
//
// This file defines a dataflow model for Chromium's family of CHECK functions.
//
//===----------------------------------------------------------------------===//
#ifndef CLANG_ANALYSIS_FLOWSENSITIVE_MODELS_CHROMIUMCHECKMODEL_H
#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"
namespace clang {
namespace dataflow {
/// Models the behavior of Chromium's CHECK, DCHECK, etc. macros, so that code
/// after a call to `*CHECK` can rely on the condition being true.
class ChromiumCheckModel : public DataflowModel {
public:
ChromiumCheckModel() = default;
bool transfer(const Stmt *Stmt, Environment &Env) override;
private:
/// Declarations for `::logging::CheckError::.*Check`, lazily initialized.
llvm::SmallDenseSet<const CXXMethodDecl *> CheckDecls;
};
} // namespace dataflow
} // namespace clang
#endif // CLANG_ANALYSIS_FLOWSENSITIVE_MODELS_CHROMIUMCHECKMODEL_H
@@ -0,0 +1,85 @@
//===-- UncheckedOptionalAccessModel.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
//
//===----------------------------------------------------------------------===//
//
// This file defines a dataflow analysis that detects unsafe uses of optional
// values.
//
//===----------------------------------------------------------------------===//
#ifndef CLANG_ANALYSIS_FLOWSENSITIVE_MODELS_UNCHECKEDOPTIONALACCESSMODEL_H
#define CLANG_ANALYSIS_FLOWSENSITIVE_MODELS_UNCHECKEDOPTIONALACCESSMODEL_H
#include "clang/AST/ASTContext.h"
#include "clang/AST/Stmt.h"
#include "clang/Analysis/FlowSensitive/DataflowAnalysis.h"
#include "clang/Analysis/FlowSensitive/DataflowEnvironment.h"
#include "clang/Analysis/FlowSensitive/MatchSwitch.h"
#include "clang/Analysis/FlowSensitive/NoopLattice.h"
#include "clang/Basic/SourceLocation.h"
#include <vector>
namespace clang {
namespace dataflow {
// FIXME: Explore using an allowlist-approach, where constructs supported by the
// analysis are always enabled and additional constructs are enabled through the
// `Options`.
struct UncheckedOptionalAccessModelOptions {
/// Ignore optionals reachable through overloaded `operator*` or `operator->`
/// (other than those of the optional type itself). The analysis does not
/// equate the results of such calls, so it can't identify when their results
/// are used safely (across calls), resulting in false positives in all such
/// cases. Note: this option does not cover access through `operator[]`.
bool IgnoreSmartPointerDereference = false;
};
/// Dataflow analysis that models whether optionals hold values or not.
///
/// Models the `std::optional`, `absl::optional`, and `base::Optional` types.
class UncheckedOptionalAccessModel
: public DataflowAnalysis<UncheckedOptionalAccessModel, NoopLattice> {
public:
UncheckedOptionalAccessModel(
ASTContext &AstContext, UncheckedOptionalAccessModelOptions Options = {});
/// Returns a matcher for the optional classes covered by this model.
static ast_matchers::DeclarationMatcher optionalClassDecl();
static NoopLattice initialElement() { return {}; }
void transfer(const Stmt *Stmt, NoopLattice &State, Environment &Env);
bool compareEquivalent(QualType Type, const Value &Val1,
const Environment &Env1, const Value &Val2,
const Environment &Env2) override;
bool merge(QualType Type, const Value &Val1, const Environment &Env1,
const Value &Val2, const Environment &Env2, Value &MergedVal,
Environment &MergedEnv) override;
private:
MatchSwitch<TransferState<NoopLattice>> TransferMatchSwitch;
};
class UncheckedOptionalAccessDiagnoser {
public:
UncheckedOptionalAccessDiagnoser(
UncheckedOptionalAccessModelOptions Options = {});
std::vector<SourceLocation> diagnose(ASTContext &Context, const Stmt *Stmt,
const Environment &Env);
private:
MatchSwitch<const Environment, std::vector<SourceLocation>>
DiagnoseMatchSwitch;
};
} // namespace dataflow
} // namespace clang
#endif // CLANG_ANALYSIS_FLOWSENSITIVE_MODELS_UNCHECKEDOPTIONALACCESSMODEL_H
@@ -0,0 +1,41 @@
//===-- NoopLattice.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
//
//===----------------------------------------------------------------------===//
//
// This file defines the lattice with exactly one element.
//
//===----------------------------------------------------------------------===//
#ifndef LLVM_CLANG_ANALYSIS_FLOWSENSITIVE_NOOP_LATTICE_H
#define LLVM_CLANG_ANALYSIS_FLOWSENSITIVE_NOOP_LATTICE_H
#include "clang/Analysis/FlowSensitive/DataflowLattice.h"
#include <ostream>
namespace clang {
namespace dataflow {
/// Trivial lattice for dataflow analysis with exactly one element.
///
/// Useful for analyses that only need the Environment and nothing more.
class NoopLattice {
public:
bool operator==(const NoopLattice &Other) const { return true; }
LatticeJoinEffect join(const NoopLattice &Other) {
return LatticeJoinEffect::Unchanged;
}
};
inline std::ostream &operator<<(std::ostream &OS, const NoopLattice &) {
return OS << "noop";
}
} // namespace dataflow
} // namespace clang
#endif // LLVM_CLANG_ANALYSIS_FLOWSENSITIVE_NOOP_LATTICE_H
@@ -0,0 +1,56 @@
//===- Solver.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
//
//===----------------------------------------------------------------------===//
//
// This file defines an interface for a SAT solver that can be used by
// dataflow analyses.
//
//===----------------------------------------------------------------------===//
#ifndef LLVM_CLANG_ANALYSIS_FLOWSENSITIVE_SOLVER_H
#define LLVM_CLANG_ANALYSIS_FLOWSENSITIVE_SOLVER_H
#include "clang/Analysis/FlowSensitive/Value.h"
#include "llvm/ADT/DenseSet.h"
namespace clang {
namespace dataflow {
/// An interface for a SAT solver that can be used by dataflow analyses.
class Solver {
public:
enum class Result {
/// Indicates that there exists a satisfying assignment for a boolean
/// formula.
Satisfiable,
/// Indicates that there is no satisfying assignment for a boolean formula.
Unsatisfiable,
/// Indicates that the solver gave up trying to find a satisfying assignment
/// for a boolean formula.
TimedOut,
};
virtual ~Solver() = default;
/// Checks if the conjunction of `Vals` is satisfiable and returns the
/// corresponding result.
///
/// Requirements:
///
/// All elements in `Vals` must not be null.
///
/// FIXME: Consider returning a model in case the conjunction of `Vals` is
/// satisfiable so that it can be used to generate warning messages.
virtual Result solve(llvm::DenseSet<BoolValue *> Vals) = 0;
};
} // namespace dataflow
} // namespace clang
#endif // LLVM_CLANG_ANALYSIS_FLOWSENSITIVE_SOLVER_H
@@ -31,6 +31,12 @@ class StorageLocation {
StorageLocation(Kind LocKind, QualType Type) : LocKind(LocKind), Type(Type) {}
// Non-copyable because addresses of storage locations are used as their
// identities throughout framework and user code. The framework is responsible
// for construction and destruction of storage locations.
StorageLocation(const StorageLocation &) = delete;
StorageLocation &operator=(const StorageLocation &) = delete;
virtual ~StorageLocation() = default;
Kind getKind() const { return LocKind; }
@@ -56,7 +62,9 @@ class ScalarStorageLocation final : public StorageLocation {
/// A storage location which is subdivided into smaller storage locations that
/// can be traced independently by abstract interpretation. For example: a
/// struct with public members.
/// 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.
class AggregateStorageLocation final : public StorageLocation {
public:
explicit AggregateStorageLocation(QualType Type)
@@ -20,12 +20,23 @@
namespace clang {
namespace dataflow {
/// Maps statements to the environments of basic blocks that contain them.
class StmtToEnvMap {
public:
virtual ~StmtToEnvMap() = default;
/// 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;
};
/// Evaluates `S` and updates `Env` accordingly.
///
/// Requirements:
///
/// The type of `S` must not be `ParenExpr`.
void transfer(const Stmt &S, Environment &Env);
/// `S` must not be `ParenExpr` or `ExprWithCleanups`.
void transfer(const StmtToEnvMap &StmtToEnv, const Stmt &S, Environment &Env);
} // namespace dataflow
} // namespace clang
@@ -115,13 +115,17 @@ TypeErasedDataflowAnalysisState transferBlock(
HandleTransferredStmt = nullptr);
/// Performs dataflow analysis and returns a mapping from basic block IDs to
/// dataflow analysis states that model the respective basic blocks. Indices
/// of the returned vector correspond to basic block IDs. Returns an error if
/// the dataflow analysis cannot be performed successfully.
/// dataflow analysis states that model the respective basic blocks. Indices of
/// the returned vector correspond to basic block IDs. Returns an error if the
/// dataflow analysis cannot be performed successfully. Otherwise, calls
/// `PostVisitStmt` on each statement with the final analysis results at that
/// program point.
llvm::Expected<std::vector<llvm::Optional<TypeErasedDataflowAnalysisState>>>
runTypeErasedDataflowAnalysis(const ControlFlowContext &CFCtx,
TypeErasedDataflowAnalysis &Analysis,
const Environment &InitEnv);
runTypeErasedDataflowAnalysis(
const ControlFlowContext &CFCtx, TypeErasedDataflowAnalysis &Analysis,
const Environment &InitEnv,
std::function<void(const Stmt *, const TypeErasedDataflowAnalysisState &)>
PostVisitStmt = nullptr);
} // namespace dataflow
} // namespace clang
@@ -26,100 +26,37 @@ namespace clang {
namespace dataflow {
/// Base class for all values computed by abstract interpretation.
///
/// Don't use `Value` instances by value. All `Value` instances are allocated
/// and owned by `DataflowAnalysisContext`.
class Value {
public:
enum class Kind { Bool, Integer, Reference, Pointer, Struct };
enum class Kind {
Integer,
Reference,
Pointer,
Struct,
// Synthetic boolean values are either atomic values or composites that
// represent conjunctions, disjunctions, and negations.
AtomicBool,
Conjunction,
Disjunction,
Negation
};
explicit Value(Kind ValKind) : ValKind(ValKind) {}
// Non-copyable because addresses of values are used as their identities
// throughout framework and user code. The framework is responsible for
// construction and destruction of values.
Value(const Value &) = delete;
Value &operator=(const Value &) = delete;
virtual ~Value() = default;
Kind getKind() const { return ValKind; }
private:
Kind ValKind;
};
/// Models a boolean.
class BoolValue : public Value {
public:
explicit BoolValue() : Value(Kind::Bool) {}
static bool classof(const Value *Val) { return Val->getKind() == Kind::Bool; }
};
/// Models an integer.
class IntegerValue : public Value {
public:
explicit IntegerValue() : Value(Kind::Integer) {}
static bool classof(const Value *Val) {
return Val->getKind() == Kind::Integer;
}
};
/// Base class for values that refer to storage locations.
class IndirectionValue : public Value {
public:
/// Constructs a value that refers to `PointeeLoc`.
explicit IndirectionValue(Kind ValueKind, StorageLocation &PointeeLoc)
: Value(ValueKind), PointeeLoc(PointeeLoc) {}
static bool classof(const Value *Val) {
return Val->getKind() == Kind::Reference || Val->getKind() == Kind::Pointer;
}
StorageLocation &getPointeeLoc() const { return PointeeLoc; }
private:
StorageLocation &PointeeLoc;
};
/// Models a dereferenced pointer. For example, a reference in C++ or an lvalue
/// in C.
class ReferenceValue final : public IndirectionValue {
public:
explicit ReferenceValue(StorageLocation &PointeeLoc)
: IndirectionValue(Kind::Reference, PointeeLoc) {}
static bool classof(const Value *Val) {
return Val->getKind() == Kind::Reference;
}
};
/// Models a symbolic pointer. Specifically, any value of type `T*`.
class PointerValue final : public IndirectionValue {
public:
explicit PointerValue(StorageLocation &PointeeLoc)
: IndirectionValue(Kind::Pointer, PointeeLoc) {}
static bool classof(const Value *Val) {
return Val->getKind() == Kind::Pointer;
}
};
/// Models a value of `struct` or `class` type.
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)) {}
static bool classof(const Value *Val) {
return Val->getKind() == Kind::Struct;
}
/// Returns the child value that is assigned for `D`.
Value &getChild(const ValueDecl &D) const {
auto It = Children.find(&D);
assert(It != Children.end());
return *It->second;
}
/// Assigns `Val` as the child value for `D`.
void setChild(const ValueDecl &D, Value &Val) { Children[&D] = &Val; }
/// 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 {
@@ -134,10 +71,170 @@ class StructValue final : public Value {
}
private:
llvm::DenseMap<const ValueDecl *, Value *> Children;
Kind ValKind;
llvm::StringMap<Value *> Properties;
};
/// Models a boolean.
class BoolValue : public Value {
public:
explicit BoolValue(Kind ValueKind) : Value(ValueKind) {}
static bool classof(const Value *Val) {
return Val->getKind() == Kind::AtomicBool ||
Val->getKind() == Kind::Conjunction ||
Val->getKind() == Kind::Disjunction ||
Val->getKind() == Kind::Negation;
}
};
/// Models an atomic boolean.
class AtomicBoolValue : public BoolValue {
public:
explicit AtomicBoolValue() : BoolValue(Kind::AtomicBool) {}
static bool classof(const Value *Val) {
return Val->getKind() == Kind::AtomicBool;
}
};
/// 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 {
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;
}
/// 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;
}
/// 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 an integer.
class IntegerValue : public Value {
public:
explicit IntegerValue() : Value(Kind::Integer) {}
static bool classof(const Value *Val) {
return Val->getKind() == Kind::Integer;
}
};
/// Models a dereferenced pointer. For example, a reference in C++ or an lvalue
/// in C.
class ReferenceValue final : public Value {
public:
explicit ReferenceValue(StorageLocation &ReferentLoc)
: Value(Kind::Reference), ReferentLoc(ReferentLoc) {}
static bool classof(const Value *Val) {
return Val->getKind() == Kind::Reference;
}
StorageLocation &getReferentLoc() const { return ReferentLoc; }
private:
StorageLocation &ReferentLoc;
};
/// Models a symbolic pointer. Specifically, any value of type `T*`.
class PointerValue final : public Value {
public:
explicit PointerValue(StorageLocation &PointeeLoc)
: Value(Kind::Pointer), PointeeLoc(PointeeLoc) {}
static bool classof(const Value *Val) {
return Val->getKind() == Kind::Pointer;
}
StorageLocation &getPointeeLoc() const { return PointeeLoc; }
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.
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)) {}
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;
}
/// 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;
};
} // namespace dataflow
} // namespace clang
@@ -0,0 +1,37 @@
//===- WatchedLiteralsSolver.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
//
//===----------------------------------------------------------------------===//
//
// This file defines a SAT solver implementation that can be used by dataflow
// analyses.
//
//===----------------------------------------------------------------------===//
#ifndef LLVM_CLANG_ANALYSIS_FLOWSENSITIVE_WATCHEDLITERALSSOLVER_H
#define LLVM_CLANG_ANALYSIS_FLOWSENSITIVE_WATCHEDLITERALSSOLVER_H
#include "clang/Analysis/FlowSensitive/Solver.h"
#include "clang/Analysis/FlowSensitive/Value.h"
#include "llvm/ADT/DenseSet.h"
namespace clang {
namespace dataflow {
/// A SAT solver that is an implementation of Algorithm D from Knuth's The Art
/// of Computer Programming Volume 4: Satisfiability, Fascicle 6. It is based on
/// the Davis-Putnam-Logemann-Loveland (DPLL) algorithm, keeps references to a
/// single "watched" literal per clause, and uses a set of "active" variables
/// for unit propagation.
class WatchedLiteralsSolver : public Solver {
public:
Result solve(llvm::DenseSet<BoolValue *> Vals) override;
};
} // namespace dataflow
} // namespace clang
#endif // LLVM_CLANG_ANALYSIS_FLOWSENSITIVE_WATCHEDLITERALSSOLVER_H
@@ -544,15 +544,13 @@ class PathDiagnosticEventPiece : public PathDiagnosticSpotPiece {
/// flag may have been previously set, at which point it will not
/// be reset unless one specifies to do so.
void setPrunable(bool isPrunable, bool override = false) {
if (IsPrunable.hasValue() && !override)
return;
if (IsPrunable && !override)
return;
IsPrunable = isPrunable;
}
/// Return true if the diagnostic piece is prunable.
bool isPrunable() const {
return IsPrunable.getValueOr(false);
}
bool isPrunable() const { return IsPrunable.value_or(false); }
void dump() const override;
@@ -19,10 +19,19 @@ def DocCatType : DocumentationCategory<"Type Attributes">;
def DocCatStmt : DocumentationCategory<"Statement Attributes">;
def DocCatDecl : DocumentationCategory<"Declaration Attributes">;
// Attributes listed under the Undocumented category do not generate any public
// documentation. Ideally, this category should be used for internal-only
// attributes which contain no spellings.
def DocCatUndocumented : DocumentationCategory<"Undocumented">;
// This category is for attributes which have not yet been properly documented,
// but should be.
def DocCatUndocumented : DocumentationCategory<"Undocumented"> {
let Content = [{
This section lists attributes which are recognized by Clang, but which are
currently missing documentation.
}];
}
// Attributes listed under the InternalOnly category do not generate any entry
// in the documentation. This category should be used only when we _want_
// to not document the attribute, e.g. if the attribute has no spellings.
def DocCatInternalOnly : DocumentationCategory<"InternalOnly">;
class DocDeprecated<string replacement = ""> {
// If the Replacement field is empty, no replacement will be listed with the
@@ -48,11 +57,17 @@ class Documentation {
DocDeprecated Deprecated;
}
// Specifies that the attribute is explicitly undocumented. This can be a
// helpful placeholder for the attribute while working on the implementation,
// but should not be used once feature work has been completed.
// Specifies that the attribute is explicitly omitted from the documentation,
// because it is not intended to be user-facing.
def InternalOnly : Documentation {
let Category = DocCatInternalOnly;
}
// Specifies that the attribute is undocumented, but that it _should_ have
// documentation.
def Undocumented : Documentation {
let Category = DocCatUndocumented;
let Content = "No documentation.";
}
include "clang/Basic/AttrDocs.td"
@@ -126,6 +141,11 @@ def FunctionTmpl
FunctionDecl::TK_FunctionTemplate}],
"function templates">;
def HLSLEntry
: SubsetSubject<Function,
[{S->isExternallyVisible() && !isa<CXXMethodDecl>(S)}],
"global functions">;
def ClassTmpl : SubsetSubject<CXXRecord, [{S->getDescribedClassTemplate()}],
"class templates">;
@@ -295,6 +315,9 @@ class Clang<string name, bit allowInC = 1> : Spelling<name, "Clang"> {
bit AllowInC = allowInC;
}
// HLSL Semantic spellings
class HLSLSemantic<string name> : Spelling<name, "HLSLSemantic">;
class Accessor<string name, list<Spelling> spellings> {
string Name = name;
list<Spelling> Spellings = spellings;
@@ -336,6 +359,8 @@ def ObjCAutoRefCount : LangOpt<"ObjCAutoRefCount">;
def ObjCNonFragileRuntime
: LangOpt<"", "LangOpts.ObjCRuntime.allowsClassStubs()">;
def HLSL : LangOpt<"HLSL">;
// Language option for CMSE extensions
def Cmse : LangOpt<"Cmse">;
@@ -541,6 +566,8 @@ class Attr {
// match rules.
// - It has GNU/CXX11 spelling and doesn't require delayed parsing.
bit PragmaAttributeSupport;
// Set to true if this attribute accepts parameter pack expansion expressions.
bit AcceptsExprPack = 0;
// Lists language options, one of which is required to be true for the
// attribute to be applicable. If empty, no language options are required.
list<LangOpt> LangOpts = [];
@@ -614,7 +641,7 @@ class IgnoredAttr : Attr {
let Ignored = 1;
let ASTNode = 0;
let SemaHandler = 0;
let Documentation = [Undocumented];
let Documentation = [InternalOnly];
}
//
@@ -694,19 +721,23 @@ def AlignMac68k : InheritableAttr {
// This attribute has no spellings as it is only ever created implicitly.
let Spellings = [];
let SemaHandler = 0;
let Documentation = [Undocumented];
let Documentation = [InternalOnly];
}
def AlignNatural : InheritableAttr {
// This attribute has no spellings as it is only ever created implicitly.
let Spellings = [];
let SemaHandler = 0;
let Documentation = [Undocumented];
let Documentation = [InternalOnly];
}
def AlwaysInline : InheritableAttr {
let Spellings = [GCC<"always_inline">, Keyword<"__forceinline">];
let Subjects = SubjectList<[Function]>;
def AlwaysInline : DeclOrStmtAttr {
let Spellings = [GCC<"always_inline">, CXX11<"clang", "always_inline">,
C2x<"clang", "always_inline">, Keyword<"__forceinline">];
let Accessors = [Accessor<"isClangAlwaysInline", [CXX11<"clang", "always_inline">,
C2x<"clang", "always_inline">]>];
let Subjects = SubjectList<[Function, Stmt], WarnDiag,
"functions and statements">;
let Documentation = [AlwaysInlineDocs];
}
@@ -784,9 +815,18 @@ def Annotate : InheritableParamAttr {
}
}];
let PragmaAttributeSupport = 1;
let AcceptsExprPack = 1;
let Documentation = [Undocumented];
}
def AnnotateType : TypeAttr {
let Spellings = [CXX11<"clang", "annotate_type">, C2x<"clang", "annotate_type">];
let Args = [StringArgument<"Annotation">, VariadicExprArgument<"Args">];
let HasCustomParsing = 1;
let AcceptsExprPack = 1;
let Documentation = [AnnotateTypeDocs];
}
def ARMInterrupt : InheritableAttr, TargetSpecificAttr<TargetARM> {
// NOTE: If you add any additional spellings, M68kInterrupt's,
// MSP430Interrupt's, MipsInterrupt's and AnyX86Interrupt's spellings
@@ -853,6 +893,7 @@ def Availability : InheritableAttr {
.Case("macos", "macOS")
.Case("tvos", "tvOS")
.Case("watchos", "watchOS")
.Case("driverkit", "DriverKit")
.Case("ios_app_extension", "iOS (App Extension)")
.Case("macos_app_extension", "macOS (App Extension)")
.Case("tvos_app_extension", "tvOS (App Extension)")
@@ -1162,7 +1203,7 @@ def CUDAInvalidTarget : InheritableAttr {
let Spellings = [];
let Subjects = SubjectList<[Function]>;
let LangOpts = [CUDA];
let Documentation = [Undocumented];
let Documentation = [InternalOnly];
}
def CUDALaunchBounds : InheritableAttr {
@@ -1206,10 +1247,10 @@ def C11NoReturn : InheritableAttr {
}
def CXX11NoReturn : InheritableAttr {
let Spellings = [CXX11<"", "noreturn", 200809>];
let Spellings = [CXX11<"", "noreturn", 200809>,
C2x<"", "noreturn", 202202>, C2x<"", "_Noreturn", 202202>];
let Subjects = SubjectList<[Function], ErrorDiag>;
let Documentation = [CXX11NoReturnDocs];
let SimpleHandler = 1;
}
// Similar to CUDA, OpenCL attributes do not receive a [[]] spelling because
@@ -1387,7 +1428,6 @@ def : MutualExclusions<[Likely, Unlikely]>;
def NoMerge : DeclOrStmtAttr {
let Spellings = [Clang<"nomerge">];
let Documentation = [NoMergeDocs];
let InheritEvenIfAlreadyPresent = 1;
let Subjects = SubjectList<[Function, Stmt], ErrorDiag,
"functions and statements">;
let SimpleHandler = 1;
@@ -1415,13 +1455,15 @@ def Final : InheritableAttr {
let Spellings = [Keyword<"final">, Keyword<"sealed">];
let Accessors = [Accessor<"isSpelledAsSealed", [Keyword<"sealed">]>];
let SemaHandler = 0;
let Documentation = [Undocumented];
// Omitted from docs, since this is language syntax, not an attribute, as far
// as users are concerned.
let Documentation = [InternalOnly];
}
def MinSize : InheritableAttr {
let Spellings = [Clang<"minsize">];
let Subjects = SubjectList<[Function, ObjCMethod], ErrorDiag>;
let Documentation = [Undocumented];
let Documentation = [MinSizeDocs];
}
def FlagEnum : InheritableAttr {
@@ -1477,8 +1519,6 @@ def GNUInline : InheritableAttr {
def Hot : InheritableAttr {
let Spellings = [GCC<"hot">];
let Subjects = SubjectList<[Function]>;
// An AST node is created for this attribute, but not actually used beyond
// semantic checking for mutual exclusion with the Cold attribute.
let Documentation = [Undocumented];
let SimpleHandler = 1;
}
@@ -1557,7 +1597,7 @@ def MaxFieldAlignment : InheritableAttr {
let Spellings = [];
let Args = [UnsignedArgument<"Alignment">];
let SemaHandler = 0;
let Documentation = [Undocumented];
let Documentation = [InternalOnly];
}
def MayAlias : InheritableAttr {
@@ -1758,10 +1798,15 @@ def Convergent : InheritableAttr {
let SimpleHandler = 1;
}
def NoInline : InheritableAttr {
let Spellings = [GCC<"noinline">, Declspec<"noinline">];
let Subjects = SubjectList<[Function]>;
let Documentation = [Undocumented];
def NoInline : DeclOrStmtAttr {
let Spellings = [Keyword<"__noinline__">, GCC<"noinline">,
CXX11<"clang", "noinline">, C2x<"clang", "noinline">,
Declspec<"noinline">];
let Accessors = [Accessor<"isClangNoInline", [CXX11<"clang", "noinline">,
C2x<"clang", "noinline">]>];
let Documentation = [NoInlineDocs];
let Subjects = SubjectList<[Function, Stmt], WarnDiag,
"functions and statements">;
let SimpleHandler = 1;
}
@@ -1835,6 +1880,11 @@ def AMDGPUNumVGPR : InheritableAttr {
let Subjects = SubjectList<[Function], ErrorDiag, "kernel functions">;
}
def AMDGPUKernelCall : DeclOrTypeAttr {
let Spellings = [Clang<"amdgpu_kernel">];
let Documentation = [Undocumented];
}
def BPFPreserveAccessIndex : InheritableAttr,
TargetSpecificAttr<TargetBPF> {
let Spellings = [Clang<"preserve_access_index">];
@@ -1899,9 +1949,9 @@ def NonNull : InheritableParamAttr {
bool isNonNull(unsigned IdxAST) const {
if (!args_size())
return true;
return args_end() != std::find_if(
args_begin(), args_end(),
[=](const ParamIdx &Idx) { return Idx.getASTIndex() == IdxAST; });
return llvm::any_of(args(), [=](const ParamIdx &Idx) {
return Idx.getASTIndex() == IdxAST;
});
}
}];
// FIXME: We should merge duplicates into a single nonnull attribute.
@@ -1959,7 +2009,7 @@ def TypeNullUnspecified : TypeAttr {
// qualifier is as an ObjCOwnership attribute with Kind == "none".
def ObjCInertUnsafeUnretained : TypeAttr {
let Spellings = [Keyword<"__unsafe_unretained">];
let Documentation = [Undocumented];
let Documentation = [InternalOnly];
}
def ObjCKindOf : TypeAttr {
@@ -2243,7 +2293,9 @@ def Overloadable : Attr {
def Override : InheritableAttr {
let Spellings = [Keyword<"override">];
let SemaHandler = 0;
let Documentation = [Undocumented];
// Omitted from docs, since this is language syntax, not an attribute, as far
// as users are concerned.
let Documentation = [InternalOnly];
}
def Ownership : InheritableAttr {
@@ -2292,6 +2344,11 @@ def AArch64VectorPcs: DeclOrTypeAttr {
let Documentation = [AArch64VectorPcsDocs];
}
def AArch64SVEPcs: DeclOrTypeAttr {
let Spellings = [Clang<"aarch64_sve_pcs">];
let Documentation = [AArch64SVEPcsDocs];
}
def Pure : InheritableAttr {
let Spellings = [GCC<"pure">];
let Documentation = [Undocumented];
@@ -2427,7 +2484,7 @@ def PragmaClangBSSSection : InheritableAttr {
let Spellings = [];
let Args = [StringArgument<"Name">];
let Subjects = SubjectList<[GlobalVar], ErrorDiag>;
let Documentation = [Undocumented];
let Documentation = [InternalOnly];
}
def PragmaClangDataSection : InheritableAttr {
@@ -2435,7 +2492,7 @@ def PragmaClangDataSection : InheritableAttr {
let Spellings = [];
let Args = [StringArgument<"Name">];
let Subjects = SubjectList<[GlobalVar], ErrorDiag>;
let Documentation = [Undocumented];
let Documentation = [InternalOnly];
}
def PragmaClangRodataSection : InheritableAttr {
@@ -2443,7 +2500,7 @@ def PragmaClangRodataSection : InheritableAttr {
let Spellings = [];
let Args = [StringArgument<"Name">];
let Subjects = SubjectList<[GlobalVar], ErrorDiag>;
let Documentation = [Undocumented];
let Documentation = [InternalOnly];
}
def PragmaClangRelroSection : InheritableAttr {
@@ -2451,7 +2508,7 @@ def PragmaClangRelroSection : InheritableAttr {
let Spellings = [];
let Args = [StringArgument<"Name">];
let Subjects = SubjectList<[GlobalVar], ErrorDiag>;
let Documentation = [Undocumented];
let Documentation = [InternalOnly];
}
def StrictFP : InheritableAttr {
@@ -2459,7 +2516,7 @@ def StrictFP : InheritableAttr {
// Function uses strict floating point operations.
let Spellings = [];
let Subjects = SubjectList<[Function]>;
let Documentation = [Undocumented];
let Documentation = [InternalOnly];
}
def PragmaClangTextSection : InheritableAttr {
@@ -2467,7 +2524,7 @@ def PragmaClangTextSection : InheritableAttr {
let Spellings = [];
let Args = [StringArgument<"Name">];
let Subjects = SubjectList<[Function], ErrorDiag>;
let Documentation = [Undocumented];
let Documentation = [InternalOnly];
}
def Sentinel : InheritableAttr {
@@ -2561,6 +2618,19 @@ def VectorCall : DeclOrTypeAttr {
let Documentation = [VectorCallDocs];
}
def ZeroCallUsedRegs : InheritableAttr {
let Spellings = [GCC<"zero_call_used_regs">];
let Subjects = SubjectList<[Function], ErrorDiag>;
let Args = [
EnumArgument<"ZeroCallUsedRegs", "ZeroCallUsedRegsKind",
["skip", "used-gpr-arg", "used-gpr", "used-arg", "used",
"all-gpr-arg", "all-gpr", "all-arg", "all"],
["Skip", "UsedGPRArg", "UsedGPR", "UsedArg", "Used",
"AllGPRArg", "AllGPR", "AllArg", "All"]>
];
let Documentation = [ZeroCallUsedRegsDocs];
}
def Pascal : DeclOrTypeAttr {
let Spellings = [Clang<"pascal">, Keyword<"__pascal">, Keyword<"_pascal">];
// let Subjects = [Function, ObjCMethod];
@@ -2693,8 +2763,12 @@ def TargetClones : InheritableAttr {
StringRef getFeatureStr(unsigned Index) const {
return *(featuresStrs_begin() + Index);
}
// 'default' is always moved to the end, so it isn't considered
// when mangling the index.
// Given an index into the 'featuresStrs' sequence, compute a unique
// ID to be used with function name mangling for the associated variant.
// This mapping is necessary due to a requirement that the mangling ID
// used for the "default" variant be the largest mangling ID in the
// variant set. Duplicate variants present in 'featuresStrs' are also
// assigned their own unique ID (the mapping is bijective).
unsigned getMangledIndex(unsigned Index) const {
if (getFeatureStr(Index) == "default")
return std::count_if(featuresStrs_begin(), featuresStrs_end(),
@@ -2704,9 +2778,10 @@ def TargetClones : InheritableAttr {
[](StringRef S) { return S != "default"; });
}
// True if this is the first of this version to appear in the config string.
// This is used to make sure we don't try to emit this function multiple
// times.
// Given an index into the 'featuresStrs' sequence, determine if the
// index corresponds to the first instance of the named variant. This
// is used to skip over duplicate variant instances when iterating over
// 'featuresStrs'.
bool isFirstOfVersion(unsigned Index) const {
StringRef FeatureStr(getFeatureStr(Index));
return 0 == std::count_if(
@@ -2894,7 +2969,7 @@ def WarnUnusedResult : InheritableAttr {
C2x<"", "nodiscard", 201904>,
CXX11<"clang", "warn_unused_result">,
GCC<"warn_unused_result">];
let Subjects = SubjectList<[ObjCMethod, Enum, Record, FunctionLike]>;
let Subjects = SubjectList<[ObjCMethod, Enum, Record, FunctionLike, TypedefName]>;
let Args = [StringArgument<"Message", 1>];
let Documentation = [WarnUnusedResultsDocs];
let AdditionalMembers = [{
@@ -2909,7 +2984,7 @@ def WarnUnusedResult : InheritableAttr {
def Weak : InheritableAttr {
let Spellings = [GCC<"weak">];
let Subjects = SubjectList<[Var, Function, CXXRecord]>;
let Documentation = [Undocumented];
let Documentation = [WeakDocs];
let SimpleHandler = 1;
}
@@ -3438,7 +3513,7 @@ def DLLExportStaticLocal : InheritableAttr, TargetSpecificAttr<TargetHasDLLImpor
// the function has local static variables, the function is dllexported too.
let Spellings = [];
let Subjects = SubjectList<[Function]>;
let Documentation = [Undocumented];
let Documentation = [InternalOnly];
}
def DLLImport : InheritableAttr, TargetSpecificAttr<TargetHasDLLImportExport> {
@@ -3464,7 +3539,7 @@ def DLLImportStaticLocal : InheritableAttr, TargetSpecificAttr<TargetHasDLLImpor
// attribute is used to determine whether the variables are imported or not.
let Spellings = [];
let Subjects = SubjectList<[Function]>;
let Documentation = [Undocumented];
let Documentation = [InternalOnly];
}
def SelectAny : InheritableAttr {
@@ -3530,7 +3605,7 @@ def MSVtorDisp : InheritableAttr {
let AdditionalMembers = [{
MSVtorDispMode getVtorDispMode() const { return MSVtorDispMode(vdm); }
}];
let Documentation = [Undocumented];
let Documentation = [InternalOnly];
}
def InitSeg : Attr {
@@ -3622,21 +3697,21 @@ def CapturedRecord : InheritableAttr {
// This attribute has no spellings as it is only ever created implicitly.
let Spellings = [];
let SemaHandler = 0;
let Documentation = [Undocumented];
let Documentation = [InternalOnly];
}
def OMPThreadPrivateDecl : InheritableAttr {
// This attribute has no spellings as it is only ever created implicitly.
let Spellings = [];
let SemaHandler = 0;
let Documentation = [Undocumented];
let Documentation = [InternalOnly];
}
def OMPCaptureNoInit : InheritableAttr {
// This attribute has no spellings as it is only ever created implicitly.
let Spellings = [];
let SemaHandler = 0;
let Documentation = [Undocumented];
let Documentation = [InternalOnly];
}
def OMPCaptureKind : Attr {
@@ -3644,7 +3719,7 @@ def OMPCaptureKind : Attr {
let Spellings = [];
let SemaHandler = 0;
let Args = [UnsignedArgument<"CaptureKindVal">];
let Documentation = [Undocumented];
let Documentation = [InternalOnly];
let AdditionalMembers = [{
llvm::omp::Clause getCaptureKind() const {
return static_cast<llvm::omp::Clause>(getCaptureKindVal());
@@ -3657,7 +3732,7 @@ def OMPReferencedVar : Attr {
let Spellings = [];
let SemaHandler = 0;
let Args = [ExprArgument<"Ref">];
let Documentation = [Undocumented];
let Documentation = [InternalOnly];
}
def OMPDeclareSimdDecl : Attr {
@@ -3730,7 +3805,7 @@ def OMPAllocateDecl : InheritableAttr {
ExprArgument<"Allocator">,
ExprArgument<"Alignment">
];
let Documentation = [Undocumented];
let Documentation = [InternalOnly];
}
def OMPDeclareVariant : InheritableAttr {
@@ -3887,12 +3962,12 @@ def Builtin : InheritableAttr {
let Args = [UnsignedArgument<"ID">];
let Subjects = SubjectList<[Function]>;
let SemaHandler = 0;
let Documentation = [Undocumented];
let Documentation = [InternalOnly];
}
def EnforceTCB : InheritableAttr {
let Spellings = [Clang<"enforce_tcb">];
let Subjects = SubjectList<[Function]>;
let Subjects = SubjectList<[Function, ObjCMethod]>;
let Args = [StringArgument<"TCBName">];
let Documentation = [EnforceTCBDocs];
bit InheritEvenIfAlreadyPresent = 1;
@@ -3900,7 +3975,7 @@ def EnforceTCB : InheritableAttr {
def EnforceTCBLeaf : InheritableAttr {
let Spellings = [Clang<"enforce_tcb_leaf">];
let Subjects = SubjectList<[Function]>;
let Subjects = SubjectList<[Function, ObjCMethod]>;
let Args = [StringArgument<"TCBName">];
let Documentation = [EnforceTCBLeafDocs];
bit InheritEvenIfAlreadyPresent = 1;
@@ -3914,3 +3989,50 @@ def Error : InheritableAttr {
let Subjects = SubjectList<[Function], ErrorDiag>;
let Documentation = [ErrorAttrDocs];
}
def HLSLNumThreads: InheritableAttr {
let Spellings = [Microsoft<"numthreads">];
let Args = [IntArgument<"X">, IntArgument<"Y">, IntArgument<"Z">];
let Subjects = SubjectList<[HLSLEntry]>;
let LangOpts = [HLSL];
let Documentation = [NumThreadsDocs];
}
def HLSLSV_GroupIndex: InheritableAttr {
let Spellings = [HLSLSemantic<"SV_GroupIndex">];
let Subjects = SubjectList<[ParmVar, GlobalVar]>;
let LangOpts = [HLSL];
let Documentation = [HLSLSV_GroupIndexDocs];
}
def HLSLShader : InheritableAttr {
let Spellings = [Microsoft<"shader">];
let Subjects = SubjectList<[HLSLEntry]>;
let LangOpts = [HLSL];
let Args = [EnumArgument<"Type", "ShaderType",
["pixel", "vertex", "geometry", "hull", "domain",
"compute", "raygeneration", "intersection",
"anyhit", "closesthit", "miss", "callable", "mesh",
"amplification"],
["Pixel", "Vertex", "Geometry", "Hull", "Domain",
"Compute", "RayGeneration", "Intersection",
"AnyHit", "ClosestHit", "Miss", "Callable", "Mesh",
"Amplification"]
>];
let Documentation = [HLSLSV_ShaderTypeAttrDocs];
}
def RandomizeLayout : InheritableAttr {
let Spellings = [GCC<"randomize_layout">];
let Subjects = SubjectList<[Record]>;
let Documentation = [ClangRandomizeLayoutDocs];
let LangOpts = [COnly];
}
def NoRandomizeLayout : InheritableAttr {
let Spellings = [GCC<"no_randomize_layout">];
let Subjects = SubjectList<[Record]>;
let Documentation = [ClangRandomizeLayoutDocs];
let LangOpts = [COnly];
}
def : MutualExclusions<[RandomizeLayout, NoRandomizeLayout]>;
@@ -285,6 +285,17 @@ features that are required for the function to be called. The result of this is
that future processors execute the most restrictive version of the function the
new processor can execute.
In addition, unlike the ICC implementation of this feature, the selection of the
version does not consider the manufacturer or microarchitecture of the processor.
It tests solely the list of features that are both supported by the specified
processor and present in the compiler-rt library. This can be surprising at times,
as the runtime processor may be from a completely different manufacturer, as long
as it supports the same feature set.
This can additionally be surprising, as some processors are indistringuishable from
others based on the list of testable features. When this happens, the variant
is selected in an unspecified manner.
Function versions are defined with ``cpu_specific``, which takes one or more CPU
names as a parameter. For example:
@@ -487,10 +498,14 @@ pointer type.
def CXX11NoReturnDocs : Documentation {
let Category = DocCatFunction;
let Heading = "noreturn, _Noreturn";
let Content = [{
A function declared as ``[[noreturn]]`` shall not return to its caller. The
compiler will generate a diagnostic for a function declared as ``[[noreturn]]``
that appears to be capable of returning to its caller.
The ``[[_Noreturn]]`` spelling is deprecated and only exists to ease code
migration for code using ``[[noreturn]]`` after including ``<stdnoreturn.h>``.
}];
}
@@ -512,6 +527,33 @@ calls.
}];
}
def NoInlineDocs : Documentation {
let Category = DocCatFunction;
let Content = [{
This function attribute suppresses the inlining of a function at the call sites
of the function.
``[[clang::noinline]]`` spelling can be used as a statement attribute; other
spellings of the attribute are not supported on statements. If a statement is
marked ``[[clang::noinline]]`` and contains calls, those calls inside the
statement will not be inlined by the compiler.
``__noinline__`` can be used as a keyword in CUDA/HIP languages. This is to
avoid diagnostics due to usage of ``__attribute__((__noinline__))``
with ``__noinline__`` defined as a macro as ``__attribute__((noinline))``.
.. code-block:: c
int example(void) {
int r;
[[clang::noinline]] foo();
[[clang::noinline]] r = bar();
return r;
}
}];
}
def MustTailDocs : Documentation {
let Category = DocCatStmt;
let Content = [{
@@ -1513,6 +1555,10 @@ 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.
A declaration can typically be used even when deploying back to a platform
version prior to when the declaration was introduced. When this happens, the
@@ -2509,6 +2555,32 @@ the Arm Developer website.
}];
}
def AArch64SVEPcsDocs : Documentation {
let Category = DocCatCallingConvs;
let Content = [{
On AArch64 targets, this attribute changes the calling convention of a
function to preserve additional Scalable Vector registers and Scalable
Predicate registers relative to the default calling convention used for
AArch64.
This means it is more efficient to call such functions from code that performs
extensive scalable vector and scalable predicate calculations, because fewer
live SVE registers need to be saved. This property makes it well-suited for SVE
math library functions, which are typically leaf functions that require a small
number of registers.
However, using this attribute also means that it is more expensive to call
a function that adheres to the default calling convention from within such
a function. Therefore, it is recommended that this attribute is only used
for leaf functions.
For more information, see the documentation for `aarch64_sve_pcs` in the
ARM C Language Extension (ACLE) documentation.
.. _`aarch64_sve_pcs`: https://github.com/ARM-software/acle/blob/main/main/acle.md#scalable-vector-extension-procedure-call-standard-attribute
}];
}
def RegparmDocs : Documentation {
let Category = DocCatCallingConvs;
let Content = [{
@@ -3295,6 +3367,9 @@ If a type is trivial for the purposes of calls, has a non-trivial destructor,
and is passed as an argument by value, the convention is that the callee will
destroy the object before returning.
If a type is trivial for the purpose of calls, it is assumed to be trivially
relocatable for the purpose of ``__is_trivially_relocatable``.
Attribute ``trivial_abi`` has no effect in the following cases:
- The class directly declares a virtual base or virtual methods.
@@ -3813,10 +3888,10 @@ completion handler in a Swift async method. For instance, here:
This method asynchronously calls ``completionHandler`` when the data is
available, or calls it with an error. ``_Nullable_result`` indicates to the
Swift importer that this is the uncommon case where ``result`` can get ``nil``
even if no error has occured, and will therefore import it as a Swift optional
even if no error has occurred, and will therefore import it as a Swift optional
type. Otherwise, if ``result`` was annotated with ``_Nullable``, the Swift
importer will assume that ``result`` will always be non-nil unless an error
occured.
occurred.
}];
}
@@ -4255,6 +4330,7 @@ Clang provides the following context selector extensions, used via
match_none
disable_implicit_base
allow_templates
bind_to_declaration
The match extensions change when the *entire* context selector is considered a
match for an OpenMP context. The default is ``all``, with ``none`` no trait in the
@@ -4270,8 +4346,9 @@ The allow extensions change when the ``begin declare variant`` effect is
applied to a definition. If ``allow_templates`` is given, template function
definitions are considered as specializations of existing or assumed template
declarations with the same name. The template parameters for the base functions
are used to instantiate the specialization.
are used to instantiate the specialization. If ``bind_to_declartion`` is given,
apply the same variant rules to function declarations. This allows the user to
override declarations with only a function declaration.
}];
}
@@ -5758,6 +5835,15 @@ attribute can also be written using C++11 syntax: ``[[mig::server_routine]]``.
}];
}
def MinSizeDocs : Documentation {
let Category = DocCatFunction;
let Content = [{
This function attribute indicates that optimization passes and code generator passes
make choices that keep the function code size as small as possible. Optimizations may
also sacrifice runtime performance in order to minimize the size of the generated code.
}];
}
def MSAllocatorDocs : Documentation {
let Category = DocCatFunction;
let Content = [{
@@ -5925,9 +6011,6 @@ attribute `clang_builtin_alias`.
def NoBuiltinDocs : Documentation {
let Category = DocCatFunction;
let Content = [{
.. Note:: This attribute is not yet fully implemented, it is validated but has
no effect on the generated code.
The ``__attribute__((no_builtin))`` is similar to the ``-fno-builtin`` flag
except it is specific to the body of a function. The attribute may also be
applied to a virtual function but has no effect on the behavior of overriding
@@ -6200,7 +6283,36 @@ def AlwaysInlineDocs : Documentation {
Inlining heuristics are disabled and inlining is always attempted regardless of
optimization level.
Does not guarantee that inline substitution actually occurs.
``[[clang::always_inline]]`` spelling can be used as a statement attribute; other
spellings of the attribute are not supported on statements. If a statement is
marked ``[[clang::always_inline]]`` and contains calls, the compiler attempts
to inline those calls.
.. code-block:: c
int example(void) {
int i;
[[clang::always_inline]] foo(); // attempts to inline foo
[[clang::always_inline]] i = bar(); // attempts to inline bar
[[clang::always_inline]] return f(42, baz(bar())); // attempts to inline everything
}
A declaration statement, which is a statement, is not a statement that can have an
attribute associated with it (the attribute applies to the declaration, not the
statement in that case). So this use case will not work:
.. code-block:: c
int example(void) {
[[clang::always_inline]] int i = bar();
return i;
}
This attribute does not guarantee that inline substitution actually occurs.
<ins>Note: applying this attribute to a coroutine at the `-O0` optimization level
has no effect; other optimization levels may only partially inline and result in a
diagnostic.</ins>
See also `the Microsoft Docs on Inline Functions`_, `the GCC Common Function
Attribute docs`_, and `the GCC Inline docs`_.
@@ -6263,3 +6375,216 @@ pointing to precise locations of the call site in the source.
}
}];
}
def ZeroCallUsedRegsDocs : Documentation {
let Category = DocCatFunction;
let Content = [{
This attribute, when attached to a function, causes the compiler to zero a
subset of all call-used registers before the function returns. It's used to
increase program security by either mitigating `Return-Oriented Programming`_
(ROP) attacks or preventing information leakage through registers.
The term "call-used" means registers which are not guaranteed to be preserved
unchanged for the caller by the current calling convention. This could also be
described as "caller-saved" or "not callee-saved".
The `choice` parameters gives the programmer flexibility to choose the subset
of the call-used registers to be zeroed:
- ``skip`` doesn't zero any call-used registers. This choice overrides any
command-line arguments.
- ``used`` only zeros call-used registers used in the function. By ``used``, we
mean a register whose contents have been set or referenced in the function.
- ``used-gpr`` only zeros call-used GPR registers used in the funciton.
- ``used-arg`` only zeros call-used registers used to pass arguments to the
function.
- ``used-gpr-arg`` only zeros call-used GPR registers used to pass arguments to
the function.
- ``all`` zeros all call-used registers.
- ``all-gpr`` zeros all call-used GPR registers.
- ``all-arg`` zeros all call-used registers used to pass arguments to the
function.
- ``all-gpr-arg`` zeros all call-used GPR registers used to pass arguments to
the function.
The default for the attribute is contolled by the ``-fzero-call-used-regs``
flag.
.. _Return-Oriented Programming: https://en.wikipedia.org/wiki/Return-oriented_programming
}];
}
def NumThreadsDocs : Documentation {
let Category = DocCatFunction;
let Content = [{
The ``numthreads`` attribute applies to HLSL shaders where explcit thread counts
are required. The ``X``, ``Y``, and ``Z`` values provided to the attribute
dictate the thread id. Total number of threads executed is ``X * Y * Z``.
The full documentation is available here: https://docs.microsoft.com/en-us/windows/win32/direct3dhlsl/sm5-attributes-numthreads
}];
}
def HLSLSV_ShaderTypeAttrDocs : Documentation {
let Category = DocCatFunction;
let Content = [{
The ``shader`` type attribute applies to HLSL shader entry functions to
identify the shader type for the entry function.
The syntax is:
.. code-block:: text
``[shader(string-literal)]``
where the string literal is one of: "pixel", "vertex", "geometry", "hull",
"domain", "compute", "raygeneration", "intersection", "anyhit", "closesthit",
"miss", "callable", "mesh", "amplification". Normally the shader type is set
by shader target with the ``-T`` option like ``-Tps_6_1``. When compiling to a
library target like ``lib_6_3``, the shader type attribute can help the
compiler to identify the shader type. It is mostly used by Raytracing shaders
where shaders must be compiled into a library and linked at runtime.
}];
}
def ClangRandomizeLayoutDocs : Documentation {
let Category = DocCatDecl;
let Heading = "randomize_layout, no_randomize_layout";
let Content = [{
The attribute ``randomize_layout``, when attached to a C structure, selects it
for structure layout field randomization; a compile-time hardening technique. A
"seed" value, is specified via the ``-frandomize-layout-seed=`` command line flag.
For example:
.. code-block:: bash
SEED=`od -A n -t x8 -N 32 /dev/urandom | tr -d ' \n'`
make ... CFLAGS="-frandomize-layout-seed=$SEED" ...
You can also supply the seed in a file with ``-frandomize-layout-seed-file=``.
For example:
.. code-block:: bash
od -A n -t x8 -N 32 /dev/urandom | tr -d ' \n' > /tmp/seed_file.txt
make ... CFLAGS="-frandomize-layout-seed-file=/tmp/seed_file.txt" ...
The randomization is deterministic based for a given seed, so the entire
program should be compiled with the same seed, but keep the seed safe
otherwise.
The attribute ``no_randomize_layout``, when attached to a C structure,
instructs the compiler that this structure should not have its field layout
randomized.
}];
}
def HLSLSV_GroupIndexDocs : Documentation {
let Category = DocCatFunction;
let Content = [{
The ``SV_GroupIndex`` semantic, when applied to an input parameter, specifies a
data binding to map the group index to the specified parameter. This attribute
is only supported in compute shaders.
The full documentation is available here: https://docs.microsoft.com/en-us/windows/win32/direct3dhlsl/sv-groupindex
}];
}
def AnnotateTypeDocs : Documentation {
let Category = DocCatType;
let Heading = "annotate_type";
let Content = [{
This attribute is used to add annotations to types, typically for use by static
analysis tools that are not integrated into the core Clang compiler (e.g.,
Clang-Tidy checks or out-of-tree Clang-based tools). It is a counterpart to the
`annotate` attribute, which serves the same purpose, but for declarations.
The attribute takes a mandatory string literal argument specifying the
annotation category and an arbitrary number of optional arguments that provide
additional information specific to the annotation category. The optional
arguments must be constant expressions of arbitrary type.
For example:
.. code-block:: c++
int* [[clang::annotate("category1", "foo", 1)]] f(int[[clang::annotate("category2")]] *);
The attribute does not have any effect on the semantics of the type system,
neither type checking rules, nor runtime semantics. In particular:
- ``std::is_same<T, T [[clang::annotate_type("foo")]]>`` is true for all types
``T``.
- It is not permissible for overloaded functions or template specializations
to differ merely by an ``annotate_type`` attribute.
- The presence of an ``annotate_type`` attribute will not affect name
mangling.
}];
}
def WeakDocs : Documentation {
let Category = DocCatDecl;
let Content = [{
In supported output formats the ``weak`` attribute can be used to
specify that a variable or function should be emitted as a symbol with
``weak`` (if a definition) or ``extern_weak`` (if a declaration of an
external symbol) `linkage
<https://llvm.org/docs/LangRef.html#linkage-types>`_.
If there is a non-weak definition of the symbol the linker will select
that over the weak. They must have same type and alignment (variables
must also have the same size), but may have a different value.
If there are multiple weak definitions of same symbol, but no non-weak
definition, they should have same type, size, alignment and value, the
linker will select one of them (see also selectany_ attribute).
If the ``weak`` attribute is applied to a ``const`` qualified variable
definition that variable is no longer consider a compiletime constant
as its value can change during linking (or dynamic linking). This
means that it can e.g no longer be part of an initializer expression.
.. code-block:: c
const int ANSWER __attribute__ ((weak)) = 42;
/* This function may be replaced link-time */
__attribute__ ((weak)) void debug_log(const char *msg)
{
fprintf(stderr, "DEBUG: %s\n", msg);
}
int main(int argc, const char **argv)
{
debug_log ("Starting up...");
/* This may print something else than "6 * 7 = 42",
if there is a non-weak definition of "ANSWER" in
an object linked in */
printf("6 * 7 = %d\n", ANSWER);
return 0;
}
If an external declaration is marked weak and that symbol does not
exist during linking (possibly dynamic) the address of the symbol will
evaluate to NULL.
.. code-block:: c
void may_not_exist(void) __attribute__ ((weak));
int main(int argc, const char **argv)
{
if (may_not_exist) {
may_not_exist();
} else {
printf("Function did not exist\n");
}
return 0;
}
}];
}
@@ -18,6 +18,9 @@ namespace attr {
/// A list of all the recognized kinds of attributes.
enum SubjectMatchRule {
#define ATTR_MATCH_RULE(X, Spelling, IsAbstract) X,
#include "clang/Basic/AttrSubMatchRulesList.inc"
SubjectMatchRule_Last = -1
#define ATTR_MATCH_RULE(X, Spelling, IsAbstract) +1
#include "clang/Basic/AttrSubMatchRulesList.inc"
};
@@ -48,6 +48,9 @@ class AttributeCommonInfo {
// without adding related code to TableGen/ClangAttrEmitter.cpp.
/// Context-sensitive version of a keyword attribute.
AS_ContextSensitiveKeyword,
/// <vardecl> : <semantic>
AS_HLSLSemantic,
};
enum Kind {
#define PARSED_ATTR(NAME) AT_##NAME,
@@ -66,7 +69,7 @@ class AttributeCommonInfo {
// Corresponds to the Kind enum.
unsigned AttrKind : 16;
/// Corresponds to the Syntax enum.
unsigned SyntaxUsed : 3;
unsigned SyntaxUsed : 4;
unsigned SpellingIndex : 4;
protected:
@@ -143,9 +146,25 @@ class AttributeCommonInfo {
bool isMicrosoftAttribute() const { return SyntaxUsed == AS_Microsoft; }
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();
}
@@ -161,6 +180,8 @@ class AttributeCommonInfo {
return isCXX11Attribute() || isC2xAttribute();
}
bool isGNUAttribute() const { return SyntaxUsed == AS_GNU; }
bool isKeywordAttribute() const {
return SyntaxUsed == AS_Keyword || SyntaxUsed == AS_ContextSensitiveKeyword;
}
@@ -9,6 +9,7 @@
#ifndef LLVM_CLANG_BASIC_ATTRIBUTES_H
#define LLVM_CLANG_BASIC_ATTRIBUTES_H
#include "clang/Basic/AttributeCommonInfo.h"
#include "clang/Basic/LangOptions.h"
#include "clang/Basic/TargetInfo.h"
@@ -16,26 +17,11 @@ namespace clang {
class IdentifierInfo;
enum class AttrSyntax {
/// Is the identifier known as a GNU-style attribute?
GNU,
/// Is the identifier known as a __declspec-style attribute?
Declspec,
/// Is the identifier known as a [] Microsoft-style attribute?
Microsoft,
// Is the identifier known as a C++-style attribute?
CXX,
// Is the identifier known as a C-style attribute?
C,
// Is the identifier known as a pragma attribute?
Pragma
};
/// Return the version number associated with the attribute if we
/// recognize and implement the attribute specified by the given information.
int hasAttribute(AttrSyntax Syntax, const IdentifierInfo *Scope,
const IdentifierInfo *Attr, const TargetInfo &Target,
const LangOptions &LangOpts);
int hasAttribute(AttributeCommonInfo::Syntax Syntax,
const IdentifierInfo *Scope, const IdentifierInfo *Attr,
const TargetInfo &Target, const LangOptions &LangOpts);
} // end namespace clang
@@ -81,7 +81,9 @@
// builtin even if type doesn't match signature, and don't warn if we
// can't be sure the type is right
// F -> this is a libc/libm function with a '__builtin_' prefix added.
// f -> this is a libc/libm function without the '__builtin_' prefix.
// f -> this is a libc/libm function without a '__builtin_' prefix, or with
// 'z', a C++ standard library function in namespace std::. This builtin
// is disableable by '-fno-builtin-foo' / '-fno-builtin-std-foo'.
// h -> this function requires a specific header or an explicit declaration.
// i -> this is a runtime library implemented function without the
// '__builtin_' prefix. It will be implemented in compiler-rt or libgcc.
@@ -101,6 +103,7 @@
// V:N: -> requires vectors of at least N bits to be legal
// C<N,M_0,...,M_k> -> callback behavior: argument N is called with argument
// M_0, ..., M_k as payload
// z -> this is a function in (possibly-versioned) namespace std
// FIXME: gcc has nonnull
#if defined(BUILTIN) && !defined(LIBBUILTIN)
@@ -139,10 +142,12 @@ BUILTIN(__builtin_frexpf128, "LLdLLdi*", "Fn")
BUILTIN(__builtin_huge_val, "d", "nc")
BUILTIN(__builtin_huge_valf, "f", "nc")
BUILTIN(__builtin_huge_vall, "Ld", "nc")
BUILTIN(__builtin_huge_valf16, "x", "nc")
BUILTIN(__builtin_huge_valf128, "LLd", "nc")
BUILTIN(__builtin_inf , "d" , "nc")
BUILTIN(__builtin_inff , "f" , "nc")
BUILTIN(__builtin_infl , "Ld" , "nc")
BUILTIN(__builtin_inff16 , "x" , "nc")
BUILTIN(__builtin_inff128 , "LLd" , "nc")
BUILTIN(__builtin_labs , "LiLi" , "Fnc")
BUILTIN(__builtin_llabs, "LLiLLi", "Fnc")
@@ -157,10 +162,12 @@ BUILTIN(__builtin_modff128, "LLdLLdLLd*", "Fn")
BUILTIN(__builtin_nan, "dcC*" , "FnU")
BUILTIN(__builtin_nanf, "fcC*" , "FnU")
BUILTIN(__builtin_nanl, "LdcC*", "FnU")
BUILTIN(__builtin_nanf16, "xcC*", "FnU")
BUILTIN(__builtin_nanf128, "LLdcC*", "FnU")
BUILTIN(__builtin_nans, "dcC*" , "FnU")
BUILTIN(__builtin_nansf, "fcC*" , "FnU")
BUILTIN(__builtin_nansl, "LdcC*", "FnU")
BUILTIN(__builtin_nansf16, "xcC*", "FnU")
BUILTIN(__builtin_nansf128, "LLdcC*", "FnU")
BUILTIN(__builtin_powi , "ddi" , "Fnc")
BUILTIN(__builtin_powif, "ffi" , "Fnc")
@@ -548,10 +555,11 @@ BUILTIN(__builtin_malloc, "v*z", "nF")
BUILTIN(__builtin_memchr, "v*vC*iz", "nF")
BUILTIN(__builtin_memcmp, "ivC*vC*z", "nF")
BUILTIN(__builtin_memcpy, "v*v*vC*z", "nF")
BUILTIN(__builtin_memcpy_inline, "vv*vC*Iz", "nt")
BUILTIN(__builtin_memcpy_inline, "vv*vC*Iz", "n")
BUILTIN(__builtin_memmove, "v*v*vC*z", "nF")
BUILTIN(__builtin_mempcpy, "v*v*vC*z", "nF")
BUILTIN(__builtin_memset, "v*v*iz", "nF")
BUILTIN(__builtin_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")
@@ -653,11 +661,15 @@ BUILTIN(__builtin_elementwise_ceil, "v.", "nct")
BUILTIN(__builtin_elementwise_floor, "v.", "nct")
BUILTIN(__builtin_elementwise_roundeven, "v.", "nct")
BUILTIN(__builtin_elementwise_trunc, "v.", "nct")
BUILTIN(__builtin_elementwise_add_sat, "v.", "nct")
BUILTIN(__builtin_elementwise_sub_sat, "v.", "nct")
BUILTIN(__builtin_reduce_max, "v.", "nct")
BUILTIN(__builtin_reduce_min, "v.", "nct")
BUILTIN(__builtin_reduce_xor, "v.", "nct")
BUILTIN(__builtin_reduce_or, "v.", "nct")
BUILTIN(__builtin_reduce_and, "v.", "nct")
BUILTIN(__builtin_reduce_add, "v.", "nct")
BUILTIN(__builtin_reduce_mul, "v.", "nct")
BUILTIN(__builtin_matrix_transpose, "v.", "nFt")
BUILTIN(__builtin_matrix_column_major_load, "v.", "nFt")
@@ -917,7 +929,7 @@ LANGBUILTIN(__exception_info, "v*", "n", ALL_MS_LANGUAGES)
LANGBUILTIN(_exception_info, "v*", "n", ALL_MS_LANGUAGES)
LANGBUILTIN(__abnormal_termination, "i", "n", ALL_MS_LANGUAGES)
LANGBUILTIN(_abnormal_termination, "i", "n", ALL_MS_LANGUAGES)
LANGBUILTIN(__GetExceptionInfo, "v*.", "ntu", ALL_MS_LANGUAGES)
LANGBUILTIN(__GetExceptionInfo, "v*.", "zntu", ALL_MS_LANGUAGES)
LANGBUILTIN(_InterlockedAnd8, "ccD*c", "n", ALL_MS_LANGUAGES)
LANGBUILTIN(_InterlockedAnd16, "ssD*s", "n", ALL_MS_LANGUAGES)
LANGBUILTIN(_InterlockedAnd, "NiNiD*Ni", "n", ALL_MS_LANGUAGES)
@@ -1541,6 +1553,15 @@ LIBBUILTIN(_Block_object_assign, "vv*vC*iC", "f", "Blocks.h", ALL_LANGUAGES)
LIBBUILTIN(_Block_object_dispose, "vvC*iC", "f", "Blocks.h", ALL_LANGUAGES)
// FIXME: Also declare NSConcreteGlobalBlock and NSConcreteStackBlock.
// C++ standard library builtins in namespace 'std'.
LIBBUILTIN(addressof, "v*v&", "zfncTh", "memory", CXX_LANG)
// Synonym for addressof used internally by libstdc++.
LANGBUILTIN(__addressof, "v*v&", "zfncT", CXX_LANG)
LIBBUILTIN(as_const, "v&v&", "zfncTh", "utility", CXX_LANG)
LIBBUILTIN(forward, "v&v&", "zfncTh", "utility", CXX_LANG)
LIBBUILTIN(move, "v&v&", "zfncTh", "utility", CXX_LANG)
LIBBUILTIN(move_if_noexcept, "v&v&", "zfncTh", "utility", CXX_LANG)
// Annotation function
BUILTIN(__builtin_annotation, "v.", "tn")
@@ -1588,7 +1609,7 @@ BUILTIN(__builtin_function_start, "v*v&", "nct")
BUILTIN(__builtin_operator_new, "v*z", "tc")
BUILTIN(__builtin_operator_delete, "vv*", "tn")
BUILTIN(__builtin_char_memchr, "c*cC*iz", "n")
BUILTIN(__builtin_dump_struct, "ivC*v*", "tn")
BUILTIN(__builtin_dump_struct, "v.", "t")
BUILTIN(__builtin_preserve_access_index, "v.", "t")
// Alignment builtins (uses custom parsing to support pointers and integers)
@@ -1677,6 +1698,9 @@ BUILTIN(__builtin_os_log_format, "v*v*cC*.", "p:0:nt")
// CUDA/HIP
LANGBUILTIN(__builtin_get_device_side_mangled_name, "cC*.", "ncT", CUDA_LANG)
// HLSL
LANGBUILTIN(__builtin_hlsl_wave_active_count_bits, "Uib", "nc", HLSL_LANG)
// Builtins for XRay
BUILTIN(__xray_customevent, "vcC*z", "")
BUILTIN(__xray_typedevent, "vzcC*z", "")
@@ -16,6 +16,8 @@
#define LLVM_CLANG_BASIC_BUILTINS_H
#include "llvm/ADT/ArrayRef.h"
#include "llvm/ADT/StringMap.h"
#include "llvm/ADT/StringRef.h"
#include <cstring>
// VC++ defines 'alloca' as an object-like macro, which interferes with our
@@ -40,6 +42,7 @@ enum LanguageID {
OCL_PIPE = 0x200, // builtin requires OpenCL pipe.
OCL_DSE = 0x400, // builtin requires OpenCL device side enqueue.
ALL_OCL_LANGUAGES = 0x800, // builtin for OCL languages.
HLSL_LANG = 0x1000, // builtin requires HLSL.
ALL_LANGUAGES = C_LANG | CXX_LANG | OBJC_LANG, // builtin for all languages.
ALL_GNU_LANGUAGES = ALL_LANGUAGES | GNU_LANG, // builtin requires GNU mode.
ALL_MS_LANGUAGES = ALL_LANGUAGES | MS_LANG // builtin requires MS mode.
@@ -70,7 +73,7 @@ class Context {
llvm::ArrayRef<Info> AuxTSRecords;
public:
Context() {}
Context() = default;
/// Perform target-specific initialization
/// \param AuxTarget Target info to incorporate builtins from. May be nullptr.
@@ -138,6 +141,10 @@ class Context {
/// Determines whether this builtin is a predefined libc/libm
/// function, such as "malloc", where we know the signature a
/// priori.
/// In C, such functions behave as if they are predeclared,
/// possibly with a warning on first use. In Objective-C and C++,
/// they do not, but they are recognized as builtins once we see
/// a declaration.
bool isPredefinedLibFunction(unsigned ID) const {
return strchr(getRecord(ID).Attributes, 'f') != nullptr;
}
@@ -156,6 +163,23 @@ class Context {
return strchr(getRecord(ID).Attributes, 'i') != nullptr;
}
/// Determines whether this builtin is a C++ standard library function
/// that lives in (possibly-versioned) namespace std, possibly a template
/// specialization, where the signature is determined by the standard library
/// declaration.
bool isInStdNamespace(unsigned ID) const {
return strchr(getRecord(ID).Attributes, 'z') != nullptr;
}
/// Determines whether this builtin can have its address taken with no
/// special action required.
bool isDirectlyAddressable(unsigned ID) const {
// Most standard library functions can have their addresses taken. C++
// standard library functions formally cannot in C++20 onwards, and when
// we allow it, we need to ensure we instantiate a definition.
return isPredefinedLibFunction(ID) && !isInStdNamespace(ID);
}
/// Determines whether this builtin has custom typechecking.
bool hasCustomTypechecking(unsigned ID) const {
return strchr(getRecord(ID).Attributes, 't') != nullptr;
@@ -237,16 +261,20 @@ class Context {
private:
const Info &getRecord(unsigned ID) const;
/// Is this builtin supported according to the given language options?
bool builtinIsSupported(const Builtin::Info &BuiltinInfo,
const LangOptions &LangOpts);
/// Helper function for isPrintfLike and isScanfLike.
bool isLike(unsigned ID, unsigned &FormatIdx, bool &HasVAListArg,
const char *Fmt) const;
};
}
/// Returns true if the required target features of a builtin function are
/// enabled.
/// \p TargetFeatureMap maps a target feature to true if it is enabled and
/// false if it is disabled.
bool evaluateRequiredTargetFeatures(
llvm::StringRef RequiredFatures,
const llvm::StringMap<bool> &TargetFetureMap);
} // namespace Builtin
/// Kinds of BuiltinTemplateDecl.
enum BuiltinTemplateKind : int {
@@ -249,6 +249,18 @@ TARGET_HEADER_BUILTIN(_AddressOfReturnAddress, "v*", "nh", "intrin.h", ALL_MS_LA
TARGET_HEADER_BUILTIN(__mulh, "SLLiSLLiSLLi", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
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, "")
#undef BUILTIN
#undef LANGBUILTIN
#undef TARGET_HEADER_BUILTIN
@@ -62,6 +62,7 @@ BUILTIN(__builtin_amdgcn_s_sendmsg, "vIiUi", "n")
BUILTIN(__builtin_amdgcn_s_sendmsghalt, "vIiUi", "n")
BUILTIN(__builtin_amdgcn_s_barrier, "v", "n")
BUILTIN(__builtin_amdgcn_wave_barrier, "v", "n")
BUILTIN(__builtin_amdgcn_sched_barrier, "vIi", "n")
BUILTIN(__builtin_amdgcn_s_dcache_inv, "v", "n")
BUILTIN(__builtin_amdgcn_buffer_wbinvl1, "v", "n")
BUILTIN(__builtin_amdgcn_ds_gws_init, "vUiUi", "n")
@@ -116,6 +117,7 @@ BUILTIN(__builtin_amdgcn_cubema, "ffff", "nc")
BUILTIN(__builtin_amdgcn_s_sleep, "vIi", "n")
BUILTIN(__builtin_amdgcn_s_incperflevel, "vIi", "n")
BUILTIN(__builtin_amdgcn_s_decperflevel, "vIi", "n")
BUILTIN(__builtin_amdgcn_s_setprio, "vIs", "n")
BUILTIN(__builtin_amdgcn_uicmp, "WUiUiUiIi", "nc")
BUILTIN(__builtin_amdgcn_uicmpl, "WUiWUiWUiIi", "nc")
BUILTIN(__builtin_amdgcn_sicmp, "WUiiiIi", "nc")
@@ -209,17 +211,28 @@ TARGET_BUILTIN(__builtin_amdgcn_flat_atomic_fmax_f64, "dd*0d", "t", "gfx90a-inst
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")
//===----------------------------------------------------------------------===//
// Deep learning builtins.
//===----------------------------------------------------------------------===//
TARGET_BUILTIN(__builtin_amdgcn_fdot2, "fV2hV2hfIb", "nc", "dot7-insts")
TARGET_BUILTIN(__builtin_amdgcn_fdot2_f16_f16, "hV2hV2hh", "nc", "dot8-insts")
TARGET_BUILTIN(__builtin_amdgcn_fdot2_bf16_bf16, "sV2sV2ss", "nc", "dot8-insts")
TARGET_BUILTIN(__builtin_amdgcn_fdot2_f32_bf16, "fV2sV2sfIb", "nc", "dot8-insts")
TARGET_BUILTIN(__builtin_amdgcn_sdot2, "SiV2SsV2SsSiIb", "nc", "dot2-insts")
TARGET_BUILTIN(__builtin_amdgcn_udot2, "UiV2UsV2UsUiIb", "nc", "dot2-insts")
TARGET_BUILTIN(__builtin_amdgcn_sdot4, "SiSiSiSiIb", "nc", "dot1-insts")
TARGET_BUILTIN(__builtin_amdgcn_udot4, "UiUiUiUiIb", "nc", "dot7-insts")
TARGET_BUILTIN(__builtin_amdgcn_sudot4, "iIbiIbiiIb", "nc", "dot8-insts")
TARGET_BUILTIN(__builtin_amdgcn_sdot8, "SiSiSiSiIb", "nc", "dot1-insts")
TARGET_BUILTIN(__builtin_amdgcn_udot8, "UiUiUiUiIb", "nc", "dot7-insts")
TARGET_BUILTIN(__builtin_amdgcn_sudot8, "iIbiIbiiIb", "nc", "dot8-insts")
//===----------------------------------------------------------------------===//
// GFX10+ only builtins.
@@ -239,6 +252,30 @@ TARGET_BUILTIN(__builtin_amdgcn_image_bvh_intersect_ray_h, "V4UiUifV4fV4hV4hV4Ui
TARGET_BUILTIN(__builtin_amdgcn_image_bvh_intersect_ray_l, "V4UiWUifV4fV4fV4fV4Ui", "nc", "gfx10-insts")
TARGET_BUILTIN(__builtin_amdgcn_image_bvh_intersect_ray_lh, "V4UiWUifV4fV4hV4hV4Ui", "nc", "gfx10-insts")
//===----------------------------------------------------------------------===//
// GFX11+ only builtins.
//===----------------------------------------------------------------------===//
//===----------------------------------------------------------------------===//
// WMMA builtins.
// Postfix w32 indicates the builtin requires wavefront size of 32.
// Postfix w64 indicates the builtin requires wavefront size of 64.
//===----------------------------------------------------------------------===//
TARGET_BUILTIN(__builtin_amdgcn_wmma_f32_16x16x16_f16_w32, "V8fV16hV16hV8f", "nc", "gfx11-insts")
TARGET_BUILTIN(__builtin_amdgcn_wmma_f32_16x16x16_bf16_w32, "V8fV16sV16sV8f", "nc", "gfx11-insts")
TARGET_BUILTIN(__builtin_amdgcn_wmma_f16_16x16x16_f16_w32, "V16hV16hV16hV16hIb", "nc", "gfx11-insts")
TARGET_BUILTIN(__builtin_amdgcn_wmma_bf16_16x16x16_bf16_w32, "V16sV16sV16sV16sIb", "nc", "gfx11-insts")
TARGET_BUILTIN(__builtin_amdgcn_wmma_i32_16x16x16_iu8_w32, "V8iIbV4iIbV4iV8iIb", "nc", "gfx11-insts")
TARGET_BUILTIN(__builtin_amdgcn_wmma_i32_16x16x16_iu4_w32, "V8iIbV2iIbV2iV8iIb", "nc", "gfx11-insts")
TARGET_BUILTIN(__builtin_amdgcn_wmma_f32_16x16x16_f16_w64, "V4fV16hV16hV4f", "nc", "gfx11-insts")
TARGET_BUILTIN(__builtin_amdgcn_wmma_f32_16x16x16_bf16_w64, "V4fV16sV16sV4f", "nc", "gfx11-insts")
TARGET_BUILTIN(__builtin_amdgcn_wmma_f16_16x16x16_f16_w64, "V8hV16hV16hV8hIb", "nc", "gfx11-insts")
TARGET_BUILTIN(__builtin_amdgcn_wmma_bf16_16x16x16_bf16_w64, "V8sV16sV16sV8sIb", "nc", "gfx11-insts")
TARGET_BUILTIN(__builtin_amdgcn_wmma_i32_16x16x16_iu8_w64, "V4iIbV4iIbV4iV4iIb", "nc", "gfx11-insts")
TARGET_BUILTIN(__builtin_amdgcn_wmma_i32_16x16x16_iu4_w64, "V4iIbV2iIbV2iV4iIb", "nc", "gfx11-insts")
//===----------------------------------------------------------------------===//
// Special builtins.
//===----------------------------------------------------------------------===//
@@ -298,5 +335,16 @@ TARGET_BUILTIN(__builtin_amdgcn_mfma_f32_16x16x16bf16_1k, "V4fV4sV4sV4fIiIiIi",
TARGET_BUILTIN(__builtin_amdgcn_mfma_f64_16x16x4f64, "V4dddV4dIiIiIi", "nc", "mai-insts")
TARGET_BUILTIN(__builtin_amdgcn_mfma_f64_4x4x4f64, "ddddIiIiIi", "nc", "mai-insts")
TARGET_BUILTIN(__builtin_amdgcn_mfma_i32_16x16x32_i8, "V4iWiWiV4iIiIiIi", "nc", "mai-insts")
TARGET_BUILTIN(__builtin_amdgcn_mfma_i32_32x32x16_i8, "V16iWiWiV16iIiIiIi", "nc", "mai-insts")
TARGET_BUILTIN(__builtin_amdgcn_mfma_f32_16x16x8_xf32, "V4fV2fV2fV4fIiIiIi", "nc", "mai-insts")
TARGET_BUILTIN(__builtin_amdgcn_mfma_f32_32x32x4_xf32, "V16fV2fV2fV16fIiIiIi", "nc", "mai-insts")
TARGET_BUILTIN(__builtin_amdgcn_smfmac_f32_16x16x32_f16, "V4fV4hV8hV4fiIiIi", "nc", "mai-insts")
TARGET_BUILTIN(__builtin_amdgcn_smfmac_f32_32x32x16_f16, "V16fV4hV8hV16fiIiIi", "nc", "mai-insts")
TARGET_BUILTIN(__builtin_amdgcn_smfmac_f32_16x16x32_bf16, "V4fV4sV8sV4fiIiIi", "nc", "mai-insts")
TARGET_BUILTIN(__builtin_amdgcn_smfmac_f32_32x32x16_bf16, "V16fV4sV8sV16fiIiIi", "nc", "mai-insts")
TARGET_BUILTIN(__builtin_amdgcn_smfmac_i32_16x16x64_i8, "V4iV2iV4iV4iiIiIi", "nc", "mai-insts")
TARGET_BUILTIN(__builtin_amdgcn_smfmac_i32_32x32x32_i8, "V16iV2iV4iV16iiIiIi", "nc", "mai-insts")
#undef BUILTIN
#undef TARGET_BUILTIN
@@ -197,6 +197,9 @@ BUILTIN(__builtin_arm_wsr, "vcC*Ui", "nc")
BUILTIN(__builtin_arm_wsr64, "vcC*LLUi", "nc")
BUILTIN(__builtin_arm_wsrp, "vcC*vC*", "nc")
// Misc
BUILTIN(__builtin_sponentry, "v*", "c")
// Builtins for implementing ACLE MVE intrinsics. (Unlike NEON, these
// don't need to live in a separate BuiltinsMVE.def, because they
// aren't included from both here and BuiltinsAArch64.def.)
@@ -17,6 +17,7 @@
# define TARGET_BUILTIN(ID, TYPE, ATTRS, FEATURE) BUILTIN(ID, TYPE, ATTRS)
#endif
#pragma push_macro("SM_53")
#pragma push_macro("SM_70")
#pragma push_macro("SM_72")
#pragma push_macro("SM_75")
@@ -30,7 +31,9 @@
#pragma push_macro("SM_60")
#define SM_60 "sm_60|sm_61|sm_62|" SM_70
#define SM_53 "sm_53|" SM_60
#pragma push_macro("PTX42")
#pragma push_macro("PTX60")
#pragma push_macro("PTX61")
#pragma push_macro("PTX63")
@@ -53,6 +56,7 @@
#define PTX63 "ptx63|" PTX64
#define PTX61 "ptx61|" PTX63
#define PTX60 "ptx60|" PTX61
#define PTX42 "ptx42|" PTX60
#pragma push_macro("AND")
#define AND(a, b) "(" a "),(" b ")"
@@ -107,14 +111,90 @@ BUILTIN(__nvvm_prmt, "UiUiUiUi", "")
// Min Max
BUILTIN(__nvvm_fmax_ftz_f, "fff", "")
BUILTIN(__nvvm_fmax_f, "fff", "")
BUILTIN(__nvvm_fmin_ftz_f, "fff", "")
BUILTIN(__nvvm_fmin_f, "fff", "")
BUILTIN(__nvvm_fmax_d, "ddd", "")
TARGET_BUILTIN(__nvvm_fmin_f16, "hhh", "", AND(SM_80, PTX70))
TARGET_BUILTIN(__nvvm_fmin_ftz_f16, "hhh", "", AND(SM_80, PTX70))
TARGET_BUILTIN(__nvvm_fmin_nan_f16, "hhh", "", AND(SM_80, PTX70))
TARGET_BUILTIN(__nvvm_fmin_ftz_nan_f16, "hhh", "", AND(SM_80, PTX70))
TARGET_BUILTIN(__nvvm_fmin_xorsign_abs_f16, "hhh", "", AND(SM_86, PTX72))
TARGET_BUILTIN(__nvvm_fmin_ftz_xorsign_abs_f16, "hhh", "", AND(SM_86, PTX72))
TARGET_BUILTIN(__nvvm_fmin_nan_xorsign_abs_f16, "hhh", "", AND(SM_86, PTX72))
TARGET_BUILTIN(__nvvm_fmin_ftz_nan_xorsign_abs_f16, "hhh", "",
AND(SM_86, PTX72))
TARGET_BUILTIN(__nvvm_fmin_f16x2, "V2hV2hV2h", "", AND(SM_80, PTX70))
TARGET_BUILTIN(__nvvm_fmin_ftz_f16x2, "V2hV2hV2h", "", AND(SM_80, PTX70))
TARGET_BUILTIN(__nvvm_fmin_nan_f16x2, "V2hV2hV2h", "", AND(SM_80, PTX70))
TARGET_BUILTIN(__nvvm_fmin_ftz_nan_f16x2, "V2hV2hV2h", "", AND(SM_80, PTX70))
TARGET_BUILTIN(__nvvm_fmin_xorsign_abs_f16x2, "V2hV2hV2h", "",
AND(SM_86, PTX72))
TARGET_BUILTIN(__nvvm_fmin_ftz_xorsign_abs_f16x2, "V2hV2hV2h", "",
AND(SM_86, PTX72))
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", "",
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", "",
AND(SM_86, PTX72))
TARGET_BUILTIN(__nvvm_fmin_nan_xorsign_abs_bf16x2, "ZUiZUiZUi", "",
AND(SM_86, PTX72))
BUILTIN(__nvvm_fmin_f, "fff", "")
BUILTIN(__nvvm_fmin_ftz_f, "fff", "")
TARGET_BUILTIN(__nvvm_fmin_nan_f, "fff", "", AND(SM_80, PTX70))
TARGET_BUILTIN(__nvvm_fmin_ftz_nan_f, "fff", "", AND(SM_80, PTX70))
TARGET_BUILTIN(__nvvm_fmin_xorsign_abs_f, "fff", "", AND(SM_86, PTX72))
TARGET_BUILTIN(__nvvm_fmin_ftz_xorsign_abs_f, "fff", "", AND(SM_86, PTX72))
TARGET_BUILTIN(__nvvm_fmin_nan_xorsign_abs_f, "fff", "", AND(SM_86, PTX72))
TARGET_BUILTIN(__nvvm_fmin_ftz_nan_xorsign_abs_f, "fff", "", AND(SM_86, PTX72))
BUILTIN(__nvvm_fmin_d, "ddd", "")
TARGET_BUILTIN(__nvvm_fmax_f16, "hhh", "", AND(SM_80, PTX70))
TARGET_BUILTIN(__nvvm_fmax_ftz_f16, "hhh", "", AND(SM_80, PTX70))
TARGET_BUILTIN(__nvvm_fmax_nan_f16, "hhh", "", AND(SM_80, PTX70))
TARGET_BUILTIN(__nvvm_fmax_ftz_nan_f16, "hhh", "", AND(SM_80, PTX70))
TARGET_BUILTIN(__nvvm_fmax_xorsign_abs_f16, "hhh", "", AND(SM_86, PTX72))
TARGET_BUILTIN(__nvvm_fmax_ftz_xorsign_abs_f16, "hhh", "", AND(SM_86, PTX72))
TARGET_BUILTIN(__nvvm_fmax_nan_xorsign_abs_f16, "hhh", "", AND(SM_86, PTX72))
TARGET_BUILTIN(__nvvm_fmax_ftz_nan_xorsign_abs_f16, "hhh", "",
AND(SM_86, PTX72))
TARGET_BUILTIN(__nvvm_fmax_f16x2, "V2hV2hV2h", "", AND(SM_80, PTX70))
TARGET_BUILTIN(__nvvm_fmax_ftz_f16x2, "V2hV2hV2h", "", AND(SM_80, PTX70))
TARGET_BUILTIN(__nvvm_fmax_nan_f16x2, "V2hV2hV2h", "", AND(SM_80, PTX70))
TARGET_BUILTIN(__nvvm_fmax_ftz_nan_f16x2, "V2hV2hV2h", "", AND(SM_80, PTX70))
TARGET_BUILTIN(__nvvm_fmax_xorsign_abs_f16x2, "V2hV2hV2h", "",
AND(SM_86, PTX72))
TARGET_BUILTIN(__nvvm_fmax_ftz_xorsign_abs_f16x2, "V2hV2hV2h", "",
AND(SM_86, PTX72))
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", "",
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", "",
AND(SM_86, PTX72))
TARGET_BUILTIN(__nvvm_fmax_nan_xorsign_abs_bf16x2, "ZUiZUiZUi", "",
AND(SM_86, PTX72))
BUILTIN(__nvvm_fmax_f, "fff", "")
BUILTIN(__nvvm_fmax_ftz_f, "fff", "")
TARGET_BUILTIN(__nvvm_fmax_nan_f, "fff", "", AND(SM_80, PTX70))
TARGET_BUILTIN(__nvvm_fmax_ftz_nan_f, "fff", "", AND(SM_80, PTX70))
TARGET_BUILTIN(__nvvm_fmax_xorsign_abs_f, "fff", "", AND(SM_86, PTX72))
TARGET_BUILTIN(__nvvm_fmax_ftz_xorsign_abs_f, "fff", "", AND(SM_86, PTX72))
TARGET_BUILTIN(__nvvm_fmax_nan_xorsign_abs_f, "fff", "", AND(SM_86, PTX72))
TARGET_BUILTIN(__nvvm_fmax_ftz_nan_xorsign_abs_f, "fff", "", AND(SM_86, PTX72))
BUILTIN(__nvvm_fmax_d, "ddd", "")
// Multiplication
BUILTIN(__nvvm_mulhi_i, "iii", "")
@@ -202,6 +282,8 @@ BUILTIN(__nvvm_saturate_d, "dd", "")
BUILTIN(__nvvm_ex2_approx_ftz_f, "ff", "")
BUILTIN(__nvvm_ex2_approx_f, "ff", "")
BUILTIN(__nvvm_ex2_approx_d, "dd", "")
TARGET_BUILTIN(__nvvm_ex2_approx_f16, "hh", "", AND(SM_75, PTX70))
TARGET_BUILTIN(__nvvm_ex2_approx_f16x2, "V2hV2h", "", AND(SM_75, PTX70))
BUILTIN(__nvvm_lg2_approx_ftz_f, "ff", "")
BUILTIN(__nvvm_lg2_approx_f, "ff", "")
@@ -217,6 +299,22 @@ BUILTIN(__nvvm_cos_approx_f, "ff", "")
// Fma
TARGET_BUILTIN(__nvvm_fma_rn_f16, "hhhh", "", AND(SM_53, PTX42))
TARGET_BUILTIN(__nvvm_fma_rn_ftz_f16, "hhhh", "", AND(SM_53, PTX42))
TARGET_BUILTIN(__nvvm_fma_rn_sat_f16, "hhhh", "", AND(SM_53, PTX42))
TARGET_BUILTIN(__nvvm_fma_rn_ftz_sat_f16, "hhhh", "", AND(SM_53, PTX42))
TARGET_BUILTIN(__nvvm_fma_rn_relu_f16, "hhhh", "", AND(SM_80, PTX70))
TARGET_BUILTIN(__nvvm_fma_rn_ftz_relu_f16, "hhhh", "", AND(SM_80, PTX70))
TARGET_BUILTIN(__nvvm_fma_rn_f16x2, "V2hV2hV2hV2h", "", AND(SM_53, PTX42))
TARGET_BUILTIN(__nvvm_fma_rn_ftz_f16x2, "V2hV2hV2hV2h", "", AND(SM_53, PTX42))
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))
BUILTIN(__nvvm_fma_rn_ftz_f, "ffff", "")
BUILTIN(__nvvm_fma_rn_f, "ffff", "")
BUILTIN(__nvvm_fma_rz_ftz_f, "ffff", "")
@@ -245,6 +343,8 @@ BUILTIN(__nvvm_rcp_rn_d, "dd", "")
BUILTIN(__nvvm_rcp_rz_d, "dd", "")
BUILTIN(__nvvm_rcp_rm_d, "dd", "")
BUILTIN(__nvvm_rcp_rp_d, "dd", "")
BUILTIN(__nvvm_rcp_approx_ftz_f, "ff", "")
BUILTIN(__nvvm_rcp_approx_ftz_d, "dd", "")
// Sqrt
@@ -473,11 +573,11 @@ TARGET_BUILTIN(__nvvm_vote_uni_sync, "bUib", "", PTX60)
TARGET_BUILTIN(__nvvm_vote_ballot_sync, "UiUib", "", PTX60)
// Match
TARGET_BUILTIN(__nvvm_match_any_sync_i32, "UiUiUi", "", PTX60)
TARGET_BUILTIN(__nvvm_match_any_sync_i64, "WiUiWi", "", PTX60)
TARGET_BUILTIN(__nvvm_match_any_sync_i32, "UiUiUi", "", AND(SM_70,PTX60))
TARGET_BUILTIN(__nvvm_match_any_sync_i64, "UiUiWi", "", AND(SM_70,PTX60))
// These return a pair {value, predicate}, which requires custom lowering.
TARGET_BUILTIN(__nvvm_match_all_sync_i32p, "UiUiUii*", "", PTX60)
TARGET_BUILTIN(__nvvm_match_all_sync_i64p, "WiUiWii*", "", PTX60)
TARGET_BUILTIN(__nvvm_match_all_sync_i32p, "UiUiUii*", "", AND(SM_70,PTX60))
TARGET_BUILTIN(__nvvm_match_all_sync_i64p, "UiUiWii*", "", AND(SM_70,PTX60))
// Redux
TARGET_BUILTIN(__nvvm_redux_sync_add, "iii", "", AND(SM_80,PTX70))
@@ -827,15 +927,24 @@ TARGET_BUILTIN(__nvvm_cp_async_commit_group, "v", "", AND(SM_80,PTX70))
TARGET_BUILTIN(__nvvm_cp_async_wait_group, "vIi", "", AND(SM_80,PTX70))
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))
#undef BUILTIN
#undef TARGET_BUILTIN
#pragma pop_macro("AND")
#pragma pop_macro("SM_53")
#pragma pop_macro("SM_60")
#pragma pop_macro("SM_70")
#pragma pop_macro("SM_72")
#pragma pop_macro("SM_75")
#pragma pop_macro("SM_80")
#pragma pop_macro("SM_86")
#pragma pop_macro("PTX42")
#pragma pop_macro("PTX60")
#pragma pop_macro("PTX61")
#pragma pop_macro("PTX63")
@@ -152,6 +152,16 @@ BUILTIN(__builtin_ppc_mtmsr, "vUi", "")
BUILTIN(__builtin_ppc_mtspr, "vIiULi", "")
BUILTIN(__builtin_ppc_stfiw, "viC*d", "")
BUILTIN(__builtin_ppc_addex, "LLiLLiLLiCIi", "")
// select
BUILTIN(__builtin_ppc_maxfe, "LdLdLdLd.", "t")
BUILTIN(__builtin_ppc_maxfl, "dddd.", "t")
BUILTIN(__builtin_ppc_maxfs, "ffff.", "t")
BUILTIN(__builtin_ppc_minfe, "LdLdLdLd.", "t")
BUILTIN(__builtin_ppc_minfl, "dddd.", "t")
BUILTIN(__builtin_ppc_minfs, "ffff.", "t")
// Floating Negative Absolute Value
BUILTIN(__builtin_ppc_fnabs, "dd", "")
BUILTIN(__builtin_ppc_fnabss, "ff", "")
BUILTIN(__builtin_ppc_get_timebase, "ULLi", "n")
@@ -168,6 +178,9 @@ BUILTIN(__builtin_altivec_vaddeuqm, "V1ULLLiV1ULLLiV1ULLLiV1ULLLi","")
BUILTIN(__builtin_altivec_vaddcuq, "V1ULLLiV1ULLLiV1ULLLi","")
BUILTIN(__builtin_altivec_vaddecuq, "V1ULLLiV1ULLLiV1ULLLiV1ULLLi","")
BUILTIN(__builtin_altivec_vadduqm, "V1ULLLiV16UcV16Uc","")
BUILTIN(__builtin_altivec_vaddeuqm_c, "V16UcV16UcV16UcV16Uc","")
BUILTIN(__builtin_altivec_vaddcuq_c, "V16UcV16UcV16Uc","")
BUILTIN(__builtin_altivec_vaddecuq_c, "V16UcV16UcV16UcV16Uc","")
BUILTIN(__builtin_altivec_vsubsbs, "V16ScV16ScV16Sc", "")
BUILTIN(__builtin_altivec_vsububs, "V16UcV16UcV16Uc", "")
@@ -179,6 +192,9 @@ BUILTIN(__builtin_altivec_vsubeuqm, "V1ULLLiV1ULLLiV1ULLLiV1ULLLi","")
BUILTIN(__builtin_altivec_vsubcuq, "V1ULLLiV1ULLLiV1ULLLi","")
BUILTIN(__builtin_altivec_vsubecuq, "V1ULLLiV1ULLLiV1ULLLiV1ULLLi","")
BUILTIN(__builtin_altivec_vsubuqm, "V1ULLLiV16UcV16Uc","")
BUILTIN(__builtin_altivec_vsubeuqm_c, "V16UcV16UcV16UcV16Uc","")
BUILTIN(__builtin_altivec_vsubcuq_c, "V16UcV16UcV16Uc","")
BUILTIN(__builtin_altivec_vsubecuq_c, "V16UcV16UcV16UcV16Uc","")
BUILTIN(__builtin_altivec_vavgsb, "V16ScV16ScV16Sc", "")
BUILTIN(__builtin_altivec_vavgub, "V16UcV16UcV16Uc", "")
@@ -514,12 +530,12 @@ BUILTIN(__builtin_altivec_vpdepd, "V2ULLiV2ULLiV2ULLi", "")
BUILTIN(__builtin_altivec_vpextd, "V2ULLiV2ULLiV2ULLi", "")
// P10 Vector String Isolate Built-ins.
BUILTIN(__builtin_altivec_vstribr, "V16cV16c", "")
BUILTIN(__builtin_altivec_vstribl, "V16cV16c", "")
BUILTIN(__builtin_altivec_vstribr, "V16UcV16Uc", "")
BUILTIN(__builtin_altivec_vstribl, "V16UcV16Uc", "")
BUILTIN(__builtin_altivec_vstrihr, "V8sV8s", "")
BUILTIN(__builtin_altivec_vstrihl, "V8sV8s", "")
BUILTIN(__builtin_altivec_vstribr_p, "iiV16c", "")
BUILTIN(__builtin_altivec_vstribl_p, "iiV16c", "")
BUILTIN(__builtin_altivec_vstribr_p, "iiV16Uc", "")
BUILTIN(__builtin_altivec_vstribl_p, "iiV16Uc", "")
BUILTIN(__builtin_altivec_vstrihr_p, "iiV8s", "")
BUILTIN(__builtin_altivec_vstrihl_p, "iiV8s", "")
@@ -530,8 +546,8 @@ BUILTIN(__builtin_altivec_vcfuged, "V2ULLiV2ULLiV2ULLi", "")
BUILTIN(__builtin_altivec_vgnb, "ULLiV1ULLLiIi", "")
// P10 Vector Clear Bytes built-ins.
BUILTIN(__builtin_altivec_vclrlb, "V16cV16cUi", "")
BUILTIN(__builtin_altivec_vclrrb, "V16cV16cUi", "")
BUILTIN(__builtin_altivec_vclrlb, "V16UcV16UcUi", "")
BUILTIN(__builtin_altivec_vclrrb, "V16UcV16UcUi", "")
// P10 Vector Count Leading / Trailing Zeroes under bit Mask built-ins.
BUILTIN(__builtin_altivec_vclzdm, "V2ULLiV2ULLiV2ULLi", "")
@@ -556,8 +572,10 @@ BUILTIN(__builtin_altivec_vinshvlx, "V8UsV8UsUiV8Us", "")
BUILTIN(__builtin_altivec_vinshvrx, "V8UsV8UsUiV8Us", "")
BUILTIN(__builtin_altivec_vinswvlx, "V4UiV4UiUiV4Ui", "")
BUILTIN(__builtin_altivec_vinswvrx, "V4UiV4UiUiV4Ui", "")
BUILTIN(__builtin_altivec_vec_replace_elt, "V4UiV4UiUiIi", "t")
BUILTIN(__builtin_altivec_vec_replace_unaligned, "V4UiV4UiUiIi", "t")
BUILTIN(__builtin_altivec_vinsw, "V16UcV16UcUiIi", "")
BUILTIN(__builtin_altivec_vinsd, "V16UcV16UcULLiIi", "")
BUILTIN(__builtin_altivec_vinsw_elt, "V16UcV16UcUiiC", "")
BUILTIN(__builtin_altivec_vinsd_elt, "V16UcV16UcULLiiC", "")
// P10 Vector Extract built-ins.
BUILTIN(__builtin_altivec_vextdubvlx, "V2ULLiV16UcV16UcUi", "")
@@ -833,7 +851,7 @@ BUILTIN(__builtin_dcbf, "vvC*", "")
// Provided builtins with _mma_ prefix for compatibility.
CUSTOM_BUILTIN(mma_lxvp, vsx_lxvp, "W256SLiW256C*", false)
CUSTOM_BUILTIN(mma_stxvp, vsx_stxvp, "vW256SLiW256C*", false)
CUSTOM_BUILTIN(mma_stxvp, vsx_stxvp, "vW256SLiW256*", false)
CUSTOM_BUILTIN(mma_assemble_pair, vsx_assemble_pair, "vW256*VV", false)
CUSTOM_BUILTIN(mma_disassemble_pair, vsx_disassemble_pair, "vv*W256*", false)
CUSTOM_BUILTIN(vsx_build_pair, vsx_assemble_pair, "vW256*VV", false)
@@ -845,7 +863,7 @@ CUSTOM_BUILTIN(mma_build_acc, mma_assemble_acc, "vW512*VVVV", false)
// This avoids repeating the ID and INTR in the macro expression.
UNALIASED_CUSTOM_BUILTIN(vsx_lxvp, "W256SLiW256C*", false)
UNALIASED_CUSTOM_BUILTIN(vsx_stxvp, "vW256SLiW256C*", false)
UNALIASED_CUSTOM_BUILTIN(vsx_stxvp, "vW256SLiW256*", false)
UNALIASED_CUSTOM_BUILTIN(vsx_assemble_pair, "vW256*VV", false)
UNALIASED_CUSTOM_BUILTIN(vsx_disassemble_pair, "vv*W256*", false)
@@ -18,12 +18,20 @@
// 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")
// Zbc extension
TARGET_BUILTIN(__builtin_riscv_clmul, "LiLiLi", "nc", "zbc")
TARGET_BUILTIN(__builtin_riscv_clmulh, "LiLiLi", "nc", "zbc")
// 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")
// Zbkx
TARGET_BUILTIN(__builtin_riscv_xperm4, "LiLiLi", "nc", "zbkx")
TARGET_BUILTIN(__builtin_riscv_xperm8, "LiLiLi", "nc", "zbkx")
// Zbe extension
TARGET_BUILTIN(__builtin_riscv_bcompress_32, "ZiZiZi", "nc", "experimental-zbe")
TARGET_BUILTIN(__builtin_riscv_bcompress_64, "WiWiWi", "nc",
@@ -67,5 +75,52 @@ TARGET_BUILTIN(__builtin_riscv_fsr_32, "LiLiLiLi", "nc", "experimental-zbt")
TARGET_BUILTIN(__builtin_riscv_fsl_64, "WiWiWiWi", "nc", "experimental-zbt,64bit")
TARGET_BUILTIN(__builtin_riscv_fsr_64, "WiWiWiWi", "nc", "experimental-zbt,64bit")
// Zbkb extension
TARGET_BUILTIN(__builtin_riscv_brev8, "LiLi", "nc", "zbkb")
TARGET_BUILTIN(__builtin_riscv_zip_32, "ZiZi", "nc", "zbkb")
TARGET_BUILTIN(__builtin_riscv_unzip_32, "ZiZi", "nc", "zbkb")
// Zknd extension
TARGET_BUILTIN(__builtin_riscv_aes32dsi_32, "ZiZiZiIUc", "nc", "zknd")
TARGET_BUILTIN(__builtin_riscv_aes32dsmi_32, "ZiZiZiIUc", "nc", "zknd")
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")
// Zknd & zkne
TARGET_BUILTIN(__builtin_riscv_aes64ks1i_64, "WiWiIUi", "nc", "zknd|zkne,64bit")
TARGET_BUILTIN(__builtin_riscv_aes64ks2_64, "WiWiWi", "nc", "zknd|zkne,64bit")
// Zkne extension
TARGET_BUILTIN(__builtin_riscv_aes32esi_32, "ZiZiZiIUc", "nc", "zkne")
TARGET_BUILTIN(__builtin_riscv_aes32esmi_32, "ZiZiZiIUc", "nc", "zkne")
TARGET_BUILTIN(__builtin_riscv_aes64es_64, "WiWiWi", "nc", "zkne,64bit")
TARGET_BUILTIN(__builtin_riscv_aes64esm_64, "WiWiWi", "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_sha512sig0h_32, "ZiZiZi", "nc", "zknh")
TARGET_BUILTIN(__builtin_riscv_sha512sig0l_32, "ZiZiZi", "nc", "zknh")
TARGET_BUILTIN(__builtin_riscv_sha512sig1h_32, "ZiZiZi", "nc", "zknh")
TARGET_BUILTIN(__builtin_riscv_sha512sig1l_32, "ZiZiZi", "nc", "zknh")
TARGET_BUILTIN(__builtin_riscv_sha512sum0r_32, "ZiZiZi", "nc", "zknh")
TARGET_BUILTIN(__builtin_riscv_sha512sum1r_32, "ZiZiZi", "nc", "zknh")
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")
// Zksed extension
TARGET_BUILTIN(__builtin_riscv_sm4ed, "LiLiLiIUc", "nc", "zksed")
TARGET_BUILTIN(__builtin_riscv_sm4ks, "LiLiLiIUc", "nc", "zksed")
// Zksh extension
TARGET_BUILTIN(__builtin_riscv_sm3p0, "LiLi", "nc", "zksh")
TARGET_BUILTIN(__builtin_riscv_sm3p1, "LiLi", "nc", "zksh")
#undef BUILTIN
#undef TARGET_BUILTIN
@@ -0,0 +1,32 @@
//===--- BuiltinsVE.def - VE 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 VE-specific builtin function database. Users of
// this file must define the BUILTIN macro to make use of this information.
//
//===----------------------------------------------------------------------===//
#if defined(BUILTIN) && !defined(TARGET_BUILTIN)
# define TARGET_BUILTIN(ID, TYPE, ATTRS, FEATURE) BUILTIN(ID, TYPE, ATTRS)
#endif
// The format of this database is decribed in clang/Basic/Builtins.def.
BUILTIN(__builtin_ve_vl_pack_f32p, "ULifC*fC*", "n")
BUILTIN(__builtin_ve_vl_pack_f32a, "ULifC*", "n")
BUILTIN(__builtin_ve_vl_extract_vm512u, "V256bV512b", "n")
BUILTIN(__builtin_ve_vl_extract_vm512l, "V256bV512b", "n")
BUILTIN(__builtin_ve_vl_insert_vm512u, "V512bV512bV256b", "n")
BUILTIN(__builtin_ve_vl_insert_vm512l, "V512bV512bV256b", "n")
// Use generated BUILTIN definitions
#include "clang/Basic/BuiltinsVEVL.gen.def"
#undef BUILTIN
#undef TARGET_BUILTIN
File diff suppressed because it is too large Load Diff
@@ -158,8 +158,8 @@ TARGET_BUILTIN(__builtin_wasm_narrow_u_i8x16_i16x8, "V16UcV8sV8s", "nc", "simd12
TARGET_BUILTIN(__builtin_wasm_narrow_s_i16x8_i32x4, "V8sV4iV4i", "nc", "simd128")
TARGET_BUILTIN(__builtin_wasm_narrow_u_i16x8_i32x4, "V8UsV4iV4i", "nc", "simd128")
TARGET_BUILTIN(__builtin_wasm_trunc_sat_zero_s_f64x2_i32x4, "V4iV2d", "nc", "simd128")
TARGET_BUILTIN(__builtin_wasm_trunc_sat_zero_u_f64x2_i32x4, "V4UiV2d", "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)
TARGET_BUILTIN(__builtin_wasm_fma_f32x4, "V4fV4fV4fV4f", "nc", "relaxed-simd")
@@ -181,8 +181,13 @@ TARGET_BUILTIN(__builtin_wasm_relaxed_max_f64x2, "V2dV2dV2d", "nc", "relaxed-sim
TARGET_BUILTIN(__builtin_wasm_relaxed_trunc_s_i32x4_f32x4, "V4iV4f", "nc", "relaxed-simd")
TARGET_BUILTIN(__builtin_wasm_relaxed_trunc_u_i32x4_f32x4, "V4UiV4f", "nc", "relaxed-simd")
TARGET_BUILTIN(__builtin_wasm_relaxed_trunc_zero_s_i32x4_f64x2, "V4iV2d", "nc", "relaxed-simd")
TARGET_BUILTIN(__builtin_wasm_relaxed_trunc_zero_u_i32x4_f64x2, "V4UiV2d", "nc", "relaxed-simd")
TARGET_BUILTIN(__builtin_wasm_relaxed_trunc_s_zero_i32x4_f64x2, "V4iV2d", "nc", "relaxed-simd")
TARGET_BUILTIN(__builtin_wasm_relaxed_trunc_u_zero_i32x4_f64x2, "V4UiV2d", "nc", "relaxed-simd")
TARGET_BUILTIN(__builtin_wasm_relaxed_q15mulr_s_i16x8, "V8sV8sV8s", "nc", "relaxed-simd")
TARGET_BUILTIN(__builtin_wasm_dot_i8x16_i7x16_s_i16x8, "V8sV16ScV16Sc", "nc", "relaxed-simd")
TARGET_BUILTIN(__builtin_wasm_dot_i8x16_i7x16_add_s_i32x4, "V4iV16ScV16ScV4i", "nc", "relaxed-simd")
#undef BUILTIN
#undef TARGET_BUILTIN
@@ -254,14 +254,6 @@ TARGET_BUILTIN(__builtin_ia32_minpd, "V2dV2dV2d", "ncV:128:", "sse2")
TARGET_BUILTIN(__builtin_ia32_maxpd, "V2dV2dV2d", "ncV:128:", "sse2")
TARGET_BUILTIN(__builtin_ia32_minsd, "V2dV2dV2d", "ncV:128:", "sse2")
TARGET_BUILTIN(__builtin_ia32_maxsd, "V2dV2dV2d", "ncV:128:", "sse2")
TARGET_BUILTIN(__builtin_ia32_paddsb128, "V16cV16cV16c", "ncV:128:", "sse2")
TARGET_BUILTIN(__builtin_ia32_paddsw128, "V8sV8sV8s", "ncV:128:", "sse2")
TARGET_BUILTIN(__builtin_ia32_psubsb128, "V16cV16cV16c", "ncV:128:", "sse2")
TARGET_BUILTIN(__builtin_ia32_psubsw128, "V8sV8sV8s", "ncV:128:", "sse2")
TARGET_BUILTIN(__builtin_ia32_paddusb128, "V16cV16cV16c", "ncV:128:", "sse2")
TARGET_BUILTIN(__builtin_ia32_paddusw128, "V8sV8sV8s", "ncV:128:", "sse2")
TARGET_BUILTIN(__builtin_ia32_psubusb128, "V16cV16cV16c", "ncV:128:", "sse2")
TARGET_BUILTIN(__builtin_ia32_psubusw128, "V8sV8sV8s", "ncV:128:", "sse2")
TARGET_BUILTIN(__builtin_ia32_pmulhw128, "V8sV8sV8s", "ncV:128:", "sse2")
TARGET_BUILTIN(__builtin_ia32_pavgb128, "V16cV16cV16c", "ncV:128:", "sse2")
TARGET_BUILTIN(__builtin_ia32_pavgw128, "V8sV8sV8s", "ncV:128:", "sse2")
@@ -269,6 +261,7 @@ TARGET_BUILTIN(__builtin_ia32_packsswb128, "V16cV8sV8s", "ncV:128:", "sse2")
TARGET_BUILTIN(__builtin_ia32_packssdw128, "V8sV4iV4i", "ncV:128:", "sse2")
TARGET_BUILTIN(__builtin_ia32_packuswb128, "V16cV8sV8s", "ncV:128:", "sse2")
TARGET_BUILTIN(__builtin_ia32_pmulhuw128, "V8sV8sV8s", "ncV:128:", "sse2")
TARGET_BUILTIN(__builtin_ia32_vec_ext_v2di, "OiV2OiIi", "ncV:128:", "sse2")
TARGET_BUILTIN(__builtin_ia32_vec_ext_v4si, "iV4iIi", "ncV:128:", "sse2")
TARGET_BUILTIN(__builtin_ia32_vec_ext_v4sf, "fV4fIi", "ncV:128:", "sse2")
TARGET_BUILTIN(__builtin_ia32_vec_ext_v8hi, "sV8sIi", "ncV:128:", "sse2")
@@ -547,14 +540,6 @@ TARGET_BUILTIN(__builtin_ia32_packsswb256, "V32cV16sV16s", "ncV:256:", "avx2")
TARGET_BUILTIN(__builtin_ia32_packssdw256, "V16sV8iV8i", "ncV:256:", "avx2")
TARGET_BUILTIN(__builtin_ia32_packuswb256, "V32cV16sV16s", "ncV:256:", "avx2")
TARGET_BUILTIN(__builtin_ia32_packusdw256, "V16sV8iV8i", "ncV:256:", "avx2")
TARGET_BUILTIN(__builtin_ia32_paddsb256, "V32cV32cV32c", "ncV:256:", "avx2")
TARGET_BUILTIN(__builtin_ia32_paddsw256, "V16sV16sV16s", "ncV:256:", "avx2")
TARGET_BUILTIN(__builtin_ia32_psubsb256, "V32cV32cV32c", "ncV:256:", "avx2")
TARGET_BUILTIN(__builtin_ia32_psubsw256, "V16sV16sV16s", "ncV:256:", "avx2")
TARGET_BUILTIN(__builtin_ia32_paddusb256, "V32cV32cV32c", "ncV:256:", "avx2")
TARGET_BUILTIN(__builtin_ia32_paddusw256, "V16sV16sV16s", "ncV:256:", "avx2")
TARGET_BUILTIN(__builtin_ia32_psubusb256, "V32cV32cV32c", "ncV:256:", "avx2")
TARGET_BUILTIN(__builtin_ia32_psubusw256, "V16sV16sV16s", "ncV:256:", "avx2")
TARGET_BUILTIN(__builtin_ia32_palignr256, "V32cV32cV32cIi", "ncV:256:", "avx2")
TARGET_BUILTIN(__builtin_ia32_pavgb256, "V32cV32cV32c", "ncV:256:", "avx2")
TARGET_BUILTIN(__builtin_ia32_pavgw256, "V16sV16sV16s", "ncV:256:", "avx2")
@@ -1009,17 +994,9 @@ TARGET_BUILTIN(__builtin_ia32_packssdw512, "V32sV16iV16i", "ncV:512:", "avx512bw
TARGET_BUILTIN(__builtin_ia32_packsswb512, "V64cV32sV32s", "ncV:512:", "avx512bw")
TARGET_BUILTIN(__builtin_ia32_packusdw512, "V32sV16iV16i", "ncV:512:", "avx512bw")
TARGET_BUILTIN(__builtin_ia32_packuswb512, "V64cV32sV32s", "ncV:512:", "avx512bw")
TARGET_BUILTIN(__builtin_ia32_paddsb512, "V64cV64cV64c", "ncV:512:", "avx512bw")
TARGET_BUILTIN(__builtin_ia32_paddsw512, "V32sV32sV32s", "ncV:512:", "avx512bw")
TARGET_BUILTIN(__builtin_ia32_paddusb512, "V64cV64cV64c", "ncV:512:", "avx512bw")
TARGET_BUILTIN(__builtin_ia32_paddusw512, "V32sV32sV32s", "ncV:512:", "avx512bw")
TARGET_BUILTIN(__builtin_ia32_pavgb512, "V64cV64cV64c", "ncV:512:", "avx512bw")
TARGET_BUILTIN(__builtin_ia32_pavgw512, "V32sV32sV32s", "ncV:512:", "avx512bw")
TARGET_BUILTIN(__builtin_ia32_pshufb512, "V64cV64cV64c", "ncV:512:", "avx512bw")
TARGET_BUILTIN(__builtin_ia32_psubsb512, "V64cV64cV64c", "ncV:512:", "avx512bw")
TARGET_BUILTIN(__builtin_ia32_psubsw512, "V32sV32sV32s", "ncV:512:", "avx512bw")
TARGET_BUILTIN(__builtin_ia32_psubusb512, "V64cV64cV64c", "ncV:512:", "avx512bw")
TARGET_BUILTIN(__builtin_ia32_psubusw512, "V32sV32sV32s", "ncV:512:", "avx512bw")
TARGET_BUILTIN(__builtin_ia32_vpconflictdi_128, "V2OiV2Oi", "ncV:128:", "avx512cd,avx512vl")
TARGET_BUILTIN(__builtin_ia32_vpconflictdi_256, "V4OiV4Oi", "ncV:256:", "avx512cd,avx512vl")
@@ -2013,8 +1990,6 @@ TARGET_BUILTIN(__builtin_ia32_selectss_128, "V4fUcV4fV4f", "ncV:128:", "avx512f"
TARGET_BUILTIN(__builtin_ia32_selectsd_128, "V2dUcV2dV2d", "ncV:128:", "avx512f")
// generic reduction intrinsics
TARGET_BUILTIN(__builtin_ia32_reduce_add_d512, "iV16i", "ncV:512:", "avx512f")
TARGET_BUILTIN(__builtin_ia32_reduce_add_q512, "OiV8Oi", "ncV:512:", "avx512f")
TARGET_BUILTIN(__builtin_ia32_reduce_fadd_pd512, "ddV8d", "ncV:512:", "avx512f")
TARGET_BUILTIN(__builtin_ia32_reduce_fadd_ps512, "ffV16f", "ncV:512:", "avx512f")
TARGET_BUILTIN(__builtin_ia32_reduce_fadd_ph512, "xxV32x", "ncV:512:", "avx512fp16")
@@ -2035,8 +2010,6 @@ TARGET_BUILTIN(__builtin_ia32_reduce_fmul_ps512, "ffV16f", "ncV:512:", "avx512f"
TARGET_BUILTIN(__builtin_ia32_reduce_fmul_ph512, "xxV32x", "ncV:512:", "avx512fp16")
TARGET_BUILTIN(__builtin_ia32_reduce_fmul_ph256, "xxV16x", "ncV:256:", "avx512fp16,avx512vl")
TARGET_BUILTIN(__builtin_ia32_reduce_fmul_ph128, "xxV8x", "ncV:128:", "avx512fp16,avx512vl")
TARGET_BUILTIN(__builtin_ia32_reduce_mul_d512, "iV16i", "ncV:512:", "avx512f")
TARGET_BUILTIN(__builtin_ia32_reduce_mul_q512, "OiV8Oi", "ncV:512:", "avx512f")
// MONITORX/MWAITX
TARGET_BUILTIN(__builtin_ia32_monitorx, "vvC*UiUi", "n", "mwaitx")
@@ -2095,6 +2068,9 @@ TARGET_HEADER_BUILTIN(_ReadWriteBarrier, "v", "nh", "intrin.h", ALL_MS_LANGUAGES
TARGET_HEADER_BUILTIN(_ReadBarrier, "v", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
TARGET_HEADER_BUILTIN(_WriteBarrier, "v", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
TARGET_HEADER_BUILTIN(__cpuid, "vi*i", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
TARGET_HEADER_BUILTIN(__cpuidex, "vi*ii", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
TARGET_HEADER_BUILTIN(__emul, "LLiii", "nch", "intrin.h", ALL_MS_LANGUAGES, "")
TARGET_HEADER_BUILTIN(__emulu, "ULLiUiUi", "nch", "intrin.h", ALL_MS_LANGUAGES, "")
@@ -42,7 +42,6 @@ TARGET_BUILTIN(__builtin_ia32_cvttss2si64, "OiV4f", "ncV:128:", "sse")
TARGET_BUILTIN(__builtin_ia32_cvtsd2si64, "OiV2d", "ncV:128:", "sse2")
TARGET_BUILTIN(__builtin_ia32_cvttsd2si64, "OiV2d", "ncV:128:", "sse2")
TARGET_BUILTIN(__builtin_ia32_movnti64, "vOi*Oi", "n", "sse2")
TARGET_BUILTIN(__builtin_ia32_vec_ext_v2di, "OiV2OiIi", "ncV:128:", "sse2")
TARGET_BUILTIN(__builtin_ia32_vec_set_v2di, "V2OiV2OiOiIi", "ncV:128:", "sse4.1")
TARGET_BUILTIN(__builtin_ia32_crc32di, "UOiUOiUOi", "nc", "crc32")
TARGET_BUILTIN(__builtin_ia32_vec_ext_v4di, "OiV4OiIi", "ncV:256:", "avx")
@@ -38,15 +38,16 @@ namespace charinfo {
};
} // end namespace charinfo
/// Returns true if this is an ASCII character.
/// Returns true if a byte is an ASCII character.
LLVM_READNONE inline bool isASCII(char c) {
return static_cast<unsigned char>(c) <= 127;
}
LLVM_READNONE inline bool isASCII(unsigned char c) { return c <= 127; }
/// Returns true if this is an ASCII character.
/// Returns true if a codepoint is an ASCII character.
LLVM_READNONE inline bool isASCII(uint32_t c) { return c <= 127; }
LLVM_READNONE inline bool isASCII(int64_t c) { return 0 <= c && c <= 127; }
/// Returns true if this is a valid first character of a C identifier,
/// which is [a-zA-Z_].
@@ -162,6 +163,44 @@ LLVM_READONLY inline bool isRawStringDelimBody(unsigned char c) {
CHAR_DIGIT|CHAR_UNDER|CHAR_RAWDEL)) != 0;
}
enum class EscapeChar {
Single = 1,
Double = 2,
SingleAndDouble = static_cast<int>(Single) | static_cast<int>(Double),
};
/// Return C-style escaped string for special characters, or an empty string if
/// there is no such mapping.
template <EscapeChar Opt, class CharT>
LLVM_READONLY inline auto escapeCStyle(CharT Ch) -> StringRef {
switch (Ch) {
case '\\':
return "\\\\";
case '\'':
if ((static_cast<int>(Opt) & static_cast<int>(EscapeChar::Single)) == 0)
break;
return "\\'";
case '"':
if ((static_cast<int>(Opt) & static_cast<int>(EscapeChar::Double)) == 0)
break;
return "\\\"";
case '\a':
return "\\a";
case '\b':
return "\\b";
case '\f':
return "\\f";
case '\n':
return "\\n";
case '\r':
return "\\r";
case '\t':
return "\\t";
case '\v':
return "\\v";
}
return {};
}
/// Converts the given ASCII character to its lowercase equivalent.
///
@@ -64,8 +64,7 @@ CODEGENOPT(DisableLifetimeMarkers, 1, 0) ///< Don't emit any lifetime markers
CODEGENOPT(DisableO0ImplyOptNone , 1, 0) ///< Don't annonate function with optnone at O0
CODEGENOPT(ExperimentalStrictFloatingPoint, 1, 0) ///< Enables the new, experimental
///< strict floating point.
CODEGENOPT(DisableNoundefAttrs, 1, 0) ///< Disable emitting `noundef` attributes on IR call arguments and return values
CODEGENOPT(LegacyPassManager, 1, 0) ///< Use the legacy pass manager.
CODEGENOPT(EnableNoundefAttrs, 1, 0) ///< Enable emitting `noundef` attributes on IR call arguments and return values
CODEGENOPT(DebugPassManager, 1, 0) ///< Prints debug information for the new
///< pass manager.
CODEGENOPT(DisableRedZone , 1, 0) ///< Set when -mno-red-zone is enabled.
@@ -115,6 +114,10 @@ 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-dwarf-unwind is passed.
ENUM_CODEGENOPT(EmitDwarfUnwind, llvm::EmitDwarfUnwindType, 2,
llvm::EmitDwarfUnwindType::Default)
///< Set when -fxray-always-emit-customevents is enabled.
CODEGENOPT(XRayAlwaysEmitCustomEvents , 1, 0)
@@ -144,6 +147,7 @@ VALUE_CODEGENOPT(PatchableFunctionEntryOffset , 32, 0)
CODEGENOPT(HotPatch, 1, 0) ///< Supports the Microsoft /HOTPATCH flag and
///< generates a 'patchable-function' attribute.
CODEGENOPT(JMCInstrument, 1, 0) ///< Set when -fjmc is enabled.
CODEGENOPT(InstrumentForProfiling , 1, 0) ///< Set when -pg is enabled.
CODEGENOPT(CallFEntry , 1, 0) ///< Set when -mfentry is enabled.
CODEGENOPT(MNopMCount , 1, 0) ///< Set when -mnop-mcount is enabled.
@@ -174,6 +178,7 @@ CODEGENOPT(NoExecStack , 1, 0) ///< Set when -Wa,--noexecstack is enabled.
CODEGENOPT(FatalWarnings , 1, 0) ///< Set when -Wa,--fatal-warnings is
///< enabled.
CODEGENOPT(NoWarn , 1, 0) ///< Set when -Wa,--no-warn is enabled.
CODEGENOPT(MisExpect , 1, 0) ///< Set when -Wmisexpect is enabled
CODEGENOPT(EnableSegmentedStacks , 1, 0) ///< Set when -fsplit-stack is enabled.
CODEGENOPT(NoInlineLineTables, 1, 0) ///< Whether debug info should contain
///< inline line tables.
@@ -182,6 +187,7 @@ CODEGENOPT(NoImplicitFloat , 1, 0) ///< Set when -mno-implicit-float is enable
CODEGENOPT(NullPointerIsValid , 1, 0) ///< Assume Null pointer deference is defined.
CODEGENOPT(OpenCLCorrectlyRoundedDivSqrt, 1, 0) ///< -cl-fp32-correctly-rounded-divide-sqrt
CODEGENOPT(HIPCorrectlyRoundedDivSqrt, 1, 1) ///< -fno-hip-fp32-correctly-rounded-divide-sqrt
CODEGENOPT(HIPSaveKernelArgName, 1, 0) ///< Set when -fhip-kernel-arg-name is enabled.
CODEGENOPT(UniqueInternalLinkageNames, 1, 0) ///< Internal Linkage symbols get unique names.
CODEGENOPT(SplitMachineFunctions, 1, 0) ///< Split machine functions using profile information.
@@ -464,6 +470,13 @@ ENUM_CODEGENOPT(SwiftAsyncFramePointer, SwiftAsyncFramePointerKind, 2,
/// Whether to skip RAX setup when passing variable arguments (x86 only).
CODEGENOPT(SkipRaxSetup, 1, 0)
/// Whether to zero out caller-used registers before returning.
ENUM_CODEGENOPT(ZeroCallUsedRegs, llvm::ZeroCallUsedRegs::ZeroCallUsedRegsKind,
5, llvm::ZeroCallUsedRegs::ZeroCallUsedRegsKind::Skip)
/// Whether to use opaque pointers.
CODEGENOPT(OpaquePointers, 1, 0)
#undef CODEGENOPT
#undef ENUM_CODEGENOPT
#undef VALUE_CODEGENOPT
@@ -276,9 +276,8 @@ class CodeGenOptions : public CodeGenOptionsBase {
/// CUDA runtime back-end for incorporating them into host-side object file.
std::string CudaGpuBinaryFileName;
/// List of filenames and section name pairs passed in using the
/// -fembed-offload-object option to embed device-side offloading objects into
/// the host as a named section. Input passed in as '<filename>,<section>'
/// List of filenames passed in using the -fembed-offload-object option. These
/// are offloading binaries containing device images and metadata.
std::vector<std::string> OffloadObjects;
/// The name of the file to which the backend should save YAML optimization
@@ -420,6 +419,10 @@ class CodeGenOptions : public CodeGenOptionsBase {
/// If threshold option is not specified, it is disabled by default.
Optional<uint64_t> DiagnosticsHotnessThreshold = 0;
/// The maximum percentage profiling weights can deviate from the expected
/// values in order to be included in misexpect diagnostics.
Optional<uint64_t> DiagnosticsMisExpectTolerance = 0;
public:
// Define accessors/mutators for code generation options of enumeration type.
#define CODEGENOPT(Name, Bits, Default)
@@ -85,6 +85,7 @@ enum class CudaArch {
GFX909,
GFX90a,
GFX90c,
GFX940,
GFX1010,
GFX1011,
GFX1012,
@@ -95,9 +96,17 @@ enum class CudaArch {
GFX1033,
GFX1034,
GFX1035,
GFX1036,
GFX1100,
GFX1101,
GFX1102,
GFX1103,
Generic, // A processor model named 'generic' if the target backend defines a
// public one.
LAST,
CudaDefault = CudaArch::SM_35,
HIPDefault = CudaArch::GFX803,
};
static inline bool IsNVIDIAGpuArch(CudaArch A) {
@@ -142,8 +142,7 @@ class DarwinSDKInfo {
auto Mapping = VersionMappings.find(Kind.Value);
if (Mapping == VersionMappings.end())
return nullptr;
return Mapping->getSecond().hasValue() ? Mapping->getSecond().getPointer()
: nullptr;
return Mapping->getSecond() ? Mapping->getSecond().getPointer() : nullptr;
}
static Optional<DarwinSDKInfo>
@@ -41,6 +41,7 @@ def Named : DeclNode<Decl, "named declarations", 1>;
def OMPDeclareReduction : DeclNode<Value>, DeclContext;
def OMPDeclareMapper : DeclNode<Value>, DeclContext;
def MSGuid : DeclNode<Value>;
def UnnamedGlobalConstant : DeclNode<Value>;
def TemplateParamObject : DeclNode<Value>;
def Declarator : DeclNode<Value, "declarators", 1>;
def Field : DeclNode<Declarator, "non-static data members">;
@@ -39,7 +39,8 @@
namespace llvm {
class Error;
}
class raw_ostream;
} // namespace llvm
namespace clang {
@@ -544,6 +545,7 @@ class DiagnosticsEngine : public RefCountedBase<DiagnosticsEngine> {
DiagnosticsEngine &operator=(const DiagnosticsEngine &) = delete;
~DiagnosticsEngine();
friend void DiagnosticsTestHelper(DiagnosticsEngine &);
LLVM_DUMP_METHOD void dump() const;
LLVM_DUMP_METHOD void dump(StringRef DiagName) const;
@@ -890,9 +892,9 @@ class DiagnosticsEngine : public RefCountedBase<DiagnosticsEngine> {
LastDiagLevel = Other.LastDiagLevel;
}
/// Reset the state of the diagnostic object to its initial
/// configuration.
void Reset();
/// Reset the state of the diagnostic object to its initial configuration.
/// \param[in] soft - if true, doesn't reset the diagnostic mappings and state
void Reset(bool soft = false);
//===--------------------------------------------------------------------===//
// DiagnosticsEngine classification and reporting interfaces.
@@ -1403,7 +1405,13 @@ inline const StreamingDiagnostic &operator<<(const StreamingDiagnostic &DB,
}
inline const StreamingDiagnostic &operator<<(const StreamingDiagnostic &DB,
int64_t I) {
long I) {
DB.AddTaggedVal(I, DiagnosticsEngine::ak_sint);
return DB;
}
inline const StreamingDiagnostic &operator<<(const StreamingDiagnostic &DB,
long long I) {
DB.AddTaggedVal(I, DiagnosticsEngine::ak_sint);
return DB;
}
@@ -1425,7 +1433,13 @@ inline const StreamingDiagnostic &operator<<(const StreamingDiagnostic &DB,
}
inline const StreamingDiagnostic &operator<<(const StreamingDiagnostic &DB,
uint64_t I) {
unsigned long I) {
DB.AddTaggedVal(I, DiagnosticsEngine::ak_uint);
return DB;
}
inline const StreamingDiagnostic &operator<<(const StreamingDiagnostic &DB,
unsigned long long I) {
DB.AddTaggedVal(I, DiagnosticsEngine::ak_uint);
return DB;
}
@@ -1717,6 +1731,9 @@ class StoredDiagnostic {
}
};
// Simple debug printing of StoredDiagnostic.
llvm::raw_ostream &operator<<(llvm::raw_ostream &OS, const StoredDiagnostic &);
/// Abstract interface, implemented by clients of the front-end, which
/// formats and prints fully processed diagnostics.
class DiagnosticConsumer {
@@ -65,6 +65,8 @@ def note_consteval_address_accessible : Note<
"is not a constant expression">;
def note_constexpr_uninitialized : Note<
"%select{|sub}0object of type %1 is not initialized">;
def note_constexpr_static_local : Note<
"control flows through the definition of a %select{static|thread_local}0 variable">;
def note_constexpr_subobject_declared_here : Note<
"subobject declared here">;
def note_constexpr_array_index : Note<"cannot refer to element %0 of "
@@ -362,6 +364,8 @@ def note_constexpr_memory_leak : Note<
"%plural{0:|: (along with %0 other memory leak%s0)}0">;
def note_constexpr_unsupported_layout : Note<
"type %0 has unexpected layout">;
def note_constexpr_unsupported_flexible_array : Note<
"flexible array initialization is not yet supported">;
def err_experimental_clang_interp_failed : Error<
"the experimental clang interpreter failed to evaluate an expression">;
@@ -439,8 +443,6 @@ def note_odr_tag_kind_here: Note<
def note_odr_field : Note<"field %0 has type %1 here">;
def note_odr_field_name : Note<"field has name %0 here">;
def note_odr_missing_field : Note<"no corresponding field here">;
def note_odr_bit_field : Note<"bit-field %0 with type %1 and length %2 here">;
def note_odr_not_bit_field : Note<"field %0 is not a bit-field">;
def note_odr_base : Note<"class has base type %0">;
def note_odr_virtual_base : Note<
"%select{non-virtual|virtual}0 derivation here">;
@@ -21,7 +21,8 @@ namespace clang {
};
enum class Group {
#define DIAG_ENTRY(GroupName, FlagNameOffset, Members, SubGroups) GroupName,
#define DIAG_ENTRY(GroupName, FlagNameOffset, Members, SubGroups, Docs) \
GroupName,
#include "clang/Basic/DiagnosticGroups.inc"
#undef CATEGORY
#undef DIAG_ENTRY
@@ -155,8 +155,8 @@ def note_add_deprecation_attr : Note<
// inline contents commands
def warn_doc_inline_contents_no_argument : Warning<
"'%select{\\|@}0%1' command does not have a valid word argument">,
def warn_doc_inline_command_not_enough_arguments : Warning<
"'%select{\\|@}0%1' command has %plural{0:no|:%2}2 word argument%s2, expected %3">,
InGroup<Documentation>, DefaultIgnore;
// verbatim block commands

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