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:
+2
-1
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
+213
-11
@@ -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
|
||||
|
||||
+114
-12
@@ -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_
|
||||
+39
@@ -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
|
||||
+85
@@ -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
|
||||
|
||||
+10
-6
@@ -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
|
||||
|
||||
|
||||
+37
@@ -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
Reference in New Issue
Block a user