Merge llvm-project main llvmorg-16-init-18548-gb0daacf58f41

This updates llvm, clang, compiler-rt, libc++, libunwind, lld, lldb and
openmp to llvmorg-16-init-18548-gb0daacf58f41.

PR:		271047
MFC after:	1 month
This commit is contained in:
Dimitry Andric
2023-04-14 23:41:27 +02:00
6373 changed files with 393930 additions and 218406 deletions
+329
View File
@@ -52,6 +52,335 @@
# xargs -n1 | sort | uniq -d;
# done
# 20230622: new clang import which bumps version from 15.0.7 to 16.0.1
OLD_FILES+=usr/lib/clang/15.0.7/include/__clang_cuda_builtin_vars.h
OLD_FILES+=usr/lib/clang/15.0.7/include/__clang_cuda_cmath.h
OLD_FILES+=usr/lib/clang/15.0.7/include/__clang_cuda_complex_builtins.h
OLD_FILES+=usr/lib/clang/15.0.7/include/__clang_cuda_device_functions.h
OLD_FILES+=usr/lib/clang/15.0.7/include/__clang_cuda_intrinsics.h
OLD_FILES+=usr/lib/clang/15.0.7/include/__clang_cuda_libdevice_declares.h
OLD_FILES+=usr/lib/clang/15.0.7/include/__clang_cuda_math.h
OLD_FILES+=usr/lib/clang/15.0.7/include/__clang_cuda_math_forward_declares.h
OLD_FILES+=usr/lib/clang/15.0.7/include/__clang_cuda_runtime_wrapper.h
OLD_FILES+=usr/lib/clang/15.0.7/include/__clang_cuda_texture_intrinsics.h
OLD_FILES+=usr/lib/clang/15.0.7/include/__clang_hip_cmath.h
OLD_FILES+=usr/lib/clang/15.0.7/include/__clang_hip_libdevice_declares.h
OLD_FILES+=usr/lib/clang/15.0.7/include/__clang_hip_math.h
OLD_FILES+=usr/lib/clang/15.0.7/include/__clang_hip_runtime_wrapper.h
OLD_FILES+=usr/lib/clang/15.0.7/include/__stddef_max_align_t.h
OLD_FILES+=usr/lib/clang/15.0.7/include/__wmmintrin_aes.h
OLD_FILES+=usr/lib/clang/15.0.7/include/__wmmintrin_pclmul.h
OLD_FILES+=usr/lib/clang/15.0.7/include/adxintrin.h
OLD_FILES+=usr/lib/clang/15.0.7/include/altivec.h
OLD_FILES+=usr/lib/clang/15.0.7/include/ammintrin.h
OLD_FILES+=usr/lib/clang/15.0.7/include/amxintrin.h
OLD_FILES+=usr/lib/clang/15.0.7/include/arm64intr.h
OLD_FILES+=usr/lib/clang/15.0.7/include/arm_acle.h
OLD_FILES+=usr/lib/clang/15.0.7/include/arm_bf16.h
OLD_FILES+=usr/lib/clang/15.0.7/include/arm_cde.h
OLD_FILES+=usr/lib/clang/15.0.7/include/arm_cmse.h
OLD_FILES+=usr/lib/clang/15.0.7/include/arm_fp16.h
OLD_FILES+=usr/lib/clang/15.0.7/include/arm_mve.h
OLD_FILES+=usr/lib/clang/15.0.7/include/arm_neon.h
OLD_FILES+=usr/lib/clang/15.0.7/include/arm_neon_sve_bridge.h
OLD_FILES+=usr/lib/clang/15.0.7/include/arm_sve.h
OLD_FILES+=usr/lib/clang/15.0.7/include/armintr.h
OLD_FILES+=usr/lib/clang/15.0.7/include/avx2intrin.h
OLD_FILES+=usr/lib/clang/15.0.7/include/avx512bf16intrin.h
OLD_FILES+=usr/lib/clang/15.0.7/include/avx512bitalgintrin.h
OLD_FILES+=usr/lib/clang/15.0.7/include/avx512bwintrin.h
OLD_FILES+=usr/lib/clang/15.0.7/include/avx512cdintrin.h
OLD_FILES+=usr/lib/clang/15.0.7/include/avx512dqintrin.h
OLD_FILES+=usr/lib/clang/15.0.7/include/avx512erintrin.h
OLD_FILES+=usr/lib/clang/15.0.7/include/avx512fintrin.h
OLD_FILES+=usr/lib/clang/15.0.7/include/avx512fp16intrin.h
OLD_FILES+=usr/lib/clang/15.0.7/include/avx512ifmaintrin.h
OLD_FILES+=usr/lib/clang/15.0.7/include/avx512ifmavlintrin.h
OLD_FILES+=usr/lib/clang/15.0.7/include/avx512pfintrin.h
OLD_FILES+=usr/lib/clang/15.0.7/include/avx512vbmi2intrin.h
OLD_FILES+=usr/lib/clang/15.0.7/include/avx512vbmiintrin.h
OLD_FILES+=usr/lib/clang/15.0.7/include/avx512vbmivlintrin.h
OLD_FILES+=usr/lib/clang/15.0.7/include/avx512vlbf16intrin.h
OLD_FILES+=usr/lib/clang/15.0.7/include/avx512vlbitalgintrin.h
OLD_FILES+=usr/lib/clang/15.0.7/include/avx512vlbwintrin.h
OLD_FILES+=usr/lib/clang/15.0.7/include/avx512vlcdintrin.h
OLD_FILES+=usr/lib/clang/15.0.7/include/avx512vldqintrin.h
OLD_FILES+=usr/lib/clang/15.0.7/include/avx512vlfp16intrin.h
OLD_FILES+=usr/lib/clang/15.0.7/include/avx512vlintrin.h
OLD_FILES+=usr/lib/clang/15.0.7/include/avx512vlvbmi2intrin.h
OLD_FILES+=usr/lib/clang/15.0.7/include/avx512vlvnniintrin.h
OLD_FILES+=usr/lib/clang/15.0.7/include/avx512vlvp2intersectintrin.h
OLD_FILES+=usr/lib/clang/15.0.7/include/avx512vnniintrin.h
OLD_FILES+=usr/lib/clang/15.0.7/include/avx512vp2intersectintrin.h
OLD_FILES+=usr/lib/clang/15.0.7/include/avx512vpopcntdqintrin.h
OLD_FILES+=usr/lib/clang/15.0.7/include/avx512vpopcntdqvlintrin.h
OLD_FILES+=usr/lib/clang/15.0.7/include/avxintrin.h
OLD_FILES+=usr/lib/clang/15.0.7/include/avxvnniintrin.h
OLD_FILES+=usr/lib/clang/15.0.7/include/bmi2intrin.h
OLD_FILES+=usr/lib/clang/15.0.7/include/bmiintrin.h
OLD_FILES+=usr/lib/clang/15.0.7/include/builtins.h
OLD_FILES+=usr/lib/clang/15.0.7/include/cet.h
OLD_FILES+=usr/lib/clang/15.0.7/include/cetintrin.h
OLD_FILES+=usr/lib/clang/15.0.7/include/cldemoteintrin.h
OLD_FILES+=usr/lib/clang/15.0.7/include/clflushoptintrin.h
OLD_FILES+=usr/lib/clang/15.0.7/include/clwbintrin.h
OLD_FILES+=usr/lib/clang/15.0.7/include/clzerointrin.h
OLD_FILES+=usr/lib/clang/15.0.7/include/cpuid.h
OLD_FILES+=usr/lib/clang/15.0.7/include/crc32intrin.h
OLD_FILES+=usr/lib/clang/15.0.7/include/cuda_wrappers/algorithm
OLD_FILES+=usr/lib/clang/15.0.7/include/cuda_wrappers/complex
OLD_FILES+=usr/lib/clang/15.0.7/include/cuda_wrappers/new
OLD_DIRS+=usr/lib/clang/15.0.7/include/cuda_wrappers
OLD_FILES+=usr/lib/clang/15.0.7/include/emmintrin.h
OLD_FILES+=usr/lib/clang/15.0.7/include/enqcmdintrin.h
OLD_FILES+=usr/lib/clang/15.0.7/include/f16cintrin.h
OLD_FILES+=usr/lib/clang/15.0.7/include/float.h
OLD_FILES+=usr/lib/clang/15.0.7/include/fma4intrin.h
OLD_FILES+=usr/lib/clang/15.0.7/include/fmaintrin.h
OLD_FILES+=usr/lib/clang/15.0.7/include/fuzzer/FuzzedDataProvider.h
OLD_DIRS+=usr/lib/clang/15.0.7/include/fuzzer
OLD_FILES+=usr/lib/clang/15.0.7/include/fxsrintrin.h
OLD_FILES+=usr/lib/clang/15.0.7/include/gfniintrin.h
OLD_FILES+=usr/lib/clang/15.0.7/include/hexagon_circ_brev_intrinsics.h
OLD_FILES+=usr/lib/clang/15.0.7/include/hexagon_protos.h
OLD_FILES+=usr/lib/clang/15.0.7/include/hexagon_types.h
OLD_FILES+=usr/lib/clang/15.0.7/include/hlsl/hlsl_basic_types.h
OLD_FILES+=usr/lib/clang/15.0.7/include/hlsl/hlsl_intrinsics.h
OLD_DIRS+=usr/lib/clang/15.0.7/include/hlsl
OLD_FILES+=usr/lib/clang/15.0.7/include/hlsl.h
OLD_FILES+=usr/lib/clang/15.0.7/include/hresetintrin.h
OLD_FILES+=usr/lib/clang/15.0.7/include/htmintrin.h
OLD_FILES+=usr/lib/clang/15.0.7/include/htmxlintrin.h
OLD_FILES+=usr/lib/clang/15.0.7/include/hvx_hexagon_protos.h
OLD_FILES+=usr/lib/clang/15.0.7/include/ia32intrin.h
OLD_FILES+=usr/lib/clang/15.0.7/include/immintrin.h
OLD_FILES+=usr/lib/clang/15.0.7/include/intrin.h
OLD_FILES+=usr/lib/clang/15.0.7/include/inttypes.h
OLD_FILES+=usr/lib/clang/15.0.7/include/invpcidintrin.h
OLD_FILES+=usr/lib/clang/15.0.7/include/iso646.h
OLD_FILES+=usr/lib/clang/15.0.7/include/keylockerintrin.h
OLD_FILES+=usr/lib/clang/15.0.7/include/limits.h
OLD_FILES+=usr/lib/clang/15.0.7/include/lwpintrin.h
OLD_FILES+=usr/lib/clang/15.0.7/include/lzcntintrin.h
OLD_FILES+=usr/lib/clang/15.0.7/include/mm3dnow.h
OLD_FILES+=usr/lib/clang/15.0.7/include/mm_malloc.h
OLD_FILES+=usr/lib/clang/15.0.7/include/mmintrin.h
OLD_FILES+=usr/lib/clang/15.0.7/include/module.modulemap
OLD_FILES+=usr/lib/clang/15.0.7/include/movdirintrin.h
OLD_FILES+=usr/lib/clang/15.0.7/include/msa.h
OLD_FILES+=usr/lib/clang/15.0.7/include/mwaitxintrin.h
OLD_FILES+=usr/lib/clang/15.0.7/include/nmmintrin.h
OLD_FILES+=usr/lib/clang/15.0.7/include/omp-tools.h
OLD_FILES+=usr/lib/clang/15.0.7/include/omp.h
OLD_FILES+=usr/lib/clang/15.0.7/include/ompt.h
OLD_FILES+=usr/lib/clang/15.0.7/include/opencl-c-base.h
OLD_FILES+=usr/lib/clang/15.0.7/include/opencl-c.h
OLD_FILES+=usr/lib/clang/15.0.7/include/openmp_wrappers/__clang_openmp_device_functions.h
OLD_FILES+=usr/lib/clang/15.0.7/include/openmp_wrappers/cmath
OLD_FILES+=usr/lib/clang/15.0.7/include/openmp_wrappers/complex
OLD_FILES+=usr/lib/clang/15.0.7/include/openmp_wrappers/complex.h
OLD_FILES+=usr/lib/clang/15.0.7/include/openmp_wrappers/complex_cmath.h
OLD_FILES+=usr/lib/clang/15.0.7/include/openmp_wrappers/math.h
OLD_FILES+=usr/lib/clang/15.0.7/include/openmp_wrappers/new
OLD_DIRS+=usr/lib/clang/15.0.7/include/openmp_wrappers
OLD_FILES+=usr/lib/clang/15.0.7/include/pconfigintrin.h
OLD_FILES+=usr/lib/clang/15.0.7/include/pkuintrin.h
OLD_FILES+=usr/lib/clang/15.0.7/include/pmmintrin.h
OLD_FILES+=usr/lib/clang/15.0.7/include/popcntintrin.h
OLD_FILES+=usr/lib/clang/15.0.7/include/ppc_wrappers/bmi2intrin.h
OLD_FILES+=usr/lib/clang/15.0.7/include/ppc_wrappers/bmiintrin.h
OLD_FILES+=usr/lib/clang/15.0.7/include/ppc_wrappers/emmintrin.h
OLD_FILES+=usr/lib/clang/15.0.7/include/ppc_wrappers/immintrin.h
OLD_FILES+=usr/lib/clang/15.0.7/include/ppc_wrappers/mm_malloc.h
OLD_FILES+=usr/lib/clang/15.0.7/include/ppc_wrappers/mmintrin.h
OLD_FILES+=usr/lib/clang/15.0.7/include/ppc_wrappers/pmmintrin.h
OLD_FILES+=usr/lib/clang/15.0.7/include/ppc_wrappers/smmintrin.h
OLD_FILES+=usr/lib/clang/15.0.7/include/ppc_wrappers/tmmintrin.h
OLD_FILES+=usr/lib/clang/15.0.7/include/ppc_wrappers/x86gprintrin.h
OLD_FILES+=usr/lib/clang/15.0.7/include/ppc_wrappers/x86intrin.h
OLD_FILES+=usr/lib/clang/15.0.7/include/ppc_wrappers/xmmintrin.h
OLD_DIRS+=usr/lib/clang/15.0.7/include/ppc_wrappers
OLD_FILES+=usr/lib/clang/15.0.7/include/prfchwintrin.h
OLD_FILES+=usr/lib/clang/15.0.7/include/profile/InstrProfData.inc
OLD_FILES+=usr/lib/clang/15.0.7/include/profile/MemProfData.inc
OLD_DIRS+=usr/lib/clang/15.0.7/include/profile
OLD_FILES+=usr/lib/clang/15.0.7/include/ptwriteintrin.h
OLD_FILES+=usr/lib/clang/15.0.7/include/rdpruintrin.h
OLD_FILES+=usr/lib/clang/15.0.7/include/rdseedintrin.h
OLD_FILES+=usr/lib/clang/15.0.7/include/riscv_vector.h
OLD_FILES+=usr/lib/clang/15.0.7/include/rtmintrin.h
OLD_FILES+=usr/lib/clang/15.0.7/include/s390intrin.h
OLD_FILES+=usr/lib/clang/15.0.7/include/sanitizer/allocator_interface.h
OLD_FILES+=usr/lib/clang/15.0.7/include/sanitizer/asan_interface.h
OLD_FILES+=usr/lib/clang/15.0.7/include/sanitizer/common_interface_defs.h
OLD_FILES+=usr/lib/clang/15.0.7/include/sanitizer/coverage_interface.h
OLD_FILES+=usr/lib/clang/15.0.7/include/sanitizer/dfsan_interface.h
OLD_FILES+=usr/lib/clang/15.0.7/include/sanitizer/hwasan_interface.h
OLD_FILES+=usr/lib/clang/15.0.7/include/sanitizer/linux_syscall_hooks.h
OLD_FILES+=usr/lib/clang/15.0.7/include/sanitizer/lsan_interface.h
OLD_FILES+=usr/lib/clang/15.0.7/include/sanitizer/memprof_interface.h
OLD_FILES+=usr/lib/clang/15.0.7/include/sanitizer/msan_interface.h
OLD_FILES+=usr/lib/clang/15.0.7/include/sanitizer/netbsd_syscall_hooks.h
OLD_FILES+=usr/lib/clang/15.0.7/include/sanitizer/scudo_interface.h
OLD_FILES+=usr/lib/clang/15.0.7/include/sanitizer/tsan_interface.h
OLD_FILES+=usr/lib/clang/15.0.7/include/sanitizer/tsan_interface_atomic.h
OLD_FILES+=usr/lib/clang/15.0.7/include/sanitizer/ubsan_interface.h
OLD_DIRS+=usr/lib/clang/15.0.7/include/sanitizer
OLD_FILES+=usr/lib/clang/15.0.7/include/serializeintrin.h
OLD_FILES+=usr/lib/clang/15.0.7/include/sgxintrin.h
OLD_FILES+=usr/lib/clang/15.0.7/include/shaintrin.h
OLD_FILES+=usr/lib/clang/15.0.7/include/smmintrin.h
OLD_FILES+=usr/lib/clang/15.0.7/include/stdalign.h
OLD_FILES+=usr/lib/clang/15.0.7/include/stdarg.h
OLD_FILES+=usr/lib/clang/15.0.7/include/stdatomic.h
OLD_FILES+=usr/lib/clang/15.0.7/include/stdbool.h
OLD_FILES+=usr/lib/clang/15.0.7/include/stddef.h
OLD_FILES+=usr/lib/clang/15.0.7/include/stdint.h
OLD_FILES+=usr/lib/clang/15.0.7/include/stdnoreturn.h
OLD_FILES+=usr/lib/clang/15.0.7/include/tbmintrin.h
OLD_FILES+=usr/lib/clang/15.0.7/include/tgmath.h
OLD_FILES+=usr/lib/clang/15.0.7/include/tmmintrin.h
OLD_FILES+=usr/lib/clang/15.0.7/include/tsxldtrkintrin.h
OLD_FILES+=usr/lib/clang/15.0.7/include/uintrintrin.h
OLD_FILES+=usr/lib/clang/15.0.7/include/unwind.h
OLD_FILES+=usr/lib/clang/15.0.7/include/vadefs.h
OLD_FILES+=usr/lib/clang/15.0.7/include/vaesintrin.h
OLD_FILES+=usr/lib/clang/15.0.7/include/varargs.h
OLD_FILES+=usr/lib/clang/15.0.7/include/vecintrin.h
OLD_FILES+=usr/lib/clang/15.0.7/include/velintrin.h
OLD_FILES+=usr/lib/clang/15.0.7/include/velintrin_approx.h
OLD_FILES+=usr/lib/clang/15.0.7/include/velintrin_gen.h
OLD_FILES+=usr/lib/clang/15.0.7/include/vpclmulqdqintrin.h
OLD_FILES+=usr/lib/clang/15.0.7/include/waitpkgintrin.h
OLD_FILES+=usr/lib/clang/15.0.7/include/wasm_simd128.h
OLD_FILES+=usr/lib/clang/15.0.7/include/wbnoinvdintrin.h
OLD_FILES+=usr/lib/clang/15.0.7/include/wmmintrin.h
OLD_FILES+=usr/lib/clang/15.0.7/include/x86gprintrin.h
OLD_FILES+=usr/lib/clang/15.0.7/include/x86intrin.h
OLD_FILES+=usr/lib/clang/15.0.7/include/xmmintrin.h
OLD_FILES+=usr/lib/clang/15.0.7/include/xopintrin.h
OLD_FILES+=usr/lib/clang/15.0.7/include/xray/xray_interface.h
OLD_FILES+=usr/lib/clang/15.0.7/include/xray/xray_log_interface.h
OLD_FILES+=usr/lib/clang/15.0.7/include/xray/xray_records.h
OLD_DIRS+=usr/lib/clang/15.0.7/include/xray
OLD_FILES+=usr/lib/clang/15.0.7/include/xsavecintrin.h
OLD_FILES+=usr/lib/clang/15.0.7/include/xsaveintrin.h
OLD_FILES+=usr/lib/clang/15.0.7/include/xsaveoptintrin.h
OLD_FILES+=usr/lib/clang/15.0.7/include/xsavesintrin.h
OLD_FILES+=usr/lib/clang/15.0.7/include/xtestintrin.h
OLD_DIRS+=usr/lib/clang/15.0.7/include
OLD_FILES+=usr/lib/clang/15.0.7/lib/freebsd/libclang_rt.asan-aarch64.a
OLD_FILES+=usr/lib/clang/15.0.7/lib/freebsd/libclang_rt.asan-aarch64.so
OLD_FILES+=usr/lib/clang/15.0.7/lib/freebsd/libclang_rt.asan-arm.a
OLD_FILES+=usr/lib/clang/15.0.7/lib/freebsd/libclang_rt.asan-arm.so
OLD_FILES+=usr/lib/clang/15.0.7/lib/freebsd/libclang_rt.asan-armhf.a
OLD_FILES+=usr/lib/clang/15.0.7/lib/freebsd/libclang_rt.asan-armhf.so
OLD_FILES+=usr/lib/clang/15.0.7/lib/freebsd/libclang_rt.asan-i386.a
OLD_FILES+=usr/lib/clang/15.0.7/lib/freebsd/libclang_rt.asan-i386.so
OLD_FILES+=usr/lib/clang/15.0.7/lib/freebsd/libclang_rt.asan-preinit-aarch64.a
OLD_FILES+=usr/lib/clang/15.0.7/lib/freebsd/libclang_rt.asan-preinit-arm.a
OLD_FILES+=usr/lib/clang/15.0.7/lib/freebsd/libclang_rt.asan-preinit-armhf.a
OLD_FILES+=usr/lib/clang/15.0.7/lib/freebsd/libclang_rt.asan-preinit-i386.a
OLD_FILES+=usr/lib/clang/15.0.7/lib/freebsd/libclang_rt.asan-preinit-x86_64.a
OLD_FILES+=usr/lib/clang/15.0.7/lib/freebsd/libclang_rt.asan-x86_64.a
OLD_FILES+=usr/lib/clang/15.0.7/lib/freebsd/libclang_rt.asan-x86_64.so
OLD_FILES+=usr/lib/clang/15.0.7/lib/freebsd/libclang_rt.asan_cxx-aarch64.a
OLD_FILES+=usr/lib/clang/15.0.7/lib/freebsd/libclang_rt.asan_cxx-arm.a
OLD_FILES+=usr/lib/clang/15.0.7/lib/freebsd/libclang_rt.asan_cxx-armhf.a
OLD_FILES+=usr/lib/clang/15.0.7/lib/freebsd/libclang_rt.asan_cxx-i386.a
OLD_FILES+=usr/lib/clang/15.0.7/lib/freebsd/libclang_rt.asan_cxx-x86_64.a
OLD_FILES+=usr/lib/clang/15.0.7/lib/freebsd/libclang_rt.asan_static-i386.a
OLD_FILES+=usr/lib/clang/15.0.7/lib/freebsd/libclang_rt.asan_static-x86_64.a
OLD_FILES+=usr/lib/clang/15.0.7/lib/freebsd/libclang_rt.cfi-aarch64.a
OLD_FILES+=usr/lib/clang/15.0.7/lib/freebsd/libclang_rt.cfi-arm.a
OLD_FILES+=usr/lib/clang/15.0.7/lib/freebsd/libclang_rt.cfi-armhf.a
OLD_FILES+=usr/lib/clang/15.0.7/lib/freebsd/libclang_rt.cfi-i386.a
OLD_FILES+=usr/lib/clang/15.0.7/lib/freebsd/libclang_rt.cfi-x86_64.a
OLD_FILES+=usr/lib/clang/15.0.7/lib/freebsd/libclang_rt.cfi_diag-aarch64.a
OLD_FILES+=usr/lib/clang/15.0.7/lib/freebsd/libclang_rt.cfi_diag-arm.a
OLD_FILES+=usr/lib/clang/15.0.7/lib/freebsd/libclang_rt.cfi_diag-armhf.a
OLD_FILES+=usr/lib/clang/15.0.7/lib/freebsd/libclang_rt.cfi_diag-i386.a
OLD_FILES+=usr/lib/clang/15.0.7/lib/freebsd/libclang_rt.cfi_diag-x86_64.a
OLD_FILES+=usr/lib/clang/15.0.7/lib/freebsd/libclang_rt.dd-aarch64.a
OLD_FILES+=usr/lib/clang/15.0.7/lib/freebsd/libclang_rt.dd-x86_64.a
OLD_FILES+=usr/lib/clang/15.0.7/lib/freebsd/libclang_rt.fuzzer-aarch64.a
OLD_FILES+=usr/lib/clang/15.0.7/lib/freebsd/libclang_rt.fuzzer-x86_64.a
OLD_FILES+=usr/lib/clang/15.0.7/lib/freebsd/libclang_rt.fuzzer_interceptors-x86_64.a
OLD_FILES+=usr/lib/clang/15.0.7/lib/freebsd/libclang_rt.fuzzer_no_main-aarch64.a
OLD_FILES+=usr/lib/clang/15.0.7/lib/freebsd/libclang_rt.fuzzer_no_main-x86_64.a
OLD_FILES+=usr/lib/clang/15.0.7/lib/freebsd/libclang_rt.msan-aarch64.a
OLD_FILES+=usr/lib/clang/15.0.7/lib/freebsd/libclang_rt.msan-x86_64.a
OLD_FILES+=usr/lib/clang/15.0.7/lib/freebsd/libclang_rt.msan_cxx-aarch64.a
OLD_FILES+=usr/lib/clang/15.0.7/lib/freebsd/libclang_rt.msan_cxx-x86_64.a
OLD_FILES+=usr/lib/clang/15.0.7/lib/freebsd/libclang_rt.profile-aarch64.a
OLD_FILES+=usr/lib/clang/15.0.7/lib/freebsd/libclang_rt.profile-arm.a
OLD_FILES+=usr/lib/clang/15.0.7/lib/freebsd/libclang_rt.profile-armhf.a
OLD_FILES+=usr/lib/clang/15.0.7/lib/freebsd/libclang_rt.profile-i386.a
OLD_FILES+=usr/lib/clang/15.0.7/lib/freebsd/libclang_rt.profile-powerpc.a
OLD_FILES+=usr/lib/clang/15.0.7/lib/freebsd/libclang_rt.profile-powerpc64.a
OLD_FILES+=usr/lib/clang/15.0.7/lib/freebsd/libclang_rt.profile-powerpc64le.a
OLD_FILES+=usr/lib/clang/15.0.7/lib/freebsd/libclang_rt.profile-x86_64.a
OLD_FILES+=usr/lib/clang/15.0.7/lib/freebsd/libclang_rt.safestack-aarch64.a
OLD_FILES+=usr/lib/clang/15.0.7/lib/freebsd/libclang_rt.safestack-i386.a
OLD_FILES+=usr/lib/clang/15.0.7/lib/freebsd/libclang_rt.safestack-x86_64.a
OLD_FILES+=usr/lib/clang/15.0.7/lib/freebsd/libclang_rt.stats-aarch64.a
OLD_FILES+=usr/lib/clang/15.0.7/lib/freebsd/libclang_rt.stats-arm.a
OLD_FILES+=usr/lib/clang/15.0.7/lib/freebsd/libclang_rt.stats-armhf.a
OLD_FILES+=usr/lib/clang/15.0.7/lib/freebsd/libclang_rt.stats-i386.a
OLD_FILES+=usr/lib/clang/15.0.7/lib/freebsd/libclang_rt.stats-x86_64.a
OLD_FILES+=usr/lib/clang/15.0.7/lib/freebsd/libclang_rt.stats_client-aarch64.a
OLD_FILES+=usr/lib/clang/15.0.7/lib/freebsd/libclang_rt.stats_client-arm.a
OLD_FILES+=usr/lib/clang/15.0.7/lib/freebsd/libclang_rt.stats_client-armhf.a
OLD_FILES+=usr/lib/clang/15.0.7/lib/freebsd/libclang_rt.stats_client-i386.a
OLD_FILES+=usr/lib/clang/15.0.7/lib/freebsd/libclang_rt.stats_client-x86_64.a
OLD_FILES+=usr/lib/clang/15.0.7/lib/freebsd/libclang_rt.tsan-aarch64.a
OLD_FILES+=usr/lib/clang/15.0.7/lib/freebsd/libclang_rt.tsan-x86_64.a
OLD_FILES+=usr/lib/clang/15.0.7/lib/freebsd/libclang_rt.tsan_cxx-aarch64.a
OLD_FILES+=usr/lib/clang/15.0.7/lib/freebsd/libclang_rt.tsan_cxx-x86_64.a
OLD_FILES+=usr/lib/clang/15.0.7/lib/freebsd/libclang_rt.ubsan_minimal-aarch64.a
OLD_FILES+=usr/lib/clang/15.0.7/lib/freebsd/libclang_rt.ubsan_minimal-arm.a
OLD_FILES+=usr/lib/clang/15.0.7/lib/freebsd/libclang_rt.ubsan_minimal-armhf.a
OLD_FILES+=usr/lib/clang/15.0.7/lib/freebsd/libclang_rt.ubsan_minimal-i386.a
OLD_FILES+=usr/lib/clang/15.0.7/lib/freebsd/libclang_rt.ubsan_minimal-x86_64.a
OLD_FILES+=usr/lib/clang/15.0.7/lib/freebsd/libclang_rt.ubsan_standalone-aarch64.a
OLD_FILES+=usr/lib/clang/15.0.7/lib/freebsd/libclang_rt.ubsan_standalone-arm.a
OLD_FILES+=usr/lib/clang/15.0.7/lib/freebsd/libclang_rt.ubsan_standalone-armhf.a
OLD_FILES+=usr/lib/clang/15.0.7/lib/freebsd/libclang_rt.ubsan_standalone-i386.a
OLD_FILES+=usr/lib/clang/15.0.7/lib/freebsd/libclang_rt.ubsan_standalone-x86_64.a
OLD_FILES+=usr/lib/clang/15.0.7/lib/freebsd/libclang_rt.ubsan_standalone_cxx-aarch64.a
OLD_FILES+=usr/lib/clang/15.0.7/lib/freebsd/libclang_rt.ubsan_standalone_cxx-arm.a
OLD_FILES+=usr/lib/clang/15.0.7/lib/freebsd/libclang_rt.ubsan_standalone_cxx-armhf.a
OLD_FILES+=usr/lib/clang/15.0.7/lib/freebsd/libclang_rt.ubsan_standalone_cxx-i386.a
OLD_FILES+=usr/lib/clang/15.0.7/lib/freebsd/libclang_rt.ubsan_standalone_cxx-x86_64.a
OLD_FILES+=usr/lib/clang/15.0.7/lib/freebsd/libclang_rt.xray-aarch64.a
OLD_FILES+=usr/lib/clang/15.0.7/lib/freebsd/libclang_rt.xray-arm.a
OLD_FILES+=usr/lib/clang/15.0.7/lib/freebsd/libclang_rt.xray-armhf.a
OLD_FILES+=usr/lib/clang/15.0.7/lib/freebsd/libclang_rt.xray-basic-aarch64.a
OLD_FILES+=usr/lib/clang/15.0.7/lib/freebsd/libclang_rt.xray-basic-arm.a
OLD_FILES+=usr/lib/clang/15.0.7/lib/freebsd/libclang_rt.xray-basic-armhf.a
OLD_FILES+=usr/lib/clang/15.0.7/lib/freebsd/libclang_rt.xray-basic-x86_64.a
OLD_FILES+=usr/lib/clang/15.0.7/lib/freebsd/libclang_rt.xray-fdr-aarch64.a
OLD_FILES+=usr/lib/clang/15.0.7/lib/freebsd/libclang_rt.xray-fdr-arm.a
OLD_FILES+=usr/lib/clang/15.0.7/lib/freebsd/libclang_rt.xray-fdr-armhf.a
OLD_FILES+=usr/lib/clang/15.0.7/lib/freebsd/libclang_rt.xray-fdr-x86_64.a
OLD_FILES+=usr/lib/clang/15.0.7/lib/freebsd/libclang_rt.xray-profiling-aarch64.a
OLD_FILES+=usr/lib/clang/15.0.7/lib/freebsd/libclang_rt.xray-profiling-arm.a
OLD_FILES+=usr/lib/clang/15.0.7/lib/freebsd/libclang_rt.xray-profiling-armhf.a
OLD_FILES+=usr/lib/clang/15.0.7/lib/freebsd/libclang_rt.xray-profiling-x86_64.a
OLD_FILES+=usr/lib/clang/15.0.7/lib/freebsd/libclang_rt.xray-x86_64.a
OLD_DIRS+=usr/lib/clang/15.0.7/lib/freebsd
OLD_DIRS+=usr/lib/clang/15.0.7/lib
OLD_FILES+=usr/lib/clang/15.0.7/share/asan_ignorelist.txt
OLD_FILES+=usr/lib/clang/15.0.7/share/cfi_ignorelist.txt
OLD_FILES+=usr/lib/clang/15.0.7/share/msan_ignorelist.txt
OLD_DIRS+=usr/lib/clang/15.0.7/share
OLD_DIRS+=usr/lib/clang/15.0.7
# 20230622: new libc++ import which bumps version from 15.0.7 to 16.0.1
OLD_FILES+=usr/include/c++/v1/__bits
OLD_FILES+=usr/include/c++/v1/__tuple
OLD_FILES+=usr/include/c++/v1/__utility/transaction.h
# 20230614: caroot bundle updated
OLD_FILES+=usr/share/certs/trusted/Cybertrust_Global_Root.pem
OLD_FILES+=usr/share/certs/trusted/DST_Root_CA_X3.pem
+39 -13
View File
@@ -7,6 +7,7 @@
.gitignore
.mailmap
CONTRIBUTING.md
LICENSE.TXT
README.md
SECURITY.md
bolt/
@@ -15,7 +16,7 @@ clang/.clang-format
clang/.clang-tidy
clang/.gitignore
clang/CMakeLists.txt
clang/CODE_OWNERS.TXT
clang/CodeOwners.rst
clang/INSTALL.txt
clang/ModuleInfo.txt
clang/NOTES.txt
@@ -31,6 +32,7 @@ clang/include/clang/Basic/Version.inc.in
clang/include/clang/CMakeLists.txt
clang/include/clang/Config/
clang/include/clang/Driver/CMakeLists.txt
clang/include/clang/Format/.clang-format
clang/include/clang/Parse/CMakeLists.txt
clang/include/clang/Sema/CMakeLists.txt
clang/include/clang/Serialization/CMakeLists.txt
@@ -57,6 +59,7 @@ clang/lib/DirectoryWatcher/CMakeLists.txt
clang/lib/Driver/CMakeLists.txt
clang/lib/Edit/CMakeLists.txt
clang/lib/ExtractAPI/CMakeLists.txt
clang/lib/Format/.clang-format
clang/lib/Format/CMakeLists.txt
clang/lib/Frontend/CMakeLists.txt
clang/lib/Frontend/Rewrite/CMakeLists.txt
@@ -84,6 +87,7 @@ clang/lib/Tooling/DependencyScanning/CMakeLists.txt
clang/lib/Tooling/DumpTool/CMakeLists.txt
clang/lib/Tooling/DumpTool/generate_cxx_src_locs.py
clang/lib/Tooling/Inclusions/CMakeLists.txt
clang/lib/Tooling/Inclusions/Stdlib/CMakeLists.txt
clang/lib/Tooling/Refactoring/CMakeLists.txt
clang/lib/Tooling/Syntax/CMakeLists.txt
clang/lib/Tooling/Transformer/CMakeLists.txt
@@ -99,6 +103,7 @@ clang/tools/clang-check/
clang/tools/clang-diff/
clang/tools/clang-extdef-mapping/
clang/tools/clang-format-vs/
clang/tools/clang-format/.clang-format
clang/tools/clang-format/CMakeLists.txt
clang/tools/clang-format/clang-format-bbedit.applescript
clang/tools/clang-format/clang-format-diff.py
@@ -111,10 +116,8 @@ clang/tools/clang-format/git-clang-format
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/
clang/tools/clang-repl/CMakeLists.txt
@@ -126,6 +129,7 @@ clang/tools/driver/CMakeLists.txt
clang/tools/driver/Info.plist.in
clang/tools/include-mapping/
clang/tools/libclang/
clang/tools/nvptx-arch/CMakeLists.txt
clang/tools/scan-build-py/
clang/tools/scan-build/
clang/tools/scan-view/
@@ -201,7 +205,9 @@ compiler-rt/lib/msan/.clang-format
compiler-rt/lib/msan/CMakeLists.txt
compiler-rt/lib/msan/tests/
compiler-rt/lib/orc/CMakeLists.txt
compiler-rt/lib/orc/unittests/
compiler-rt/lib/orc/tests/CMakeLists.txt
compiler-rt/lib/orc/tests/tools/CMakeLists.txt
compiler-rt/lib/orc/tests/unit/CMakeLists.txt
compiler-rt/lib/profile/CMakeLists.txt
compiler-rt/lib/safestack/.clang-format
compiler-rt/lib/safestack/CMakeLists.txt
@@ -209,7 +215,6 @@ compiler-rt/lib/sanitizer_common/.clang-format
compiler-rt/lib/sanitizer_common/CMakeLists.txt
compiler-rt/lib/sanitizer_common/scripts/
compiler-rt/lib/sanitizer_common/tests/
compiler-rt/lib/scudo/CMakeLists.txt
compiler-rt/lib/scudo/standalone/CMakeLists.txt
compiler-rt/lib/scudo/standalone/benchmarks/
compiler-rt/lib/scudo/standalone/fuzz/CMakeLists.txt
@@ -224,7 +229,6 @@ 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-old/CMakeLists.txt
compiler-rt/lib/tsan/rtl/CMakeLists.txt
compiler-rt/lib/tsan/tests/
compiler-rt/lib/ubsan/CMakeLists.txt
@@ -355,9 +359,11 @@ lldb/source/Plugins/ExpressionParser/Clang/CMakeLists.txt
lldb/source/Plugins/Instruction/ARM/CMakeLists.txt
lldb/source/Plugins/Instruction/ARM64/CMakeLists.txt
lldb/source/Plugins/Instruction/CMakeLists.txt
lldb/source/Plugins/Instruction/LoongArch/CMakeLists.txt
lldb/source/Plugins/Instruction/MIPS/CMakeLists.txt
lldb/source/Plugins/Instruction/MIPS64/CMakeLists.txt
lldb/source/Plugins/Instruction/PPC64/CMakeLists.txt
lldb/source/Plugins/Instruction/RISCV/CMakeLists.txt
lldb/source/Plugins/InstrumentationRuntime/ASan/CMakeLists.txt
lldb/source/Plugins/InstrumentationRuntime/CMakeLists.txt
lldb/source/Plugins/InstrumentationRuntime/MainThreadChecker/CMakeLists.txt
@@ -381,6 +387,7 @@ lldb/source/Plugins/MemoryHistory/CMakeLists.txt
lldb/source/Plugins/MemoryHistory/asan/CMakeLists.txt
lldb/source/Plugins/ObjectContainer/BSD-Archive/CMakeLists.txt
lldb/source/Plugins/ObjectContainer/CMakeLists.txt
lldb/source/Plugins/ObjectContainer/Mach-O-Fileset/CMakeLists.txt
lldb/source/Plugins/ObjectContainer/Universal-Mach-O/
lldb/source/Plugins/ObjectFile/Breakpad/CMakeLists.txt
lldb/source/Plugins/ObjectFile/CMakeLists.txt
@@ -500,6 +507,7 @@ llvm/include/llvm/Frontend/OpenMP/CMakeLists.txt
llvm/include/llvm/IR/CMakeLists.txt
llvm/include/llvm/Support/CMakeLists.txt
llvm/include/llvm/Support/LICENSE.TXT
llvm/include/llvm/TargetParser/CMakeLists.txt
llvm/lib/Analysis/CMakeLists.txt
llvm/lib/Analysis/README.txt
llvm/lib/Analysis/models/
@@ -518,11 +526,13 @@ llvm/lib/CodeGen/MIRParser/CMakeLists.txt
llvm/lib/CodeGen/README.txt
llvm/lib/CodeGen/SelectionDAG/CMakeLists.txt
llvm/lib/DWARFLinker/CMakeLists.txt
llvm/lib/DWARFLinkerParallel/CMakeLists.txt
llvm/lib/DWP/CMakeLists.txt
llvm/lib/DebugInfo/CMakeLists.txt
llvm/lib/DebugInfo/CodeView/CMakeLists.txt
llvm/lib/DebugInfo/DWARF/CMakeLists.txt
llvm/lib/DebugInfo/GSYM/CMakeLists.txt
llvm/lib/DebugInfo/LogicalView/CMakeLists.txt
llvm/lib/DebugInfo/MSF/CMakeLists.txt
llvm/lib/DebugInfo/PDB/CMakeLists.txt
llvm/lib/DebugInfo/Symbolize/CMakeLists.txt
@@ -542,11 +552,13 @@ llvm/lib/ExecutionEngine/RuntimeDyld/CMakeLists.txt
llvm/lib/Extensions/
llvm/lib/FileCheck/CMakeLists.txt
llvm/lib/Frontend/CMakeLists.txt
llvm/lib/Frontend/HLSL/CMakeLists.txt
llvm/lib/Frontend/OpenACC/CMakeLists.txt
llvm/lib/Frontend/OpenMP/CMakeLists.txt
llvm/lib/FuzzMutate/CMakeLists.txt
llvm/lib/Fuzzer/
llvm/lib/IR/CMakeLists.txt
llvm/lib/IRPrinter/CMakeLists.txt
llvm/lib/IRReader/CMakeLists.txt
llvm/lib/InterfaceStub/CMakeLists.txt
llvm/lib/LTO/CMakeLists.txt
@@ -612,6 +624,7 @@ 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/DirectXIRPasses/CMakeLists.txt
llvm/lib/Target/DirectX/MCTargetDesc/CMakeLists.txt
llvm/lib/Target/DirectX/TargetInfo/CMakeLists.txt
llvm/lib/Target/Hexagon/AsmParser/CMakeLists.txt
@@ -659,6 +672,7 @@ llvm/lib/Target/README.txt
llvm/lib/Target/RISCV/AsmParser/CMakeLists.txt
llvm/lib/Target/RISCV/CMakeLists.txt
llvm/lib/Target/RISCV/Disassembler/CMakeLists.txt
llvm/lib/Target/RISCV/MCA/CMakeLists.txt
llvm/lib/Target/RISCV/MCTargetDesc/CMakeLists.txt
llvm/lib/Target/RISCV/TargetInfo/CMakeLists.txt
llvm/lib/Target/SPIRV/CMakeLists.txt
@@ -701,6 +715,13 @@ llvm/lib/Target/XCore/Disassembler/CMakeLists.txt
llvm/lib/Target/XCore/MCTargetDesc/CMakeLists.txt
llvm/lib/Target/XCore/README.txt
llvm/lib/Target/XCore/TargetInfo/CMakeLists.txt
llvm/lib/Target/Xtensa/AsmParser/CMakeLists.txt
llvm/lib/Target/Xtensa/CMakeLists.txt
llvm/lib/Target/Xtensa/Disassembler/CMakeLists.txt
llvm/lib/Target/Xtensa/MCTargetDesc/CMakeLists.txt
llvm/lib/Target/Xtensa/TargetInfo/CMakeLists.txt
llvm/lib/TargetParser/CMakeLists.txt
llvm/lib/Testing/Annotations/CMakeLists.txt
llvm/lib/Testing/CMakeLists.txt
llvm/lib/Testing/Support/CMakeLists.txt
llvm/lib/TextAPI/CMakeLists.txt
@@ -749,7 +770,9 @@ llvm/tools/llvm-cvtres/
llvm/tools/llvm-cxxdump/CMakeLists.txt
llvm/tools/llvm-cxxfilt/CMakeLists.txt
llvm/tools/llvm-cxxmap/CMakeLists.txt
llvm/tools/llvm-debuginfo-analyzer/CMakeLists.txt
llvm/tools/llvm-debuginfod-find/
llvm/tools/llvm-debuginfod/
llvm/tools/llvm-diff/CMakeLists.txt
llvm/tools/llvm-diff/lib/CMakeLists.txt
llvm/tools/llvm-dis-fuzzer/
@@ -758,10 +781,10 @@ llvm/tools/llvm-dlang-demangle-fuzzer/
llvm/tools/llvm-driver/
llvm/tools/llvm-dwarfdump/CMakeLists.txt
llvm/tools/llvm-dwarfdump/fuzzer/
llvm/tools/llvm-dwarfutil/CMakeLists.txt
llvm/tools/llvm-dwp/CMakeLists.txt
llvm/tools/llvm-exegesis/
llvm/tools/llvm-extract/CMakeLists.txt
llvm/tools/llvm-go/
llvm/tools/llvm-gsymutil/
llvm/tools/llvm-ifs/
llvm/tools/llvm-isel-fuzzer/
@@ -793,6 +816,7 @@ llvm/tools/llvm-rc/
llvm/tools/llvm-readobj/CMakeLists.txt
llvm/tools/llvm-reduce/
llvm/tools/llvm-remark-size-diff/
llvm/tools/llvm-remarkutil/CMakeLists.txt
llvm/tools/llvm-rtdyld/CMakeLists.txt
llvm/tools/llvm-rust-demangle-fuzzer/
llvm/tools/llvm-shlib/
@@ -816,7 +840,6 @@ llvm/tools/opt/CMakeLists.txt
llvm/tools/remarks-shlib/
llvm/tools/sancov/
llvm/tools/sanstats/
llvm/tools/split-file/
llvm/tools/verify-uselistorder/
llvm/tools/vfabi-demangle-fuzzer/
llvm/tools/xcode-toolchain/
@@ -834,6 +857,7 @@ llvm/utils/PerfectShuffle/
llvm/utils/Reviewing/
llvm/utils/TableGen/CMakeLists.txt
llvm/utils/TableGen/GlobalISel/CMakeLists.txt
llvm/utils/TableGen/jupyter/
llvm/utils/TableGen/tdtags
llvm/utils/Target/
llvm/utils/UnicodeData/
@@ -853,7 +877,6 @@ llvm/utils/codegen-diff
llvm/utils/collect_and_build_with_pgo.py
llvm/utils/convert-constraint-log-to-z3.py
llvm/utils/count/
llvm/utils/countloc.sh
llvm/utils/create_ladder_graph.py
llvm/utils/crosstool/
llvm/utils/demangle_tree.py
@@ -862,12 +885,12 @@ llvm/utils/emacs/
llvm/utils/extract-section.py
llvm/utils/extract_symbols.py
llvm/utils/extract_vplan.py
llvm/utils/filecheck_lint/
llvm/utils/findmisopt
llvm/utils/findoptdiff
llvm/utils/findsym.pl
llvm/utils/fpcmp/
llvm/utils/gdb-scripts/
llvm/utils/getsrcs.sh
llvm/utils/git/
llvm/utils/gn/
llvm/utils/indirect_calls.py
@@ -884,14 +907,14 @@ llvm/utils/llvm-mca-compare.py
llvm/utils/llvm-native-gxx
llvm/utils/llvm-original-di-preservation.py
llvm/utils/llvm.grm
llvm/utils/llvmdo
llvm/utils/llvmgrep
llvm/utils/merge-stats.py
llvm/utils/not/
llvm/utils/phabricator/
llvm/utils/pipeline.py
llvm/utils/prepare-code-coverage-artifact.py
llvm/utils/reduce_pipeline.py
llvm/utils/reduce_pipeline_test/
llvm/utils/relative_lines.py
llvm/utils/release/
llvm/utils/remote-exec.py
llvm/utils/revert_checker.py
@@ -903,12 +926,14 @@ llvm/utils/schedcover.py
llvm/utils/shuffle_fuzz.py
llvm/utils/shuffle_select_fuzz_tester.py
llvm/utils/sort_includes.py
llvm/utils/split-file/.clang-tidy
llvm/utils/split-file/CMakeLists.txt
llvm/utils/sysroot.py
llvm/utils/testgen/
llvm/utils/textmate/
llvm/utils/unicode-case-fold.py
llvm/utils/unittest/
llvm/utils/update_analyze_test_checks.py
llvm/utils/update_any_test_checks.py
llvm/utils/update_cc_test_checks.py
llvm/utils/update_llc_test_checks.py
llvm/utils/update_mca_test_checks.py
@@ -935,6 +960,7 @@ openmp/runtime/README.txt
openmp/runtime/cmake/
openmp/runtime/doc/
openmp/runtime/src/CMakeLists.txt
openmp/runtime/src/exports_test_so.txt
openmp/runtime/test/
openmp/runtime/tools/
openmp/tools/
@@ -0,0 +1,379 @@
/*===-- clang-c/CXDiagnostic.h - C Index Diagnostics --------------*- 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 header provides the interface to C Index diagnostics. *|
|* *|
\*===----------------------------------------------------------------------===*/
#ifndef LLVM_CLANG_C_CXDIAGNOSTIC_H
#define LLVM_CLANG_C_CXDIAGNOSTIC_H
#include "clang-c/CXSourceLocation.h"
#include "clang-c/CXString.h"
#include "clang-c/ExternC.h"
#include "clang-c/Platform.h"
LLVM_CLANG_C_EXTERN_C_BEGIN
/**
* \defgroup CINDEX_DIAG Diagnostic reporting
*
* @{
*/
/**
* Describes the severity of a particular diagnostic.
*/
enum CXDiagnosticSeverity {
/**
* A diagnostic that has been suppressed, e.g., by a command-line
* option.
*/
CXDiagnostic_Ignored = 0,
/**
* This diagnostic is a note that should be attached to the
* previous (non-note) diagnostic.
*/
CXDiagnostic_Note = 1,
/**
* This diagnostic indicates suspicious code that may not be
* wrong.
*/
CXDiagnostic_Warning = 2,
/**
* This diagnostic indicates that the code is ill-formed.
*/
CXDiagnostic_Error = 3,
/**
* This diagnostic indicates that the code is ill-formed such
* that future parser recovery is unlikely to produce useful
* results.
*/
CXDiagnostic_Fatal = 4
};
/**
* A single diagnostic, containing the diagnostic's severity,
* location, text, source ranges, and fix-it hints.
*/
typedef void *CXDiagnostic;
/**
* A group of CXDiagnostics.
*/
typedef void *CXDiagnosticSet;
/**
* Determine the number of diagnostics in a CXDiagnosticSet.
*/
CINDEX_LINKAGE unsigned clang_getNumDiagnosticsInSet(CXDiagnosticSet Diags);
/**
* Retrieve a diagnostic associated with the given CXDiagnosticSet.
*
* \param Diags the CXDiagnosticSet to query.
* \param Index the zero-based diagnostic number to retrieve.
*
* \returns the requested diagnostic. This diagnostic must be freed
* via a call to \c clang_disposeDiagnostic().
*/
CINDEX_LINKAGE CXDiagnostic clang_getDiagnosticInSet(CXDiagnosticSet Diags,
unsigned Index);
/**
* Describes the kind of error that occurred (if any) in a call to
* \c clang_loadDiagnostics.
*/
enum CXLoadDiag_Error {
/**
* Indicates that no error occurred.
*/
CXLoadDiag_None = 0,
/**
* Indicates that an unknown error occurred while attempting to
* deserialize diagnostics.
*/
CXLoadDiag_Unknown = 1,
/**
* Indicates that the file containing the serialized diagnostics
* could not be opened.
*/
CXLoadDiag_CannotLoad = 2,
/**
* Indicates that the serialized diagnostics file is invalid or
* corrupt.
*/
CXLoadDiag_InvalidFile = 3
};
/**
* Deserialize a set of diagnostics from a Clang diagnostics bitcode
* file.
*
* \param file The name of the file to deserialize.
* \param error A pointer to a enum value recording if there was a problem
* deserializing the diagnostics.
* \param errorString A pointer to a CXString for recording the error string
* if the file was not successfully loaded.
*
* \returns A loaded CXDiagnosticSet if successful, and NULL otherwise. These
* diagnostics should be released using clang_disposeDiagnosticSet().
*/
CINDEX_LINKAGE CXDiagnosticSet clang_loadDiagnostics(
const char *file, enum CXLoadDiag_Error *error, CXString *errorString);
/**
* Release a CXDiagnosticSet and all of its contained diagnostics.
*/
CINDEX_LINKAGE void clang_disposeDiagnosticSet(CXDiagnosticSet Diags);
/**
* Retrieve the child diagnostics of a CXDiagnostic.
*
* This CXDiagnosticSet does not need to be released by
* clang_disposeDiagnosticSet.
*/
CINDEX_LINKAGE CXDiagnosticSet clang_getChildDiagnostics(CXDiagnostic D);
/**
* Destroy a diagnostic.
*/
CINDEX_LINKAGE void clang_disposeDiagnostic(CXDiagnostic Diagnostic);
/**
* Options to control the display of diagnostics.
*
* The values in this enum are meant to be combined to customize the
* behavior of \c clang_formatDiagnostic().
*/
enum CXDiagnosticDisplayOptions {
/**
* Display the source-location information where the
* diagnostic was located.
*
* When set, diagnostics will be prefixed by the file, line, and
* (optionally) column to which the diagnostic refers. For example,
*
* \code
* test.c:28: warning: extra tokens at end of #endif directive
* \endcode
*
* This option corresponds to the clang flag \c -fshow-source-location.
*/
CXDiagnostic_DisplaySourceLocation = 0x01,
/**
* If displaying the source-location information of the
* diagnostic, also include the column number.
*
* This option corresponds to the clang flag \c -fshow-column.
*/
CXDiagnostic_DisplayColumn = 0x02,
/**
* If displaying the source-location information of the
* diagnostic, also include information about source ranges in a
* machine-parsable format.
*
* This option corresponds to the clang flag
* \c -fdiagnostics-print-source-range-info.
*/
CXDiagnostic_DisplaySourceRanges = 0x04,
/**
* Display the option name associated with this diagnostic, if any.
*
* The option name displayed (e.g., -Wconversion) will be placed in brackets
* after the diagnostic text. This option corresponds to the clang flag
* \c -fdiagnostics-show-option.
*/
CXDiagnostic_DisplayOption = 0x08,
/**
* Display the category number associated with this diagnostic, if any.
*
* The category number is displayed within brackets after the diagnostic text.
* This option corresponds to the clang flag
* \c -fdiagnostics-show-category=id.
*/
CXDiagnostic_DisplayCategoryId = 0x10,
/**
* Display the category name associated with this diagnostic, if any.
*
* The category name is displayed within brackets after the diagnostic text.
* This option corresponds to the clang flag
* \c -fdiagnostics-show-category=name.
*/
CXDiagnostic_DisplayCategoryName = 0x20
};
/**
* Format the given diagnostic in a manner that is suitable for display.
*
* This routine will format the given diagnostic to a string, rendering
* the diagnostic according to the various options given. The
* \c clang_defaultDiagnosticDisplayOptions() function returns the set of
* options that most closely mimics the behavior of the clang compiler.
*
* \param Diagnostic The diagnostic to print.
*
* \param Options A set of options that control the diagnostic display,
* created by combining \c CXDiagnosticDisplayOptions values.
*
* \returns A new string containing for formatted diagnostic.
*/
CINDEX_LINKAGE CXString clang_formatDiagnostic(CXDiagnostic Diagnostic,
unsigned Options);
/**
* Retrieve the set of display options most similar to the
* default behavior of the clang compiler.
*
* \returns A set of display options suitable for use with \c
* clang_formatDiagnostic().
*/
CINDEX_LINKAGE unsigned clang_defaultDiagnosticDisplayOptions(void);
/**
* Determine the severity of the given diagnostic.
*/
CINDEX_LINKAGE enum CXDiagnosticSeverity
clang_getDiagnosticSeverity(CXDiagnostic);
/**
* Retrieve the source location of the given diagnostic.
*
* This location is where Clang would print the caret ('^') when
* displaying the diagnostic on the command line.
*/
CINDEX_LINKAGE CXSourceLocation clang_getDiagnosticLocation(CXDiagnostic);
/**
* Retrieve the text of the given diagnostic.
*/
CINDEX_LINKAGE CXString clang_getDiagnosticSpelling(CXDiagnostic);
/**
* Retrieve the name of the command-line option that enabled this
* diagnostic.
*
* \param Diag The diagnostic to be queried.
*
* \param Disable If non-NULL, will be set to the option that disables this
* diagnostic (if any).
*
* \returns A string that contains the command-line option used to enable this
* warning, such as "-Wconversion" or "-pedantic".
*/
CINDEX_LINKAGE CXString clang_getDiagnosticOption(CXDiagnostic Diag,
CXString *Disable);
/**
* Retrieve the category number for this diagnostic.
*
* Diagnostics can be categorized into groups along with other, related
* diagnostics (e.g., diagnostics under the same warning flag). This routine
* retrieves the category number for the given diagnostic.
*
* \returns The number of the category that contains this diagnostic, or zero
* if this diagnostic is uncategorized.
*/
CINDEX_LINKAGE unsigned clang_getDiagnosticCategory(CXDiagnostic);
/**
* Retrieve the name of a particular diagnostic category. This
* is now deprecated. Use clang_getDiagnosticCategoryText()
* instead.
*
* \param Category A diagnostic category number, as returned by
* \c clang_getDiagnosticCategory().
*
* \returns The name of the given diagnostic category.
*/
CINDEX_DEPRECATED CINDEX_LINKAGE CXString
clang_getDiagnosticCategoryName(unsigned Category);
/**
* Retrieve the diagnostic category text for a given diagnostic.
*
* \returns The text of the given diagnostic category.
*/
CINDEX_LINKAGE CXString clang_getDiagnosticCategoryText(CXDiagnostic);
/**
* Determine the number of source ranges associated with the given
* diagnostic.
*/
CINDEX_LINKAGE unsigned clang_getDiagnosticNumRanges(CXDiagnostic);
/**
* Retrieve a source range associated with the diagnostic.
*
* A diagnostic's source ranges highlight important elements in the source
* code. On the command line, Clang displays source ranges by
* underlining them with '~' characters.
*
* \param Diagnostic the diagnostic whose range is being extracted.
*
* \param Range the zero-based index specifying which range to
*
* \returns the requested source range.
*/
CINDEX_LINKAGE CXSourceRange clang_getDiagnosticRange(CXDiagnostic Diagnostic,
unsigned Range);
/**
* Determine the number of fix-it hints associated with the
* given diagnostic.
*/
CINDEX_LINKAGE unsigned clang_getDiagnosticNumFixIts(CXDiagnostic Diagnostic);
/**
* Retrieve the replacement information for a given fix-it.
*
* Fix-its are described in terms of a source range whose contents
* should be replaced by a string. This approach generalizes over
* three kinds of operations: removal of source code (the range covers
* the code to be removed and the replacement string is empty),
* replacement of source code (the range covers the code to be
* replaced and the replacement string provides the new code), and
* insertion (both the start and end of the range point at the
* insertion location, and the replacement string provides the text to
* insert).
*
* \param Diagnostic The diagnostic whose fix-its are being queried.
*
* \param FixIt The zero-based index of the fix-it.
*
* \param ReplacementRange The source range whose contents will be
* replaced with the returned replacement string. Note that source
* ranges are half-open ranges [a, b), so the source code should be
* replaced from a and up to (but not including) b.
*
* \returns A string containing text that should be replace the source
* code indicated by the \c ReplacementRange.
*/
CINDEX_LINKAGE CXString clang_getDiagnosticFixIt(
CXDiagnostic Diagnostic, unsigned FixIt, CXSourceRange *ReplacementRange);
/**
* @}
*/
LLVM_CLANG_C_EXTERN_C_END
#endif
@@ -0,0 +1,83 @@
/*===-- clang-c/CXFile.h - C Index File ---------------------------*- 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 header provides the interface to C Index files. *|
|* *|
\*===----------------------------------------------------------------------===*/
#ifndef LLVM_CLANG_C_CXFILE_H
#define LLVM_CLANG_C_CXFILE_H
#include <time.h>
#include "clang-c/CXString.h"
#include "clang-c/ExternC.h"
#include "clang-c/Platform.h"
LLVM_CLANG_C_EXTERN_C_BEGIN
/**
* \defgroup CINDEX_FILES File manipulation routines
*
* @{
*/
/**
* A particular source file that is part of a translation unit.
*/
typedef void *CXFile;
/**
* Retrieve the complete file and path name of the given file.
*/
CINDEX_LINKAGE CXString clang_getFileName(CXFile SFile);
/**
* Retrieve the last modification time of the given file.
*/
CINDEX_LINKAGE time_t clang_getFileTime(CXFile SFile);
/**
* Uniquely identifies a CXFile, that refers to the same underlying file,
* across an indexing session.
*/
typedef struct {
unsigned long long data[3];
} CXFileUniqueID;
/**
* Retrieve the unique ID for the given \c file.
*
* \param file the file to get the ID for.
* \param outID stores the returned CXFileUniqueID.
* \returns If there was a failure getting the unique ID, returns non-zero,
* otherwise returns 0.
*/
CINDEX_LINKAGE int clang_getFileUniqueID(CXFile file, CXFileUniqueID *outID);
/**
* Returns non-zero if the \c file1 and \c file2 point to the same file,
* or they are both NULL.
*/
CINDEX_LINKAGE int clang_File_isEqual(CXFile file1, CXFile file2);
/**
* Returns the real path name of \c file.
*
* An empty string may be returned. Use \c clang_getFileName() in that case.
*/
CINDEX_LINKAGE CXString clang_File_tryGetRealPathName(CXFile file);
/**
* @}
*/
LLVM_CLANG_C_EXTERN_C_END
#endif
@@ -0,0 +1,286 @@
/*===-- clang-c/CXSourceLocation.h - C Index Source Location ------*- 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 header provides the interface to C Index source locations. *|
|* *|
\*===----------------------------------------------------------------------===*/
#ifndef LLVM_CLANG_C_CXSOURCE_LOCATION_H
#define LLVM_CLANG_C_CXSOURCE_LOCATION_H
#include "clang-c/CXFile.h"
#include "clang-c/CXString.h"
#include "clang-c/ExternC.h"
#include "clang-c/Platform.h"
LLVM_CLANG_C_EXTERN_C_BEGIN
/**
* \defgroup CINDEX_LOCATIONS Physical source locations
*
* Clang represents physical source locations in its abstract syntax tree in
* great detail, with file, line, and column information for the majority of
* the tokens parsed in the source code. These data types and functions are
* used to represent source location information, either for a particular
* point in the program or for a range of points in the program, and extract
* specific location information from those data types.
*
* @{
*/
/**
* Identifies a specific source location within a translation
* unit.
*
* Use clang_getExpansionLocation() or clang_getSpellingLocation()
* to map a source location to a particular file, line, and column.
*/
typedef struct {
const void *ptr_data[2];
unsigned int_data;
} CXSourceLocation;
/**
* Identifies a half-open character range in the source code.
*
* Use clang_getRangeStart() and clang_getRangeEnd() to retrieve the
* starting and end locations from a source range, respectively.
*/
typedef struct {
const void *ptr_data[2];
unsigned begin_int_data;
unsigned end_int_data;
} CXSourceRange;
/**
* Retrieve a NULL (invalid) source location.
*/
CINDEX_LINKAGE CXSourceLocation clang_getNullLocation(void);
/**
* Determine whether two source locations, which must refer into
* the same translation unit, refer to exactly the same point in the source
* code.
*
* \returns non-zero if the source locations refer to the same location, zero
* if they refer to different locations.
*/
CINDEX_LINKAGE unsigned clang_equalLocations(CXSourceLocation loc1,
CXSourceLocation loc2);
/**
* Returns non-zero if the given source location is in a system header.
*/
CINDEX_LINKAGE int clang_Location_isInSystemHeader(CXSourceLocation location);
/**
* Returns non-zero if the given source location is in the main file of
* the corresponding translation unit.
*/
CINDEX_LINKAGE int clang_Location_isFromMainFile(CXSourceLocation location);
/**
* Retrieve a NULL (invalid) source range.
*/
CINDEX_LINKAGE CXSourceRange clang_getNullRange(void);
/**
* Retrieve a source range given the beginning and ending source
* locations.
*/
CINDEX_LINKAGE CXSourceRange clang_getRange(CXSourceLocation begin,
CXSourceLocation end);
/**
* Determine whether two ranges are equivalent.
*
* \returns non-zero if the ranges are the same, zero if they differ.
*/
CINDEX_LINKAGE unsigned clang_equalRanges(CXSourceRange range1,
CXSourceRange range2);
/**
* Returns non-zero if \p range is null.
*/
CINDEX_LINKAGE int clang_Range_isNull(CXSourceRange range);
/**
* Retrieve the file, line, column, and offset represented by
* the given source location.
*
* If the location refers into a macro expansion, retrieves the
* location of the macro expansion.
*
* \param location the location within a source file that will be decomposed
* into its parts.
*
* \param file [out] if non-NULL, will be set to the file to which the given
* source location points.
*
* \param line [out] if non-NULL, will be set to the line to which the given
* source location points.
*
* \param column [out] if non-NULL, will be set to the column to which the given
* source location points.
*
* \param offset [out] if non-NULL, will be set to the offset into the
* buffer to which the given source location points.
*/
CINDEX_LINKAGE void clang_getExpansionLocation(CXSourceLocation location,
CXFile *file, unsigned *line,
unsigned *column,
unsigned *offset);
/**
* Retrieve the file, line and column represented by the given source
* location, as specified in a # line directive.
*
* Example: given the following source code in a file somefile.c
*
* \code
* #123 "dummy.c" 1
*
* static int func(void)
* {
* return 0;
* }
* \endcode
*
* the location information returned by this function would be
*
* File: dummy.c Line: 124 Column: 12
*
* whereas clang_getExpansionLocation would have returned
*
* File: somefile.c Line: 3 Column: 12
*
* \param location the location within a source file that will be decomposed
* into its parts.
*
* \param filename [out] if non-NULL, will be set to the filename of the
* source location. Note that filenames returned will be for "virtual" files,
* which don't necessarily exist on the machine running clang - e.g. when
* parsing preprocessed output obtained from a different environment. If
* a non-NULL value is passed in, remember to dispose of the returned value
* using \c clang_disposeString() once you've finished with it. For an invalid
* source location, an empty string is returned.
*
* \param line [out] if non-NULL, will be set to the line number of the
* source location. For an invalid source location, zero is returned.
*
* \param column [out] if non-NULL, will be set to the column number of the
* source location. For an invalid source location, zero is returned.
*/
CINDEX_LINKAGE void clang_getPresumedLocation(CXSourceLocation location,
CXString *filename,
unsigned *line, unsigned *column);
/**
* Legacy API to retrieve the file, line, column, and offset represented
* by the given source location.
*
* This interface has been replaced by the newer interface
* #clang_getExpansionLocation(). See that interface's documentation for
* details.
*/
CINDEX_LINKAGE void clang_getInstantiationLocation(CXSourceLocation location,
CXFile *file, unsigned *line,
unsigned *column,
unsigned *offset);
/**
* Retrieve the file, line, column, and offset represented by
* the given source location.
*
* If the location refers into a macro instantiation, return where the
* location was originally spelled in the source file.
*
* \param location the location within a source file that will be decomposed
* into its parts.
*
* \param file [out] if non-NULL, will be set to the file to which the given
* source location points.
*
* \param line [out] if non-NULL, will be set to the line to which the given
* source location points.
*
* \param column [out] if non-NULL, will be set to the column to which the given
* source location points.
*
* \param offset [out] if non-NULL, will be set to the offset into the
* buffer to which the given source location points.
*/
CINDEX_LINKAGE void clang_getSpellingLocation(CXSourceLocation location,
CXFile *file, unsigned *line,
unsigned *column,
unsigned *offset);
/**
* Retrieve the file, line, column, and offset represented by
* the given source location.
*
* If the location refers into a macro expansion, return where the macro was
* expanded or where the macro argument was written, if the location points at
* a macro argument.
*
* \param location the location within a source file that will be decomposed
* into its parts.
*
* \param file [out] if non-NULL, will be set to the file to which the given
* source location points.
*
* \param line [out] if non-NULL, will be set to the line to which the given
* source location points.
*
* \param column [out] if non-NULL, will be set to the column to which the given
* source location points.
*
* \param offset [out] if non-NULL, will be set to the offset into the
* buffer to which the given source location points.
*/
CINDEX_LINKAGE void clang_getFileLocation(CXSourceLocation location,
CXFile *file, unsigned *line,
unsigned *column, unsigned *offset);
/**
* Retrieve a source location representing the first character within a
* source range.
*/
CINDEX_LINKAGE CXSourceLocation clang_getRangeStart(CXSourceRange range);
/**
* Retrieve a source location representing the last character within a
* source range.
*/
CINDEX_LINKAGE CXSourceLocation clang_getRangeEnd(CXSourceRange range);
/**
* Identifies an array of ranges.
*/
typedef struct {
/** The number of ranges in the \c ranges array. */
unsigned count;
/**
* An array of \c CXSourceRanges.
*/
CXSourceRange *ranges;
} CXSourceRangeList;
/**
* Destroy the given \c CXSourceRangeList.
*/
CINDEX_LINKAGE void clang_disposeSourceRangeList(CXSourceRangeList *ranges);
/**
* @}
*/
LLVM_CLANG_C_EXTERN_C_END
#endif
@@ -15,6 +15,7 @@
#ifndef LLVM_CLANG_C_DOCUMENTATION_H
#define LLVM_CLANG_C_DOCUMENTATION_H
#include "clang-c/CXErrorCode.h"
#include "clang-c/ExternC.h"
#include "clang-c/Index.h"
@@ -545,6 +546,69 @@ CINDEX_LINKAGE CXString clang_FullComment_getAsHTML(CXComment Comment);
*/
CINDEX_LINKAGE CXString clang_FullComment_getAsXML(CXComment Comment);
/**
* CXAPISet is an opaque type that represents a data structure containing all
* the API information for a given translation unit. This can be used for a
* single symbol symbol graph for a given symbol.
*/
typedef struct CXAPISetImpl *CXAPISet;
/**
* Traverses the translation unit to create a \c CXAPISet.
*
* \param tu is the \c CXTranslationUnit to build the \c CXAPISet for.
*
* \param out_api is a pointer to the output of this function. It is needs to be
* disposed of by calling clang_disposeAPISet.
*
* \returns Error code indicating success or failure of the APISet creation.
*/
CINDEX_LINKAGE enum CXErrorCode clang_createAPISet(CXTranslationUnit tu,
CXAPISet *out_api);
/**
* Dispose of an APISet.
*
* The provided \c CXAPISet can not be used after this function is called.
*/
CINDEX_LINKAGE void clang_disposeAPISet(CXAPISet api);
/**
* Generate a single symbol symbol graph for the given USR. Returns a null
* string if the associated symbol can not be found in the provided \c CXAPISet.
*
* The output contains the symbol graph as well as some additional information
* about related symbols.
*
* \param usr is a string containing the USR of the symbol to generate the
* symbol graph for.
*
* \param api the \c CXAPISet to look for the symbol in.
*
* \returns a string containing the serialized symbol graph representation for
* the symbol being queried or a null string if it can not be found in the
* APISet.
*/
CINDEX_LINKAGE CXString clang_getSymbolGraphForUSR(const char *usr,
CXAPISet api);
/**
* Generate a single symbol symbol graph for the declaration at the given
* cursor. Returns a null string if the AST node for the cursor isn't a
* declaration.
*
* The output contains the symbol graph as well as some additional information
* about related symbols.
*
* \param cursor the declaration for which to generate the single symbol symbol
* graph.
*
* \returns a string containing the serialized symbol graph representation for
* the symbol being queried or a null string if it can not be found in the
* APISet.
*/
CINDEX_LINKAGE CXString clang_getSymbolGraphForCursor(CXCursor cursor);
/**
* @}
*/
+130 -682
View File
@@ -16,10 +16,11 @@
#ifndef LLVM_CLANG_C_INDEX_H
#define LLVM_CLANG_C_INDEX_H
#include <time.h>
#include "clang-c/BuildSystem.h"
#include "clang-c/CXDiagnostic.h"
#include "clang-c/CXErrorCode.h"
#include "clang-c/CXFile.h"
#include "clang-c/CXSourceLocation.h"
#include "clang-c/CXString.h"
#include "clang-c/ExternC.h"
#include "clang-c/Platform.h"
@@ -341,45 +342,6 @@ CINDEX_LINKAGE unsigned clang_CXIndex_getGlobalOptions(CXIndex);
CINDEX_LINKAGE void
clang_CXIndex_setInvocationEmissionPathOption(CXIndex, const char *Path);
/**
* \defgroup CINDEX_FILES File manipulation routines
*
* @{
*/
/**
* A particular source file that is part of a translation unit.
*/
typedef void *CXFile;
/**
* Retrieve the complete file and path name of the given file.
*/
CINDEX_LINKAGE CXString clang_getFileName(CXFile SFile);
/**
* Retrieve the last modification time of the given file.
*/
CINDEX_LINKAGE time_t clang_getFileTime(CXFile SFile);
/**
* Uniquely identifies a CXFile, that refers to the same underlying file,
* across an indexing session.
*/
typedef struct {
unsigned long long data[3];
} CXFileUniqueID;
/**
* Retrieve the unique ID for the given \c file.
*
* \param file the file to get the ID for.
* \param outID stores the returned CXFileUniqueID.
* \returns If there was a failure getting the unique ID, returns non-zero,
* otherwise returns 0.
*/
CINDEX_LINKAGE int clang_getFileUniqueID(CXFile file, CXFileUniqueID *outID);
/**
* Determine whether the given header is guarded against
* multiple inclusions, either with the conventional
@@ -416,76 +378,6 @@ CINDEX_LINKAGE CXFile clang_getFile(CXTranslationUnit tu,
CINDEX_LINKAGE const char *clang_getFileContents(CXTranslationUnit tu,
CXFile file, size_t *size);
/**
* Returns non-zero if the \c file1 and \c file2 point to the same file,
* or they are both NULL.
*/
CINDEX_LINKAGE int clang_File_isEqual(CXFile file1, CXFile file2);
/**
* Returns the real path name of \c file.
*
* An empty string may be returned. Use \c clang_getFileName() in that case.
*/
CINDEX_LINKAGE CXString clang_File_tryGetRealPathName(CXFile file);
/**
* @}
*/
/**
* \defgroup CINDEX_LOCATIONS Physical source locations
*
* Clang represents physical source locations in its abstract syntax tree in
* great detail, with file, line, and column information for the majority of
* the tokens parsed in the source code. These data types and functions are
* used to represent source location information, either for a particular
* point in the program or for a range of points in the program, and extract
* specific location information from those data types.
*
* @{
*/
/**
* Identifies a specific source location within a translation
* unit.
*
* Use clang_getExpansionLocation() or clang_getSpellingLocation()
* to map a source location to a particular file, line, and column.
*/
typedef struct {
const void *ptr_data[2];
unsigned int_data;
} CXSourceLocation;
/**
* Identifies a half-open character range in the source code.
*
* Use clang_getRangeStart() and clang_getRangeEnd() to retrieve the
* starting and end locations from a source range, respectively.
*/
typedef struct {
const void *ptr_data[2];
unsigned begin_int_data;
unsigned end_int_data;
} CXSourceRange;
/**
* Retrieve a NULL (invalid) source location.
*/
CINDEX_LINKAGE CXSourceLocation clang_getNullLocation(void);
/**
* Determine whether two source locations, which must refer into
* the same translation unit, refer to exactly the same point in the source
* code.
*
* \returns non-zero if the source locations refer to the same location, zero
* if they refer to different locations.
*/
CINDEX_LINKAGE unsigned clang_equalLocations(CXSourceLocation loc1,
CXSourceLocation loc2);
/**
* Retrieves the source location associated with a given file/line/column
* in a particular translation unit.
@@ -501,204 +393,6 @@ CINDEX_LINKAGE CXSourceLocation clang_getLocationForOffset(CXTranslationUnit tu,
CXFile file,
unsigned offset);
/**
* Returns non-zero if the given source location is in a system header.
*/
CINDEX_LINKAGE int clang_Location_isInSystemHeader(CXSourceLocation location);
/**
* Returns non-zero if the given source location is in the main file of
* the corresponding translation unit.
*/
CINDEX_LINKAGE int clang_Location_isFromMainFile(CXSourceLocation location);
/**
* Retrieve a NULL (invalid) source range.
*/
CINDEX_LINKAGE CXSourceRange clang_getNullRange(void);
/**
* Retrieve a source range given the beginning and ending source
* locations.
*/
CINDEX_LINKAGE CXSourceRange clang_getRange(CXSourceLocation begin,
CXSourceLocation end);
/**
* Determine whether two ranges are equivalent.
*
* \returns non-zero if the ranges are the same, zero if they differ.
*/
CINDEX_LINKAGE unsigned clang_equalRanges(CXSourceRange range1,
CXSourceRange range2);
/**
* Returns non-zero if \p range is null.
*/
CINDEX_LINKAGE int clang_Range_isNull(CXSourceRange range);
/**
* Retrieve the file, line, column, and offset represented by
* the given source location.
*
* If the location refers into a macro expansion, retrieves the
* location of the macro expansion.
*
* \param location the location within a source file that will be decomposed
* into its parts.
*
* \param file [out] if non-NULL, will be set to the file to which the given
* source location points.
*
* \param line [out] if non-NULL, will be set to the line to which the given
* source location points.
*
* \param column [out] if non-NULL, will be set to the column to which the given
* source location points.
*
* \param offset [out] if non-NULL, will be set to the offset into the
* buffer to which the given source location points.
*/
CINDEX_LINKAGE void clang_getExpansionLocation(CXSourceLocation location,
CXFile *file, unsigned *line,
unsigned *column,
unsigned *offset);
/**
* Retrieve the file, line and column represented by the given source
* location, as specified in a # line directive.
*
* Example: given the following source code in a file somefile.c
*
* \code
* #123 "dummy.c" 1
*
* static int func(void)
* {
* return 0;
* }
* \endcode
*
* the location information returned by this function would be
*
* File: dummy.c Line: 124 Column: 12
*
* whereas clang_getExpansionLocation would have returned
*
* File: somefile.c Line: 3 Column: 12
*
* \param location the location within a source file that will be decomposed
* into its parts.
*
* \param filename [out] if non-NULL, will be set to the filename of the
* source location. Note that filenames returned will be for "virtual" files,
* which don't necessarily exist on the machine running clang - e.g. when
* parsing preprocessed output obtained from a different environment. If
* a non-NULL value is passed in, remember to dispose of the returned value
* using \c clang_disposeString() once you've finished with it. For an invalid
* source location, an empty string is returned.
*
* \param line [out] if non-NULL, will be set to the line number of the
* source location. For an invalid source location, zero is returned.
*
* \param column [out] if non-NULL, will be set to the column number of the
* source location. For an invalid source location, zero is returned.
*/
CINDEX_LINKAGE void clang_getPresumedLocation(CXSourceLocation location,
CXString *filename,
unsigned *line, unsigned *column);
/**
* Legacy API to retrieve the file, line, column, and offset represented
* by the given source location.
*
* This interface has been replaced by the newer interface
* #clang_getExpansionLocation(). See that interface's documentation for
* details.
*/
CINDEX_LINKAGE void clang_getInstantiationLocation(CXSourceLocation location,
CXFile *file, unsigned *line,
unsigned *column,
unsigned *offset);
/**
* Retrieve the file, line, column, and offset represented by
* the given source location.
*
* If the location refers into a macro instantiation, return where the
* location was originally spelled in the source file.
*
* \param location the location within a source file that will be decomposed
* into its parts.
*
* \param file [out] if non-NULL, will be set to the file to which the given
* source location points.
*
* \param line [out] if non-NULL, will be set to the line to which the given
* source location points.
*
* \param column [out] if non-NULL, will be set to the column to which the given
* source location points.
*
* \param offset [out] if non-NULL, will be set to the offset into the
* buffer to which the given source location points.
*/
CINDEX_LINKAGE void clang_getSpellingLocation(CXSourceLocation location,
CXFile *file, unsigned *line,
unsigned *column,
unsigned *offset);
/**
* Retrieve the file, line, column, and offset represented by
* the given source location.
*
* If the location refers into a macro expansion, return where the macro was
* expanded or where the macro argument was written, if the location points at
* a macro argument.
*
* \param location the location within a source file that will be decomposed
* into its parts.
*
* \param file [out] if non-NULL, will be set to the file to which the given
* source location points.
*
* \param line [out] if non-NULL, will be set to the line to which the given
* source location points.
*
* \param column [out] if non-NULL, will be set to the column to which the given
* source location points.
*
* \param offset [out] if non-NULL, will be set to the offset into the
* buffer to which the given source location points.
*/
CINDEX_LINKAGE void clang_getFileLocation(CXSourceLocation location,
CXFile *file, unsigned *line,
unsigned *column, unsigned *offset);
/**
* Retrieve a source location representing the first character within a
* source range.
*/
CINDEX_LINKAGE CXSourceLocation clang_getRangeStart(CXSourceRange range);
/**
* Retrieve a source location representing the last character within a
* source range.
*/
CINDEX_LINKAGE CXSourceLocation clang_getRangeEnd(CXSourceRange range);
/**
* Identifies an array of ranges.
*/
typedef struct {
/** The number of ranges in the \c ranges array. */
unsigned count;
/**
* An array of \c CXSourceRanges.
*/
CXSourceRange *ranges;
} CXSourceRangeList;
/**
* Retrieve all ranges that were skipped by the preprocessor.
*
@@ -718,142 +412,6 @@ CINDEX_LINKAGE CXSourceRangeList *clang_getSkippedRanges(CXTranslationUnit tu,
CINDEX_LINKAGE CXSourceRangeList *
clang_getAllSkippedRanges(CXTranslationUnit tu);
/**
* Destroy the given \c CXSourceRangeList.
*/
CINDEX_LINKAGE void clang_disposeSourceRangeList(CXSourceRangeList *ranges);
/**
* @}
*/
/**
* \defgroup CINDEX_DIAG Diagnostic reporting
*
* @{
*/
/**
* Describes the severity of a particular diagnostic.
*/
enum CXDiagnosticSeverity {
/**
* A diagnostic that has been suppressed, e.g., by a command-line
* option.
*/
CXDiagnostic_Ignored = 0,
/**
* This diagnostic is a note that should be attached to the
* previous (non-note) diagnostic.
*/
CXDiagnostic_Note = 1,
/**
* This diagnostic indicates suspicious code that may not be
* wrong.
*/
CXDiagnostic_Warning = 2,
/**
* This diagnostic indicates that the code is ill-formed.
*/
CXDiagnostic_Error = 3,
/**
* This diagnostic indicates that the code is ill-formed such
* that future parser recovery is unlikely to produce useful
* results.
*/
CXDiagnostic_Fatal = 4
};
/**
* A single diagnostic, containing the diagnostic's severity,
* location, text, source ranges, and fix-it hints.
*/
typedef void *CXDiagnostic;
/**
* A group of CXDiagnostics.
*/
typedef void *CXDiagnosticSet;
/**
* Determine the number of diagnostics in a CXDiagnosticSet.
*/
CINDEX_LINKAGE unsigned clang_getNumDiagnosticsInSet(CXDiagnosticSet Diags);
/**
* Retrieve a diagnostic associated with the given CXDiagnosticSet.
*
* \param Diags the CXDiagnosticSet to query.
* \param Index the zero-based diagnostic number to retrieve.
*
* \returns the requested diagnostic. This diagnostic must be freed
* via a call to \c clang_disposeDiagnostic().
*/
CINDEX_LINKAGE CXDiagnostic clang_getDiagnosticInSet(CXDiagnosticSet Diags,
unsigned Index);
/**
* Describes the kind of error that occurred (if any) in a call to
* \c clang_loadDiagnostics.
*/
enum CXLoadDiag_Error {
/**
* Indicates that no error occurred.
*/
CXLoadDiag_None = 0,
/**
* Indicates that an unknown error occurred while attempting to
* deserialize diagnostics.
*/
CXLoadDiag_Unknown = 1,
/**
* Indicates that the file containing the serialized diagnostics
* could not be opened.
*/
CXLoadDiag_CannotLoad = 2,
/**
* Indicates that the serialized diagnostics file is invalid or
* corrupt.
*/
CXLoadDiag_InvalidFile = 3
};
/**
* Deserialize a set of diagnostics from a Clang diagnostics bitcode
* file.
*
* \param file The name of the file to deserialize.
* \param error A pointer to a enum value recording if there was a problem
* deserializing the diagnostics.
* \param errorString A pointer to a CXString for recording the error string
* if the file was not successfully loaded.
*
* \returns A loaded CXDiagnosticSet if successful, and NULL otherwise. These
* diagnostics should be released using clang_disposeDiagnosticSet().
*/
CINDEX_LINKAGE CXDiagnosticSet clang_loadDiagnostics(
const char *file, enum CXLoadDiag_Error *error, CXString *errorString);
/**
* Release a CXDiagnosticSet and all of its contained diagnostics.
*/
CINDEX_LINKAGE void clang_disposeDiagnosticSet(CXDiagnosticSet Diags);
/**
* Retrieve the child diagnostics of a CXDiagnostic.
*
* This CXDiagnosticSet does not need to be released by
* clang_disposeDiagnosticSet.
*/
CINDEX_LINKAGE CXDiagnosticSet clang_getChildDiagnostics(CXDiagnostic D);
/**
* Determine the number of diagnostics produced for the given
* translation unit.
@@ -881,232 +439,6 @@ CINDEX_LINKAGE CXDiagnostic clang_getDiagnostic(CXTranslationUnit Unit,
CINDEX_LINKAGE CXDiagnosticSet
clang_getDiagnosticSetFromTU(CXTranslationUnit Unit);
/**
* Destroy a diagnostic.
*/
CINDEX_LINKAGE void clang_disposeDiagnostic(CXDiagnostic Diagnostic);
/**
* Options to control the display of diagnostics.
*
* The values in this enum are meant to be combined to customize the
* behavior of \c clang_formatDiagnostic().
*/
enum CXDiagnosticDisplayOptions {
/**
* Display the source-location information where the
* diagnostic was located.
*
* When set, diagnostics will be prefixed by the file, line, and
* (optionally) column to which the diagnostic refers. For example,
*
* \code
* test.c:28: warning: extra tokens at end of #endif directive
* \endcode
*
* This option corresponds to the clang flag \c -fshow-source-location.
*/
CXDiagnostic_DisplaySourceLocation = 0x01,
/**
* If displaying the source-location information of the
* diagnostic, also include the column number.
*
* This option corresponds to the clang flag \c -fshow-column.
*/
CXDiagnostic_DisplayColumn = 0x02,
/**
* If displaying the source-location information of the
* diagnostic, also include information about source ranges in a
* machine-parsable format.
*
* This option corresponds to the clang flag
* \c -fdiagnostics-print-source-range-info.
*/
CXDiagnostic_DisplaySourceRanges = 0x04,
/**
* Display the option name associated with this diagnostic, if any.
*
* The option name displayed (e.g., -Wconversion) will be placed in brackets
* after the diagnostic text. This option corresponds to the clang flag
* \c -fdiagnostics-show-option.
*/
CXDiagnostic_DisplayOption = 0x08,
/**
* Display the category number associated with this diagnostic, if any.
*
* The category number is displayed within brackets after the diagnostic text.
* This option corresponds to the clang flag
* \c -fdiagnostics-show-category=id.
*/
CXDiagnostic_DisplayCategoryId = 0x10,
/**
* Display the category name associated with this diagnostic, if any.
*
* The category name is displayed within brackets after the diagnostic text.
* This option corresponds to the clang flag
* \c -fdiagnostics-show-category=name.
*/
CXDiagnostic_DisplayCategoryName = 0x20
};
/**
* Format the given diagnostic in a manner that is suitable for display.
*
* This routine will format the given diagnostic to a string, rendering
* the diagnostic according to the various options given. The
* \c clang_defaultDiagnosticDisplayOptions() function returns the set of
* options that most closely mimics the behavior of the clang compiler.
*
* \param Diagnostic The diagnostic to print.
*
* \param Options A set of options that control the diagnostic display,
* created by combining \c CXDiagnosticDisplayOptions values.
*
* \returns A new string containing for formatted diagnostic.
*/
CINDEX_LINKAGE CXString clang_formatDiagnostic(CXDiagnostic Diagnostic,
unsigned Options);
/**
* Retrieve the set of display options most similar to the
* default behavior of the clang compiler.
*
* \returns A set of display options suitable for use with \c
* clang_formatDiagnostic().
*/
CINDEX_LINKAGE unsigned clang_defaultDiagnosticDisplayOptions(void);
/**
* Determine the severity of the given diagnostic.
*/
CINDEX_LINKAGE enum CXDiagnosticSeverity
clang_getDiagnosticSeverity(CXDiagnostic);
/**
* Retrieve the source location of the given diagnostic.
*
* This location is where Clang would print the caret ('^') when
* displaying the diagnostic on the command line.
*/
CINDEX_LINKAGE CXSourceLocation clang_getDiagnosticLocation(CXDiagnostic);
/**
* Retrieve the text of the given diagnostic.
*/
CINDEX_LINKAGE CXString clang_getDiagnosticSpelling(CXDiagnostic);
/**
* Retrieve the name of the command-line option that enabled this
* diagnostic.
*
* \param Diag The diagnostic to be queried.
*
* \param Disable If non-NULL, will be set to the option that disables this
* diagnostic (if any).
*
* \returns A string that contains the command-line option used to enable this
* warning, such as "-Wconversion" or "-pedantic".
*/
CINDEX_LINKAGE CXString clang_getDiagnosticOption(CXDiagnostic Diag,
CXString *Disable);
/**
* Retrieve the category number for this diagnostic.
*
* Diagnostics can be categorized into groups along with other, related
* diagnostics (e.g., diagnostics under the same warning flag). This routine
* retrieves the category number for the given diagnostic.
*
* \returns The number of the category that contains this diagnostic, or zero
* if this diagnostic is uncategorized.
*/
CINDEX_LINKAGE unsigned clang_getDiagnosticCategory(CXDiagnostic);
/**
* Retrieve the name of a particular diagnostic category. This
* is now deprecated. Use clang_getDiagnosticCategoryText()
* instead.
*
* \param Category A diagnostic category number, as returned by
* \c clang_getDiagnosticCategory().
*
* \returns The name of the given diagnostic category.
*/
CINDEX_DEPRECATED CINDEX_LINKAGE CXString
clang_getDiagnosticCategoryName(unsigned Category);
/**
* Retrieve the diagnostic category text for a given diagnostic.
*
* \returns The text of the given diagnostic category.
*/
CINDEX_LINKAGE CXString clang_getDiagnosticCategoryText(CXDiagnostic);
/**
* Determine the number of source ranges associated with the given
* diagnostic.
*/
CINDEX_LINKAGE unsigned clang_getDiagnosticNumRanges(CXDiagnostic);
/**
* Retrieve a source range associated with the diagnostic.
*
* A diagnostic's source ranges highlight important elements in the source
* code. On the command line, Clang displays source ranges by
* underlining them with '~' characters.
*
* \param Diagnostic the diagnostic whose range is being extracted.
*
* \param Range the zero-based index specifying which range to
*
* \returns the requested source range.
*/
CINDEX_LINKAGE CXSourceRange clang_getDiagnosticRange(CXDiagnostic Diagnostic,
unsigned Range);
/**
* Determine the number of fix-it hints associated with the
* given diagnostic.
*/
CINDEX_LINKAGE unsigned clang_getDiagnosticNumFixIts(CXDiagnostic Diagnostic);
/**
* Retrieve the replacement information for a given fix-it.
*
* Fix-its are described in terms of a source range whose contents
* should be replaced by a string. This approach generalizes over
* three kinds of operations: removal of source code (the range covers
* the code to be removed and the replacement string is empty),
* replacement of source code (the range covers the code to be
* replaced and the replacement string provides the new code), and
* insertion (both the start and end of the range point at the
* insertion location, and the replacement string provides the text to
* insert).
*
* \param Diagnostic The diagnostic whose fix-its are being queried.
*
* \param FixIt The zero-based index of the fix-it.
*
* \param ReplacementRange The source range whose contents will be
* replaced with the returned replacement string. Note that source
* ranges are half-open ranges [a, b), so the source code should be
* replaced from a and up to (but not including) b.
*
* \returns A string containing text that should be replace the source
* code indicated by the \c ReplacementRange.
*/
CINDEX_LINKAGE CXString clang_getDiagnosticFixIt(
CXDiagnostic Diagnostic, unsigned FixIt, CXSourceRange *ReplacementRange);
/**
* @}
*/
/**
* \defgroup CINDEX_TRANSLATION_UNIT Translation unit manipulation
*
@@ -2199,7 +1531,13 @@ enum CXCursorKind {
*/
CXCursor_RequiresExpr = 154,
CXCursor_LastExpr = CXCursor_RequiresExpr,
/**
* Expression that references a C++20 parenthesized list aggregate
* initializer.
*/
CXCursor_CXXParenListInitExpr = 155,
CXCursor_LastExpr = CXCursor_CXXParenListInitExpr,
/* Statements */
CXCursor_FirstStmt = 200,
@@ -2646,7 +1984,11 @@ enum CXCursorKind {
*/
CXCursor_OMPParallelMaskedTaskLoopSimdDirective = 304,
CXCursor_LastStmt = CXCursor_OMPParallelMaskedTaskLoopSimdDirective,
/** OpenMP error directive.
*/
CXCursor_OMPErrorDirective = 305,
CXCursor_LastStmt = CXCursor_OMPErrorDirective,
/**
* Cursor that represents the translation unit itself.
@@ -3591,8 +2933,8 @@ enum CXTemplateArgumentKind {
};
/**
*Returns the number of template args of a function decl representing a
* template specialization.
* Returns the number of template args of a function, struct, or class decl
* representing a template specialization.
*
* If the argument cursor cannot be converted into a template function
* declaration, -1 is returned.
@@ -3611,8 +2953,9 @@ CINDEX_LINKAGE int clang_Cursor_getNumTemplateArguments(CXCursor C);
/**
* Retrieve the kind of the I'th template argument of the CXCursor C.
*
* If the argument CXCursor does not represent a FunctionDecl, an invalid
* template argument kind is returned.
* If the argument CXCursor does not represent a FunctionDecl, StructDecl, or
* ClassTemplatePartialSpecialization, an invalid template argument kind is
* returned.
*
* For example, for the following declaration and specialization:
* template <typename T, int kInt, bool kBool>
@@ -3631,9 +2974,9 @@ clang_Cursor_getTemplateArgumentKind(CXCursor C, unsigned I);
* Retrieve a CXType representing the type of a TemplateArgument of a
* function decl representing a template specialization.
*
* If the argument CXCursor does not represent a FunctionDecl whose I'th
* template argument has a kind of CXTemplateArgKind_Integral, an invalid type
* is returned.
* If the argument CXCursor does not represent a FunctionDecl, StructDecl,
* ClassDecl or ClassTemplatePartialSpecialization whose I'th template argument
* has a kind of CXTemplateArgKind_Integral, an invalid type is returned.
*
* For example, for the following declaration and specialization:
* template <typename T, int kInt, bool kBool>
@@ -3653,7 +2996,8 @@ CINDEX_LINKAGE CXType clang_Cursor_getTemplateArgumentType(CXCursor C,
* decl representing a template specialization) as a signed long long.
*
* It is undefined to call this function on a CXCursor that does not represent a
* FunctionDecl or whose I'th template argument is not an integral value.
* FunctionDecl, StructDecl, ClassDecl or ClassTemplatePartialSpecialization
* whose I'th template argument is not an integral value.
*
* For example, for the following declaration and specialization:
* template <typename T, int kInt, bool kBool>
@@ -3673,7 +3017,8 @@ CINDEX_LINKAGE long long clang_Cursor_getTemplateArgumentValue(CXCursor C,
* decl representing a template specialization) as an unsigned long long.
*
* It is undefined to call this function on a CXCursor that does not represent a
* FunctionDecl or whose I'th template argument is not an integral value.
* FunctionDecl, StructDecl, ClassDecl or ClassTemplatePartialSpecialization or
* whose I'th template argument is not an integral value.
*
* For example, for the following declaration and specialization:
* template <typename T, int kInt, bool kBool>
@@ -3760,6 +3105,54 @@ CINDEX_LINKAGE CXString clang_getTypedefName(CXType CT);
*/
CINDEX_LINKAGE CXType clang_getPointeeType(CXType T);
/**
* Retrieve the unqualified variant of the given type, removing as
* little sugar as possible.
*
* For example, given the following series of typedefs:
*
* \code
* typedef int Integer;
* typedef const Integer CInteger;
* typedef CInteger DifferenceType;
* \endcode
*
* Executing \c clang_getUnqualifiedType() on a \c CXType that
* represents \c DifferenceType, will desugar to a type representing
* \c Integer, that has no qualifiers.
*
* And, executing \c clang_getUnqualifiedType() on the type of the
* first argument of the following function declaration:
*
* \code
* void foo(const int);
* \endcode
*
* Will return a type representing \c int, removing the \c const
* qualifier.
*
* Sugar over array types is not desugared.
*
* A type can be checked for qualifiers with \c
* clang_isConstQualifiedType(), \c clang_isVolatileQualifiedType()
* and \c clang_isRestrictQualifiedType().
*
* A type that resulted from a call to \c clang_getUnqualifiedType
* will return \c false for all of the above calls.
*/
CINDEX_LINKAGE CXType clang_getUnqualifiedType(CXType CT);
/**
* For reference types (e.g., "const int&"), returns the type that the
* reference refers to (e.g "const int").
*
* Otherwise, returns the type itself.
*
* A type that has kind \c CXType_LValueReference or
* \c CXType_RValueReference is a reference type.
*/
CINDEX_LINKAGE CXType clang_getNonReferenceType(CXType CT);
/**
* Return the cursor for the declaration of the given type.
*/
@@ -4876,6 +4269,11 @@ CINDEX_LINKAGE unsigned clang_CXXField_isMutable(CXCursor C);
*/
CINDEX_LINKAGE unsigned clang_CXXMethod_isDefaulted(CXCursor C);
/**
* Determine if a C++ method is declared '= delete'.
*/
CINDEX_LINKAGE unsigned clang_CXXMethod_isDeleted(CXCursor C);
/**
* Determine if a C++ member function or member function template is
* pure virtual.
@@ -4895,6 +4293,56 @@ CINDEX_LINKAGE unsigned clang_CXXMethod_isStatic(CXCursor C);
*/
CINDEX_LINKAGE unsigned clang_CXXMethod_isVirtual(CXCursor C);
/**
* Determine if a C++ member function is a copy-assignment operator,
* returning 1 if such is the case and 0 otherwise.
*
* > A copy-assignment operator `X::operator=` is a non-static,
* > non-template member function of _class_ `X` with exactly one
* > parameter of type `X`, `X&`, `const X&`, `volatile X&` or `const
* > volatile X&`.
*
* That is, for example, the `operator=` in:
*
* class Foo {
* bool operator=(const volatile Foo&);
* };
*
* Is a copy-assignment operator, while the `operator=` in:
*
* class Bar {
* bool operator=(const int&);
* };
*
* Is not.
*/
CINDEX_LINKAGE unsigned clang_CXXMethod_isCopyAssignmentOperator(CXCursor C);
/**
* Determine if a C++ member function is a move-assignment operator,
* returning 1 if such is the case and 0 otherwise.
*
* > A move-assignment operator `X::operator=` is a non-static,
* > non-template member function of _class_ `X` with exactly one
* > parameter of type `X&&`, `const X&&`, `volatile X&&` or `const
* > volatile X&&`.
*
* That is, for example, the `operator=` in:
*
* class Foo {
* bool operator=(const volatile Foo&&);
* };
*
* Is a move-assignment operator, while the `operator=` in:
*
* class Bar {
* bool operator=(const int&&);
* };
*
* Is not.
*/
CINDEX_LINKAGE unsigned clang_CXXMethod_isMoveAssignmentOperator(CXCursor C);
/**
* Determine if a C++ record is abstract, i.e. whether a class or struct
* has a pure virtual member function.
@@ -10,11 +10,15 @@
#define LLVM_CLANG_APINOTES_TYPES_H
#include "clang/Basic/Specifiers.h"
#include "llvm/ADT/Optional.h"
#include "llvm/ADT/StringRef.h"
#include <climits>
#include <optional>
#include <vector>
namespace llvm {
class raw_ostream;
} // namespace llvm
namespace clang {
namespace api_notes {
enum class RetainCountConventionKind {
@@ -70,12 +74,12 @@ class CommonEntityInfo {
: Unavailable(0), UnavailableInSwift(0), SwiftPrivateSpecified(0),
SwiftPrivate(0) {}
llvm::Optional<bool> isSwiftPrivate() const {
return SwiftPrivateSpecified ? llvm::Optional<bool>(SwiftPrivate)
: llvm::None;
std::optional<bool> isSwiftPrivate() const {
return SwiftPrivateSpecified ? std::optional<bool>(SwiftPrivate)
: std::nullopt;
}
void setSwiftPrivate(llvm::Optional<bool> Private) {
void setSwiftPrivate(std::optional<bool> Private) {
SwiftPrivateSpecified = Private.has_value();
SwiftPrivate = Private.value_or(0);
}
@@ -127,39 +131,39 @@ class CommonTypeInfo : public CommonEntityInfo {
/// The Swift type to which a given type is bridged.
///
/// Reflects the swift_bridge attribute.
llvm::Optional<std::string> SwiftBridge;
std::optional<std::string> SwiftBridge;
/// The NS error domain for this type.
llvm::Optional<std::string> NSErrorDomain;
std::optional<std::string> NSErrorDomain;
public:
CommonTypeInfo() {}
const llvm::Optional<std::string> &getSwiftBridge() const {
const std::optional<std::string> &getSwiftBridge() const {
return SwiftBridge;
}
void setSwiftBridge(const llvm::Optional<std::string> &SwiftType) {
void setSwiftBridge(const std::optional<std::string> &SwiftType) {
SwiftBridge = SwiftType;
}
void setSwiftBridge(const llvm::Optional<llvm::StringRef> &SwiftType) {
void setSwiftBridge(const std::optional<llvm::StringRef> &SwiftType) {
SwiftBridge = SwiftType
? llvm::Optional<std::string>(std::string(*SwiftType))
: llvm::None;
? std::optional<std::string>(std::string(*SwiftType))
: std::nullopt;
}
const llvm::Optional<std::string> &getNSErrorDomain() const {
const std::optional<std::string> &getNSErrorDomain() const {
return NSErrorDomain;
}
void setNSErrorDomain(const llvm::Optional<std::string> &Domain) {
void setNSErrorDomain(const std::optional<std::string> &Domain) {
NSErrorDomain = Domain;
}
void setNSErrorDomain(const llvm::Optional<llvm::StringRef> &Domain) {
NSErrorDomain =
Domain ? llvm::Optional<std::string>(std::string(*Domain)) : llvm::None;
void setNSErrorDomain(const std::optional<llvm::StringRef> &Domain) {
NSErrorDomain = Domain ? std::optional<std::string>(std::string(*Domain))
: std::nullopt;
}
friend bool operator==(const CommonTypeInfo &, const CommonTypeInfo &);
@@ -215,12 +219,13 @@ class ObjCContextInfo : public CommonTypeInfo {
/// Determine the default nullability for properties and methods of this
/// class.
///
/// eturns the default nullability, if implied, or None if there is no
llvm::Optional<NullabilityKind> getDefaultNullability() const {
/// Returns the default nullability, if implied, or std::nullopt if there is
/// none.
std::optional<NullabilityKind> getDefaultNullability() const {
return HasDefaultNullability
? llvm::Optional<NullabilityKind>(
? std::optional<NullabilityKind>(
static_cast<NullabilityKind>(DefaultNullability))
: llvm::None;
: std::nullopt;
}
/// Set the default nullability for properties and methods of this class.
@@ -232,21 +237,21 @@ class ObjCContextInfo : public CommonTypeInfo {
bool hasDesignatedInits() const { return HasDesignatedInits; }
void setHasDesignatedInits(bool Value) { HasDesignatedInits = Value; }
llvm::Optional<bool> getSwiftImportAsNonGeneric() const {
std::optional<bool> getSwiftImportAsNonGeneric() const {
return SwiftImportAsNonGenericSpecified
? llvm::Optional<bool>(SwiftImportAsNonGeneric)
: llvm::None;
? std::optional<bool>(SwiftImportAsNonGeneric)
: std::nullopt;
}
void setSwiftImportAsNonGeneric(llvm::Optional<bool> Value) {
void setSwiftImportAsNonGeneric(std::optional<bool> Value) {
SwiftImportAsNonGenericSpecified = Value.has_value();
SwiftImportAsNonGeneric = Value.value_or(false);
}
llvm::Optional<bool> getSwiftObjCMembers() const {
return SwiftObjCMembersSpecified ? llvm::Optional<bool>(SwiftObjCMembers)
: llvm::None;
std::optional<bool> getSwiftObjCMembers() const {
return SwiftObjCMembersSpecified ? std::optional<bool>(SwiftObjCMembers)
: std::nullopt;
}
void setSwiftObjCMembers(llvm::Optional<bool> Value) {
void setSwiftObjCMembers(std::optional<bool> Value) {
SwiftObjCMembersSpecified = Value.has_value();
SwiftObjCMembers = Value.value_or(false);
}
@@ -310,10 +315,10 @@ class VariableInfo : public CommonEntityInfo {
public:
VariableInfo() : NullabilityAudited(false), Nullable(0) {}
llvm::Optional<NullabilityKind> getNullability() const {
return NullabilityAudited ? llvm::Optional<NullabilityKind>(
std::optional<NullabilityKind> getNullability() const {
return NullabilityAudited ? std::optional<NullabilityKind>(
static_cast<NullabilityKind>(Nullable))
: llvm::None;
: std::nullopt;
}
void setNullabilityAudited(NullabilityKind kind) {
@@ -359,12 +364,12 @@ class ObjCPropertyInfo : public VariableInfo {
ObjCPropertyInfo()
: SwiftImportAsAccessorsSpecified(false), SwiftImportAsAccessors(false) {}
llvm::Optional<bool> getSwiftImportAsAccessors() const {
std::optional<bool> getSwiftImportAsAccessors() const {
return SwiftImportAsAccessorsSpecified
? llvm::Optional<bool>(SwiftImportAsAccessors)
: llvm::None;
? std::optional<bool>(SwiftImportAsAccessors)
: std::nullopt;
}
void setSwiftImportAsAccessors(llvm::Optional<bool> Value) {
void setSwiftImportAsAccessors(std::optional<bool> Value) {
SwiftImportAsAccessorsSpecified = Value.has_value();
SwiftImportAsAccessors = Value.value_or(false);
}
@@ -423,23 +428,23 @@ class ParamInfo : public VariableInfo {
ParamInfo()
: NoEscapeSpecified(false), NoEscape(false), RawRetainCountConvention() {}
llvm::Optional<bool> isNoEscape() const {
std::optional<bool> isNoEscape() const {
if (!NoEscapeSpecified)
return llvm::None;
return std::nullopt;
return NoEscape;
}
void setNoEscape(llvm::Optional<bool> Value) {
void setNoEscape(std::optional<bool> Value) {
NoEscapeSpecified = Value.has_value();
NoEscape = Value.value_or(false);
}
llvm::Optional<RetainCountConventionKind> getRetainCountConvention() const {
std::optional<RetainCountConventionKind> getRetainCountConvention() const {
if (!RawRetainCountConvention)
return llvm::None;
return std::nullopt;
return static_cast<RetainCountConventionKind>(RawRetainCountConvention - 1);
}
void
setRetainCountConvention(llvm::Optional<RetainCountConventionKind> Value) {
setRetainCountConvention(std::optional<RetainCountConventionKind> Value) {
RawRetainCountConvention = Value ? static_cast<unsigned>(*Value) + 1 : 0;
assert(getRetainCountConvention() == Value && "bitfield too small");
}
@@ -477,7 +482,7 @@ inline bool operator!=(const ParamInfo &LHS, const ParamInfo &RHS) {
/// API notes for a function or method.
class FunctionInfo : public CommonEntityInfo {
private:
static constexpr const unsigned NullabilityKindMask = 0x3;
static constexpr const uint64_t NullabilityKindMask = 0x3;
static constexpr const unsigned NullabilityKindSize = 2;
static constexpr const unsigned ReturnInfoIndex = 0;
@@ -551,13 +556,13 @@ class FunctionInfo : public CommonEntityInfo {
NullabilityKind getReturnTypeInfo() const { return getTypeInfo(0); }
llvm::Optional<RetainCountConventionKind> getRetainCountConvention() const {
std::optional<RetainCountConventionKind> getRetainCountConvention() const {
if (!RawRetainCountConvention)
return llvm::None;
return std::nullopt;
return static_cast<RetainCountConventionKind>(RawRetainCountConvention - 1);
}
void
setRetainCountConvention(llvm::Optional<RetainCountConventionKind> Value) {
setRetainCountConvention(std::optional<RetainCountConventionKind> Value) {
RawRetainCountConvention = Value ? static_cast<unsigned>(*Value) + 1 : 0;
assert(getRetainCountConvention() == Value && "bitfield too small");
}
@@ -654,16 +659,16 @@ class TagInfo : public CommonTypeInfo {
unsigned IsFlagEnum : 1;
public:
llvm::Optional<EnumExtensibilityKind> EnumExtensibility;
std::optional<EnumExtensibilityKind> EnumExtensibility;
TagInfo() : HasFlagEnum(0), IsFlagEnum(0) {}
llvm::Optional<bool> isFlagEnum() const {
std::optional<bool> isFlagEnum() const {
if (HasFlagEnum)
return IsFlagEnum;
return llvm::None;
return std::nullopt;
}
void setFlagEnum(llvm::Optional<bool> Value) {
void setFlagEnum(std::optional<bool> Value) {
HasFlagEnum = Value.has_value();
IsFlagEnum = Value.value_or(false);
}
@@ -698,7 +703,7 @@ inline bool operator!=(const TagInfo &LHS, const TagInfo &RHS) {
/// Describes API notes data for a typedef.
class TypedefInfo : public CommonTypeInfo {
public:
llvm::Optional<SwiftNewTypeKind> SwiftWrapper;
std::optional<SwiftNewTypeKind> SwiftWrapper;
TypedefInfo() {}
@@ -43,7 +43,7 @@ class MigrateSourceAction : public ASTFrontendAction {
class MigrateAction : public WrapperFrontendAction {
std::string MigrateDir;
std::string PlistOut;
bool EmitPremigrationARCErros;
bool EmitPremigrationARCErrors;
protected:
bool BeginInvocation(CompilerInstance &CI) override;
@@ -238,7 +238,7 @@ class APValue {
}
};
class LValuePathSerializationHelper {
const void *ElemTy;
const void *Ty;
public:
ArrayRef<LValuePathEntry> Path;
@@ -44,6 +44,7 @@ class ConstraintSatisfaction : public llvm::FoldingSetNode {
using Detail = llvm::PointerUnion<Expr *, SubstitutionDiagnostic *>;
bool IsSatisfied = false;
bool ContainsErrors = false;
/// \brief Pairs of unsatisfied atomic constraint expressions along with the
/// substituted constraint expr, if the template arguments could be
@@ -58,6 +59,13 @@ class ConstraintSatisfaction : public llvm::FoldingSetNode {
static void Profile(llvm::FoldingSetNodeID &ID, const ASTContext &C,
const NamedDecl *ConstraintOwner,
ArrayRef<TemplateArgument> TemplateArgs);
bool HasSubstitutionFailure() {
for (const auto &Detail : Details)
if (Detail.second.dyn_cast<SubstitutionDiagnostic *>())
return true;
return false;
}
};
/// Pairs of unsatisfied atomic constraint expressions along with the
@@ -78,6 +86,7 @@ struct ASTConstraintSatisfaction final :
UnsatisfiedConstraintRecord> {
std::size_t NumRecords;
bool IsSatisfied : 1;
bool ContainsErrors : 1;
const UnsatisfiedConstraintRecord *begin() const {
return getTrailingObjects<UnsatisfiedConstraintRecord>();
@@ -89,9 +98,13 @@ struct ASTConstraintSatisfaction final :
ASTConstraintSatisfaction(const ASTContext &C,
const ConstraintSatisfaction &Satisfaction);
ASTConstraintSatisfaction(const ASTContext &C,
const ASTConstraintSatisfaction &Satisfaction);
static ASTConstraintSatisfaction *
Create(const ASTContext &C, const ConstraintSatisfaction &Satisfaction);
static ASTConstraintSatisfaction *
Rebuild(const ASTContext &C, const ASTConstraintSatisfaction &Satisfaction);
};
/// \brief Common data class for constructs that reference concepts with
@@ -76,7 +76,7 @@ class ASTConsumer {
virtual void HandleTagDeclRequiredDefinition(const TagDecl *D) {}
/// Invoked when a function is implicitly instantiated.
/// Note that at this point point it does not have a body, its body is
/// Note that at this point it does not have a body, its body is
/// instantiated at the end of the translation unit and passed to
/// HandleTopLevelDecl.
virtual void HandleCXXImplicitFunctionInstantiation(FunctionDecl *D) {}
@@ -14,65 +14,38 @@
#ifndef LLVM_CLANG_AST_ASTCONTEXT_H
#define LLVM_CLANG_AST_ASTCONTEXT_H
#include "clang/AST/ASTContextAllocate.h"
#include "clang/AST/ASTFwd.h"
#include "clang/AST/CanonicalType.h"
#include "clang/AST/CommentCommandTraits.h"
#include "clang/AST/ComparisonCategories.h"
#include "clang/AST/Decl.h"
#include "clang/AST/DeclBase.h"
#include "clang/AST/DeclarationName.h"
#include "clang/AST/ExternalASTSource.h"
#include "clang/AST/NestedNameSpecifier.h"
#include "clang/AST/PrettyPrinter.h"
#include "clang/AST/RawCommentList.h"
#include "clang/AST/TemplateName.h"
#include "clang/AST/Type.h"
#include "clang/Basic/AddressSpaces.h"
#include "clang/Basic/AttrKinds.h"
#include "clang/Basic/IdentifierTable.h"
#include "clang/Basic/LLVM.h"
#include "clang/Basic/LangOptions.h"
#include "clang/Basic/Linkage.h"
#include "clang/Basic/NoSanitizeList.h"
#include "clang/Basic/OperatorKinds.h"
#include "clang/Basic/PartialDiagnostic.h"
#include "clang/Basic/ProfileList.h"
#include "clang/Basic/SourceLocation.h"
#include "clang/Basic/Specifiers.h"
#include "clang/Basic/TargetCXXABI.h"
#include "clang/Basic/XRayLists.h"
#include "llvm/ADT/APSInt.h"
#include "llvm/ADT/ArrayRef.h"
#include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/DenseSet.h"
#include "llvm/ADT/FoldingSet.h"
#include "llvm/ADT/IntrusiveRefCntPtr.h"
#include "llvm/ADT/MapVector.h"
#include "llvm/ADT/None.h"
#include "llvm/ADT/Optional.h"
#include "llvm/ADT/PointerIntPair.h"
#include "llvm/ADT/PointerUnion.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/ADT/StringMap.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/ADT/TinyPtrVector.h"
#include "llvm/ADT/Triple.h"
#include "llvm/ADT/iterator_range.h"
#include "llvm/Support/AlignOf.h"
#include "llvm/Support/Allocator.h"
#include "llvm/Support/Casting.h"
#include "llvm/Support/Compiler.h"
#include "llvm/Support/TypeSize.h"
#include <cassert>
#include <cstddef>
#include <cstdint>
#include <iterator>
#include <memory>
#include <string>
#include <type_traits>
#include <utility>
#include <vector>
#include <optional>
namespace llvm {
@@ -246,6 +219,7 @@ class ASTContext : public RefCountedBase<ASTContext> {
TemplateSpecializationTypes;
mutable llvm::FoldingSet<ParenType> ParenTypes{GeneralTypesLog2InitSize};
mutable llvm::FoldingSet<UsingType> UsingTypes;
mutable llvm::FoldingSet<TypedefType> TypedefTypes;
mutable llvm::FoldingSet<ElaboratedType> ElaboratedTypes{
GeneralTypesLog2InitSize};
mutable llvm::FoldingSet<DependentNameType> DependentNameTypes;
@@ -639,9 +613,6 @@ class ASTContext : public RefCountedBase<ASTContext> {
std::unique_ptr<CXXABI> ABI;
CXXABI *createCXXABI(const TargetInfo &T);
/// The logical -> physical address space map.
const LangASMap *AddrSpaceMap = nullptr;
/// Address space map mangling must be used with language specific
/// address spaces (e.g. OpenCL/CUDA)
bool AddrSpaceMapMangling;
@@ -1366,6 +1337,9 @@ class ASTContext : public RefCountedBase<ASTContext> {
CanQualType getDecayedType(CanQualType T) const {
return CanQualType::CreateUnsafe(getDecayedType((QualType) T));
}
/// Return the uniqued reference to a specified decay from the original
/// type to the decayed type.
QualType getDecayedType(QualType Orig, QualType Decayed) const;
/// Return the uniqued reference to the atomic type for the specified
/// type.
@@ -1613,10 +1587,12 @@ class ASTContext : public RefCountedBase<ASTContext> {
QualType getBTFTagAttributedType(const BTFTypeTagAttr *BTFAttr,
QualType Wrapped);
QualType getSubstTemplateTypeParmType(const TemplateTypeParmType *Replaced,
QualType Replacement) const;
QualType getSubstTemplateTypeParmPackType(
const TemplateTypeParmType *Replaced,
QualType
getSubstTemplateTypeParmType(QualType Replacement, Decl *AssociatedDecl,
unsigned Index,
std::optional<unsigned> PackIndex) const;
QualType getSubstTemplateTypeParmPackType(Decl *AssociatedDecl,
unsigned Index, bool Final,
const TemplateArgument &ArgPack);
QualType
@@ -1633,7 +1609,7 @@ class ASTContext : public RefCountedBase<ASTContext> {
ArrayRef<TemplateArgument> Args) const;
QualType getTemplateSpecializationType(TemplateName T,
const TemplateArgumentListInfo &Args,
ArrayRef<TemplateArgumentLoc> Args,
QualType Canon = QualType()) const;
TypeSourceInfo *
@@ -1654,10 +1630,9 @@ class ASTContext : public RefCountedBase<ASTContext> {
const IdentifierInfo *Name,
QualType Canon = QualType()) const;
QualType getDependentTemplateSpecializationType(ElaboratedTypeKeyword Keyword,
NestedNameSpecifier *NNS,
const IdentifierInfo *Name,
const TemplateArgumentListInfo &Args) const;
QualType getDependentTemplateSpecializationType(
ElaboratedTypeKeyword Keyword, NestedNameSpecifier *NNS,
const IdentifierInfo *Name, ArrayRef<TemplateArgumentLoc> Args) const;
QualType getDependentTemplateSpecializationType(
ElaboratedTypeKeyword Keyword, NestedNameSpecifier *NNS,
const IdentifierInfo *Name, ArrayRef<TemplateArgument> Args) const;
@@ -1678,7 +1653,7 @@ class ASTContext : public RefCountedBase<ASTContext> {
/// elsewhere, such as if the pattern contains a placeholder type or
/// if this is the canonical type of another pack expansion type.
QualType getPackExpansionType(QualType Pattern,
Optional<unsigned> NumExpansions,
std::optional<unsigned> NumExpansions,
bool ExpectPackInType = true);
QualType getObjCInterfaceType(const ObjCInterfaceDecl *Decl,
@@ -1710,9 +1685,9 @@ class ASTContext : public RefCountedBase<ASTContext> {
/// Return a ObjCObjectPointerType type for the given ObjCObjectType.
QualType getObjCObjectPointerType(QualType OIT) const;
/// GCC extension.
QualType getTypeOfExprType(Expr *e) const;
QualType getTypeOfType(QualType t) const;
/// C2x feature and GCC extension.
QualType getTypeOfExprType(Expr *E, TypeOfKind Kind) const;
QualType getTypeOfType(QualType QT, TypeOfKind Kind) const;
QualType getReferenceQualifiedType(const Expr *e) const;
@@ -2197,10 +2172,14 @@ class ASTContext : public RefCountedBase<ASTContext> {
const IdentifierInfo *Name) const;
TemplateName getDependentTemplateName(NestedNameSpecifier *NNS,
OverloadedOperatorKind Operator) const;
TemplateName getSubstTemplateTemplateParm(TemplateTemplateParmDecl *param,
TemplateName replacement) const;
TemplateName getSubstTemplateTemplateParmPack(TemplateTemplateParmDecl *Param,
const TemplateArgument &ArgPack) const;
TemplateName
getSubstTemplateTemplateParm(TemplateName replacement, Decl *AssociatedDecl,
unsigned Index,
std::optional<unsigned> PackIndex) const;
TemplateName getSubstTemplateTemplateParmPack(const TemplateArgument &ArgPack,
Decl *AssociatedDecl,
unsigned Index,
bool Final) const;
enum GetBuiltinTypeError {
/// No error
@@ -2310,13 +2289,13 @@ class ASTContext : public RefCountedBase<ASTContext> {
CharUnits getTypeSizeInChars(QualType T) const;
CharUnits getTypeSizeInChars(const Type *T) const;
Optional<CharUnits> getTypeSizeInCharsIfKnown(QualType Ty) const {
std::optional<CharUnits> getTypeSizeInCharsIfKnown(QualType Ty) const {
if (Ty->isIncompleteType() || Ty->isDependentType())
return None;
return std::nullopt;
return getTypeSizeInChars(Ty);
}
Optional<CharUnits> getTypeSizeInCharsIfKnown(const Type *Ty) const {
std::optional<CharUnits> getTypeSizeInCharsIfKnown(const Type *Ty) const {
return getTypeSizeInCharsIfKnown(QualType(Ty, 0));
}
@@ -2372,6 +2351,9 @@ class ASTContext : public RefCountedBase<ASTContext> {
bool isAlignmentRequired(const Type *T) const;
bool isAlignmentRequired(QualType T) const;
/// More type predicates useful for type checking/promotion
bool isPromotableIntegerType(QualType T) const; // C99 6.3.1.1p2
/// Return the "preferred" alignment of the specified type \p T for
/// the current target, in bits.
///
@@ -2537,6 +2519,9 @@ class ASTContext : public RefCountedBase<ASTContext> {
return getCanonicalType(T1) == getCanonicalType(T2);
}
/// Determine whether the given expressions \p X and \p Y are equivalent.
bool hasSameExpr(const Expr *X, const Expr *Y) const;
/// Return this type as a completely-unqualified array type,
/// capturing the qualifiers in \p Quals.
///
@@ -2561,8 +2546,8 @@ class ASTContext : public RefCountedBase<ASTContext> {
bool hasSameNullabilityTypeQualifier(QualType SubT, QualType SuperT,
bool IsParam) const {
auto SubTnullability = SubT->getNullability(*this);
auto SuperTnullability = SuperT->getNullability(*this);
auto SubTnullability = SubT->getNullability();
auto SuperTnullability = SuperT->getNullability();
if (SubTnullability.has_value() == SuperTnullability.has_value()) {
// Neither has nullability; return true
if (!SubTnullability)
@@ -2662,6 +2647,11 @@ class ASTContext : public RefCountedBase<ASTContext> {
/// template.
bool hasSameTemplateName(const TemplateName &X, const TemplateName &Y) const;
/// Determine whether two Friend functions are different because constraints
/// that refer to an enclosing template, according to [temp.friend] p9.
bool FriendsDifferByConstraints(const FunctionDecl *X,
const FunctionDecl *Y) const;
/// Determine whether the two declarations refer to the same entity.
bool isSameEntity(const NamedDecl *X, const NamedDecl *Y) const;
@@ -2730,6 +2720,10 @@ class ASTContext : public RefCountedBase<ASTContext> {
/// Return number of constant array elements.
uint64_t getConstantArrayElementCount(const ConstantArrayType *CA) const;
/// Return number of elements initialized in an ArrayInitLoopExpr.
uint64_t
getArrayInitLoopExprElementCount(const ArrayInitLoopExpr *AILE) const;
/// Perform adjustment on the parameter type of a function.
///
/// This routine adjusts the given parameter type @p T to the actual
@@ -2787,10 +2781,6 @@ class ASTContext : public RefCountedBase<ASTContext> {
/// long double and double on AArch64 will return 0).
int getFloatingTypeSemanticOrder(QualType LHS, QualType RHS) const;
unsigned getTargetAddressSpace(QualType T) const;
unsigned getTargetAddressSpace(Qualifiers Q) const;
unsigned getTargetAddressSpace(LangAS AS) const;
LangAS getLangASForBuiltinAddressSpace(unsigned AS) const;
@@ -2803,6 +2793,23 @@ class ASTContext : public RefCountedBase<ASTContext> {
return AddrSpaceMapMangling || isTargetAddressSpace(AS);
}
// Merges two exception specifications, such that the resulting
// exception spec is the union of both. For example, if either
// of them can throw something, the result can throw it as well.
FunctionProtoType::ExceptionSpecInfo
mergeExceptionSpecs(FunctionProtoType::ExceptionSpecInfo ESI1,
FunctionProtoType::ExceptionSpecInfo ESI2,
SmallVectorImpl<QualType> &ExceptionTypeStorage,
bool AcceptDependent);
// For two "same" types, return a type which has
// the common sugar between them. If Unqualified is true,
// both types need only be the same unqualified type.
// The result will drop the qualifiers which do not occur
// in both types.
QualType getCommonSugaredType(QualType X, QualType Y,
bool Unqualified = false);
private:
// Helper for integer ordering
unsigned getIntegerRank(const Type *T) const;
@@ -2820,14 +2827,20 @@ class ASTContext : public RefCountedBase<ASTContext> {
bool typesAreBlockPointerCompatible(QualType, QualType);
bool isObjCIdType(QualType T) const {
if (const auto *ET = dyn_cast<ElaboratedType>(T))
T = ET->getNamedType();
return T == getObjCIdType();
}
bool isObjCClassType(QualType T) const {
if (const auto *ET = dyn_cast<ElaboratedType>(T))
T = ET->getNamedType();
return T == getObjCClassType();
}
bool isObjCSelType(QualType T) const {
if (const auto *ET = dyn_cast<ElaboratedType>(T))
T = ET->getNamedType();
return T == getObjCSelType();
}
@@ -2854,9 +2867,11 @@ class ASTContext : public RefCountedBase<ASTContext> {
// Functions for calculating composite types
QualType mergeTypes(QualType, QualType, bool OfBlockPointer = false,
bool Unqualified = false, bool BlockReturnType = false);
bool Unqualified = false, bool BlockReturnType = false,
bool IsConditionalOperator = false);
QualType mergeFunctionTypes(QualType, QualType, bool OfBlockPointer = false,
bool Unqualified = false, bool AllowCXX = false);
bool Unqualified = false, bool AllowCXX = false,
bool IsConditionalOperator = false);
QualType mergeFunctionParameterTypes(QualType, QualType,
bool OfBlockPointer = false,
bool Unqualified = false);
@@ -3104,6 +3119,9 @@ class ASTContext : public RefCountedBase<ASTContext> {
/// valid feature names.
ParsedTargetAttr filterFunctionTargetAttrs(const TargetAttr *TD) const;
std::vector<std::string>
filterFunctionTargetVersionAttrs(const TargetVersionAttr *TV) const;
void getFunctionFeatureMap(llvm::StringMap<bool> &FeatureMap,
const FunctionDecl *) const;
void getFunctionFeatureMap(llvm::StringMap<bool> &FeatureMap,
@@ -3196,11 +3214,11 @@ OPT_LIST(V)
#undef OPT_LIST
LLVM_NODISCARD ObjCEncOptions keepingOnly(ObjCEncOptions Mask) const {
[[nodiscard]] ObjCEncOptions keepingOnly(ObjCEncOptions Mask) const {
return Bits & Mask.Bits;
}
LLVM_NODISCARD ObjCEncOptions forComponentType() const {
[[nodiscard]] ObjCEncOptions forComponentType() const {
ObjCEncOptions Mask = ObjCEncOptions()
.setIsOutermostType()
.setIsStructField();
@@ -32,6 +32,7 @@ class ASTDumper : public ASTNodeTraverser<ASTDumper, TextNodeDumper> {
TextNodeDumper &doGetNodeDelegate() { return NodeDumper; }
void dumpInvalidDeclContext(const DeclContext *DC);
void dumpLookups(const DeclContext *DC, bool DumpDecls);
template <typename SpecializationDecl>
@@ -27,8 +27,8 @@
#include "clang/Basic/SourceLocation.h"
#include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/DenseSet.h"
#include "llvm/ADT/Optional.h"
#include "llvm/ADT/SmallVector.h"
#include <optional>
#include <utility>
namespace clang {
@@ -304,7 +304,7 @@ class TypeSourceInfo;
/// \param From Object to import.
/// \return Error information (success or error).
template <typename ImportT>
LLVM_NODISCARD llvm::Error importInto(ImportT &To, const ImportT &From) {
[[nodiscard]] llvm::Error importInto(ImportT &To, const ImportT &From) {
auto ToOrErr = Import(From);
if (ToOrErr)
To = *ToOrErr;
@@ -367,7 +367,7 @@ class TypeSourceInfo;
/// in the "to" context was imported. If it was not imported or of the wrong
/// type a null value is returned.
template <typename DeclT>
llvm::Optional<DeclT *> getImportedFromDecl(const DeclT *ToD) const {
std::optional<DeclT *> getImportedFromDecl(const DeclT *ToD) const {
auto FromI = ImportedFromDecls.find(ToD);
if (FromI == ImportedFromDecls.end())
return {};
@@ -482,7 +482,7 @@ class TypeSourceInfo;
/// Import the definition of the given declaration, including all of
/// the declarations it contains.
LLVM_NODISCARD llvm::Error ImportDefinition(Decl *From);
[[nodiscard]] llvm::Error ImportDefinition(Decl *From);
/// Cope with a name conflict when importing a declaration into the
/// given context.
@@ -564,7 +564,7 @@ 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<ASTImportError> getImportDeclErrorIfAny(Decl *FromD) const;
std::optional<ASTImportError> getImportDeclErrorIfAny(Decl *FromD) const;
/// Mark (newly) imported declaration with error.
void setImportDeclError(Decl *From, ASTImportError Error);
@@ -577,8 +577,8 @@ class TypeSourceInfo;
/// Determine the index of a field in its parent record.
/// F should be a field (or indirect field) declaration.
/// \returns The index of the field in its parent context (starting from 0).
/// On error `None` is returned (parent context is non-record).
static llvm::Optional<unsigned> getFieldIndex(Decl *F);
/// On error `std::nullopt` is returned (parent context is non-record).
static std::optional<unsigned> getFieldIndex(Decl *F);
};
} // namespace clang
@@ -18,6 +18,7 @@
#include "clang/AST/ASTImporterLookupTable.h"
#include "clang/AST/Decl.h"
#include "llvm/ADT/DenseMap.h"
#include <optional>
namespace clang {
@@ -65,12 +66,12 @@ class ASTImporterSharedState {
LookupTable->remove(ND);
}
llvm::Optional<ASTImportError> getImportDeclErrorIfAny(Decl *ToD) const {
std::optional<ASTImportError> getImportDeclErrorIfAny(Decl *ToD) const {
auto Pos = ImportErrors.find(ToD);
if (Pos != ImportErrors.end())
return Pos->second;
else
return Optional<ASTImportError>();
return std::nullopt;
}
void setImportDeclError(Decl *To, ASTImportError Error) {
@@ -246,7 +246,7 @@ class ASTNodeTraverser
.getTypeConstraint()
->getImmediatelyDeclaredConstraint());
} else if (auto *NR = dyn_cast<concepts::NestedRequirement>(R)) {
if (!NR->isSubstitutionFailure())
if (!NR->hasInvalidConstraint())
Visit(NR->getConstraintExpr());
}
});
@@ -389,16 +389,13 @@ class ASTNodeTraverser
void VisitBTFTagAttributedType(const BTFTagAttributedType *T) {
Visit(T->getWrappedType());
}
void VisitSubstTemplateTypeParmType(const SubstTemplateTypeParmType *T) {
Visit(T->getReplacedParameter());
}
void VisitSubstTemplateTypeParmType(const SubstTemplateTypeParmType *) {}
void
VisitSubstTemplateTypeParmPackType(const SubstTemplateTypeParmPackType *T) {
Visit(T->getReplacedParameter());
Visit(T->getArgumentPack());
}
void VisitTemplateSpecializationType(const TemplateSpecializationType *T) {
for (const auto &Arg : *T)
for (const auto &Arg : T->template_arguments())
Visit(Arg);
}
void VisitObjCObjectPointerType(const ObjCObjectPointerType *T) {
@@ -479,6 +476,8 @@ class ASTNodeTraverser
Visit(D->getAsmString());
}
void VisitTopLevelStmtDecl(const TopLevelStmtDecl *D) { Visit(D->getStmt()); }
void VisitCapturedDecl(const CapturedDecl *D) { Visit(D->getBody()); }
void VisitOMPThreadPrivateDecl(const OMPThreadPrivateDecl *D) {
@@ -626,7 +625,14 @@ class ASTNodeTraverser
Visit(D->getConstraintExpr());
}
void VisitImplicitConceptSpecializationDecl(
const ImplicitConceptSpecializationDecl *CSD) {
for (const TemplateArgument &Arg : CSD->getTemplateArguments())
Visit(Arg);
}
void VisitConceptSpecializationExpr(const ConceptSpecializationExpr *CSE) {
Visit(CSE->getSpecializationDecl());
if (CSE->hasExplicitTemplateArgs())
for (const auto &ArgLoc : CSE->getTemplateArgsAsWritten()->arguments())
dumpTemplateArgumentLoc(ArgLoc);
@@ -638,9 +644,16 @@ class ASTNodeTraverser
}
void VisitFriendDecl(const FriendDecl *D) {
if (!D->getFriendType())
if (D->getFriendType()) {
// Traverse any CXXRecordDecl owned by this type, since
// it will not be in the parent context:
if (auto *ET = D->getFriendType()->getType()->getAs<ElaboratedType>())
if (auto *TD = ET->getOwnedTagDecl())
Visit(TD);
} else {
Visit(D->getFriendDecl());
}
}
void VisitObjCMethodDecl(const ObjCMethodDecl *D) {
if (D->isThisDeclarationADefinition())
@@ -704,6 +717,12 @@ class ASTNodeTraverser
}
}
void VisitCXXParenListInitExpr(const CXXParenListInitExpr *PLIE) {
if (auto *Filler = PLIE->getArrayFiller()) {
Visit(Filler, "array_filler");
}
}
void VisitBlockExpr(const BlockExpr *Node) { Visit(Node->getBlockDecl()); }
void VisitOpaqueValueExpr(const OpaqueValueExpr *Node) {
@@ -17,7 +17,7 @@
#include "clang/AST/DeclBase.h"
#include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/DenseSet.h"
#include "llvm/ADT/Optional.h"
#include <optional>
#include <queue>
#include <utility>
@@ -114,7 +114,7 @@ struct StructuralEquivalenceContext {
///
/// FIXME: This is needed by ASTImporter and ASTStructureEquivalence. It
/// probably makes more sense in some other common place then here.
static llvm::Optional<unsigned>
static std::optional<unsigned>
findUntaggedStructOrUnionIndex(RecordDecl *Anon);
// If ErrorOnTagTypeMismatch is set, return the error, otherwise get the
@@ -51,11 +51,10 @@ enum TraversalKind {
class ASTNodeKind {
public:
/// Empty identifier. It matches nothing.
ASTNodeKind() : KindId(NKI_None) {}
constexpr ASTNodeKind() : KindId(NKI_None) {}
/// Construct an identifier for T.
template <class T>
static ASTNodeKind getFromNodeKind() {
template <class T> static constexpr ASTNodeKind getFromNodeKind() {
return ASTNodeKind(KindToKindId<T>::Id);
}
@@ -71,12 +70,12 @@ class ASTNodeKind {
/// \}
/// Returns \c true if \c this and \c Other represent the same kind.
bool isSame(ASTNodeKind Other) const {
constexpr bool isSame(ASTNodeKind Other) const {
return KindId != NKI_None && KindId == Other.KindId;
}
/// Returns \c true only for the default \c ASTNodeKind()
bool isNone() const { return KindId == NKI_None; }
constexpr bool isNone() const { return KindId == NKI_None; }
/// Returns \c true if \c this is a base kind of (or same as) \c Other.
/// \param Distance If non-null, used to return the distance between \c this
@@ -87,7 +86,7 @@ class ASTNodeKind {
StringRef asStringRef() const;
/// Strict weak ordering for ASTNodeKind.
bool operator<(const ASTNodeKind &Other) const {
constexpr bool operator<(const ASTNodeKind &Other) const {
return KindId < Other.KindId;
}
@@ -121,7 +120,7 @@ class ASTNodeKind {
/// Check if the given ASTNodeKind identifies a type that offers pointer
/// identity. This is useful for the fast path in DynTypedNode.
bool hasPointerIdentity() const {
constexpr bool hasPointerIdentity() const {
return KindId > NKI_LastKindWithoutPointerIdentity;
}
@@ -165,7 +164,7 @@ class ASTNodeKind {
};
/// Use getFromNodeKind<T>() to construct the kind.
ASTNodeKind(NodeKindId KindId) : KindId(KindId) {}
constexpr ASTNodeKind(NodeKindId KindId) : KindId(KindId) {}
/// Returns \c true if \c Base is a base kind of (or same as) \c
/// Derived.
@@ -69,7 +69,12 @@ class ASTUnresolvedSet {
return false;
}
void erase(unsigned I) { Decls[I] = Decls.pop_back_val(); }
void erase(unsigned I) {
if (I == Decls.size() - 1)
Decls.pop_back();
else
Decls[I] = Decls.pop_back_val();
}
void clear() { Decls.clear(); }
@@ -10,17 +10,17 @@
#define LLVM_CLANG_AST_ABSTRACTBASICREADER_H
#include "clang/AST/DeclTemplate.h"
#include <optional>
namespace clang {
namespace serialization {
template <class T>
inline T makeNullableFromOptional(const Optional<T> &value) {
inline T makeNullableFromOptional(const std::optional<T> &value) {
return (value ? *value : T());
}
template <class T>
inline T *makePointerFromOptional(Optional<T *> value) {
template <class T> inline T *makePointerFromOptional(std::optional<T *> value) {
return value.value_or(nullptr);
}
@@ -49,7 +49,7 @@ inline T *makePointerFromOptional(Optional<T *> value) {
// type-specific readers for all the enum types.
//
// template <class ValueType>
// Optional<ValueType> writeOptional();
// std::optional<ValueType> writeOptional();
//
// Reads an optional value from the current property.
//
@@ -157,7 +157,7 @@ class DataStreamBasicReader : public BasicReaderBase<Impl> {
}
template <class T, class... Args>
llvm::Optional<T> readOptional(Args &&...args) {
std::optional<T> readOptional(Args &&...args) {
return UnpackOptionalValue<T>::unpack(
ReadDispatcher<T>::read(asImpl(), std::forward<Args>(args)...));
}
@@ -190,7 +190,8 @@ class DataStreamBasicReader : public BasicReaderBase<Impl> {
APValue::LValuePathSerializationHelper readLValuePathSerializationHelper(
SmallVectorImpl<APValue::LValuePathEntry> &path) {
auto elemTy = asImpl().readQualType();
auto origTy = asImpl().readQualType();
auto elemTy = origTy;
unsigned pathLength = asImpl().readUInt32();
for (unsigned i = 0; i < pathLength; ++i) {
if (elemTy->template getAs<RecordType>()) {
@@ -208,7 +209,7 @@ class DataStreamBasicReader : public BasicReaderBase<Impl> {
APValue::LValuePathEntry::ArrayIndex(asImpl().readUInt32()));
}
}
return APValue::LValuePathSerializationHelper(path, elemTy);
return APValue::LValuePathSerializationHelper(path, origTy);
}
Qualifiers readQualifiers() {
@@ -11,20 +11,18 @@
#include "clang/AST/ASTContext.h"
#include "clang/AST/DeclTemplate.h"
#include <optional>
namespace clang {
namespace serialization {
template <class T>
inline llvm::Optional<T> makeOptionalFromNullable(const T &value) {
return (value.isNull()
? llvm::Optional<T>()
: llvm::Optional<T>(value));
inline std::optional<T> makeOptionalFromNullable(const T &value) {
return (value.isNull() ? std::optional<T>() : std::optional<T>(value));
}
template <class T>
inline llvm::Optional<T*> makeOptionalFromPointer(T *value) {
return (value ? llvm::Optional<T*>(value) : llvm::Optional<T*>());
template <class T> inline std::optional<T *> makeOptionalFromPointer(T *value) {
return (value ? std::optional<T *>(value) : std::optional<T *>());
}
// PropertyWriter is a class concept that requires the following method:
@@ -51,7 +49,7 @@ inline llvm::Optional<T*> makeOptionalFromPointer(T *value) {
// type-specific writers for all the enum types.
//
// template <class ValueType>
// void writeOptional(Optional<ValueType> value);
// void writeOptional(std::optional<ValueType> value);
//
// Writes an optional value as the current property.
//
@@ -148,8 +146,7 @@ class DataStreamBasicWriter : public BasicWriterBase<Impl> {
}
}
template <class T>
void writeOptional(llvm::Optional<T> value) {
template <class T> void writeOptional(std::optional<T> value) {
WriteDispatcher<T>::write(asImpl(), PackOptionalValue<T>::pack(value));
}
@@ -24,7 +24,6 @@
#include "clang/Basic/OpenMPKinds.h"
#include "clang/Basic/Sanitizers.h"
#include "clang/Basic/SourceLocation.h"
#include "llvm/ADT/StringSwitch.h"
#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/VersionTuple.h"
#include "llvm/Support/raw_ostream.h"
@@ -190,6 +189,22 @@ class InheritableParamAttr : public InheritableAttr {
}
};
class HLSLAnnotationAttr : public InheritableAttr {
protected:
HLSLAnnotationAttr(ASTContext &Context, const AttributeCommonInfo &CommonInfo,
attr::Kind AK, bool IsLateParsed,
bool InheritEvenIfAlreadyPresent)
: InheritableAttr(Context, CommonInfo, AK, IsLateParsed,
InheritEvenIfAlreadyPresent) {}
public:
// Implement isa/cast/dyncast/etc.
static bool classof(const Attr *A) {
return A->getKind() >= attr::FirstHLSLAnnotationAttr &&
A->getKind() <= attr::LastHLSLAnnotationAttr;
}
};
/// A parameter attribute which changes the argument-passing ABI rule
/// for the parameter.
class ParameterABIAttr : public InheritableParamAttr {
@@ -347,24 +362,6 @@ class ParamIdx {
static_assert(sizeof(ParamIdx) == sizeof(ParamIdx::SerialType),
"ParamIdx does not fit its serialization type");
/// Contains information gathered from parsing the contents of TargetAttr.
struct ParsedTargetAttr {
std::vector<std::string> Features;
StringRef Architecture;
StringRef Tune;
StringRef BranchProtection;
bool DuplicateArchitecture = false;
bool DuplicateTune = false;
bool operator ==(const ParsedTargetAttr &Other) const {
return DuplicateArchitecture == Other.DuplicateArchitecture &&
DuplicateTune == Other.DuplicateTune &&
Architecture == Other.Architecture &&
Tune == Other.Tune &&
BranchProtection == Other.BranchProtection &&
Features == Other.Features;
}
};
#include "clang/AST/Attrs.inc"
inline const StreamingDiagnostic &operator<<(const StreamingDiagnostic &DB,
@@ -305,7 +305,6 @@ class CanProxyBase {
LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, hasSignedIntegerRepresentation)
LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, hasUnsignedIntegerRepresentation)
LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, hasFloatingRepresentation)
LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isPromotableIntegerType)
LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isSignedIntegerType)
LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isUnsignedIntegerType)
LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isSignedIntegerOrEnumerationType)
@@ -529,7 +528,7 @@ struct CanProxyAdaptor<FunctionProtoType>
template<>
struct CanProxyAdaptor<TypeOfType> : public CanProxyBase<TypeOfType> {
LLVM_CLANG_CANPROXY_TYPE_ACCESSOR(getUnderlyingType)
LLVM_CLANG_CANPROXY_TYPE_ACCESSOR(getUnmodifiedType)
};
template<>
@@ -64,6 +64,12 @@ namespace clang {
return CharUnits(Quantity);
}
/// fromQuantity - Construct a CharUnits quantity from an llvm::Align
/// quantity.
static CharUnits fromQuantity(llvm::Align Quantity) {
return CharUnits(Quantity.value());
}
// Compound assignment.
CharUnits& operator+= (const CharUnits &Other) {
Quantity += Other.Quantity;
@@ -183,7 +189,8 @@ namespace clang {
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.
/// std::nullopt, Beware llvm::MaybeAlign assumes power of two 8-bit
/// bytes.
llvm::MaybeAlign getAsMaybeAlign() const {
return llvm::MaybeAlign(Quantity);
}
@@ -80,7 +80,7 @@ class Sema {
ArrayRef<T> copyArray(ArrayRef<T> Source) {
if (!Source.empty())
return Source.copy(Allocator);
return None;
return std::nullopt;
}
ParagraphComment *actOnParagraphComment(
@@ -19,6 +19,7 @@
#include "llvm/ADT/DenseMap.h"
#include <array>
#include <cassert>
#include <optional>
#include <vector>
namespace llvm {
@@ -58,7 +59,8 @@ inline ComparisonCategoryType commonComparisonType(ComparisonCategoryType A,
/// Get the comparison category that should be used when comparing values of
/// type \c T.
Optional<ComparisonCategoryType> getComparisonCategoryForBuiltinCmp(QualType T);
std::optional<ComparisonCategoryType>
getComparisonCategoryForBuiltinCmp(QualType T);
/// An enumeration representing the possible results of a three-way
/// comparison. These values map onto instances of comparison category types
@@ -79,6 +79,7 @@ class CXXUnresolvedConstructExpr;
class CXXDependentScopeMemberExpr;
class MaterializeTemporaryExpr;
class CXXFoldExpr;
class CXXParenListInitExpr;
class TypeTraitExpr;
class ConceptSpecializationExpr;
class SYCLUniqueStableNameExpr;
@@ -168,6 +169,7 @@ ExprDependence computeDependence(CXXUnresolvedConstructExpr *E);
ExprDependence computeDependence(CXXDependentScopeMemberExpr *E);
ExprDependence computeDependence(MaterializeTemporaryExpr *E);
ExprDependence computeDependence(CXXFoldExpr *E);
ExprDependence computeDependence(CXXParenListInitExpr *E);
ExprDependence computeDependence(TypeTraitExpr *E);
ExprDependence computeDependence(ConceptSpecializationExpr *E,
bool ValueDependent);
@@ -35,7 +35,6 @@
#include "clang/Basic/Visibility.h"
#include "llvm/ADT/APSInt.h"
#include "llvm/ADT/ArrayRef.h"
#include "llvm/ADT/Optional.h"
#include "llvm/ADT/PointerIntPair.h"
#include "llvm/ADT/PointerUnion.h"
#include "llvm/ADT/StringRef.h"
@@ -46,6 +45,7 @@
#include <cassert>
#include <cstddef>
#include <cstdint>
#include <optional>
#include <string>
#include <utility>
@@ -291,7 +291,9 @@ class NamedDecl : public Decl {
/// Pretty-print the unqualified name of this declaration. Can be overloaded
/// by derived classes to provide a more user-friendly name when appropriate.
virtual void printName(raw_ostream &os) const;
virtual void printName(raw_ostream &OS, const PrintingPolicy &Policy) const;
/// Calls printName() with the ASTContext printing policy from the decl.
void printName(raw_ostream &OS) const;
/// Get the actual, stored name of the declaration, which may be a special
/// name.
@@ -435,7 +437,7 @@ class NamedDecl : public Decl {
/// If visibility was explicitly specified for this
/// declaration, return that visibility.
Optional<Visibility>
std::optional<Visibility>
getExplicitVisibility(ExplicitVisibilityKind kind) const;
/// True if the computed linkage is valid. Used for consistency
@@ -540,6 +542,9 @@ class LabelDecl : public NamedDecl {
class NamespaceDecl : public NamedDecl, public DeclContext,
public Redeclarable<NamespaceDecl>
{
enum Flags : unsigned { F_Inline = 1 << 0, F_Nested = 1 << 1 };
/// The starting location of the source range, pointing
/// to either the namespace or the inline keyword.
SourceLocation LocStart;
@@ -551,11 +556,12 @@ class NamespaceDecl : public NamedDecl, public DeclContext,
/// this namespace or to the first namespace in the chain (the latter case
/// only when this is not the first in the chain), along with a
/// boolean value indicating whether this is an inline namespace.
llvm::PointerIntPair<NamespaceDecl *, 1, bool> AnonOrFirstNamespaceAndInline;
llvm::PointerIntPair<NamespaceDecl *, 2, unsigned>
AnonOrFirstNamespaceAndFlags;
NamespaceDecl(ASTContext &C, DeclContext *DC, bool Inline,
SourceLocation StartLoc, SourceLocation IdLoc,
IdentifierInfo *Id, NamespaceDecl *PrevDecl);
IdentifierInfo *Id, NamespaceDecl *PrevDecl, bool Nested);
using redeclarable_base = Redeclarable<NamespaceDecl>;
@@ -567,10 +573,10 @@ class NamespaceDecl : public NamedDecl, public DeclContext,
friend class ASTDeclReader;
friend class ASTDeclWriter;
static NamespaceDecl *Create(ASTContext &C, DeclContext *DC,
bool Inline, SourceLocation StartLoc,
SourceLocation IdLoc, IdentifierInfo *Id,
NamespaceDecl *PrevDecl);
static NamespaceDecl *Create(ASTContext &C, DeclContext *DC, bool Inline,
SourceLocation StartLoc, SourceLocation IdLoc,
IdentifierInfo *Id, NamespaceDecl *PrevDecl,
bool Nested);
static NamespaceDecl *CreateDeserialized(ASTContext &C, unsigned ID);
@@ -599,12 +605,33 @@ class NamespaceDecl : public NamedDecl, public DeclContext,
/// Returns true if this is an inline namespace declaration.
bool isInline() const {
return AnonOrFirstNamespaceAndInline.getInt();
return AnonOrFirstNamespaceAndFlags.getInt() & F_Inline;
}
/// Set whether this is an inline namespace declaration.
void setInline(bool Inline) {
AnonOrFirstNamespaceAndInline.setInt(Inline);
unsigned F = AnonOrFirstNamespaceAndFlags.getInt();
if (Inline)
AnonOrFirstNamespaceAndFlags.setInt(F | F_Inline);
else
AnonOrFirstNamespaceAndFlags.setInt(F & ~F_Inline);
}
/// Returns true if this is a nested namespace declaration.
/// \code
/// namespace outer::nested { }
/// \endcode
bool isNested() const {
return AnonOrFirstNamespaceAndFlags.getInt() & F_Nested;
}
/// Set whether this is a nested namespace declaration.
void setNested(bool Nested) {
unsigned F = AnonOrFirstNamespaceAndFlags.getInt();
if (Nested)
AnonOrFirstNamespaceAndFlags.setInt(F | F_Nested);
else
AnonOrFirstNamespaceAndFlags.setInt(F & ~F_Nested);
}
/// Returns true if the inline qualifier for \c Name is redundant.
@@ -633,11 +660,11 @@ class NamespaceDecl : public NamedDecl, public DeclContext,
/// Retrieve the anonymous namespace nested inside this namespace,
/// if any.
NamespaceDecl *getAnonymousNamespace() const {
return getOriginalNamespace()->AnonOrFirstNamespaceAndInline.getPointer();
return getOriginalNamespace()->AnonOrFirstNamespaceAndFlags.getPointer();
}
void setAnonymousNamespace(NamespaceDecl *D) {
getOriginalNamespace()->AnonOrFirstNamespaceAndInline.setPointer(D);
getOriginalNamespace()->AnonOrFirstNamespaceAndFlags.setPointer(D);
}
/// Retrieves the canonical declaration of this namespace.
@@ -668,6 +695,8 @@ class NamespaceDecl : public NamedDecl, public DeclContext,
}
};
class VarDecl;
/// Represent the declaration of a variable (in which case it is
/// an lvalue) a function (in which case it is a function designator) or
/// an enum constant.
@@ -689,6 +718,18 @@ class ValueDecl : public NamedDecl {
/// or declared with the weak or weak-ref attr.
bool isWeak() const;
/// Whether this variable is the implicit variable for a lambda init-capture.
/// Only VarDecl can be init captures, but both VarDecl and BindingDecl
/// can be captured.
bool isInitCapture() const;
// If this is a VarDecl, or a BindindDecl with an
// associated decomposed VarDecl, return that VarDecl.
VarDecl *getPotentiallyDecomposedVarDecl();
const VarDecl *getPotentiallyDecomposedVarDecl() const {
return const_cast<ValueDecl *>(this)->getPotentiallyDecomposedVarDecl();
}
// Implement isa/cast/dyncast/etc.
static bool classof(const Decl *D) { return classofKind(D->getKind()); }
static bool classofKind(Kind K) { return K >= firstValue && K <= lastValue; }
@@ -882,7 +923,10 @@ class VarDecl : public DeclaratorDecl, public Redeclarable<VarDecl> {
CallInit,
/// Direct list-initialization (C++11)
ListInit
ListInit,
/// Parenthesized list-initialization (C++20)
ParenListInit
};
/// Kinds of thread-local storage.
@@ -1853,7 +1897,8 @@ enum class MultiVersionKind {
Target,
CPUSpecific,
CPUDispatch,
TargetClones
TargetClones,
TargetVersion
};
/// Represents a function declaration or definition.
@@ -1936,6 +1981,8 @@ class FunctionDecl : public DeclaratorDecl,
/// EndRangeLoc.
SourceLocation EndRangeLoc;
SourceLocation DefaultKWLoc;
/// The template or declaration that this declaration
/// describes or was instantiated from, respectively.
///
@@ -2242,6 +2289,16 @@ class FunctionDecl : public DeclaratorDecl,
FunctionDeclBits.IsExplicitlyDefaulted = ED;
}
SourceLocation getDefaultLoc() const {
return isExplicitlyDefaulted() ? DefaultKWLoc : SourceLocation();
}
void setDefaultLoc(SourceLocation NewLoc) {
assert((NewLoc.isInvalid() || isExplicitlyDefaulted()) &&
"Can't set default loc is function isn't explicitly defaulted");
DefaultKWLoc = NewLoc;
}
/// True if this method is user-declared and was not
/// deleted or defaulted on its first declaration.
bool isUserProvided() const {
@@ -2414,7 +2471,7 @@ class FunctionDecl : public DeclaratorDecl,
/// If this function is an allocation/deallocation function that takes
/// the `std::nothrow_t` tag, return true through IsNothrow,
bool isReplaceableGlobalAllocationFunction(
Optional<unsigned> *AlignmentParam = nullptr,
std::optional<unsigned> *AlignmentParam = nullptr,
bool *IsNothrow = nullptr) const;
/// Determine if this function provides an inline implementation of a builtin.
@@ -2466,6 +2523,19 @@ class FunctionDecl : public DeclaratorDecl,
getCanonicalDecl()->FunctionDeclBits.IsMultiVersion = V;
}
// Sets that this is a constrained friend where the constraint refers to an
// enclosing template.
void setFriendConstraintRefersToEnclosingTemplate(bool V = true) {
getCanonicalDecl()
->FunctionDeclBits.FriendConstraintRefersToEnclosingTemplate = V;
}
// Indicates this function is a constrained friend, where the constraint
// refers to an enclosing template for hte purposes of [temp.friend]p9.
bool FriendConstraintRefersToEnclosingTemplate() const {
return getCanonicalDecl()
->FunctionDeclBits.FriendConstraintRefersToEnclosingTemplate;
}
/// Gets the kind of multiversioning attribute this declaration has. Note that
/// this can return a value even if the function is not multiversion, such as
/// the case of 'target'.
@@ -3144,7 +3214,7 @@ class IndirectFieldDecl : public ValueDecl,
using chain_iterator = ArrayRef<NamedDecl *>::const_iterator;
ArrayRef<NamedDecl *> chain() const {
return llvm::makeArrayRef(Chaining, ChainingSize);
return llvm::ArrayRef(Chaining, ChainingSize);
}
chain_iterator chain_begin() const { return chain().begin(); }
chain_iterator chain_end() const { return chain().end(); }
@@ -3621,6 +3691,8 @@ class TagDecl : public TypeDecl,
return getExtInfo()->TemplParamLists[i];
}
void printName(raw_ostream &OS, const PrintingPolicy &Policy) const override;
void setTemplateParameterListsInfo(ASTContext &Context,
ArrayRef<TemplateParameterList *> TPLists);
@@ -3839,6 +3911,11 @@ class EnumDecl : public TagDecl {
/// -101 1001011 8
unsigned getNumNegativeBits() const { return EnumDeclBits.NumNegativeBits; }
/// Calculates the [Min,Max) values the enum can store based on the
/// NumPositiveBits and NumNegativeBits. This matters for enums that do not
/// have a fixed underlying type.
void getValueRange(llvm::APInt &Max, llvm::APInt &Min) const;
/// Returns true if this is a C++11 scoped enumeration.
bool isScoped() const { return EnumDeclBits.IsScoped; }
@@ -3918,6 +3995,7 @@ class RecordDecl : public TagDecl {
// to save some space. Use the provided accessors to access it.
public:
friend class DeclContext;
friend class ASTDeclReader;
/// Enum that represents the different ways arguments are passed to and
/// returned from function calls. This takes into account the target-specific
/// and version-specific rules along with the rules determined by the
@@ -4173,9 +4251,16 @@ class RecordDecl : public TagDecl {
/// nullptr is returned if no named data member exists.
const FieldDecl *findFirstNamedDataMember() const;
/// Get precomputed ODRHash or add a new one.
unsigned getODRHash();
private:
/// Deserialize just the fields.
void LoadFieldsFromExternalStorage() const;
/// True if a valid hash is stored in ODRHash.
bool hasODRHash() const { return RecordDeclBits.ODRHash; }
void setODRHash(unsigned Hash) { RecordDeclBits.ODRHash = Hash; }
};
class FileScopeAsmDecl : public Decl {
@@ -4210,6 +4295,34 @@ class FileScopeAsmDecl : public Decl {
static bool classofKind(Kind K) { return K == FileScopeAsm; }
};
/// A declaration that models statements at global scope. This declaration
/// supports incremental and interactive C/C++.
///
/// \note This is used in libInterpreter, clang -cc1 -fincremental-extensions
/// and in tools such as clang-repl.
class TopLevelStmtDecl : public Decl {
friend class ASTDeclReader;
friend class ASTDeclWriter;
Stmt *Statement = nullptr;
TopLevelStmtDecl(DeclContext *DC, SourceLocation L, Stmt *S)
: Decl(TopLevelStmt, DC, L), Statement(S) {}
virtual void anchor();
public:
static TopLevelStmtDecl *Create(ASTContext &C, Stmt *Statement);
static TopLevelStmtDecl *CreateDeserialized(ASTContext &C, unsigned ID);
SourceRange getSourceRange() const override LLVM_READONLY;
Stmt *getStmt() { return Statement; }
const Stmt *getStmt() const { return Statement; }
static bool classof(const Decl *D) { return classofKind(D->getKind()); }
static bool classofKind(Kind K) { return K == TopLevelStmt; }
};
/// Represents a block literal declaration, which is like an
/// unnamed FunctionDecl. For example:
/// ^{ statement-body } or ^(int arg1, float arg2){ statement-body }
@@ -4658,6 +4771,51 @@ class EmptyDecl : public Decl {
static bool classofKind(Kind K) { return K == Empty; }
};
/// HLSLBufferDecl - Represent a cbuffer or tbuffer declaration.
class HLSLBufferDecl final : public NamedDecl, public DeclContext {
/// LBraceLoc - The ending location of the source range.
SourceLocation LBraceLoc;
/// RBraceLoc - The ending location of the source range.
SourceLocation RBraceLoc;
/// KwLoc - The location of the cbuffer or tbuffer keyword.
SourceLocation KwLoc;
/// IsCBuffer - Whether the buffer is a cbuffer (and not a tbuffer).
bool IsCBuffer;
HLSLBufferDecl(DeclContext *DC, bool CBuffer, SourceLocation KwLoc,
IdentifierInfo *ID, SourceLocation IDLoc,
SourceLocation LBrace);
public:
static HLSLBufferDecl *Create(ASTContext &C, DeclContext *LexicalParent,
bool CBuffer, SourceLocation KwLoc,
IdentifierInfo *ID, SourceLocation IDLoc,
SourceLocation LBrace);
static HLSLBufferDecl *CreateDeserialized(ASTContext &C, unsigned ID);
SourceRange getSourceRange() const override LLVM_READONLY {
return SourceRange(getLocStart(), RBraceLoc);
}
SourceLocation getLocStart() const LLVM_READONLY { return KwLoc; }
SourceLocation getLBraceLoc() const { return LBraceLoc; }
SourceLocation getRBraceLoc() const { return RBraceLoc; }
void setRBraceLoc(SourceLocation L) { RBraceLoc = L; }
bool isCBuffer() const { return IsCBuffer; }
// Implement isa/cast/dyncast/etc.
static bool classof(const Decl *D) { return classofKind(D->getKind()); }
static bool classofKind(Kind K) { return K == HLSLBuffer; }
static DeclContext *castToDeclContext(const HLSLBufferDecl *D) {
return static_cast<DeclContext *>(const_cast<HLSLBufferDecl *>(D));
}
static HLSLBufferDecl *castFromDeclContext(const DeclContext *DC) {
return static_cast<HLSLBufferDecl *>(const_cast<DeclContext *>(DC));
}
friend class ASTDeclReader;
friend class ASTDeclWriter;
};
/// Insertion operator for diagnostics. This allows sending NamedDecl's
/// into a diagnostic with <<.
inline const StreamingDiagnostic &operator<<(const StreamingDiagnostic &PD,
@@ -447,6 +447,14 @@ class alignas(8) Decl {
return const_cast<Decl*>(this)->getDeclContext();
}
/// Return the non transparent context.
/// See the comment of `DeclContext::isTransparentContext()` for the
/// definition of transparent context.
DeclContext *getNonTransparentDeclContext();
const DeclContext *getNonTransparentDeclContext() const {
return const_cast<Decl *>(this)->getNonTransparentDeclContext();
}
/// Find the innermost non-closure ancestor of this declaration,
/// walking up through blocks, lambdas, etc. If that ancestor is
/// not a code context (!isFunctionOrMethod()), returns null.
@@ -466,6 +474,9 @@ class alignas(8) Decl {
bool isInStdNamespace() const;
// Return true if this is a FileContext Decl.
bool isFileContextDecl() const;
ASTContext &getASTContext() const LLVM_READONLY;
/// Helper to get the language options from the ASTContext.
@@ -1120,7 +1131,7 @@ class alignas(8) Decl {
/// Determine whether this is a block-scope declaration with linkage.
/// This will either be a local variable declaration declared 'extern', or a
/// local function declaration.
bool isLocalExternDecl() {
bool isLocalExternDecl() const {
return IdentifierNamespace & IDNS_LocalExtern;
}
@@ -1566,10 +1577,14 @@ class DeclContext {
/// Indicates whether this struct has had its field layout randomized.
uint64_t IsRandomized : 1;
/// True if a valid hash is stored in ODRHash. This should shave off some
/// extra storage and prevent CXXRecordDecl to store unused bits.
uint64_t ODRHash : 26;
};
/// Number of non-inherited bits in RecordDeclBitfields.
enum { NumRecordDeclBits = 15 };
enum { NumRecordDeclBits = 41 };
/// Stores the bits used by OMPDeclareReductionDecl.
/// If modified NumOMPDeclareReductionDeclBits and the accessor
@@ -1656,10 +1671,14 @@ class DeclContext {
/// Indicates if the function uses Floating Point Constrained Intrinsics
uint64_t UsesFPIntrin : 1;
// Indicates this function is a constrained friend, where the constraint
// refers to an enclosing template for hte purposes of [temp.friend]p9.
uint64_t FriendConstraintRefersToEnclosingTemplate : 1;
};
/// Number of non-inherited bits in FunctionDeclBitfields.
enum { NumFunctionDeclBits = 28 };
enum { NumFunctionDeclBits = 29 };
/// Stores the bits used by CXXConstructorDecl. If modified
/// NumCXXConstructorDeclBits and the accessor
@@ -1671,12 +1690,12 @@ class DeclContext {
/// For the bits in FunctionDeclBitfields.
uint64_t : NumFunctionDeclBits;
/// 23 bits to fit in the remaining available space.
/// 22 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 : 20;
uint64_t NumCtorInitializers : 19;
uint64_t IsInheritingConstructor : 1;
/// Whether this constructor has a trail-allocated explicit specifier.
@@ -1894,6 +1913,10 @@ class DeclContext {
public:
~DeclContext();
// For use when debugging; hasValidDeclKind() will always return true for
// a correctly constructed object within its lifetime.
bool hasValidDeclKind() const;
Decl::Kind getDeclKind() const {
return static_cast<Decl::Kind>(DeclContextBits.DeclKind);
}
@@ -2009,7 +2032,7 @@ class DeclContext {
/// Here, E is a transparent context, so its enumerator (Val1) will
/// appear (semantically) that it is in the same context of E.
/// Examples of transparent contexts include: enumerations (except for
/// C++0x scoped enums), and C++ linkage specifications.
/// C++0x scoped enums), C++ linkage specifications and export declaration.
bool isTransparentContext() const;
/// Determines whether this context or some of its ancestors is a
@@ -2515,6 +2538,8 @@ class DeclContext {
static bool classof(const Decl *D);
static bool classof(const DeclContext *D) { return true; }
void dumpAsDecl() const;
void dumpAsDecl(const ASTContext *Ctx) const;
void dumpDeclContext() const;
void dumpLookups() const;
void dumpLookups(llvm::raw_ostream &OS, bool DumpDecls = false,
@@ -260,6 +260,7 @@ class CXXRecordDecl : public RecordDecl {
friend class ASTWriter;
friend class DeclContext;
friend class LambdaExpr;
friend class ODRDiagsEmitter;
friend void FunctionDecl::setPure(bool);
friend void TagDecl::startDefinition();
@@ -356,11 +357,11 @@ class CXXRecordDecl : public RecordDecl {
}
ArrayRef<CXXBaseSpecifier> bases() const {
return llvm::makeArrayRef(getBases(), NumBases);
return llvm::ArrayRef(getBases(), NumBases);
}
ArrayRef<CXXBaseSpecifier> vbases() const {
return llvm::makeArrayRef(getVBases(), NumVBases);
return llvm::ArrayRef(getVBases(), NumVBases);
}
private:
@@ -409,9 +410,11 @@ class CXXRecordDecl : public RecordDecl {
/// or within a data member initializer.
LazyDeclPtr ContextDecl;
/// The list of captures, both explicit and implicit, for this
/// lambda.
Capture *Captures = nullptr;
/// The lists of captures, both explicit and implicit, for this
/// lambda. One list is provided for each merged copy of the lambda.
/// The first list corresponds to the canonical definition.
/// The destructor is registered by AddCaptureList when necessary.
llvm::TinyPtrVector<Capture*> Captures;
/// The type of the call method.
TypeSourceInfo *MethodTyInfo;
@@ -429,6 +432,9 @@ class CXXRecordDecl : public RecordDecl {
Aggregate = false;
PlainOldData = false;
}
// Add a list of captures.
void AddCaptureList(ASTContext &Ctx, Capture *CaptureList);
};
struct DefinitionData *dataPtr() const {
@@ -1057,7 +1063,13 @@ class CXXRecordDecl : public RecordDecl {
///
/// \note No entries will be added for init-captures, as they do not capture
/// variables.
void getCaptureFields(llvm::DenseMap<const VarDecl *, FieldDecl *> &Captures,
///
/// \note If multiple versions of the lambda are merged together, they may
/// have different variable declarations corresponding to the same capture.
/// In that case, all of those variable declarations will be added to the
/// Captures list, so it may have more than one variable listed per field.
void
getCaptureFields(llvm::DenseMap<const ValueDecl *, FieldDecl *> &Captures,
FieldDecl *&ThisCapture) const;
using capture_const_iterator = const LambdaCapture *;
@@ -1068,7 +1080,9 @@ class CXXRecordDecl : public RecordDecl {
}
capture_const_iterator captures_begin() const {
return isLambda() ? getLambdaData().Captures : nullptr;
if (!isLambda()) return nullptr;
LambdaDefinitionData &LambdaData = getLambdaData();
return LambdaData.Captures.empty() ? nullptr : LambdaData.Captures.front();
}
capture_const_iterator captures_end() const {
@@ -1170,7 +1184,7 @@ class CXXRecordDecl : public RecordDecl {
/// Determine whether this class has a pure virtual function.
///
/// The class is is abstract per (C++ [class.abstract]p2) if it declares
/// The class is abstract per (C++ [class.abstract]p2) if it declares
/// a pure virtual function or inherits a pure virtual function that is
/// not overridden.
bool isAbstract() const { return data().Abstract; }
@@ -1916,7 +1930,7 @@ class CXXDeductionGuideDecl : public FunctionDecl {
ExplicitSpecifier getExplicitSpecifier() { return ExplicitSpec; }
const ExplicitSpecifier getExplicitSpecifier() const { return ExplicitSpec; }
/// Return true if the declartion is already resolved to be explicit.
/// Return true if the declaration is already resolved to be explicit.
bool isExplicit() const { return ExplicitSpec.isExplicit(); }
/// Get the template for which this guide performs deduction.
@@ -2512,7 +2526,7 @@ class CXXConstructorDecl final
return getCanonicalDecl()->getExplicitSpecifierInternal();
}
/// Return true if the declartion is already resolved to be explicit.
/// Return true if the declaration is already resolved to be explicit.
bool isExplicit() const { return getExplicitSpecifier().isExplicit(); }
/// Iterates through the member/base initializer list.
@@ -2796,7 +2810,7 @@ class CXXConversionDecl : public CXXMethodDecl {
return getCanonicalDecl()->ExplicitSpec;
}
/// Return true if the declartion is already resolved to be explicit.
/// Return true if the declaration is already resolved to be explicit.
bool isExplicit() const { return getExplicitSpecifier().isExplicit(); }
void setExplicitSpecifier(ExplicitSpecifier ES) { ExplicitSpec = ES; }
@@ -3612,17 +3626,15 @@ class ConstructorUsingShadowDecl final : public UsingShadowDecl {
class UsingEnumDecl : public BaseUsingDecl, public Mergeable<UsingEnumDecl> {
/// The source location of the 'using' keyword itself.
SourceLocation UsingLocation;
/// Location of the 'enum' keyword.
/// The source location of the 'enum' keyword.
SourceLocation EnumLocation;
/// The enum
EnumDecl *Enum;
/// 'qual::SomeEnum' as an EnumType, possibly with Elaborated/Typedef sugar.
TypeSourceInfo *EnumType;
UsingEnumDecl(DeclContext *DC, DeclarationName DN, SourceLocation UL,
SourceLocation EL, SourceLocation NL, EnumDecl *ED)
: BaseUsingDecl(UsingEnum, DC, NL, DN), UsingLocation(UL),
EnumLocation(EL), Enum(ED) {}
SourceLocation EL, SourceLocation NL, TypeSourceInfo *EnumType)
: BaseUsingDecl(UsingEnum, DC, NL, DN), UsingLocation(UL), EnumLocation(EL),
EnumType(EnumType){}
void anchor() override;
@@ -3637,13 +3649,29 @@ class UsingEnumDecl : public BaseUsingDecl, public Mergeable<UsingEnumDecl> {
/// The source location of the 'enum' keyword.
SourceLocation getEnumLoc() const { return EnumLocation; }
void setEnumLoc(SourceLocation L) { EnumLocation = L; }
NestedNameSpecifier *getQualifier() const {
return getQualifierLoc().getNestedNameSpecifier();
}
NestedNameSpecifierLoc getQualifierLoc() const {
if (auto ETL = EnumType->getTypeLoc().getAs<ElaboratedTypeLoc>())
return ETL.getQualifierLoc();
return NestedNameSpecifierLoc();
}
// Returns the "qualifier::Name" part as a TypeLoc.
TypeLoc getEnumTypeLoc() const {
return EnumType->getTypeLoc();
}
TypeSourceInfo *getEnumType() const {
return EnumType;
}
void setEnumType(TypeSourceInfo *TSI) { EnumType = TSI; }
public:
EnumDecl *getEnumDecl() const { return Enum; }
EnumDecl *getEnumDecl() const { return cast<EnumDecl>(EnumType->getType()->getAsTagDecl()); }
static UsingEnumDecl *Create(ASTContext &C, DeclContext *DC,
SourceLocation UsingL, SourceLocation EnumL,
SourceLocation NameL, EnumDecl *ED);
SourceLocation NameL, TypeSourceInfo *EnumType);
static UsingEnumDecl *CreateDeserialized(ASTContext &C, unsigned ID);
@@ -3711,7 +3739,7 @@ class UsingPackDecl final
/// Get the set of using declarations that this pack expanded into. Note that
/// some of these may still be unresolved.
ArrayRef<NamedDecl *> expansions() const {
return llvm::makeArrayRef(getTrailingObjects<NamedDecl *>(), NumExpansions);
return llvm::ArrayRef(getTrailingObjects<NamedDecl *>(), NumExpansions);
}
static UsingPackDecl *Create(ASTContext &C, DeclContext *DC,
@@ -4081,10 +4109,10 @@ class DecompositionDecl final
unsigned NumBindings);
ArrayRef<BindingDecl *> bindings() const {
return llvm::makeArrayRef(getTrailingObjects<BindingDecl *>(), NumBindings);
return llvm::ArrayRef(getTrailingObjects<BindingDecl *>(), NumBindings);
}
void printName(raw_ostream &os) const override;
void printName(raw_ostream &OS, const PrintingPolicy &Policy) const override;
static bool classof(const Decl *D) { return classofKind(D->getKind()); }
static bool classofKind(Kind K) { return K == Decomposition; }
@@ -4197,7 +4225,8 @@ class MSGuidDecl : public ValueDecl,
public:
/// Print this UUID in a human-readable format.
void printName(llvm::raw_ostream &OS) const override;
void printName(llvm::raw_ostream &OS,
const PrintingPolicy &Policy) const override;
/// Get the decomposed parts of this declaration.
Parts getParts() const { return PartVal; }
@@ -4250,7 +4279,8 @@ class UnnamedGlobalConstantDecl : public ValueDecl,
public:
/// Print this in a human-readable format.
void printName(llvm::raw_ostream &OS) const override;
void printName(llvm::raw_ostream &OS,
const PrintingPolicy &Policy) const override;
const APValue &getValue() const { return Value; }
@@ -23,7 +23,6 @@
#include "clang/Basic/LLVM.h"
#include "clang/Basic/SourceLocation.h"
#include "llvm/ADT/ArrayRef.h"
#include "llvm/ADT/None.h"
#include "llvm/ADT/PointerUnion.h"
#include "llvm/Support/Casting.h"
#include "llvm/Support/Compiler.h"
@@ -108,11 +107,10 @@ class FriendDecl final
friend class ASTNodeImporter;
friend TrailingObjects;
static FriendDecl *Create(ASTContext &C, DeclContext *DC,
SourceLocation L, FriendUnion Friend_,
static FriendDecl *
Create(ASTContext &C, DeclContext *DC, SourceLocation L, FriendUnion Friend_,
SourceLocation FriendL,
ArrayRef<TemplateParameterList*> FriendTypeTPLists
= None);
ArrayRef<TemplateParameterList *> FriendTypeTPLists = std::nullopt);
static FriendDecl *CreateDeserialized(ASTContext &C, unsigned ID,
unsigned FriendTypeNumTPLists);
@@ -25,9 +25,8 @@
#include "clang/Basic/SourceLocation.h"
#include "clang/Basic/Specifiers.h"
#include "llvm/ADT/ArrayRef.h"
#include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/DenseSet.h"
#include "llvm/ADT/None.h"
#include "llvm/ADT/MapVector.h"
#include "llvm/ADT/PointerIntPair.h"
#include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/StringRef.h"
@@ -374,8 +373,7 @@ class ObjCMethodDecl : public NamedDecl, public DeclContext {
// ArrayRef access to formal parameters. This should eventually
// replace the iterator interface above.
ArrayRef<ParmVarDecl*> parameters() const {
return llvm::makeArrayRef(const_cast<ParmVarDecl**>(getParams()),
NumParams);
return llvm::ArrayRef(const_cast<ParmVarDecl **>(getParams()), NumParams);
}
ParmVarDecl *getParamDecl(unsigned Idx) {
@@ -389,9 +387,8 @@ class ObjCMethodDecl : public NamedDecl, public DeclContext {
/// Sets the method's parameters and selector source locations.
/// If the method is implicit (not coming from source) \p SelLocs is
/// ignored.
void setMethodParams(ASTContext &C,
ArrayRef<ParmVarDecl*> Params,
ArrayRef<SourceLocation> SelLocs = llvm::None);
void setMethodParams(ASTContext &C, ArrayRef<ParmVarDecl *> Params,
ArrayRef<SourceLocation> SelLocs = std::nullopt);
// Iterator access to parameter types.
struct GetTypeFn {
@@ -1079,7 +1076,7 @@ class ObjCContainerDecl : public NamedDecl, public DeclContext {
ObjCPropertyQueryKind QueryKind) const;
using PropertyMap =
llvm::DenseMap<std::pair<IdentifierInfo *, unsigned/*isClassProperty*/>,
llvm::MapVector<std::pair<IdentifierInfo *, unsigned /*isClassProperty*/>,
ObjCPropertyDecl *>;
using ProtocolPropertySet = llvm::SmallDenseSet<const ObjCProtocolDecl *, 8>;
using PropertyDeclOrder = llvm::SmallVector<ObjCPropertyDecl *, 8>;
@@ -1087,8 +1084,7 @@ class ObjCContainerDecl : public NamedDecl, public DeclContext {
/// This routine collects list of properties to be implemented in the class.
/// This includes, class's and its conforming protocols' properties.
/// Note, the superclass's properties are not included in the list.
virtual void collectPropertiesToImplement(PropertyMap &PM,
PropertyDeclOrder &PO) const {}
virtual void collectPropertiesToImplement(PropertyMap &PM) const {}
SourceLocation getAtStartLoc() const { return ObjCContainerDeclBits.AtStart; }
@@ -1150,6 +1146,7 @@ class ObjCContainerDecl : public NamedDecl, public DeclContext {
class ObjCInterfaceDecl : public ObjCContainerDecl
, public Redeclarable<ObjCInterfaceDecl> {
friend class ASTContext;
friend class ODRDiagsEmitter;
/// TypeForDecl - This indicates the Type object that represents this
/// TypeDecl. It is a cache maintained by ASTContext::getObjCInterfaceType
@@ -1207,6 +1204,12 @@ class ObjCInterfaceDecl : public ObjCContainerDecl
/// One of the \c InheritedDesignatedInitializersState enumeratos.
mutable unsigned InheritedDesignatedInitializers : 2;
/// Tracks whether a ODR hash has been computed for this interface.
unsigned HasODRHash : 1;
/// A hash of parts of the class to help in ODR checking.
unsigned ODRHash = 0;
/// The location of the last location in this declaration, before
/// the properties/methods. For example, this will be the '>', '}', or
/// identifier,
@@ -1215,7 +1218,7 @@ class ObjCInterfaceDecl : public ObjCContainerDecl
DefinitionData()
: ExternallyCompleted(false), IvarListMissingImplementation(true),
HasDesignatedInitializers(false),
InheritedDesignatedInitializers(IDI_Unknown) {}
InheritedDesignatedInitializers(IDI_Unknown), HasODRHash(false) {}
};
/// The type parameters associated with this class, if any.
@@ -1539,6 +1542,13 @@ class ObjCInterfaceDecl : public ObjCContainerDecl
/// a forward declaration (\@class) to a definition (\@interface).
void startDefinition();
/// Starts the definition without sharing it with other redeclarations.
/// Such definition shouldn't be used for anything but only to compare if
/// a duplicate is compatible with previous definition or if it is
/// a distinct duplicate.
void startDuplicateDefinitionForComparison();
void mergeDuplicateDefinitionWithCommon(const ObjCInterfaceDecl *Definition);
/// Retrieve the superclass type.
const ObjCObjectType *getSuperClassType() const {
if (TypeSourceInfo *TInfo = getSuperClassTInfo())
@@ -1780,8 +1790,7 @@ class ObjCInterfaceDecl : public ObjCContainerDecl
*FindPropertyVisibleInPrimaryClass(IdentifierInfo *PropertyId,
ObjCPropertyQueryKind QueryKind) const;
void collectPropertiesToImplement(PropertyMap &PM,
PropertyDeclOrder &PO) const override;
void collectPropertiesToImplement(PropertyMap &PM) const override;
/// isSuperClassOf - Return true if this class is the specified class or is a
/// super class of the specified interface class.
@@ -1897,10 +1906,17 @@ class ObjCInterfaceDecl : public ObjCContainerDecl
const Type *getTypeForDecl() const { return TypeForDecl; }
void setTypeForDecl(const Type *TD) const { TypeForDecl = TD; }
/// Get precomputed ODRHash or add a new one.
unsigned getODRHash();
static bool classof(const Decl *D) { return classofKind(D->getKind()); }
static bool classofKind(Kind K) { return K == ObjCInterface; }
private:
/// True if a valid hash is stored in ODRHash.
bool hasODRHash() const;
void setHasODRHash(bool HasHash);
const ObjCInterfaceDecl *findInterfaceWithDesignatedInitializers() const;
bool inheritsDesignatedInitializers() const;
};
@@ -2057,6 +2073,12 @@ class ObjCProtocolDecl : public ObjCContainerDecl,
/// Referenced protocols
ObjCProtocolList ReferencedProtocols;
/// Tracks whether a ODR hash has been computed for this protocol.
unsigned HasODRHash : 1;
/// A hash of parts of the class to help in ODR checking.
unsigned ODRHash = 0;
};
/// Contains a pointer to the data associated with this class,
@@ -2093,10 +2115,15 @@ class ObjCProtocolDecl : public ObjCContainerDecl,
return getMostRecentDecl();
}
/// True if a valid hash is stored in ODRHash.
bool hasODRHash() const;
void setHasODRHash(bool HasHash);
public:
friend class ASTDeclReader;
friend class ASTDeclWriter;
friend class ASTReader;
friend class ODRDiagsEmitter;
static ObjCProtocolDecl *Create(ASTContext &C, DeclContext *DC,
IdentifierInfo *Id,
@@ -2221,6 +2248,13 @@ class ObjCProtocolDecl : public ObjCContainerDecl,
/// Starts the definition of this Objective-C protocol.
void startDefinition();
/// Starts the definition without sharing it with other redeclarations.
/// Such definition shouldn't be used for anything but only to compare if
/// a duplicate is compatible with previous definition or if it is
/// a distinct duplicate.
void startDuplicateDefinitionForComparison();
void mergeDuplicateDefinitionWithCommon(const ObjCProtocolDecl *Definition);
/// Produce a name to be used for protocol's metadata. It comes either via
/// objc_runtime_name attribute or protocol name.
StringRef getObjCRuntimeNameAsString() const;
@@ -2246,13 +2280,15 @@ class ObjCProtocolDecl : public ObjCContainerDecl,
ObjCProtocolDecl *getCanonicalDecl() override { return getFirstDecl(); }
const ObjCProtocolDecl *getCanonicalDecl() const { return getFirstDecl(); }
void collectPropertiesToImplement(PropertyMap &PM,
PropertyDeclOrder &PO) const override;
void collectPropertiesToImplement(PropertyMap &PM) const override;
void collectInheritedProtocolProperties(const ObjCPropertyDecl *Property,
ProtocolPropertySet &PS,
PropertyDeclOrder &PO) const;
/// Get precomputed ODRHash or add a new one.
unsigned getODRHash();
static bool classof(const Decl *D) { return classofKind(D->getKind()); }
static bool classofKind(Kind K) { return K == ObjCProtocol; }
};
@@ -34,7 +34,7 @@ template <typename U> class OMPDeclarativeDirective : public U {
/// Get the clauses storage.
MutableArrayRef<OMPClause *> getClauses() {
if (!Data)
return llvm::None;
return std::nullopt;
return Data->getClauses();
}
@@ -90,7 +90,7 @@ template <typename U> class OMPDeclarativeDirective : public U {
ArrayRef<OMPClause *> clauses() const {
if (!Data)
return llvm::None;
return std::nullopt;
return Data->getClauses();
}
};
@@ -118,12 +118,12 @@ class OMPThreadPrivateDecl final : public OMPDeclarativeDirective<Decl> {
ArrayRef<const Expr *> getVars() const {
auto **Storage = reinterpret_cast<Expr **>(Data->getChildren().data());
return llvm::makeArrayRef(Storage, Data->getNumChildren());
return llvm::ArrayRef(Storage, Data->getNumChildren());
}
MutableArrayRef<Expr *> getVars() {
auto **Storage = reinterpret_cast<Expr **>(Data->getChildren().data());
return llvm::makeMutableArrayRef(Storage, Data->getNumChildren());
return llvm::MutableArrayRef(Storage, Data->getNumChildren());
}
void setVars(ArrayRef<Expr *> VL);
@@ -481,12 +481,12 @@ class OMPAllocateDecl final : public OMPDeclarativeDirective<Decl> {
ArrayRef<const Expr *> getVars() const {
auto **Storage = reinterpret_cast<Expr **>(Data->getChildren().data());
return llvm::makeArrayRef(Storage, Data->getNumChildren());
return llvm::ArrayRef(Storage, Data->getNumChildren());
}
MutableArrayRef<Expr *> getVars() {
auto **Storage = reinterpret_cast<Expr **>(Data->getChildren().data());
return llvm::makeMutableArrayRef(Storage, Data->getNumChildren());
return llvm::MutableArrayRef(Storage, Data->getNumChildren());
}
void setVars(ArrayRef<Expr *> VL);
@@ -39,6 +39,7 @@
#include <cstddef>
#include <cstdint>
#include <iterator>
#include <optional>
#include <utility>
namespace clang {
@@ -129,11 +130,9 @@ class TemplateParameterList final
unsigned size() const { return NumParams; }
ArrayRef<NamedDecl*> asArray() {
return llvm::makeArrayRef(begin(), end());
}
ArrayRef<NamedDecl *> asArray() { return llvm::ArrayRef(begin(), end()); }
ArrayRef<const NamedDecl*> asArray() const {
return llvm::makeArrayRef(begin(), size());
return llvm::ArrayRef(begin(), size());
}
NamedDecl* getParam(unsigned Idx) {
@@ -274,8 +273,7 @@ class TemplateArgumentList final
///
/// This operation assumes that the input argument list outlives it.
/// This takes the list as a pointer to avoid looking like a copy
/// constructor, since this really really isn't safe to use that
/// way.
/// constructor, since this really isn't safe to use that way.
explicit TemplateArgumentList(const TemplateArgumentList *Other)
: Arguments(Other->data()), NumArguments(Other->size()) {}
@@ -290,7 +288,7 @@ class TemplateArgumentList final
/// Produce this as an array ref.
ArrayRef<TemplateArgument> asArray() const {
return llvm::makeArrayRef(data(), size());
return llvm::ArrayRef(data(), size());
}
/// Retrieve the number of template arguments in this
@@ -440,6 +438,9 @@ class TemplateDecl : public NamedDecl {
/// Get the underlying, templated declaration.
NamedDecl *getTemplatedDecl() const { return TemplatedDecl; }
// Should a specialization behave like an alias for another type.
bool isTypeAlias() const;
// Implement isa/cast/dyncast/etc.
static bool classof(const Decl *D) { return classofKind(D->getKind()); }
@@ -456,18 +457,17 @@ class TemplateDecl : public NamedDecl {
NamedDecl *TemplatedDecl;
TemplateParameterList *TemplateParams;
public:
void setTemplateParameters(TemplateParameterList *TParams) {
TemplateParams = TParams;
}
public:
/// Initialize the underlying templated declaration and
/// template parameters.
void init(NamedDecl *templatedDecl, TemplateParameterList* templateParams) {
assert(!TemplatedDecl && "TemplatedDecl already set!");
assert(!TemplateParams && "TemplateParams already set!");
TemplatedDecl = templatedDecl;
TemplateParams = templateParams;
/// Initialize the underlying templated declaration.
void init(NamedDecl *NewTemplatedDecl) {
if (TemplatedDecl)
assert(TemplatedDecl == NewTemplatedDecl && "Inconsistent TemplatedDecl");
else
TemplatedDecl = NewTemplatedDecl;
}
};
@@ -740,7 +740,7 @@ class DependentFunctionTemplateSpecializationInfo final
unsigned getNumTemplateArgs() const { return NumArgs; }
llvm::ArrayRef<TemplateArgumentLoc> arguments() const {
return llvm::makeArrayRef(getTemplateArgs(), getNumTemplateArgs());
return llvm::ArrayRef(getTemplateArgs(), getNumTemplateArgs());
}
/// Returns the nth template argument.
@@ -845,6 +845,15 @@ class RedeclarableTemplateDecl : public TemplateDecl,
/// The first value in the array is the number of specializations/partial
/// specializations that follow.
uint32_t *LazySpecializations = nullptr;
/// The set of "injected" template arguments used within this
/// template.
///
/// This pointer refers to the template arguments (there are as
/// many template arguments as template parameaters) for the
/// template, and is allocated lazily, since most templates do not
/// require the use of this information.
TemplateArgument *InjectedArgs = nullptr;
};
/// Pointer to the common data shared by all declarations of this
@@ -952,6 +961,14 @@ class RedeclarableTemplateDecl : public TemplateDecl,
getCommonPtr()->InstantiatedFromMember.setPointer(TD);
}
/// Retrieve the "injected" template arguments that correspond to the
/// template parameters of this template.
///
/// Although the C++ standard has no notion of the "injected" template
/// arguments for a template, the notion is convenient when
/// we need to perform substitutions inside the definition of a template.
ArrayRef<TemplateArgument> getInjectedTemplateArgs();
using redecl_range = redeclarable_base::redecl_range;
using redecl_iterator = redeclarable_base::redecl_iterator;
@@ -996,15 +1013,6 @@ class FunctionTemplateDecl : public RedeclarableTemplateDecl {
/// template, including explicit specializations and instantiations.
llvm::FoldingSetVector<FunctionTemplateSpecializationInfo> Specializations;
/// The set of "injected" template arguments used within this
/// function template.
///
/// This pointer refers to the template arguments (there are as
/// many template arguments as template parameaters) for the function
/// template, and is allocated lazily, since most function templates do not
/// require the use of this information.
TemplateArgument *InjectedArgs = nullptr;
Common() = default;
};
@@ -1104,15 +1112,6 @@ class FunctionTemplateDecl : public RedeclarableTemplateDecl {
return makeSpecIterator(getSpecializations(), true);
}
/// Retrieve the "injected" template arguments that correspond to the
/// template parameters of this function template.
///
/// Although the C++ standard has no notion of the "injected" template
/// arguments for a function template, the notion is convenient when
/// we need to perform substitutions inside the definition of a function
/// template.
ArrayRef<TemplateArgument> getInjectedTemplateArgs();
/// Return whether this function template is an abbreviated function template,
/// e.g. `void foo(auto x)` or `template<typename T> void foo(auto x)`
bool isAbbreviated() const {
@@ -1223,7 +1222,7 @@ class TemplateTypeParmDecl final : public TypeDecl,
/// type constraint.
bool TypeConstraintInitialized : 1;
/// Whether this non-type template parameter is an "expanded"
/// Whether this type template parameter is an "expanded"
/// parameter pack, meaning that its type is a pack expansion and we
/// already know the set of types that expansion expands to.
bool ExpandedParameterPack : 1;
@@ -1238,21 +1237,19 @@ class TemplateTypeParmDecl final : public TypeDecl,
TemplateTypeParmDecl(DeclContext *DC, SourceLocation KeyLoc,
SourceLocation IdLoc, IdentifierInfo *Id, bool Typename,
bool HasTypeConstraint, Optional<unsigned> NumExpanded)
bool HasTypeConstraint,
std::optional<unsigned> NumExpanded)
: TypeDecl(TemplateTypeParm, DC, IdLoc, Id, KeyLoc), Typename(Typename),
HasTypeConstraint(HasTypeConstraint), TypeConstraintInitialized(false),
ExpandedParameterPack(NumExpanded),
NumExpanded(NumExpanded.value_or(0)) {}
public:
static TemplateTypeParmDecl *Create(const ASTContext &C, DeclContext *DC,
SourceLocation KeyLoc,
SourceLocation NameLoc,
unsigned D, unsigned P,
IdentifierInfo *Id, bool Typename,
bool ParameterPack,
bool HasTypeConstraint = false,
Optional<unsigned> NumExpanded = None);
static TemplateTypeParmDecl *
Create(const ASTContext &C, DeclContext *DC, SourceLocation KeyLoc,
SourceLocation NameLoc, unsigned D, unsigned P, IdentifierInfo *Id,
bool Typename, bool ParameterPack, bool HasTypeConstraint = false,
std::optional<unsigned> NumExpanded = std::nullopt);
static TemplateTypeParmDecl *CreateDeserialized(const ASTContext &C,
unsigned ID);
static TemplateTypeParmDecl *CreateDeserialized(const ASTContext &C,
@@ -1388,7 +1385,7 @@ class TemplateTypeParmDecl final : public TypeDecl,
/// \brief Get the associated-constraints of this template parameter.
/// This will either be the immediately-introduced constraint or empty.
///
/// Use this instead of getConstraintExpression for concepts APIs that
/// Use this instead of getTypeConstraint for concepts APIs that
/// accept an ArrayRef of constraint expressions.
void getAssociatedConstraints(llvm::SmallVectorImpl<const Expr *> &AC) const {
if (HasTypeConstraint)
@@ -2929,6 +2926,14 @@ class VarTemplateSpecializationDecl : public VarDecl,
return ExplicitInfo ? ExplicitInfo->TemplateKeywordLoc : SourceLocation();
}
SourceRange getSourceRange() const override LLVM_READONLY {
if (isExplicitSpecialization()) {
if (const ASTTemplateArgumentListInfo *Info = getTemplateArgsInfo())
return SourceRange(getOuterLocStart(), Info->getRAngleLoc());
}
return VarDecl::getSourceRange();
}
void Profile(llvm::FoldingSetNodeID &ID) const {
Profile(ID, TemplateArgs->asArray(), getASTContext());
}
@@ -3086,6 +3091,14 @@ class VarTemplatePartialSpecializationDecl
return First->InstantiatedFromMember.setInt(true);
}
SourceRange getSourceRange() const override LLVM_READONLY {
if (isExplicitSpecialization()) {
if (const ASTTemplateArgumentListInfo *Info = getTemplateArgsAsWritten())
return SourceRange(getOuterLocStart(), Info->getRAngleLoc());
}
return VarDecl::getSourceRange();
}
void Profile(llvm::FoldingSetNodeID &ID) const {
Profile(ID, getTemplateArgs().asArray(), getTemplateParameters(),
getASTContext());
@@ -3258,7 +3271,7 @@ class VarTemplateDecl : public RedeclarableTemplateDecl {
static bool classofKind(Kind K) { return K == VarTemplate; }
};
/// Declaration of a C++2a concept.
/// Declaration of a C++20 concept.
class ConceptDecl : public TemplateDecl, public Mergeable<ConceptDecl> {
protected:
Expr *ConstraintExpr;
@@ -3303,6 +3316,40 @@ class ConceptDecl : public TemplateDecl, public Mergeable<ConceptDecl> {
friend class ASTDeclWriter;
};
// An implementation detail of ConceptSpecialicationExpr that holds the template
// arguments, so we can later use this to reconstitute the template arguments
// during constraint checking.
class ImplicitConceptSpecializationDecl final
: public Decl,
private llvm::TrailingObjects<ImplicitConceptSpecializationDecl,
TemplateArgument> {
unsigned NumTemplateArgs;
ImplicitConceptSpecializationDecl(DeclContext *DC, SourceLocation SL,
ArrayRef<TemplateArgument> ConvertedArgs);
ImplicitConceptSpecializationDecl(EmptyShell Empty, unsigned NumTemplateArgs);
public:
static ImplicitConceptSpecializationDecl *
Create(const ASTContext &C, DeclContext *DC, SourceLocation SL,
ArrayRef<TemplateArgument> ConvertedArgs);
static ImplicitConceptSpecializationDecl *
CreateDeserialized(const ASTContext &C, unsigned ID,
unsigned NumTemplateArgs);
ArrayRef<TemplateArgument> getTemplateArguments() const {
return ArrayRef<TemplateArgument>(getTrailingObjects<TemplateArgument>(),
NumTemplateArgs);
}
void setTemplateArguments(ArrayRef<TemplateArgument> Converted);
static bool classofKind(Kind K) { return K == ImplicitConceptSpecialization; }
static bool classof(const Decl *D) { return classofKind(D->getKind()); }
friend TrailingObjects;
friend class ASTDeclReader;
};
/// A template parameter object.
///
/// Template parameter objects represent values of class type used as template
@@ -3340,7 +3387,8 @@ class TemplateParamObjectDecl : public ValueDecl,
public:
/// Print this template parameter object in a human-readable format.
void printName(llvm::raw_ostream &OS) const override;
void printName(llvm::raw_ostream &OS,
const PrintingPolicy &Policy) const override;
/// Print this object as an equivalent expression.
void printAsExpr(llvm::raw_ostream &OS) const;
@@ -3402,7 +3450,7 @@ inline TemplateDecl *getAsTypeTemplateDecl(Decl *D) {
///
/// In \c A<int,int>::B, \c NTs and \c TTs have expanded pack size 2, and \c Us
/// is not a pack expansion, so returns an empty Optional.
inline Optional<unsigned> getExpandedPackSize(const NamedDecl *Param) {
inline std::optional<unsigned> getExpandedPackSize(const NamedDecl *Param) {
if (const auto *TTP = dyn_cast<TemplateTypeParmDecl>(Param)) {
if (TTP->isExpandedParameterPack())
return TTP->getNumExpansionParameters();
@@ -3418,9 +3466,13 @@ inline Optional<unsigned> getExpandedPackSize(const NamedDecl *Param) {
return TTP->getNumExpansionTemplateParameters();
}
return None;
return std::nullopt;
}
/// Internal helper used by Subst* nodes to retrieve the parameter list
/// for their AssociatedDecl.
TemplateParameterList *getReplacedTemplateParameterList(Decl *D);
} // namespace clang
#endif // LLVM_CLANG_AST_DECLTEMPLATE_H
@@ -941,7 +941,7 @@ class AssumedTemplateStorage : public UncommonTemplateNameStorage {
friend class ASTContext;
AssumedTemplateStorage(DeclarationName Name)
: UncommonTemplateNameStorage(Assumed, 0), Name(Name) {}
: UncommonTemplateNameStorage(Assumed, 0, 0), Name(Name) {}
DeclarationName Name;
public:
@@ -36,6 +36,7 @@
#include "llvm/Support/AtomicOrdering.h"
#include "llvm/Support/Compiler.h"
#include "llvm/Support/TrailingObjects.h"
#include <optional>
namespace clang {
class APValue;
@@ -523,14 +524,24 @@ class Expr : public ValueStmt {
/// semantically correspond to a bool.
bool isKnownToHaveBooleanValue(bool Semantic = true) const;
/// Check whether this array fits the idiom of a flexible array member,
/// depending on the value of -fstrict-flex-array.
/// When IgnoreTemplateOrMacroSubstitution is set, it doesn't consider sizes
/// resulting from the substitution of a macro or a template as special sizes.
bool isFlexibleArrayMemberLike(
ASTContext &Context,
LangOptions::StrictFlexArraysLevelKind StrictFlexArraysLevel,
bool IgnoreTemplateOrMacroSubstitution = false) const;
/// isIntegerConstantExpr - Return the value if this expression is a valid
/// integer constant expression. If not a valid i-c-e, return None and fill
/// in Loc (if specified) with the location of the invalid expression.
/// integer constant expression. If not a valid i-c-e, return std::nullopt
/// and fill in Loc (if specified) with the location of the invalid
/// expression.
///
/// Note: This does not perform the implicit conversions required by C++11
/// [expr.const]p5.
Optional<llvm::APSInt> getIntegerConstantExpr(const ASTContext &Ctx,
SourceLocation *Loc = nullptr,
std::optional<llvm::APSInt>
getIntegerConstantExpr(const ASTContext &Ctx, SourceLocation *Loc = nullptr,
bool isEvaluated = true) const;
bool isIntegerConstantExpr(const ASTContext &Ctx,
SourceLocation *Loc = nullptr) const;
@@ -1972,7 +1983,7 @@ class PredefinedExpr final
LFunction, // Same as Function, but as wide string.
FuncDName,
FuncSig,
LFuncSig, // Same as FuncSig, but as as wide string
LFuncSig, // Same as FuncSig, but as wide string
PrettyFunction,
/// The same as PrettyFunction, except that the
/// 'virtual' keyword is omitted for virtual member functions.
@@ -3009,7 +3020,7 @@ class CallExpr : public Expr {
/// Compute and set dependence bits.
void computeDependence() {
setDependence(clang::computeDependence(
this, llvm::makeArrayRef(
this, llvm::ArrayRef(
reinterpret_cast<Expr **>(getTrailingStmts() + PREARGS_START),
getNumPreArgs())));
}
@@ -3056,14 +3067,10 @@ class CallExpr : public Expr {
/// interface. This provides efficient reverse iteration of the
/// subexpressions. This is currently used for CFG construction.
ArrayRef<Stmt *> getRawSubExprs() {
return llvm::makeArrayRef(getTrailingStmts(),
return llvm::ArrayRef(getTrailingStmts(),
PREARGS_START + getNumPreArgs() + getNumArgs());
}
/// getNumCommas - Return the number of commas that must have been present in
/// this function call.
unsigned getNumCommas() const { return getNumArgs() ? getNumArgs() - 1 : 0; }
/// Get FPOptionsOverride from trailing storage.
FPOptionsOverride getStoredFPFeatures() const {
assert(hasStoredFPFeatures());
@@ -4008,7 +4015,7 @@ class BinaryOperator : public Expr {
}
// This is used in ASTImporter
FPOptionsOverride getFPFeatures(const LangOptions &LO) const {
FPOptionsOverride getFPFeatures() const {
if (BinaryOperatorBits.HasFPFeatures)
return getStoredFPFeatures();
return FPOptionsOverride();
@@ -4827,12 +4834,10 @@ class InitListExpr : public Expr {
return reinterpret_cast<Expr * const *>(InitExprs.data());
}
ArrayRef<Expr *> inits() {
return llvm::makeArrayRef(getInits(), getNumInits());
}
ArrayRef<Expr *> inits() { return llvm::ArrayRef(getInits(), getNumInits()); }
ArrayRef<Expr *> inits() const {
return llvm::makeArrayRef(getInits(), getNumInits());
return llvm::ArrayRef(getInits(), getNumInits());
}
const Expr *getInit(unsigned Init) const {
@@ -5574,9 +5579,7 @@ class ParenListExpr final
return reinterpret_cast<Expr **>(getTrailingObjects<Stmt *>());
}
ArrayRef<Expr *> exprs() {
return llvm::makeArrayRef(getExprs(), getNumExprs());
}
ArrayRef<Expr *> exprs() { return llvm::ArrayRef(getExprs(), getNumExprs()); }
SourceLocation getLParenLoc() const { return LParenLoc; }
SourceLocation getRParenLoc() const { return RParenLoc; }
@@ -6427,7 +6430,7 @@ class RecoveryExpr final : public Expr,
ArrayRef<Expr *> subExpressions() {
auto *B = getTrailingObjects<Expr *>();
return llvm::makeArrayRef(B, B + NumExprs);
return llvm::ArrayRef(B, B + NumExprs);
}
ArrayRef<const Expr *> subExpressions() const {
@@ -40,8 +40,6 @@
#include "clang/Basic/Specifiers.h"
#include "clang/Basic/TypeTraits.h"
#include "llvm/ADT/ArrayRef.h"
#include "llvm/ADT/None.h"
#include "llvm/ADT/Optional.h"
#include "llvm/ADT/PointerUnion.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/ADT/iterator_range.h"
@@ -52,6 +50,7 @@
#include <cstddef>
#include <cstdint>
#include <memory>
#include <optional>
namespace clang {
@@ -730,6 +729,11 @@ class CXXBoolLiteralExpr : public Expr {
explicit CXXBoolLiteralExpr(EmptyShell Empty)
: Expr(CXXBoolLiteralExprClass, Empty) {}
static CXXBoolLiteralExpr *Create(const ASTContext &C, bool Val, QualType Ty,
SourceLocation Loc) {
return new (C) CXXBoolLiteralExpr(Val, Ty, Loc);
}
bool getValue() const { return CXXBoolLiteralExprBits.Value; }
void setValue(bool V) { CXXBoolLiteralExprBits.Value = V; }
@@ -756,6 +760,8 @@ class CXXBoolLiteralExpr : public Expr {
/// The null pointer literal (C++11 [lex.nullptr])
///
/// Introduced in C++11, the only literal of type \c nullptr_t is \c nullptr.
/// This also implements the null pointer literal in C2x (C2x 6.4.1) which is
/// intended to have the same semantics as the feature in C++.
class CXXNullPtrLiteralExpr : public Expr {
public:
CXXNullPtrLiteralExpr(QualType Ty, SourceLocation Loc)
@@ -1238,8 +1244,12 @@ class CXXThrowExpr : public Expr {
/// This wraps up a function call argument that was created from the
/// corresponding parameter's default argument, when the call did not
/// explicitly supply arguments for all of the parameters.
class CXXDefaultArgExpr final : public Expr {
class CXXDefaultArgExpr final
: public Expr,
private llvm::TrailingObjects<CXXDefaultArgExpr, Expr *> {
friend class ASTStmtReader;
friend class ASTReader;
friend TrailingObjects;
/// The parameter whose default is being used.
ParmVarDecl *Param;
@@ -1248,7 +1258,7 @@ class CXXDefaultArgExpr final : public Expr {
DeclContext *UsedContext;
CXXDefaultArgExpr(StmtClass SC, SourceLocation Loc, ParmVarDecl *Param,
DeclContext *UsedContext)
Expr *RewrittenExpr, DeclContext *UsedContext)
: Expr(SC,
Param->hasUnparsedDefaultArg()
? Param->getType().getNonReferenceType()
@@ -1257,28 +1267,54 @@ class CXXDefaultArgExpr final : public Expr {
Param->getDefaultArg()->getObjectKind()),
Param(Param), UsedContext(UsedContext) {
CXXDefaultArgExprBits.Loc = Loc;
CXXDefaultArgExprBits.HasRewrittenInit = RewrittenExpr != nullptr;
if (RewrittenExpr)
*getTrailingObjects<Expr *>() = RewrittenExpr;
setDependence(computeDependence(this));
}
CXXDefaultArgExpr(EmptyShell Empty, bool HasRewrittenInit)
: Expr(CXXDefaultArgExprClass, Empty) {
CXXDefaultArgExprBits.HasRewrittenInit = HasRewrittenInit;
}
public:
CXXDefaultArgExpr(EmptyShell Empty) : Expr(CXXDefaultArgExprClass, Empty) {}
static CXXDefaultArgExpr *CreateEmpty(const ASTContext &C,
bool HasRewrittenInit);
// \p Param is the parameter whose default argument is used by this
// expression.
static CXXDefaultArgExpr *Create(const ASTContext &C, SourceLocation Loc,
ParmVarDecl *Param,
DeclContext *UsedContext) {
return new (C)
CXXDefaultArgExpr(CXXDefaultArgExprClass, Loc, Param, UsedContext);
}
ParmVarDecl *Param, Expr *RewrittenExpr,
DeclContext *UsedContext);
// Retrieve the parameter that the argument was created from.
const ParmVarDecl *getParam() const { return Param; }
ParmVarDecl *getParam() { return Param; }
// Retrieve the actual argument to the function call.
const Expr *getExpr() const { return getParam()->getDefaultArg(); }
Expr *getExpr() { return getParam()->getDefaultArg(); }
bool hasRewrittenInit() const {
return CXXDefaultArgExprBits.HasRewrittenInit;
}
// Retrieve the argument to the function call.
Expr *getExpr();
const Expr *getExpr() const {
return const_cast<CXXDefaultArgExpr *>(this)->getExpr();
}
Expr *getRewrittenExpr() {
return hasRewrittenInit() ? *getTrailingObjects<Expr *>() : nullptr;
}
const Expr *getRewrittenExpr() const {
return const_cast<CXXDefaultArgExpr *>(this)->getRewrittenExpr();
}
// Retrieve the rewritten init expression (for an init expression containing
// immediate calls) with the top level FullExpr and ConstantExpr stripped off.
Expr *getAdjustedRewrittenExpr();
const Expr *getAdjustedRewrittenExpr() const {
return const_cast<CXXDefaultArgExpr *>(this)->getAdjustedRewrittenExpr();
}
const DeclContext *getUsedContext() const { return UsedContext; }
DeclContext *getUsedContext() { return UsedContext; }
@@ -1315,10 +1351,13 @@ class CXXDefaultArgExpr final : public Expr {
/// is implicitly used in a mem-initializer-list in a constructor
/// (C++11 [class.base.init]p8) or in aggregate initialization
/// (C++1y [dcl.init.aggr]p7).
class CXXDefaultInitExpr : public Expr {
friend class ASTReader;
friend class ASTStmtReader;
class CXXDefaultInitExpr final
: public Expr,
private llvm::TrailingObjects<CXXDefaultInitExpr, Expr *> {
friend class ASTStmtReader;
friend class ASTReader;
friend TrailingObjects;
/// The field whose default is being used.
FieldDecl *Field;
@@ -1326,16 +1365,25 @@ class CXXDefaultInitExpr : public Expr {
DeclContext *UsedContext;
CXXDefaultInitExpr(const ASTContext &Ctx, SourceLocation Loc,
FieldDecl *Field, QualType Ty, DeclContext *UsedContext);
FieldDecl *Field, QualType Ty, DeclContext *UsedContext,
Expr *RewrittenInitExpr);
CXXDefaultInitExpr(EmptyShell Empty) : Expr(CXXDefaultInitExprClass, Empty) {}
CXXDefaultInitExpr(EmptyShell Empty, bool HasRewrittenInit)
: Expr(CXXDefaultInitExprClass, Empty) {
CXXDefaultInitExprBits.HasRewrittenInit = HasRewrittenInit;
}
public:
static CXXDefaultInitExpr *CreateEmpty(const ASTContext &C,
bool HasRewrittenInit);
/// \p Field is the non-static data member whose default initializer is used
/// by this expression.
static CXXDefaultInitExpr *Create(const ASTContext &Ctx, SourceLocation Loc,
FieldDecl *Field, DeclContext *UsedContext) {
return new (Ctx) CXXDefaultInitExpr(Ctx, Loc, Field, Field->getType(), UsedContext);
FieldDecl *Field, DeclContext *UsedContext,
Expr *RewrittenInitExpr);
bool hasRewrittenInit() const {
return CXXDefaultInitExprBits.HasRewrittenInit;
}
/// Get the field whose initializer will be used.
@@ -1343,13 +1391,23 @@ class CXXDefaultInitExpr : public Expr {
const FieldDecl *getField() const { return Field; }
/// Get the initialization expression that will be used.
Expr *getExpr();
const Expr *getExpr() const {
assert(Field->getInClassInitializer() && "initializer hasn't been parsed");
return Field->getInClassInitializer();
return const_cast<CXXDefaultInitExpr *>(this)->getExpr();
}
Expr *getExpr() {
assert(Field->getInClassInitializer() && "initializer hasn't been parsed");
return Field->getInClassInitializer();
/// Retrieve the initializing expression with evaluated immediate calls, if
/// any.
const Expr *getRewrittenExpr() const {
assert(hasRewrittenInit() && "expected a rewritten init expression");
return *getTrailingObjects<Expr *>();
}
/// Retrieve the initializing expression with evaluated immediate calls, if
/// any.
Expr *getRewrittenExpr() {
assert(hasRewrittenInit() && "expected a rewritten init expression");
return *getTrailingObjects<Expr *>();
}
const DeclContext *getUsedContext() const { return UsedContext; }
@@ -2204,7 +2262,7 @@ class CXXNewExpr final
CXXNewExpr(bool IsGlobalNew, FunctionDecl *OperatorNew,
FunctionDecl *OperatorDelete, bool ShouldPassAlignment,
bool UsualArrayDeleteWantsSize, ArrayRef<Expr *> PlacementArgs,
SourceRange TypeIdParens, Optional<Expr *> ArraySize,
SourceRange TypeIdParens, std::optional<Expr *> ArraySize,
InitializationStyle InitializationStyle, Expr *Initializer,
QualType Ty, TypeSourceInfo *AllocatedTypeInfo, SourceRange Range,
SourceRange DirectInitRange);
@@ -2219,7 +2277,7 @@ class CXXNewExpr final
Create(const ASTContext &Ctx, bool IsGlobalNew, FunctionDecl *OperatorNew,
FunctionDecl *OperatorDelete, bool ShouldPassAlignment,
bool UsualArrayDeleteWantsSize, ArrayRef<Expr *> PlacementArgs,
SourceRange TypeIdParens, Optional<Expr *> ArraySize,
SourceRange TypeIdParens, std::optional<Expr *> ArraySize,
InitializationStyle InitializationStyle, Expr *Initializer,
QualType Ty, TypeSourceInfo *AllocatedTypeInfo, SourceRange Range,
SourceRange DirectInitRange);
@@ -2261,32 +2319,32 @@ class CXXNewExpr final
bool isArray() const { return CXXNewExprBits.IsArray; }
/// This might return None even if isArray() returns true,
/// This might return std::nullopt even if isArray() returns true,
/// since there might not be an array size expression.
/// If the result is not-None, it will never wrap a nullptr.
Optional<Expr *> getArraySize() {
std::optional<Expr *> getArraySize() {
if (!isArray())
return None;
return std::nullopt;
if (auto *Result =
cast_or_null<Expr>(getTrailingObjects<Stmt *>()[arraySizeOffset()]))
return Result;
return None;
return std::nullopt;
}
/// This might return None even if isArray() returns true,
/// This might return std::nullopt even if isArray() returns true,
/// since there might not be an array size expression.
/// If the result is not-None, it will never wrap a nullptr.
Optional<const Expr *> getArraySize() const {
std::optional<const Expr *> getArraySize() const {
if (!isArray())
return None;
return std::nullopt;
if (auto *Result =
cast_or_null<Expr>(getTrailingObjects<Stmt *>()[arraySizeOffset()]))
return Result;
return None;
return std::nullopt;
}
unsigned getNumPlacementArgs() const {
@@ -2738,8 +2796,7 @@ class TypeTraitExpr final
/// Retrieve the argument types.
ArrayRef<TypeSourceInfo *> getArgs() const {
return llvm::makeArrayRef(getTrailingObjects<TypeSourceInfo *>(),
getNumArgs());
return llvm::ArrayRef(getTrailingObjects<TypeSourceInfo *>(), getNumArgs());
}
SourceLocation getBeginLoc() const LLVM_READONLY { return Loc; }
@@ -3385,8 +3442,7 @@ class ExprWithCleanups final
ArrayRef<CleanupObject> objects);
ArrayRef<CleanupObject> getObjects() const {
return llvm::makeArrayRef(getTrailingObjects<CleanupObject>(),
getNumObjects());
return llvm::ArrayRef(getTrailingObjects<CleanupObject>(), getNumObjects());
}
unsigned getNumObjects() const { return ExprWithCleanupsBits.NumObjects; }
@@ -4082,7 +4138,7 @@ class PackExpansionExpr : public Expr {
public:
PackExpansionExpr(QualType T, Expr *Pattern, SourceLocation EllipsisLoc,
Optional<unsigned> NumExpansions)
std::optional<unsigned> NumExpansions)
: Expr(PackExpansionExprClass, T, Pattern->getValueKind(),
Pattern->getObjectKind()),
EllipsisLoc(EllipsisLoc),
@@ -4105,11 +4161,11 @@ class PackExpansionExpr : public Expr {
/// Determine the number of expansions that will be produced when
/// this pack expansion is instantiated, if already known.
Optional<unsigned> getNumExpansions() const {
std::optional<unsigned> getNumExpansions() const {
if (NumExpansions)
return NumExpansions - 1;
return None;
return std::nullopt;
}
SourceLocation getBeginLoc() const LLVM_READONLY {
@@ -4176,7 +4232,7 @@ class SizeOfPackExpr final
/// the given parameter pack.
SizeOfPackExpr(QualType SizeType, SourceLocation OperatorLoc, NamedDecl *Pack,
SourceLocation PackLoc, SourceLocation RParenLoc,
Optional<unsigned> Length,
std::optional<unsigned> Length,
ArrayRef<TemplateArgument> PartialArgs)
: Expr(SizeOfPackExprClass, SizeType, VK_PRValue, OK_Ordinary),
OperatorLoc(OperatorLoc), PackLoc(PackLoc), RParenLoc(RParenLoc),
@@ -4194,11 +4250,11 @@ class SizeOfPackExpr final
: Expr(SizeOfPackExprClass, Empty), Length(NumPartialArgs) {}
public:
static SizeOfPackExpr *Create(ASTContext &Context, SourceLocation OperatorLoc,
NamedDecl *Pack, SourceLocation PackLoc,
SourceLocation RParenLoc,
Optional<unsigned> Length = None,
ArrayRef<TemplateArgument> PartialArgs = None);
static SizeOfPackExpr *
Create(ASTContext &Context, SourceLocation OperatorLoc, NamedDecl *Pack,
SourceLocation PackLoc, SourceLocation RParenLoc,
std::optional<unsigned> Length = std::nullopt,
ArrayRef<TemplateArgument> PartialArgs = std::nullopt);
static SizeOfPackExpr *CreateDeserialized(ASTContext &Context,
unsigned NumPartialArgs);
@@ -4237,7 +4293,7 @@ class SizeOfPackExpr final
ArrayRef<TemplateArgument> getPartialArguments() const {
assert(isPartiallySubstituted());
const auto *Args = getTrailingObjects<TemplateArgument>();
return llvm::makeArrayRef(Args, Args + Length);
return llvm::ArrayRef(Args, Args + Length);
}
SourceLocation getBeginLoc() const LLVM_READONLY { return OperatorLoc; }
@@ -4263,24 +4319,30 @@ class SubstNonTypeTemplateParmExpr : public Expr {
friend class ASTReader;
friend class ASTStmtReader;
/// The replaced parameter and a flag indicating if it was a reference
/// parameter. For class NTTPs, we can't determine that based on the value
/// category alone.
llvm::PointerIntPair<NonTypeTemplateParmDecl*, 1, bool> ParamAndRef;
/// The replacement expression.
Stmt *Replacement;
/// The associated declaration and a flag indicating if it was a reference
/// parameter. For class NTTPs, we can't determine that based on the value
/// category alone.
llvm::PointerIntPair<Decl *, 1, bool> AssociatedDeclAndRef;
unsigned Index : 15;
unsigned PackIndex : 16;
explicit SubstNonTypeTemplateParmExpr(EmptyShell Empty)
: Expr(SubstNonTypeTemplateParmExprClass, Empty) {}
public:
SubstNonTypeTemplateParmExpr(QualType Ty, ExprValueKind ValueKind,
SourceLocation Loc,
NonTypeTemplateParmDecl *Param, bool RefParam,
Expr *Replacement)
SourceLocation Loc, Expr *Replacement,
Decl *AssociatedDecl, unsigned Index,
std::optional<unsigned> PackIndex, bool RefParam)
: Expr(SubstNonTypeTemplateParmExprClass, Ty, ValueKind, OK_Ordinary),
ParamAndRef(Param, RefParam), Replacement(Replacement) {
Replacement(Replacement),
AssociatedDeclAndRef(AssociatedDecl, RefParam), Index(Index),
PackIndex(PackIndex ? *PackIndex + 1 : 0) {
assert(AssociatedDecl != nullptr);
SubstNonTypeTemplateParmExprBits.NameLoc = Loc;
setDependence(computeDependence(this));
}
@@ -4293,11 +4355,23 @@ class SubstNonTypeTemplateParmExpr : public Expr {
Expr *getReplacement() const { return cast<Expr>(Replacement); }
NonTypeTemplateParmDecl *getParameter() const {
return ParamAndRef.getPointer();
/// A template-like entity which owns the whole pattern being substituted.
/// This will own a set of template parameters.
Decl *getAssociatedDecl() const { return AssociatedDeclAndRef.getPointer(); }
/// Returns the index of the replaced parameter in the associated declaration.
/// This should match the result of `getParameter()->getIndex()`.
unsigned getIndex() const { return Index; }
std::optional<unsigned> getPackIndex() const {
if (PackIndex == 0)
return std::nullopt;
return PackIndex - 1;
}
bool isReferenceParameter() const { return ParamAndRef.getInt(); }
NonTypeTemplateParmDecl *getParameter() const;
bool isReferenceParameter() const { return AssociatedDeclAndRef.getInt(); }
/// Determine the substituted type of the template parameter.
QualType getParameterType(const ASTContext &Ctx) const;
@@ -4331,14 +4405,16 @@ class SubstNonTypeTemplateParmPackExpr : public Expr {
friend class ASTStmtReader;
/// The non-type template parameter pack itself.
NonTypeTemplateParmDecl *Param;
Decl *AssociatedDecl;
/// A pointer to the set of template arguments that this
/// parameter pack is instantiated with.
const TemplateArgument *Arguments;
/// The number of template arguments in \c Arguments.
unsigned NumArguments;
unsigned NumArguments : 16;
unsigned Index : 16;
/// The location of the non-type template parameter pack reference.
SourceLocation NameLoc;
@@ -4347,14 +4423,21 @@ class SubstNonTypeTemplateParmPackExpr : public Expr {
: Expr(SubstNonTypeTemplateParmPackExprClass, Empty) {}
public:
SubstNonTypeTemplateParmPackExpr(QualType T,
ExprValueKind ValueKind,
NonTypeTemplateParmDecl *Param,
SubstNonTypeTemplateParmPackExpr(QualType T, ExprValueKind ValueKind,
SourceLocation NameLoc,
const TemplateArgument &ArgPack);
const TemplateArgument &ArgPack,
Decl *AssociatedDecl, unsigned Index);
/// A template-like entity which owns the whole pattern being substituted.
/// This will own a set of template parameters.
Decl *getAssociatedDecl() const { return AssociatedDecl; }
/// Returns the index of the replaced parameter in the associated declaration.
/// This should match the result of `getParameterPack()->getIndex()`.
unsigned getIndex() const { return Index; }
/// Retrieve the non-type template parameter pack being substituted.
NonTypeTemplateParmDecl *getParameterPack() const { return Param; }
NonTypeTemplateParmDecl *getParameterPack() const;
/// Retrieve the location of the parameter pack name.
SourceLocation getParameterPackLocation() const { return NameLoc; }
@@ -4607,7 +4690,7 @@ class CXXFoldExpr : public Expr {
CXXFoldExpr(QualType T, UnresolvedLookupExpr *Callee,
SourceLocation LParenLoc, Expr *LHS, BinaryOperatorKind Opcode,
SourceLocation EllipsisLoc, Expr *RHS, SourceLocation RParenLoc,
Optional<unsigned> NumExpansions)
std::optional<unsigned> NumExpansions)
: Expr(CXXFoldExprClass, T, VK_PRValue, OK_Ordinary),
LParenLoc(LParenLoc), EllipsisLoc(EllipsisLoc), RParenLoc(RParenLoc),
NumExpansions(NumExpansions ? *NumExpansions + 1 : 0), Opcode(Opcode) {
@@ -4644,10 +4727,10 @@ class CXXFoldExpr : public Expr {
SourceLocation getEllipsisLoc() const { return EllipsisLoc; }
BinaryOperatorKind getOperator() const { return Opcode; }
Optional<unsigned> getNumExpansions() const {
std::optional<unsigned> getNumExpansions() const {
if (NumExpansions)
return NumExpansions - 1;
return None;
return std::nullopt;
}
SourceLocation getBeginLoc() const LLVM_READONLY {
@@ -4680,6 +4763,140 @@ class CXXFoldExpr : public Expr {
}
};
/// Represents a list-initialization with parenthesis.
///
/// As per P0960R3, this is a C++20 feature that allows aggregate to
/// be initialized with a parenthesized list of values:
/// ```
/// struct A {
/// int a;
/// double b;
/// };
///
/// void foo() {
/// A a1(0); // Well-formed in C++20
/// A a2(1.5, 1.0); // Well-formed in C++20
/// }
/// ```
/// It has some sort of similiarity to braced
/// list-initialization, with some differences such as
/// it allows narrowing conversion whilst braced
/// list-initialization doesn't.
/// ```
/// struct A {
/// char a;
/// };
/// void foo() {
/// A a(1.5); // Well-formed in C++20
/// A b{1.5}; // Ill-formed !
/// }
/// ```
class CXXParenListInitExpr final
: public Expr,
private llvm::TrailingObjects<CXXParenListInitExpr, Expr *> {
friend class TrailingObjects;
friend class ASTStmtReader;
friend class ASTStmtWriter;
unsigned NumExprs;
unsigned NumUserSpecifiedExprs;
SourceLocation InitLoc, LParenLoc, RParenLoc;
llvm::PointerUnion<Expr *, FieldDecl *> ArrayFillerOrUnionFieldInit;
CXXParenListInitExpr(ArrayRef<Expr *> Args, QualType T,
unsigned NumUserSpecifiedExprs, SourceLocation InitLoc,
SourceLocation LParenLoc, SourceLocation RParenLoc)
: Expr(CXXParenListInitExprClass, T, getValueKindForType(T), OK_Ordinary),
NumExprs(Args.size()), NumUserSpecifiedExprs(NumUserSpecifiedExprs),
InitLoc(InitLoc), LParenLoc(LParenLoc), RParenLoc(RParenLoc) {
std::copy(Args.begin(), Args.end(), getTrailingObjects<Expr *>());
assert(NumExprs >= NumUserSpecifiedExprs &&
"number of user specified inits is greater than the number of "
"passed inits");
setDependence(computeDependence(this));
}
size_t numTrailingObjects(OverloadToken<Expr *>) const { return NumExprs; }
public:
static CXXParenListInitExpr *
Create(ASTContext &C, ArrayRef<Expr *> Args, QualType T,
unsigned NumUserSpecifiedExprs, SourceLocation InitLoc,
SourceLocation LParenLoc, SourceLocation RParenLoc);
static CXXParenListInitExpr *CreateEmpty(ASTContext &C, unsigned numExprs,
EmptyShell Empty);
explicit CXXParenListInitExpr(EmptyShell Empty, unsigned NumExprs)
: Expr(CXXParenListInitExprClass, Empty), NumExprs(NumExprs),
NumUserSpecifiedExprs(0) {}
void updateDependence() { setDependence(computeDependence(this)); }
ArrayRef<Expr *> getInitExprs() {
return ArrayRef(getTrailingObjects<Expr *>(), NumExprs);
}
const ArrayRef<Expr *> getInitExprs() const {
return ArrayRef(getTrailingObjects<Expr *>(), NumExprs);
}
ArrayRef<Expr *> getUserSpecifiedInitExprs() {
return ArrayRef(getTrailingObjects<Expr *>(), NumUserSpecifiedExprs);
}
const ArrayRef<Expr *> getUserSpecifiedInitExprs() const {
return ArrayRef(getTrailingObjects<Expr *>(), NumUserSpecifiedExprs);
}
SourceLocation getBeginLoc() const LLVM_READONLY { return LParenLoc; }
SourceLocation getEndLoc() const LLVM_READONLY { return RParenLoc; }
SourceLocation getInitLoc() const LLVM_READONLY { return InitLoc; }
SourceRange getSourceRange() const LLVM_READONLY {
return SourceRange(getBeginLoc(), getEndLoc());
}
void setArrayFiller(Expr *E) { ArrayFillerOrUnionFieldInit = E; }
Expr *getArrayFiller() {
return ArrayFillerOrUnionFieldInit.dyn_cast<Expr *>();
}
const Expr *getArrayFiller() const {
return ArrayFillerOrUnionFieldInit.dyn_cast<Expr *>();
}
void setInitializedFieldInUnion(FieldDecl *FD) {
ArrayFillerOrUnionFieldInit = FD;
}
FieldDecl *getInitializedFieldInUnion() {
return ArrayFillerOrUnionFieldInit.dyn_cast<FieldDecl *>();
}
const FieldDecl *getInitializedFieldInUnion() const {
return ArrayFillerOrUnionFieldInit.dyn_cast<FieldDecl *>();
}
child_range children() {
Stmt **Begin = reinterpret_cast<Stmt **>(getTrailingObjects<Expr *>());
return child_range(Begin, Begin + NumExprs);
}
const_child_range children() const {
Stmt *const *Begin =
reinterpret_cast<Stmt *const *>(getTrailingObjects<Expr *>());
return const_child_range(Begin, Begin + NumExprs);
}
static bool classof(const Stmt *T) {
return T->getStmtClass() == CXXParenListInitExprClass;
}
};
/// Represents an expression that might suspend coroutine execution;
/// either a co_await or co_yield expression.
///
@@ -24,6 +24,7 @@
#include "clang/AST/TemplateBase.h"
#include "clang/AST/Type.h"
#include "clang/Basic/SourceLocation.h"
#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/TrailingObjects.h"
#include <utility>
#include <string>
@@ -37,18 +38,17 @@ class ASTStmtWriter;
///
/// According to C++2a [expr.prim.id]p3 an id-expression that denotes the
/// specialization of a concept results in a prvalue of type bool.
class ConceptSpecializationExpr final : public Expr, public ConceptReference,
private llvm::TrailingObjects<ConceptSpecializationExpr,
TemplateArgument> {
class ConceptSpecializationExpr final : public Expr, public ConceptReference {
friend class ASTReader;
friend class ASTStmtReader;
friend TrailingObjects;
public:
using SubstitutionDiagnostic = std::pair<SourceLocation, std::string>;
protected:
/// \brief The number of template arguments in the tail-allocated list of
/// converted template arguments.
unsigned NumTemplateArgs;
/// \brief The Implicit Concept Specialization Decl, which holds the template
/// arguments for this specialization.
ImplicitConceptSpecializationDecl *SpecDecl;
/// \brief Information about the satisfaction of the named concept with the
/// given arguments. If this expression is value dependent, this is to be
@@ -60,51 +60,46 @@ class ConceptSpecializationExpr final : public Expr, public ConceptReference,
DeclarationNameInfo ConceptNameInfo,
NamedDecl *FoundDecl, ConceptDecl *NamedConcept,
const ASTTemplateArgumentListInfo *ArgsAsWritten,
ArrayRef<TemplateArgument> ConvertedArgs,
ImplicitConceptSpecializationDecl *SpecDecl,
const ConstraintSatisfaction *Satisfaction);
ConceptSpecializationExpr(const ASTContext &C, ConceptDecl *NamedConcept,
ArrayRef<TemplateArgument> ConvertedArgs,
ImplicitConceptSpecializationDecl *SpecDecl,
const ConstraintSatisfaction *Satisfaction,
bool Dependent,
bool ContainsUnexpandedParameterPack);
ConceptSpecializationExpr(EmptyShell Empty, unsigned NumTemplateArgs);
ConceptSpecializationExpr(EmptyShell Empty);
public:
static ConceptSpecializationExpr *
Create(const ASTContext &C, NestedNameSpecifierLoc NNS,
SourceLocation TemplateKWLoc, DeclarationNameInfo ConceptNameInfo,
NamedDecl *FoundDecl, ConceptDecl *NamedConcept,
const ASTTemplateArgumentListInfo *ArgsAsWritten,
ArrayRef<TemplateArgument> ConvertedArgs,
ImplicitConceptSpecializationDecl *SpecDecl,
const ConstraintSatisfaction *Satisfaction);
static ConceptSpecializationExpr *
Create(const ASTContext &C, ConceptDecl *NamedConcept,
ArrayRef<TemplateArgument> ConvertedArgs,
const ConstraintSatisfaction *Satisfaction,
bool Dependent,
ImplicitConceptSpecializationDecl *SpecDecl,
const ConstraintSatisfaction *Satisfaction, bool Dependent,
bool ContainsUnexpandedParameterPack);
static ConceptSpecializationExpr *
Create(ASTContext &C, EmptyShell Empty, unsigned NumTemplateArgs);
ArrayRef<TemplateArgument> getTemplateArguments() const {
return ArrayRef<TemplateArgument>(getTrailingObjects<TemplateArgument>(),
NumTemplateArgs);
return SpecDecl->getTemplateArguments();
}
/// \brief Set new template arguments for this concept specialization.
void setTemplateArguments(ArrayRef<TemplateArgument> Converted);
const ImplicitConceptSpecializationDecl *getSpecializationDecl() const {
assert(SpecDecl && "Template Argument Decl not initialized");
return SpecDecl;
}
/// \brief Whether or not the concept with the given arguments was satisfied
/// when the expression was created.
/// The expression must not be dependent.
bool isSatisfied() const {
assert(!isValueDependent()
&& "isSatisfied called on a dependent ConceptSpecializationExpr");
assert(!isValueDependent() &&
"isSatisfied called on a dependent ConceptSpecializationExpr");
return Satisfaction->IsSatisfied;
}
@@ -112,8 +107,8 @@ class ConceptSpecializationExpr final : public Expr, public ConceptReference,
/// satisfaction of the named concept.
/// The expression must not be dependent.
const ASTConstraintSatisfaction &getSatisfaction() const {
assert(!isValueDependent()
&& "getSatisfaction called on dependent ConceptSpecializationExpr");
assert(!isValueDependent() &&
"getSatisfaction called on dependent ConceptSpecializationExpr");
return *Satisfaction;
}
@@ -407,57 +402,61 @@ class ExprRequirement : public Requirement {
/// \brief A requires-expression requirement which is satisfied when a general
/// constraint expression is satisfied ('nested' requirements).
class NestedRequirement : public Requirement {
llvm::PointerUnion<Expr *, SubstitutionDiagnostic *> Value;
Expr *Constraint = nullptr;
const ASTConstraintSatisfaction *Satisfaction = nullptr;
bool HasInvalidConstraint = false;
StringRef InvalidConstraintEntity;
public:
friend ASTStmtReader;
friend ASTStmtWriter;
NestedRequirement(SubstitutionDiagnostic *SubstDiag) :
Requirement(RK_Nested, /*IsDependent=*/false,
/*ContainsUnexpandedParameterPack*/false,
/*IsSatisfied=*/false), Value(SubstDiag) {}
NestedRequirement(Expr *Constraint) :
Requirement(RK_Nested, /*IsDependent=*/true,
NestedRequirement(Expr *Constraint)
: Requirement(RK_Nested, /*IsDependent=*/true,
Constraint->containsUnexpandedParameterPack()),
Value(Constraint) {
Constraint(Constraint) {
assert(Constraint->isInstantiationDependent() &&
"Nested requirement with non-dependent constraint must be "
"constructed with a ConstraintSatisfaction object");
}
NestedRequirement(ASTContext &C, Expr *Constraint,
const ConstraintSatisfaction &Satisfaction) :
Requirement(RK_Nested, Constraint->isInstantiationDependent(),
const ConstraintSatisfaction &Satisfaction)
: Requirement(RK_Nested, Constraint->isInstantiationDependent(),
Constraint->containsUnexpandedParameterPack(),
Satisfaction.IsSatisfied),
Value(Constraint),
Constraint(Constraint),
Satisfaction(ASTConstraintSatisfaction::Create(C, Satisfaction)) {}
bool isSubstitutionFailure() const {
return Value.is<SubstitutionDiagnostic *>();
}
NestedRequirement(StringRef InvalidConstraintEntity,
const ASTConstraintSatisfaction *Satisfaction)
: Requirement(RK_Nested,
/*IsDependent=*/false,
/*ContainsUnexpandedParameterPack*/ false,
Satisfaction->IsSatisfied),
Satisfaction(Satisfaction), HasInvalidConstraint(true),
InvalidConstraintEntity(InvalidConstraintEntity) {}
SubstitutionDiagnostic *getSubstitutionDiagnostic() const {
assert(isSubstitutionFailure() &&
"getSubstitutionDiagnostic() may not be called when there was no "
"substitution failure.");
return Value.get<SubstitutionDiagnostic *>();
NestedRequirement(ASTContext &C, StringRef InvalidConstraintEntity,
const ConstraintSatisfaction &Satisfaction)
: NestedRequirement(InvalidConstraintEntity,
ASTConstraintSatisfaction::Create(C, Satisfaction)) {}
bool hasInvalidConstraint() const { return HasInvalidConstraint; }
StringRef getInvalidConstraintEntity() {
assert(hasInvalidConstraint());
return InvalidConstraintEntity;
}
Expr *getConstraintExpr() const {
assert(!isSubstitutionFailure() && "getConstraintExpr() may not be called "
"on nested requirements with "
"substitution failures.");
return Value.get<Expr *>();
assert(!hasInvalidConstraint() &&
"getConstraintExpr() may not be called "
"on nested requirements with invalid constraint.");
return Constraint;
}
const ASTConstraintSatisfaction &getConstraintSatisfaction() const {
assert(!isSubstitutionFailure() && "getConstraintSatisfaction() may not be "
"called on nested requirements with "
"substitution failures.");
return *Satisfaction;
}
@@ -529,6 +528,12 @@ class RequiresExpr final : public Expr,
return RequiresExprBits.IsSatisfied;
}
void setSatisfied(bool IsSatisfied) {
assert(!isValueDependent() &&
"setSatisfied called on a dependent RequiresExpr");
RequiresExprBits.IsSatisfied = IsSatisfied;
}
SourceLocation getRequiresKWLoc() const {
return RequiresExprBits.RequiresKWLoc;
}
@@ -27,8 +27,6 @@
#include "clang/Basic/SourceLocation.h"
#include "clang/Basic/Specifiers.h"
#include "llvm/ADT/ArrayRef.h"
#include "llvm/ADT/None.h"
#include "llvm/ADT/Optional.h"
#include "llvm/ADT/PointerIntPair.h"
#include "llvm/ADT/PointerUnion.h"
#include "llvm/ADT/StringRef.h"
@@ -41,6 +39,7 @@
#include <cassert>
#include <cstddef>
#include <cstdint>
#include <optional>
namespace clang {
@@ -272,7 +271,7 @@ struct ObjCDictionaryElement {
/// The number of elements this pack expansion will expand to, if
/// this is a pack expansion and is known.
Optional<unsigned> NumExpansions;
std::optional<unsigned> NumExpansions;
/// Determines whether this dictionary element is a pack expansion.
bool isPackExpansion() const { return EllipsisLoc.isValid(); }
@@ -362,7 +361,8 @@ class ObjCDictionaryLiteral final
ObjCDictionaryElement getKeyValueElement(unsigned Index) const {
assert((Index < NumElements) && "Arg access out of range!");
const KeyValuePair &KV = getTrailingObjects<KeyValuePair>()[Index];
ObjCDictionaryElement Result = { KV.Key, KV.Value, SourceLocation(), None };
ObjCDictionaryElement Result = {KV.Key, KV.Value, SourceLocation(),
std::nullopt};
if (HasPackExpansions) {
const ExpansionData &Expansion =
getTrailingObjects<ExpansionData>()[Index];
@@ -1415,10 +1415,9 @@ class ObjCMessageExpr final
SourceLocation getSelectorLoc(unsigned Index) const {
assert(Index < getNumSelectorLocs() && "Index out of range!");
if (hasStandardSelLocs())
return getStandardSelectorLoc(Index, getSelector(),
getSelLocsKind() == SelLoc_StandardWithSpace,
llvm::makeArrayRef(const_cast<Expr**>(getArgs()),
getNumArgs()),
return getStandardSelectorLoc(
Index, getSelector(), getSelLocsKind() == SelLoc_StandardWithSpace,
llvm::ArrayRef(const_cast<Expr **>(getArgs()), getNumArgs()),
RBracLoc);
return getStoredSelLocs()[Index];
}
@@ -202,12 +202,12 @@ class OMPArrayShapingExpr final
/// Fetches the dimensions for array shaping expression.
ArrayRef<Expr *> getDimensions() const {
return llvm::makeArrayRef(getTrailingObjects<Expr *>(), NumDims);
return llvm::ArrayRef(getTrailingObjects<Expr *>(), NumDims);
}
/// Fetches source ranges for the brackets os the array shaping expression.
ArrayRef<SourceRange> getBracketsRanges() const {
return llvm::makeArrayRef(getTrailingObjects<SourceRange>(), NumDims);
return llvm::ArrayRef(getTrailingObjects<SourceRange>(), NumDims);
}
/// Fetches base expression of array shaping expression.
@@ -118,7 +118,7 @@ class ExternalASTMerger : public ExternalASTSource {
/// Asks all connected ASTImporters if any of them imported the given
/// declaration. If any ASTImporter did import the given declaration,
/// then this function returns the declaration that D was imported from.
/// Returns nullptr if no ASTImporter did import import D.
/// Returns nullptr if no ASTImporter did import D.
Decl *FindOriginalDecl(Decl *D);
/// Add a set of ASTContexts as possible origins.
@@ -20,7 +20,6 @@
#include "llvm/ADT/ArrayRef.h"
#include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/IntrusiveRefCntPtr.h"
#include "llvm/ADT/Optional.h"
#include "llvm/ADT/PointerUnion.h"
#include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/SmallVector.h"
@@ -30,6 +29,7 @@
#include <cstddef>
#include <cstdint>
#include <iterator>
#include <optional>
#include <utility>
namespace clang {
@@ -160,7 +160,7 @@ class ExternalASTSource : public RefCountedBase<ExternalASTSource> {
virtual Module *getModule(unsigned ID) { return nullptr; }
/// Return a descriptor for the corresponding module, if one exists.
virtual llvm::Optional<ASTSourceDescriptor> getSourceDescriptor(unsigned ID);
virtual std::optional<ASTSourceDescriptor> getSourceDescriptor(unsigned ID);
enum ExtKind { EK_Always, EK_Never, EK_ReplyHazy };
@@ -19,6 +19,7 @@
#define LLVM_CLANG_AST_FORMATSTRING_H
#include "clang/AST/CanonicalType.h"
#include <optional>
namespace clang {
@@ -127,8 +128,12 @@ class ConversionSpecifier {
dArg,
DArg, // Apple extension
iArg,
// C23 conversion specifiers.
bArg,
BArg,
IntArgBeg = dArg,
IntArgEnd = iArg,
IntArgEnd = BArg,
oArg,
OArg, // Apple extension
@@ -237,7 +242,7 @@ class ConversionSpecifier {
bool isPrintfKind() const { return IsPrintf; }
Optional<ConversionSpecifier> getStandardSpecifier() const;
std::optional<ConversionSpecifier> getStandardSpecifier() const;
protected:
bool IsPrintf;
@@ -257,8 +262,14 @@ class ArgType {
/// instance, "%d" and float.
NoMatch = 0,
/// The conversion specifier and the argument type are compatible. For
/// instance, "%d" and _Bool.
/// instance, "%d" and int.
Match = 1,
/// The conversion specifier and the argument type are compatible because of
/// default argument promotions. For instance, "%hhd" and int.
MatchPromotion,
/// The conversion specifier and the argument type are compatible but still
/// seems likely to be an error. For instanace, "%hhd" and short.
NoMatchPromotionTypeConfusion,
/// The conversion specifier and the argument type are disallowed by the C
/// standard, but are in practice harmless. For instance, "%p" and int*.
NoMatchPedantic,
@@ -456,7 +467,7 @@ class FormatSpecifier {
bool hasStandardLengthModifier() const;
Optional<LengthModifier> getCorrectedLengthModifier() const;
std::optional<LengthModifier> getCorrectedLengthModifier() const;
bool hasStandardConversionSpecifier(const LangOptions &LangOpt) const;
@@ -209,6 +209,7 @@ class JSONNodeDumper
void Visit(const APValue &Value, QualType Ty);
void VisitTypedefType(const TypedefType *TT);
void VisitUsingType(const UsingType *TT);
void VisitFunctionType(const FunctionType *T);
void VisitFunctionProtoType(const FunctionProtoType *T);
void VisitRValueReferenceType(const ReferenceType *RT);
@@ -220,6 +221,9 @@ class JSONNodeDumper
void VisitUnaryTransformType(const UnaryTransformType *UTT);
void VisitTagType(const TagType *TT);
void VisitTemplateTypeParmType(const TemplateTypeParmType *TTPT);
void VisitSubstTemplateTypeParmType(const SubstTemplateTypeParmType *STTPT);
void
VisitSubstTemplateTypeParmPackType(const SubstTemplateTypeParmPackType *T);
void VisitAutoType(const AutoType *AT);
void VisitTemplateSpecializationType(const TemplateSpecializationType *TST);
void VisitInjectedClassNameType(const InjectedClassNameType *ICNT);
@@ -245,6 +249,7 @@ class JSONNodeDumper
void VisitEnumConstantDecl(const EnumConstantDecl *ECD);
void VisitRecordDecl(const RecordDecl *RD);
void VisitCXXRecordDecl(const CXXRecordDecl *RD);
void VisitHLSLBufferDecl(const HLSLBufferDecl *D);
void VisitTemplateTypeParmDecl(const TemplateTypeParmDecl *D);
void VisitNonTypeTemplateParmDecl(const NonTypeTemplateParmDecl *D);
void VisitTemplateTemplateParmDecl(const TemplateTemplateParmDecl *D);
@@ -380,7 +385,7 @@ class JSONDumper : public ASTNodeTraverser<JSONDumper, JSONNodeDumper> {
case TSK_ExplicitInstantiationDefinition:
if (!DumpExplicitInst)
break;
LLVM_FALLTHROUGH;
[[fallthrough]];
case TSK_Undeclared:
case TSK_ImplicitInstantiation:
if (DumpRefOnly)
@@ -71,7 +71,7 @@ class LambdaCapture {
/// capture that is a pack expansion, or an invalid source
/// location to indicate that this is not a pack expansion.
LambdaCapture(SourceLocation Loc, bool Implicit, LambdaCaptureKind Kind,
VarDecl *Var = nullptr,
ValueDecl *Var = nullptr,
SourceLocation EllipsisLoc = SourceLocation());
/// Determine the kind of capture.
@@ -86,7 +86,7 @@ class LambdaCapture {
/// Determine whether this capture handles a variable.
bool capturesVariable() const {
return isa_and_nonnull<VarDecl>(DeclAndBits.getPointer());
return isa_and_nonnull<ValueDecl>(DeclAndBits.getPointer());
}
/// Determine whether this captures a variable length array bound
@@ -101,9 +101,9 @@ class LambdaCapture {
///
/// This operation is only valid if this capture is a variable capture
/// (other than a capture of \c this).
VarDecl *getCapturedVar() const {
ValueDecl *getCapturedVar() const {
assert(capturesVariable() && "No variable available for capture");
return static_cast<VarDecl *>(DeclAndBits.getPointer());
return static_cast<ValueDecl *>(DeclAndBits.getPointer());
}
/// Determine whether this was an implicit capture (not
@@ -19,6 +19,7 @@
#include "clang/Basic/ABI.h"
#include "llvm/ADT/DenseMap.h"
#include "llvm/Support/Casting.h"
#include <optional>
namespace llvm {
class raw_ostream;
@@ -61,6 +62,7 @@ class MangleContext {
llvm::DenseMap<const BlockDecl*, unsigned> GlobalBlockIds;
llvm::DenseMap<const BlockDecl*, unsigned> LocalBlockIds;
llvm::DenseMap<const NamedDecl*, uint64_t> AnonStructIds;
llvm::DenseMap<const FunctionDecl*, unsigned> FuncAnonStructSize;
public:
ManglerKind getKind() const { return Kind; }
@@ -87,9 +89,17 @@ class MangleContext {
return Result.first->second;
}
uint64_t getAnonymousStructId(const NamedDecl *D) {
uint64_t getAnonymousStructId(const NamedDecl *D,
const FunctionDecl *FD = nullptr) {
auto FindResult = AnonStructIds.find(D);
if (FindResult != AnonStructIds.end())
return FindResult->second;
// If FunctionDecl is passed in, the anonymous structID will be per-function
// based.
unsigned Id = FD ? FuncAnonStructSize[FD]++ : AnonStructIds.size();
std::pair<llvm::DenseMap<const NamedDecl *, uint64_t>::iterator, bool>
Result = AnonStructIds.insert(std::make_pair(D, AnonStructIds.size()));
Result = AnonStructIds.insert(std::make_pair(D, Id));
return Result.first->second;
}
@@ -157,10 +167,10 @@ class MangleContext {
virtual void mangleDynamicAtExitDestructor(const VarDecl *D,
raw_ostream &) = 0;
virtual void mangleSEHFilterExpression(const NamedDecl *EnclosingDecl,
virtual void mangleSEHFilterExpression(GlobalDecl EnclosingDecl,
raw_ostream &Out) = 0;
virtual void mangleSEHFinallyBlock(const NamedDecl *EnclosingDecl,
virtual void mangleSEHFinallyBlock(GlobalDecl EnclosingDecl,
raw_ostream &Out) = 0;
/// Generates a unique string for an externally visible type for use with TBAA
@@ -175,7 +185,7 @@ class MangleContext {
class ItaniumMangleContext : public MangleContext {
public:
using DiscriminatorOverrideTy =
llvm::Optional<unsigned> (*)(ASTContext &, const NamedDecl *);
std::optional<unsigned> (*)(ASTContext &, const NamedDecl *);
explicit ItaniumMangleContext(ASTContext &C, DiagnosticsEngine &D,
bool IsAux = false)
: MangleContext(C, D, MK_Itanium, IsAux) {}
@@ -11,7 +11,7 @@
#include "clang/Basic/IdentifierTable.h"
#include "llvm/ADT/ArrayRef.h"
#include "llvm/ADT/Optional.h"
#include <optional>
namespace clang {
class ASTContext;
@@ -89,7 +89,7 @@ class NSAPI {
Selector getNSArraySelector(NSArrayMethodKind MK) const;
/// Return NSArrayMethodKind if \p Sel is such a selector.
Optional<NSArrayMethodKind> getNSArrayMethodKind(Selector Sel);
std::optional<NSArrayMethodKind> getNSArrayMethodKind(Selector Sel);
/// Enumerates the NSDictionary/NSMutableDictionary methods used
/// to generate literals and to apply some checks.
@@ -114,7 +114,7 @@ class NSAPI {
Selector getNSDictionarySelector(NSDictionaryMethodKind MK) const;
/// Return NSDictionaryMethodKind if \p Sel is such a selector.
Optional<NSDictionaryMethodKind> getNSDictionaryMethodKind(Selector Sel);
std::optional<NSDictionaryMethodKind> getNSDictionaryMethodKind(Selector Sel);
/// Enumerates the NSMutableSet/NSOrderedSet methods used
/// to apply some checks.
@@ -131,7 +131,7 @@ class NSAPI {
Selector getNSSetSelector(NSSetMethodKind MK) const;
/// Return NSSetMethodKind if \p Sel is such a selector.
Optional<NSSetMethodKind> getNSSetMethodKind(Selector Sel);
std::optional<NSSetMethodKind> getNSSetMethodKind(Selector Sel);
/// Returns selector for "objectForKeyedSubscript:".
Selector getObjectForKeyedSubscriptSelector() const {
@@ -203,12 +203,12 @@ class NSAPI {
}
/// Return NSNumberLiteralMethodKind if \p Sel is such a selector.
Optional<NSNumberLiteralMethodKind>
std::optional<NSNumberLiteralMethodKind>
getNSNumberLiteralMethodKind(Selector Sel) const;
/// Determine the appropriate NSNumber factory method kind for a
/// literal of the given type.
Optional<NSNumberLiteralMethodKind>
std::optional<NSNumberLiteralMethodKind>
getNSNumberFactoryMethodKind(QualType T) const;
/// Returns true if \param T is a typedef of "BOOL" in objective-c.
@@ -0,0 +1,203 @@
//===- ODRDiagsEmitter.h - Emits diagnostic for ODR mismatches --*- C++ -*-===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
#ifndef LLVM_CLANG_AST_ODRDIAGSEMITTER_H
#define LLVM_CLANG_AST_ODRDIAGSEMITTER_H
#include "clang/AST/ASTContext.h"
#include "clang/AST/DeclCXX.h"
#include "clang/AST/DeclObjC.h"
#include "clang/Basic/Diagnostic.h"
#include "clang/Basic/LangOptions.h"
namespace clang {
class ODRDiagsEmitter {
public:
ODRDiagsEmitter(DiagnosticsEngine &Diags, const ASTContext &Context,
const LangOptions &LangOpts)
: Diags(Diags), Context(Context), LangOpts(LangOpts) {}
/// Diagnose ODR mismatch between 2 FunctionDecl.
///
/// Returns true if found a mismatch and diagnosed it.
bool diagnoseMismatch(const FunctionDecl *FirstFunction,
const FunctionDecl *SecondFunction) const;
/// Diagnose ODR mismatch between 2 EnumDecl.
///
/// Returns true if found a mismatch and diagnosed it.
bool diagnoseMismatch(const EnumDecl *FirstEnum,
const EnumDecl *SecondEnum) const;
/// Diagnose ODR mismatch between 2 CXXRecordDecl.
///
/// Returns true if found a mismatch and diagnosed it.
/// To compare 2 declarations with merged and identical definition data
/// you need to provide pre-merge definition data in \p SecondDD.
bool
diagnoseMismatch(const CXXRecordDecl *FirstRecord,
const CXXRecordDecl *SecondRecord,
const struct CXXRecordDecl::DefinitionData *SecondDD) const;
/// Diagnose ODR mismatch between 2 RecordDecl that are not CXXRecordDecl.
///
/// Returns true if found a mismatch and diagnosed it.
bool diagnoseMismatch(const RecordDecl *FirstRecord,
const RecordDecl *SecondRecord) const;
/// Diagnose ODR mismatch between 2 ObjCInterfaceDecl.
///
/// Returns true if found a mismatch and diagnosed it.
bool diagnoseMismatch(
const ObjCInterfaceDecl *FirstID, const ObjCInterfaceDecl *SecondID,
const struct ObjCInterfaceDecl::DefinitionData *SecondDD) const;
/// Diagnose ODR mismatch between ObjCInterfaceDecl with different
/// definitions.
bool diagnoseMismatch(const ObjCInterfaceDecl *FirstID,
const ObjCInterfaceDecl *SecondID) const {
assert(FirstID->data().Definition != SecondID->data().Definition &&
"Don't diagnose differences when definitions are merged already");
return diagnoseMismatch(FirstID, SecondID, &SecondID->data());
}
/// Diagnose ODR mismatch between 2 ObjCProtocolDecl.
///
/// Returns true if found a mismatch and diagnosed it.
/// To compare 2 declarations with merged and identical definition data
/// you need to provide pre-merge definition data in \p SecondDD.
bool diagnoseMismatch(
const ObjCProtocolDecl *FirstProtocol,
const ObjCProtocolDecl *SecondProtocol,
const struct ObjCProtocolDecl::DefinitionData *SecondDD) const;
/// Diagnose ODR mismatch between ObjCProtocolDecl with different definitions.
bool diagnoseMismatch(const ObjCProtocolDecl *FirstProtocol,
const ObjCProtocolDecl *SecondProtocol) const {
assert(FirstProtocol->data().Definition !=
SecondProtocol->data().Definition &&
"Don't diagnose differences when definitions are merged already");
return diagnoseMismatch(FirstProtocol, SecondProtocol,
&SecondProtocol->data());
}
/// Get the best name we know for the module that owns the given
/// declaration, or an empty string if the declaration is not from a module.
static std::string getOwningModuleNameForDiagnostic(const Decl *D);
private:
using DeclHashes = llvm::SmallVector<std::pair<const Decl *, unsigned>, 4>;
// Used with err_module_odr_violation_mismatch_decl,
// note_module_odr_violation_mismatch_decl,
// err_module_odr_violation_mismatch_decl_unknown,
// and note_module_odr_violation_mismatch_decl_unknown
// This list should be the same Decl's as in ODRHash::isSubDeclToBeProcessed
enum ODRMismatchDecl {
EndOfClass,
PublicSpecifer,
PrivateSpecifer,
ProtectedSpecifer,
StaticAssert,
Field,
CXXMethod,
TypeAlias,
TypeDef,
Var,
Friend,
FunctionTemplate,
ObjCMethod,
ObjCIvar,
ObjCProperty,
Other
};
struct DiffResult {
const Decl *FirstDecl = nullptr, *SecondDecl = nullptr;
ODRMismatchDecl FirstDiffType = Other, SecondDiffType = Other;
};
// If there is a diagnoseable difference, FirstDiffType and
// SecondDiffType will not be Other and FirstDecl and SecondDecl will be
// filled in if not EndOfClass.
static DiffResult FindTypeDiffs(DeclHashes &FirstHashes,
DeclHashes &SecondHashes);
DiagnosticBuilder Diag(SourceLocation Loc, unsigned DiagID) const {
return Diags.Report(Loc, DiagID);
}
// Use this to diagnose that an unexpected Decl was encountered
// or no difference was detected. This causes a generic error
// message to be emitted.
void diagnoseSubMismatchUnexpected(DiffResult &DR,
const NamedDecl *FirstRecord,
StringRef FirstModule,
const NamedDecl *SecondRecord,
StringRef SecondModule) const;
void diagnoseSubMismatchDifferentDeclKinds(DiffResult &DR,
const NamedDecl *FirstRecord,
StringRef FirstModule,
const NamedDecl *SecondRecord,
StringRef SecondModule) const;
bool diagnoseSubMismatchField(const NamedDecl *FirstRecord,
StringRef FirstModule, StringRef SecondModule,
const FieldDecl *FirstField,
const FieldDecl *SecondField) const;
bool diagnoseSubMismatchTypedef(const NamedDecl *FirstRecord,
StringRef FirstModule, StringRef SecondModule,
const TypedefNameDecl *FirstTD,
const TypedefNameDecl *SecondTD,
bool IsTypeAlias) const;
bool diagnoseSubMismatchVar(const NamedDecl *FirstRecord,
StringRef FirstModule, StringRef SecondModule,
const VarDecl *FirstVD,
const VarDecl *SecondVD) const;
/// Check if protocol lists are the same and diagnose if they are different.
///
/// Returns true if found a mismatch and diagnosed it.
bool diagnoseSubMismatchProtocols(const ObjCProtocolList &FirstProtocols,
const ObjCContainerDecl *FirstContainer,
StringRef FirstModule,
const ObjCProtocolList &SecondProtocols,
const ObjCContainerDecl *SecondContainer,
StringRef SecondModule) const;
/// Check if Objective-C methods are the same and diagnose if different.
///
/// Returns true if found a mismatch and diagnosed it.
bool diagnoseSubMismatchObjCMethod(const NamedDecl *FirstObjCContainer,
StringRef FirstModule,
StringRef SecondModule,
const ObjCMethodDecl *FirstMethod,
const ObjCMethodDecl *SecondMethod) const;
/// Check if Objective-C properties are the same and diagnose if different.
///
/// Returns true if found a mismatch and diagnosed it.
bool
diagnoseSubMismatchObjCProperty(const NamedDecl *FirstObjCContainer,
StringRef FirstModule, StringRef SecondModule,
const ObjCPropertyDecl *FirstProp,
const ObjCPropertyDecl *SecondProp) const;
private:
DiagnosticsEngine &Diags;
const ASTContext &Context;
const LangOptions &LangOpts;
};
} // namespace clang
#endif
@@ -55,6 +55,14 @@ class ODRHash {
// more information than the AddDecl class.
void AddCXXRecordDecl(const CXXRecordDecl *Record);
// Use this for ODR checking records in C/Objective-C between modules. This
// method compares more information than the AddDecl class.
void AddRecordDecl(const RecordDecl *Record);
// Use this for ODR checking ObjC interfaces. This
// method compares more information than the AddDecl class.
void AddObjCInterfaceDecl(const ObjCInterfaceDecl *Record);
// Use this for ODR checking functions between modules. This method compares
// more information than the AddDecl class. SkipBody will process the
// hash as if the function has no body.
@@ -64,6 +72,10 @@ class ODRHash {
// more information than the AddDecl class.
void AddEnumDecl(const EnumDecl *Enum);
// Use this for ODR checking ObjC protocols. This
// method compares more information than the AddDecl class.
void AddObjCProtocolDecl(const ObjCProtocolDecl *P);
// Process SubDecls of the main Decl. This method calls the DeclVisitor
// while AddDecl does not.
void AddSubDecl(const Decl *D);
@@ -89,7 +101,7 @@ class ODRHash {
// Save booleans until the end to lower the size of data to process.
void AddBoolean(bool value);
static bool isDeclToBeProcessed(const Decl* D, const DeclContext *Parent);
static bool isSubDeclToBeProcessed(const Decl *D, const DeclContext *Parent);
private:
void AddDeclarationNameImpl(DeclarationName Name);
File diff suppressed because it is too large Load Diff
@@ -77,7 +77,7 @@ class TraversalKindScope {
TraversalKind TK = TK_AsIs;
public:
TraversalKindScope(ASTContext &ASTCtx, llvm::Optional<TraversalKind> ScopeTK)
TraversalKindScope(ASTContext &ASTCtx, std::optional<TraversalKind> ScopeTK)
: Ctx(ASTCtx.getParentMapContext()) {
TK = Ctx.getTraversalKind();
if (ScopeTK)
@@ -65,7 +65,8 @@ struct PrintingPolicy {
SuppressStrongLifetime(false), SuppressLifetimeQualifiers(false),
SuppressTemplateArgsInCXXConstructors(false),
SuppressDefaultTemplateArgs(true), Bool(LO.Bool),
Nullptr(LO.CPlusPlus11), Restrict(LO.C99), Alignof(LO.CPlusPlus11),
Nullptr(LO.CPlusPlus11 || LO.C2x), NullptrTypeInNamespace(LO.CPlusPlus),
Restrict(LO.C99), Alignof(LO.CPlusPlus11),
UnderscoreAlignof(LO.C11), UseVoidForZeroParams(!LO.CPlusPlus),
SplitTemplateClosers(!LO.CPlusPlus11), TerseOutput(false),
PolishForDeclaration(false), Half(LO.Half),
@@ -196,6 +197,9 @@ struct PrintingPolicy {
/// constant.
unsigned Nullptr : 1;
/// Whether 'nullptr_t' is in namespace 'std' or not.
unsigned NullptrTypeInNamespace : 1;
/// Whether we can use 'restrict' rather than '__restrict'.
unsigned Restrict : 1;
@@ -41,7 +41,7 @@ class RefPropertyType<string className> : PropertyType<className # "*"> {
let PackOptional =
"value ? *value : nullptr";
let UnpackOptional =
"value ? llvm::Optional<" # CXXName # ">(value) : llvm::None";
"value ? std::optional<" # CXXName # ">(value) : std::nullopt";
}
/// Property types that correspond to a specific subclass of another type.
@@ -58,7 +58,7 @@ class DefaultValuePropertyType<string typeName = ""> : PropertyType<typeName> {
let PackOptional =
"value ? *value : " # CXXName # "()";
let UnpackOptional =
"value.isNull() ? llvm::None : llvm::Optional<" # CXXName # ">(value)";
"value.isNull() ? std::nullopt : std::optional<" # CXXName # ">(value)";
}
/// Property types that correspond to integer types and support optional
@@ -67,7 +67,7 @@ class CountPropertyType<string typeName = ""> : PropertyType<typeName> {
let PackOptional =
"value ? *value + 1 : 0";
let UnpackOptional =
"value ? llvm::Optional<" # CXXName # ">(value - 1) : llvm::None";
"value ? std::optional<" # CXXName # ">(value - 1) : std::nullopt";
}
def APInt : PropertyType<"llvm::APInt"> { let PassByReference = 1; }
@@ -138,6 +138,7 @@ def TemplateArgument : PropertyType;
def TemplateArgumentKind : EnumPropertyType<"TemplateArgument::ArgKind">;
def TemplateName : DefaultValuePropertyType;
def TemplateNameKind : EnumPropertyType<"TemplateName::NameKind">;
def TypeOfKind : EnumPropertyType<"TypeOfKind">;
def UInt32 : CountPropertyType<"uint32_t">;
def UInt64 : CountPropertyType<"uint64_t">;
def UnaryTypeTransformKind : EnumPropertyType<"UnaryTransformType::UTTKind">;
@@ -154,7 +155,7 @@ class Array<PropertyType element> : PropertyType {
let BufferElementTypes = [ element ];
}
/// llvm::Optional<T>. The corresponding C++ type is generally just the
/// std::optional<T>. The corresponding C++ type is generally just the
/// corresponding C++ type of the element.
///
/// Optional<Unsigned> may restrict the range of the operand for some
@@ -516,20 +517,16 @@ let Class = PropertyTypeCase<APValue, "LValue"> in {
def : Creator<[{
(void)ctx;
APValue::LValueBase base;
QualType elemTy;
if (hasBase) {
if (isTypeInfo) {
base = APValue::LValueBase::getTypeInfo(
TypeInfoLValue(typeInfo.value().getTypePtr()), type.value());
elemTy = base.getTypeInfoType();
TypeInfoLValue(typeInfo->getTypePtr()), *type);
} else if (isExpr) {
base = APValue::LValueBase(cast<Expr>(stmt.value()),
callIndex.value(), version.value());
elemTy = base.get<const Expr *>()->getType();
base = APValue::LValueBase(cast<Expr>(*stmt),
*callIndex, *version);
} else {
base = APValue::LValueBase(cast<ValueDecl>(decl.value()),
callIndex.value(), version.value());
elemTy = base.get<const ValueDecl *>()->getType();
base = APValue::LValueBase(cast<ValueDecl>(*decl),
*callIndex, *version);
}
}
CharUnits offset = CharUnits::fromQuantity(offsetQuantity);
@@ -542,7 +539,6 @@ let Class = PropertyTypeCase<APValue, "LValue"> in {
auto pathLength = lvaluePath->Path.size();
APValue::LValuePathEntry *path = result.setLValueUninit(
base, offset, pathLength, isLValueOnePastTheEnd, isNullPtr).data();
assert(lvaluePath->getType() == elemTy && "Unexpected type reference!");
llvm::copy(lvaluePath->Path, path);
return result;
}]>;
@@ -700,28 +696,40 @@ let Class = PropertyTypeCase<TemplateName, "SubstTemplateTemplateParm"> in {
def : ReadHelper<[{
auto parm = node.getAsSubstTemplateTemplateParm();
}]>;
def : Property<"parameter", TemplateTemplateParmDeclRef> {
let Read = [{ parm->getParameter() }];
}
def : Property<"replacement", TemplateName> {
let Read = [{ parm->getReplacement() }];
}
def : Property<"associatedDecl", DeclRef> {
let Read = [{ parm->getAssociatedDecl() }];
}
def : Property<"index", UInt32> {
let Read = [{ parm->getIndex() }];
}
def : Property<"packIndex", Optional<UInt32>> {
let Read = [{ parm->getPackIndex() }];
}
def : Creator<[{
return ctx.getSubstTemplateTemplateParm(parameter, replacement);
return ctx.getSubstTemplateTemplateParm(replacement, associatedDecl, index, packIndex);
}]>;
}
let Class = PropertyTypeCase<TemplateName, "SubstTemplateTemplateParmPack"> in {
def : ReadHelper<[{
auto parm = node.getAsSubstTemplateTemplateParmPack();
}]>;
def : Property<"parameterPack", TemplateTemplateParmDeclRef> {
let Read = [{ parm->getParameterPack() }];
}
def : Property<"argumentPack", TemplateArgument> {
let Read = [{ parm->getArgumentPack() }];
}
def : Property<"associatedDecl", DeclRef> {
let Read = [{ parm->getAssociatedDecl() }];
}
def : Property<"index", UInt32> {
let Read = [{ parm->getIndex() }];
}
def : Property<"final", Bool> {
let Read = [{ parm->getFinal() }];
}
def : Creator<[{
return ctx.getSubstTemplateTemplateParmPack(parameterPack, argumentPack);
return ctx.getSubstTemplateTemplateParmPack(argumentPack, associatedDecl, index, final);
}]>;
}
@@ -786,13 +794,14 @@ let Class = PropertyTypeCase<TemplateArgument, "TemplateExpansion"> in {
def : Property<"numExpansions", Optional<UInt32>> {
let Read = [{
// Translate unsigned -> uint32_t just in case.
node.getNumTemplateExpansions().map(
llvm::transformOptional(node.getNumTemplateExpansions(),
[](unsigned i) { return uint32_t(i); })
}];
}
def : Creator<[{
auto numExpansionsUnsigned =
numExpansions.map([](uint32_t i) { return unsigned(i); });
auto numExpansionsUnsigned = llvm::transformOptional(
numExpansions, [](uint32_t i) { return unsigned(i); });
return TemplateArgument(name, numExpansionsUnsigned);
}]>;
}
@@ -813,6 +822,6 @@ let Class = PropertyTypeCase<TemplateArgument, "Pack"> in {
TemplateArgument *ctxElements = new (ctx) TemplateArgument[elements.size()];
for (size_t i = 0, e = elements.size(); i != e; ++i)
ctxElements[i] = elements[i];
return TemplateArgument(llvm::makeArrayRef(ctxElements, elements.size()));
return TemplateArgument(llvm::ArrayRef(ctxElements, elements.size()));
}]>;
}
@@ -69,30 +69,17 @@ template <typename T, typename U, typename R, typename... P>
struct has_same_member_pointer_type<R (T::*)(P...), R (U::*)(P...)>
: std::true_type {};
template <bool has_same_type> struct is_same_method_impl {
template <typename FirstMethodPtrTy, typename SecondMethodPtrTy>
static bool isSameMethod(FirstMethodPtrTy FirstMethodPtr,
SecondMethodPtrTy SecondMethodPtr) {
return false;
}
};
template <> struct is_same_method_impl<true> {
template <typename FirstMethodPtrTy, typename SecondMethodPtrTy>
static bool isSameMethod(FirstMethodPtrTy FirstMethodPtr,
SecondMethodPtrTy SecondMethodPtr) {
return FirstMethodPtr == SecondMethodPtr;
}
};
/// Returns true if and only if \p FirstMethodPtr and \p SecondMethodPtr
/// are pointers to the same non-static member function.
template <typename FirstMethodPtrTy, typename SecondMethodPtrTy>
bool isSameMethod(FirstMethodPtrTy FirstMethodPtr,
SecondMethodPtrTy SecondMethodPtr) {
return is_same_method_impl<has_same_member_pointer_type<
FirstMethodPtrTy,
SecondMethodPtrTy>::value>::isSameMethod(FirstMethodPtr, SecondMethodPtr);
LLVM_ATTRIBUTE_ALWAYS_INLINE LLVM_ATTRIBUTE_NODEBUG auto
isSameMethod([[maybe_unused]] FirstMethodPtrTy FirstMethodPtr,
[[maybe_unused]] SecondMethodPtrTy SecondMethodPtr)
-> bool {
if constexpr (has_same_member_pointer_type<FirstMethodPtrTy,
SecondMethodPtrTy>::value)
return FirstMethodPtr == SecondMethodPtr;
return false;
}
} // end namespace detail
@@ -289,8 +276,7 @@ template <typename Derived> class RecursiveASTVisitor {
///
/// \returns false if the visitation was terminated early, true otherwise.
// FIXME: take a TemplateArgumentLoc* (or TemplateArgumentListInfo) instead.
bool TraverseTemplateArguments(const TemplateArgument *Args,
unsigned NumArgs);
bool TraverseTemplateArguments(ArrayRef<TemplateArgument> Args);
/// Recursively visit a base specifier. This can be overridden by a
/// subclass.
@@ -614,7 +600,7 @@ bool RecursiveASTVisitor<Derived>::TraverseConceptExprRequirement(
template <typename Derived>
bool RecursiveASTVisitor<Derived>::TraverseConceptNestedRequirement(
concepts::NestedRequirement *R) {
if (!R->isSubstitutionFailure())
if (!R->hasInvalidConstraint())
return getDerived().TraverseStmt(R->getConstraintExpr());
return true;
}
@@ -886,8 +872,7 @@ bool RecursiveASTVisitor<Derived>::TraverseTemplateArgument(
return getDerived().TraverseStmt(Arg.getAsExpr());
case TemplateArgument::Pack:
return getDerived().TraverseTemplateArguments(Arg.pack_begin(),
Arg.pack_size());
return getDerived().TraverseTemplateArguments(Arg.pack_elements());
}
return true;
@@ -927,8 +912,7 @@ bool RecursiveASTVisitor<Derived>::TraverseTemplateArgumentLoc(
return getDerived().TraverseStmt(ArgLoc.getSourceExpression());
case TemplateArgument::Pack:
return getDerived().TraverseTemplateArguments(Arg.pack_begin(),
Arg.pack_size());
return getDerived().TraverseTemplateArguments(Arg.pack_elements());
}
return true;
@@ -936,10 +920,9 @@ bool RecursiveASTVisitor<Derived>::TraverseTemplateArgumentLoc(
template <typename Derived>
bool RecursiveASTVisitor<Derived>::TraverseTemplateArguments(
const TemplateArgument *Args, unsigned NumArgs) {
for (unsigned I = 0; I != NumArgs; ++I) {
TRY_TO(TraverseTemplateArgument(Args[I]));
}
ArrayRef<TemplateArgument> Args) {
for (const TemplateArgument &Arg : Args)
TRY_TO(TraverseTemplateArgument(Arg));
return true;
}
@@ -1083,7 +1066,7 @@ DEF_TRAVERSE_TYPE(TypedefType, {})
DEF_TRAVERSE_TYPE(TypeOfExprType,
{ TRY_TO(TraverseStmt(T->getUnderlyingExpr())); })
DEF_TRAVERSE_TYPE(TypeOfType, { TRY_TO(TraverseType(T->getUnderlyingType())); })
DEF_TRAVERSE_TYPE(TypeOfType, { TRY_TO(TraverseType(T->getUnmodifiedType())); })
DEF_TRAVERSE_TYPE(DecltypeType,
{ TRY_TO(TraverseStmt(T->getUnderlyingExpr())); })
@@ -1096,7 +1079,7 @@ DEF_TRAVERSE_TYPE(UnaryTransformType, {
DEF_TRAVERSE_TYPE(AutoType, {
TRY_TO(TraverseType(T->getDeducedType()));
if (T->isConstrained()) {
TRY_TO(TraverseTemplateArguments(T->getArgs(), T->getNumArgs()));
TRY_TO(TraverseTemplateArguments(T->getTypeConstraintArguments()));
}
})
DEF_TRAVERSE_TYPE(DeducedTemplateSpecializationType, {
@@ -1116,7 +1099,7 @@ DEF_TRAVERSE_TYPE(SubstTemplateTypeParmPackType, {
DEF_TRAVERSE_TYPE(TemplateSpecializationType, {
TRY_TO(TraverseTemplateName(T->getTemplateName()));
TRY_TO(TraverseTemplateArguments(T->getArgs(), T->getNumArgs()));
TRY_TO(TraverseTemplateArguments(T->template_arguments()));
})
DEF_TRAVERSE_TYPE(InjectedClassNameType, {})
@@ -1144,7 +1127,7 @@ DEF_TRAVERSE_TYPE(DependentNameType,
DEF_TRAVERSE_TYPE(DependentTemplateSpecializationType, {
TRY_TO(TraverseNestedNameSpecifier(T->getQualifier()));
TRY_TO(TraverseTemplateArguments(T->getArgs(), T->getNumArgs()));
TRY_TO(TraverseTemplateArguments(T->template_arguments()));
})
DEF_TRAVERSE_TYPE(PackExpansionType, { TRY_TO(TraverseType(T->getPattern())); })
@@ -1358,7 +1341,7 @@ DEF_TRAVERSE_TYPELOC(TypeOfExprType,
{ TRY_TO(TraverseStmt(TL.getUnderlyingExpr())); })
DEF_TRAVERSE_TYPELOC(TypeOfType, {
TRY_TO(TraverseTypeLoc(TL.getUnderlyingTInfo()->getTypeLoc()));
TRY_TO(TraverseTypeLoc(TL.getUnmodifiedTInfo()->getTypeLoc()));
})
// FIXME: location of underlying expr
@@ -1551,6 +1534,8 @@ DEF_TRAVERSE_DECL(CapturedDecl, {
DEF_TRAVERSE_DECL(EmptyDecl, {})
DEF_TRAVERSE_DECL(HLSLBufferDecl, {})
DEF_TRAVERSE_DECL(LifetimeExtendedTemporaryDecl, {
TRY_TO(TraverseStmt(D->getTemporaryExpr()));
})
@@ -1558,14 +1543,21 @@ DEF_TRAVERSE_DECL(LifetimeExtendedTemporaryDecl, {
DEF_TRAVERSE_DECL(FileScopeAsmDecl,
{ TRY_TO(TraverseStmt(D->getAsmString())); })
DEF_TRAVERSE_DECL(TopLevelStmtDecl, { TRY_TO(TraverseStmt(D->getStmt())); })
DEF_TRAVERSE_DECL(ImportDecl, {})
DEF_TRAVERSE_DECL(FriendDecl, {
// Friend is either decl or a type.
if (D->getFriendType())
if (D->getFriendType()) {
TRY_TO(TraverseTypeLoc(D->getFriendType()->getTypeLoc()));
else
// Traverse any CXXRecordDecl owned by this type, since
// it will not be in the parent context:
if (auto *ET = D->getFriendType()->getType()->getAs<ElaboratedType>())
TRY_TO(TraverseDecl(ET->getOwnedTagDecl()));
} else {
TRY_TO(TraverseDecl(D->getFriendDecl()));
}
})
DEF_TRAVERSE_DECL(FriendTemplateDecl, {
@@ -1730,7 +1722,8 @@ DEF_TRAVERSE_DECL(UsingDecl, {
TRY_TO(TraverseDeclarationNameInfo(D->getNameInfo()));
})
DEF_TRAVERSE_DECL(UsingEnumDecl, {})
DEF_TRAVERSE_DECL(UsingEnumDecl,
{ TRY_TO(TraverseTypeLoc(D->getEnumTypeLoc())); })
DEF_TRAVERSE_DECL(UsingPackDecl, {})
@@ -2309,6 +2302,10 @@ DEF_TRAVERSE_DECL(ParmVarDecl, {
DEF_TRAVERSE_DECL(RequiresExprBodyDecl, {})
DEF_TRAVERSE_DECL(ImplicitConceptSpecializationDecl, {
TRY_TO(TraverseTemplateArguments(D->getTemplateArguments()));
})
#undef DEF_TRAVERSE_DECL
// ----------------- Stmt traversal -----------------
@@ -2855,6 +2852,7 @@ DEF_TRAVERSE_STMT(SubstNonTypeTemplateParmExpr, {})
DEF_TRAVERSE_STMT(FunctionParmPackExpr, {})
DEF_TRAVERSE_STMT(CXXFoldExpr, {})
DEF_TRAVERSE_STMT(AtomicExpr, {})
DEF_TRAVERSE_STMT(CXXParenListInitExpr, {})
DEF_TRAVERSE_STMT(MaterializeTemporaryExpr, {
if (S->getLifetimeExtendedTemporaryDecl()) {
@@ -3158,6 +3156,10 @@ DEF_TRAVERSE_STMT(OMPParallelGenericLoopDirective,
DEF_TRAVERSE_STMT(OMPTargetParallelGenericLoopDirective,
{ TRY_TO(TraverseOMPExecutableDirective(S)); })
DEF_TRAVERSE_STMT(OMPErrorDirective,
{ TRY_TO(TraverseOMPExecutableDirective(S)); })
// OpenMP clauses.
template <typename Derived>
bool RecursiveASTVisitor<Derived>::TraverseOMPClause(OMPClause *C) {
@@ -3311,6 +3313,22 @@ bool RecursiveASTVisitor<Derived>::VisitOMPAtomicDefaultMemOrderClause(
return true;
}
template <typename Derived>
bool RecursiveASTVisitor<Derived>::VisitOMPAtClause(OMPAtClause *) {
return true;
}
template <typename Derived>
bool RecursiveASTVisitor<Derived>::VisitOMPSeverityClause(OMPSeverityClause *) {
return true;
}
template <typename Derived>
bool RecursiveASTVisitor<Derived>::VisitOMPMessageClause(OMPMessageClause *C) {
TRY_TO(TraverseStmt(C->getMessageString()));
return true;
}
template <typename Derived>
bool
RecursiveASTVisitor<Derived>::VisitOMPScheduleClause(OMPScheduleClause *C) {
@@ -3834,6 +3852,14 @@ bool RecursiveASTVisitor<Derived>::VisitOMPBindClause(OMPBindClause *C) {
return true;
}
template <typename Derived>
bool RecursiveASTVisitor<Derived>::VisitOMPXDynCGroupMemClause(
OMPXDynCGroupMemClause *C) {
TRY_TO(VisitOMPClauseWithPreInit(C));
TRY_TO(TraverseStmt(C->getSize()));
return true;
}
// FIXME: look at the following tricky-seeming exprs to see if we
// need to recurse on anything. These are ones that have methods
// returning decls or qualtypes or nestednamespecifier -- though I'm
@@ -22,6 +22,7 @@
#include "clang/Basic/LangOptions.h"
#include "clang/Basic/SourceLocation.h"
#include "clang/Basic/Specifiers.h"
#include "llvm/ADT/APFloat.h"
#include "llvm/ADT/ArrayRef.h"
#include "llvm/ADT/BitmaskEnum.h"
#include "llvm/ADT/PointerIntPair.h"
@@ -35,6 +36,7 @@
#include <cassert>
#include <cstddef>
#include <iterator>
#include <optional>
#include <string>
namespace llvm {
@@ -389,7 +391,10 @@ class alignas(void *) Stmt {
unsigned : NumExprBits;
unsigned Semantics : 3; // Provides semantics for APFloat construction
static_assert(
llvm::APFloat::S_MaxSemantics < 16,
"Too many Semantics enum values to fit in bitfield of size 4");
unsigned Semantics : 4; // Provides semantics for APFloat construction
unsigned IsExact : 1;
};
@@ -686,6 +691,9 @@ class alignas(void *) Stmt {
unsigned : NumExprBits;
/// Whether this CXXDefaultArgExpr rewrote its argument and stores a copy.
unsigned HasRewrittenInit : 1;
/// The location where the default argument expression was used.
SourceLocation Loc;
};
@@ -696,6 +704,10 @@ class alignas(void *) Stmt {
unsigned : NumExprBits;
/// Whether this CXXDefaultInitExprBitfields rewrote its argument and stores
/// a copy.
unsigned HasRewrittenInit : 1;
/// The location where the default initializer expression was used.
SourceLocation Loc;
};
@@ -1912,7 +1924,7 @@ class AttributedStmt final
SourceLocation getAttrLoc() const { return AttributedStmtBits.AttrLoc; }
ArrayRef<const Attr *> getAttrs() const {
return llvm::makeArrayRef(getAttrArrayPtr(), AttributedStmtBits.NumAttrs);
return llvm::ArrayRef(getAttrArrayPtr(), AttributedStmtBits.NumAttrs);
}
Stmt *getSubStmt() { return SubStmt; }
@@ -2136,9 +2148,9 @@ class IfStmt final
}
/// If this is an 'if constexpr', determine which substatement will be taken.
/// Otherwise, or if the condition is value-dependent, returns None.
Optional<const Stmt*> getNondiscardedCase(const ASTContext &Ctx) const;
Optional<Stmt *> getNondiscardedCase(const ASTContext &Ctx);
/// Otherwise, or if the condition is value-dependent, returns std::nullopt.
std::optional<const Stmt *> getNondiscardedCase(const ASTContext &Ctx) const;
std::optional<Stmt *> getNondiscardedCase(const ASTContext &Ctx);
bool isObjCAvailabilityCheck() const;
@@ -3323,15 +3335,15 @@ class MSAsmStmt : public AsmStmt {
//===--- Other ---===//
ArrayRef<StringRef> getAllConstraints() const {
return llvm::makeArrayRef(Constraints, NumInputs + NumOutputs);
return llvm::ArrayRef(Constraints, NumInputs + NumOutputs);
}
ArrayRef<StringRef> getClobbers() const {
return llvm::makeArrayRef(Clobbers, NumClobbers);
return llvm::ArrayRef(Clobbers, NumClobbers);
}
ArrayRef<Expr*> getAllExprs() const {
return llvm::makeArrayRef(reinterpret_cast<Expr**>(Exprs),
return llvm::ArrayRef(reinterpret_cast<Expr **>(Exprs),
NumInputs + NumOutputs);
}
@@ -277,7 +277,7 @@ class OMPExecutableDirective : public Stmt {
/// Get the clauses storage.
MutableArrayRef<OMPClause *> getClauses() {
if (!Data)
return llvm::None;
return std::nullopt;
return Data->getClauses();
}
@@ -399,8 +399,9 @@ class OMPExecutableDirective : public Stmt {
static llvm::iterator_range<used_clauses_child_iterator>
used_clauses_children(ArrayRef<OMPClause *> Clauses) {
return {used_clauses_child_iterator(Clauses),
used_clauses_child_iterator(llvm::makeArrayRef(Clauses.end(), 0))};
return {
used_clauses_child_iterator(Clauses),
used_clauses_child_iterator(llvm::ArrayRef(Clauses.end(), (size_t)0))};
}
/// Iterates over a filtered subrange of clauses applied to a
@@ -445,7 +446,7 @@ class OMPExecutableDirective : public Stmt {
getClausesOfKind(ArrayRef<OMPClause *> Clauses) {
return {specific_clause_iterator<SpecificClause>(Clauses),
specific_clause_iterator<SpecificClause>(
llvm::makeArrayRef(Clauses.end(), 0))};
llvm::ArrayRef(Clauses.end(), (size_t)0))};
}
template <typename SpecificClause>
@@ -571,7 +572,7 @@ class OMPExecutableDirective : public Stmt {
ArrayRef<OMPClause *> clauses() const {
if (!Data)
return llvm::None;
return std::nullopt;
return Data->getClauses();
}
@@ -980,7 +981,7 @@ class OMPLoopTransformationDirective : public OMPLoopBasedDirective {
/// Return the number of loops generated by this loop transformation.
unsigned getNumGeneratedLoops() { return NumGeneratedLoops; }
/// Get the de-sugared statements after after the loop transformation.
/// Get the de-sugared statements after the loop transformation.
///
/// Might be nullptr if either the directive generates no loops and is handled
/// directly in CodeGen, or resolving a template-dependence context is
@@ -1066,7 +1067,7 @@ class OMPLoopDirective : public OMPLoopBasedDirective {
MutableArrayRef<Expr *> getCounters() {
auto **Storage = reinterpret_cast<Expr **>(
&Data->getChildren()[getArraysOffset(getDirectiveKind())]);
return llvm::makeMutableArrayRef(Storage, getLoopsNumber());
return llvm::MutableArrayRef(Storage, getLoopsNumber());
}
/// Get the private counters storage.
@@ -1074,7 +1075,7 @@ class OMPLoopDirective : public OMPLoopBasedDirective {
auto **Storage = reinterpret_cast<Expr **>(
&Data->getChildren()[getArraysOffset(getDirectiveKind()) +
getLoopsNumber()]);
return llvm::makeMutableArrayRef(Storage, getLoopsNumber());
return llvm::MutableArrayRef(Storage, getLoopsNumber());
}
/// Get the updates storage.
@@ -1082,7 +1083,7 @@ class OMPLoopDirective : public OMPLoopBasedDirective {
auto **Storage = reinterpret_cast<Expr **>(
&Data->getChildren()[getArraysOffset(getDirectiveKind()) +
2 * getLoopsNumber()]);
return llvm::makeMutableArrayRef(Storage, getLoopsNumber());
return llvm::MutableArrayRef(Storage, getLoopsNumber());
}
/// Get the updates storage.
@@ -1090,7 +1091,7 @@ class OMPLoopDirective : public OMPLoopBasedDirective {
auto **Storage = reinterpret_cast<Expr **>(
&Data->getChildren()[getArraysOffset(getDirectiveKind()) +
3 * getLoopsNumber()]);
return llvm::makeMutableArrayRef(Storage, getLoopsNumber());
return llvm::MutableArrayRef(Storage, getLoopsNumber());
}
/// Get the final counter updates storage.
@@ -1098,7 +1099,7 @@ class OMPLoopDirective : public OMPLoopBasedDirective {
auto **Storage = reinterpret_cast<Expr **>(
&Data->getChildren()[getArraysOffset(getDirectiveKind()) +
4 * getLoopsNumber()]);
return llvm::makeMutableArrayRef(Storage, getLoopsNumber());
return llvm::MutableArrayRef(Storage, getLoopsNumber());
}
/// Get the dependent counters storage.
@@ -1106,7 +1107,7 @@ class OMPLoopDirective : public OMPLoopBasedDirective {
auto **Storage = reinterpret_cast<Expr **>(
&Data->getChildren()[getArraysOffset(getDirectiveKind()) +
5 * getLoopsNumber()]);
return llvm::makeMutableArrayRef(Storage, getLoopsNumber());
return llvm::MutableArrayRef(Storage, getLoopsNumber());
}
/// Get the dependent inits storage.
@@ -1114,7 +1115,7 @@ class OMPLoopDirective : public OMPLoopBasedDirective {
auto **Storage = reinterpret_cast<Expr **>(
&Data->getChildren()[getArraysOffset(getDirectiveKind()) +
6 * getLoopsNumber()]);
return llvm::makeMutableArrayRef(Storage, getLoopsNumber());
return llvm::MutableArrayRef(Storage, getLoopsNumber());
}
/// Get the finals conditions storage.
@@ -1122,7 +1123,7 @@ class OMPLoopDirective : public OMPLoopBasedDirective {
auto **Storage = reinterpret_cast<Expr **>(
&Data->getChildren()[getArraysOffset(getDirectiveKind()) +
7 * getLoopsNumber()]);
return llvm::makeMutableArrayRef(Storage, getLoopsNumber());
return llvm::MutableArrayRef(Storage, getLoopsNumber());
}
protected:
@@ -2873,7 +2874,7 @@ class OMPOrderedDirective : public OMPExecutableDirective {
///
/// \param C AST context.
/// \param NumClauses Number of clauses.
/// \param IsStandalone true, if the the standalone directive is created.
/// \param IsStandalone true, if the standalone directive is created.
///
static OMPOrderedDirective *CreateEmpty(const ASTContext &C,
unsigned NumClauses,
@@ -6220,6 +6221,51 @@ class OMPTargetParallelGenericLoopDirective final : public OMPLoopDirective {
return T->getStmtClass() == OMPTargetParallelGenericLoopDirectiveClass;
}
};
/// This represents '#pragma omp error' directive.
///
/// \code
/// #pragma omp error
/// \endcode
class OMPErrorDirective final : public OMPExecutableDirective {
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.
///
OMPErrorDirective(SourceLocation StartLoc, SourceLocation EndLoc)
: OMPExecutableDirective(OMPErrorDirectiveClass, llvm::omp::OMPD_error,
StartLoc, EndLoc) {}
/// Build an empty directive.
///
explicit OMPErrorDirective()
: OMPExecutableDirective(OMPErrorDirectiveClass, llvm::omp::OMPD_error,
SourceLocation(), SourceLocation()) {}
public:
///
/// \param C AST context.
/// \param StartLoc Starting location of the directive kind.
/// \param EndLoc Ending Location of the directive.
/// \param Clauses List of clauses.
///
static OMPErrorDirective *Create(const ASTContext &C, SourceLocation StartLoc,
SourceLocation EndLoc,
ArrayRef<OMPClause *> Clauses);
/// Creates an empty directive.
///
/// \param C AST context.
///
static OMPErrorDirective *CreateEmpty(const ASTContext &C,
unsigned NumClauses, EmptyShell);
static bool classof(const Stmt *T) {
return T->getStmtClass() == OMPErrorDirectiveClass;
}
};
} // end namespace clang
#endif
@@ -23,14 +23,13 @@
#include "llvm/ADT/APInt.h"
#include "llvm/ADT/APSInt.h"
#include "llvm/ADT/ArrayRef.h"
#include "llvm/ADT/None.h"
#include "llvm/ADT/Optional.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/Support/Compiler.h"
#include "llvm/Support/TrailingObjects.h"
#include <cassert>
#include <cstddef>
#include <cstdint>
#include <optional>
namespace llvm {
@@ -202,7 +201,7 @@ class TemplateArgument {
///
/// \param NumExpansions The number of expansions that will be generated by
/// instantiating
TemplateArgument(TemplateName Name, Optional<unsigned> NumExpansions) {
TemplateArgument(TemplateName Name, std::optional<unsigned> NumExpansions) {
TemplateArg.Kind = TemplateExpansion;
TemplateArg.Name = Name.getAsVoidPointer();
if (NumExpansions)
@@ -233,7 +232,9 @@ class TemplateArgument {
TemplateArgument(TemplateName, bool) = delete;
static TemplateArgument getEmptyPack() { return TemplateArgument(None); }
static TemplateArgument getEmptyPack() {
return TemplateArgument(std::nullopt);
}
/// Create a new template argument pack by copying the given set of
/// template arguments.
@@ -305,7 +306,7 @@ class TemplateArgument {
/// Retrieve the number of expansions that a template template argument
/// expansion will produce, if known.
Optional<unsigned> getNumTemplateExpansions() const;
std::optional<unsigned> getNumTemplateExpansions() const;
/// Retrieve the template argument as an integral value.
// FIXME: Provide a way to read the integral data without copying the value.
@@ -318,7 +319,7 @@ class TemplateArgument {
return APSInt(APInt(Integer.BitWidth, Integer.VAL), Integer.IsUnsigned);
unsigned NumWords = APInt::getNumWords(Integer.BitWidth);
return APSInt(APInt(Integer.BitWidth, makeArrayRef(Integer.pVal, NumWords)),
return APSInt(APInt(Integer.BitWidth, ArrayRef(Integer.pVal, NumWords)),
Integer.IsUnsigned);
}
@@ -363,7 +364,7 @@ class TemplateArgument {
/// Iterator range referencing all of the elements of a template
/// argument pack.
ArrayRef<TemplateArgument> pack_elements() const {
return llvm::makeArrayRef(pack_begin(), pack_end());
return llvm::ArrayRef(pack_begin(), pack_end());
}
/// The number of template arguments in the given template argument
@@ -376,7 +377,7 @@ class TemplateArgument {
/// Return the array of arguments in this template argument pack.
ArrayRef<TemplateArgument> getPackAsArray() const {
assert(getKind() == Pack);
return llvm::makeArrayRef(Args.Args, Args.NumArgs);
return llvm::ArrayRef(Args.Args, Args.NumArgs);
}
/// Determines whether two template arguments are superficially the
@@ -641,7 +642,7 @@ struct ASTTemplateArgumentListInfo final
unsigned getNumTemplateArgs() const { return NumTemplateArgs; }
llvm::ArrayRef<TemplateArgumentLoc> arguments() const {
return llvm::makeArrayRef(getTemplateArgs(), getNumTemplateArgs());
return llvm::ArrayRef(getTemplateArgs(), getNumTemplateArgs());
}
const TemplateArgumentLoc &operator[](unsigned I) const {
@@ -698,33 +699,6 @@ struct alignas(void *) ASTTemplateKWAndArgsInfo {
const StreamingDiagnostic &operator<<(const StreamingDiagnostic &DB,
const TemplateArgument &Arg);
inline TemplateSpecializationType::iterator
TemplateSpecializationType::end() const {
return getArgs() + getNumArgs();
}
inline DependentTemplateSpecializationType::iterator
DependentTemplateSpecializationType::end() const {
return getArgs() + getNumArgs();
}
inline const TemplateArgument &
TemplateSpecializationType::getArg(unsigned Idx) const {
assert(Idx < getNumArgs() && "Template argument out of range");
return getArgs()[Idx];
}
inline const TemplateArgument &
DependentTemplateSpecializationType::getArg(unsigned Idx) const {
assert(Idx < getNumArgs() && "Template argument out of range");
return getArgs()[Idx];
}
inline const TemplateArgument &AutoType::getArg(unsigned Idx) const {
assert(Idx < getNumArgs() && "Template argument out of range");
return getArgs()[Idx];
}
} // namespace clang
#endif // LLVM_CLANG_AST_TEMPLATEBASE_H
@@ -21,6 +21,7 @@
#include "llvm/ADT/PointerUnion.h"
#include "llvm/Support/PointerLikeTypeTraits.h"
#include <cassert>
#include <optional>
namespace clang {
@@ -57,9 +58,12 @@ class UncommonTemplateNameStorage {
/// A Kind.
unsigned Kind : 2;
/// The number of stored templates or template arguments,
/// depending on which subclass we have.
unsigned Size : 30;
// The template parameter index.
unsigned Index : 15;
/// The pack index, or the number of stored templates
/// or template arguments, depending on which subclass we have.
unsigned Data : 15;
};
union {
@@ -67,14 +71,13 @@ class UncommonTemplateNameStorage {
void *PointerAlignment;
};
UncommonTemplateNameStorage(Kind kind, unsigned size) {
Bits.Kind = kind;
Bits.Size = size;
UncommonTemplateNameStorage(Kind Kind, unsigned Index, unsigned Data) {
Bits.Kind = Kind;
Bits.Index = Index;
Bits.Data = Data;
}
public:
unsigned size() const { return Bits.Size; }
OverloadedTemplateStorage *getAsOverloadedStorage() {
return Bits.Kind == Overloaded
? reinterpret_cast<OverloadedTemplateStorage *>(this)
@@ -106,7 +109,7 @@ class OverloadedTemplateStorage : public UncommonTemplateNameStorage {
friend class ASTContext;
OverloadedTemplateStorage(unsigned size)
: UncommonTemplateNameStorage(Overloaded, size) {}
: UncommonTemplateNameStorage(Overloaded, 0, size) {}
NamedDecl **getStorage() {
return reinterpret_cast<NamedDecl **>(this + 1);
@@ -116,13 +119,15 @@ class OverloadedTemplateStorage : public UncommonTemplateNameStorage {
}
public:
unsigned size() const { return Bits.Data; }
using iterator = NamedDecl *const *;
iterator begin() const { return getStorage(); }
iterator end() const { return getStorage() + size(); }
iterator end() const { return getStorage() + Bits.Data; }
llvm::ArrayRef<NamedDecl*> decls() const {
return llvm::makeArrayRef(begin(), end());
return llvm::ArrayRef(begin(), end());
}
};
@@ -132,23 +137,29 @@ class OverloadedTemplateStorage : public UncommonTemplateNameStorage {
/// This kind of template names occurs when the parameter pack has been
/// provided with a template template argument pack in a context where its
/// enclosing pack expansion could not be fully expanded.
class SubstTemplateTemplateParmPackStorage
: public UncommonTemplateNameStorage, public llvm::FoldingSetNode
{
TemplateTemplateParmDecl *Parameter;
class SubstTemplateTemplateParmPackStorage : public UncommonTemplateNameStorage,
public llvm::FoldingSetNode {
const TemplateArgument *Arguments;
llvm::PointerIntPair<Decl *, 1, bool> AssociatedDeclAndFinal;
public:
SubstTemplateTemplateParmPackStorage(TemplateTemplateParmDecl *Parameter,
unsigned Size,
const TemplateArgument *Arguments)
: UncommonTemplateNameStorage(SubstTemplateTemplateParmPack, Size),
Parameter(Parameter), Arguments(Arguments) {}
SubstTemplateTemplateParmPackStorage(ArrayRef<TemplateArgument> ArgPack,
Decl *AssociatedDecl, unsigned Index,
bool Final);
/// A template-like entity which owns the whole pattern being substituted.
/// This will own a set of template parameters.
Decl *getAssociatedDecl() const;
/// Returns the index of the replaced parameter in the associated declaration.
/// This should match the result of `getParameterPack()->getIndex()`.
unsigned getIndex() const { return Bits.Index; }
// When true the substitution will be 'Final' (subst node won't be placed).
bool getFinal() const;
/// Retrieve the template template parameter pack being substituted.
TemplateTemplateParmDecl *getParameterPack() const {
return Parameter;
}
TemplateTemplateParmDecl *getParameterPack() const;
/// Retrieve the template template argument pack with which this
/// parameter was substituted.
@@ -156,10 +167,9 @@ class SubstTemplateTemplateParmPackStorage
void Profile(llvm::FoldingSetNodeID &ID, ASTContext &Context);
static void Profile(llvm::FoldingSetNodeID &ID,
ASTContext &Context,
TemplateTemplateParmDecl *Parameter,
const TemplateArgument &ArgPack);
static void Profile(llvm::FoldingSetNodeID &ID, ASTContext &Context,
const TemplateArgument &ArgPack, Decl *AssociatedDecl,
unsigned Index, bool Final);
};
/// Represents a C++ template name within the type system.
@@ -365,23 +375,41 @@ class SubstTemplateTemplateParmStorage
: public UncommonTemplateNameStorage, public llvm::FoldingSetNode {
friend class ASTContext;
TemplateTemplateParmDecl *Parameter;
TemplateName Replacement;
Decl *AssociatedDecl;
SubstTemplateTemplateParmStorage(TemplateTemplateParmDecl *parameter,
TemplateName replacement)
: UncommonTemplateNameStorage(SubstTemplateTemplateParm, 0),
Parameter(parameter), Replacement(replacement) {}
SubstTemplateTemplateParmStorage(TemplateName Replacement,
Decl *AssociatedDecl, unsigned Index,
std::optional<unsigned> PackIndex)
: UncommonTemplateNameStorage(SubstTemplateTemplateParm, Index,
PackIndex ? *PackIndex + 1 : 0),
Replacement(Replacement), AssociatedDecl(AssociatedDecl) {
assert(AssociatedDecl != nullptr);
}
public:
TemplateTemplateParmDecl *getParameter() const { return Parameter; }
/// A template-like entity which owns the whole pattern being substituted.
/// This will own a set of template parameters.
Decl *getAssociatedDecl() const { return AssociatedDecl; }
/// Returns the index of the replaced parameter in the associated declaration.
/// This should match the result of `getParameter()->getIndex()`.
unsigned getIndex() const { return Bits.Index; }
std::optional<unsigned> getPackIndex() const {
if (Bits.Data == 0)
return std::nullopt;
return Bits.Data - 1;
}
TemplateTemplateParmDecl *getParameter() const;
TemplateName getReplacement() const { return Replacement; }
void Profile(llvm::FoldingSetNodeID &ID);
static void Profile(llvm::FoldingSetNodeID &ID,
TemplateTemplateParmDecl *parameter,
TemplateName replacement);
static void Profile(llvm::FoldingSetNodeID &ID, TemplateName Replacement,
Decl *AssociatedDecl, unsigned Index,
std::optional<unsigned> PackIndex);
};
inline TemplateName TemplateName::getUnderlying() const {
@@ -317,6 +317,9 @@ class TextNodeDumper
void VisitUnaryTransformType(const UnaryTransformType *T);
void VisitTagType(const TagType *T);
void VisitTemplateTypeParmType(const TemplateTypeParmType *T);
void VisitSubstTemplateTypeParmType(const SubstTemplateTypeParmType *T);
void
VisitSubstTemplateTypeParmPackType(const SubstTemplateTypeParmPackType *T);
void VisitAutoType(const AutoType *T);
void VisitDeducedTemplateSpecializationType(
const DeducedTemplateSpecializationType *T);
@@ -380,6 +383,7 @@ class TextNodeDumper
void VisitConceptDecl(const ConceptDecl *D);
void
VisitLifetimeExtendedTemporaryDecl(const LifetimeExtendedTemporaryDecl *D);
void VisitHLSLBufferDecl(const HLSLBufferDecl *D);
};
} // namespace clang
@@ -34,8 +34,6 @@
#include "llvm/ADT/APSInt.h"
#include "llvm/ADT/ArrayRef.h"
#include "llvm/ADT/FoldingSet.h"
#include "llvm/ADT/None.h"
#include "llvm/ADT/Optional.h"
#include "llvm/ADT/PointerIntPair.h"
#include "llvm/ADT/PointerUnion.h"
#include "llvm/ADT/StringRef.h"
@@ -51,6 +49,7 @@
#include <cstddef>
#include <cstdint>
#include <cstring>
#include <optional>
#include <string>
#include <type_traits>
#include <utility>
@@ -714,6 +713,12 @@ enum class ObjCSubstitutionContext {
Superclass,
};
/// The kind of 'typeof' expression we're after.
enum class TypeOfKind : uint8_t {
Qualified,
Unqualified,
};
/// A (possibly-)qualified type.
///
/// For efficiency, we don't store CV-qualified types as nodes on their
@@ -758,6 +763,8 @@ class QualType {
unsigned getLocalFastQualifiers() const { return Value.getInt(); }
void setLocalFastQualifiers(unsigned Quals) { Value.setInt(Quals); }
bool UseExcessPrecision(const ASTContext &Ctx);
/// Retrieves a pointer to the underlying (unqualified) type.
///
/// This function requires that the type not be NULL. If the type might be
@@ -797,6 +804,9 @@ class QualType {
return Value.getPointer().isNull();
}
// Determines if a type can form `T&`.
bool isReferenceable() const;
/// Determine whether this particular QualType instance has the
/// "const" qualifier set, without looking through typedefs that may have
/// added "const" at a different level.
@@ -1790,19 +1800,63 @@ class alignas(8) Type : public ExtQualsTypeCommonBase {
unsigned NumArgs;
};
class TypeOfBitfields {
friend class TypeOfType;
friend class TypeOfExprType;
unsigned : NumTypeBits;
unsigned IsUnqual : 1; // If true: typeof_unqual, else: typeof
};
class UsingBitfields {
friend class UsingType;
unsigned : NumTypeBits;
/// True if the underlying type is different from the declared one.
unsigned hasTypeDifferentFromDecl : 1;
};
class TypedefBitfields {
friend class TypedefType;
unsigned : NumTypeBits;
/// True if the underlying type is different from the declared one.
unsigned hasTypeDifferentFromDecl : 1;
};
class SubstTemplateTypeParmTypeBitfields {
friend class SubstTemplateTypeParmType;
unsigned : NumTypeBits;
unsigned HasNonCanonicalUnderlyingType : 1;
// The index of the template parameter this substitution represents.
unsigned Index : 15;
/// Represents the index within a pack if this represents a substitution
/// from a pack expansion. This index starts at the end of the pack and
/// increments towards the beginning.
/// Positive non-zero number represents the index + 1.
/// Zero means this is not substituted from an expansion.
unsigned PackIndex : 16;
};
class SubstTemplateTypeParmPackTypeBitfields {
friend class SubstTemplateTypeParmPackType;
unsigned : NumTypeBits;
// The index of the template parameter this substitution represents.
unsigned Index : 16;
/// The number of template arguments in \c Arguments, which is
/// expected to be able to hold at least 1024 according to [implimits].
/// However as this limit is somewhat easy to hit with template
/// metaprogramming we'd prefer to keep it as large as possible.
/// At the moment it has been left as a non-bitfield since this type
/// safely fits in 64 bits as an unsigned, so there is no reason to
/// introduce the performance impact of a bitfield.
unsigned NumArgs;
unsigned NumArgs : 16;
};
class TemplateSpecializationTypeBitfields {
@@ -1864,6 +1918,9 @@ class alignas(8) Type : public ExtQualsTypeCommonBase {
ConstantArrayTypeBitfields ConstantArrayTypeBits;
AttributedTypeBitfields AttributedTypeBits;
AutoTypeBitfields AutoTypeBits;
TypeOfBitfields TypeOfBits;
TypedefBitfields TypedefBits;
UsingBitfields UsingBits;
BuiltinTypeBitfields BuiltinTypeBits;
FunctionTypeBitfields FunctionTypeBits;
ObjCObjectTypeBitfields ObjCObjectTypeBits;
@@ -1871,6 +1928,7 @@ class alignas(8) Type : public ExtQualsTypeCommonBase {
TypeWithKeywordBitfields TypeWithKeywordBits;
ElaboratedTypeBitfields ElaboratedTypeBits;
VectorTypeBitfields VectorTypeBits;
SubstTemplateTypeParmTypeBitfields SubstTemplateTypeParmTypeBits;
SubstTemplateTypeParmPackTypeBitfields SubstTemplateTypeParmPackTypeBits;
TemplateSpecializationTypeBitfields TemplateSpecializationTypeBits;
DependentTemplateSpecializationTypeBitfields
@@ -1968,6 +2026,9 @@ class alignas(8) Type : public ExtQualsTypeCommonBase {
bool isSizelessType() const;
bool isSizelessBuiltinType() const;
/// Returns true for SVE scalable vector types.
bool isSVESizelessBuiltinType() const;
/// Determines if this is a sizeless type supported by the
/// 'arm_sve_vector_bits' type attribute, which can be applied to a single
/// SVE vector or predicate, excluding tuple types such as svint32x4_t.
@@ -2169,7 +2230,8 @@ class alignas(8) Type : public ExtQualsTypeCommonBase {
bool isObjCARCBridgableType() const;
bool isCARCBridgableType() const;
bool isTemplateTypeParmType() const; // C++ template type parameter
bool isNullPtrType() const; // C++11 std::nullptr_t
bool isNullPtrType() const; // C++11 std::nullptr_t or
// C2x nullptr_t
bool isNothrowT() const; // C++ std::nothrow_t
bool isAlignValT() const; // C++17 std::align_val_t
bool isStdByteType() const; // C++17 std::byte
@@ -2211,6 +2273,8 @@ class alignas(8) Type : public ExtQualsTypeCommonBase {
/// Check if the type is the CUDA device builtin texture type.
bool isCUDADeviceBuiltinTextureType() const;
bool isRVVType() const;
/// Return the implicit lifetime for this type, which must not be dependent.
Qualifiers::ObjCLifetime getObjCARCImplicitLifetime() const;
@@ -2413,9 +2477,6 @@ class alignas(8) Type : public ExtQualsTypeCommonBase {
/// removing any typedefs, typeofs, etc., as well as any qualifiers.
const Type *getUnqualifiedDesugaredType() const;
/// More type predicates useful for type checking/promotion
bool isPromotableIntegerType() const; // C99 6.3.1.1p2
/// Return true if this is an integer type that is
/// signed, according to C99 6.2.5p4 [char, signed char, short, int, long..],
/// or an enum decl which has a signed representation.
@@ -2491,7 +2552,7 @@ class alignas(8) Type : public ExtQualsTypeCommonBase {
/// Note that nullability is only captured as sugar within the type
/// system, not as part of the canonical type, so nullability will
/// be lost by canonicalization and desugaring.
Optional<NullabilityKind> getNullability(const ASTContext &context) const;
std::optional<NullabilityKind> getNullability() const;
/// Determine whether the given type can have a nullability
/// specifier applied to it, i.e., if it is any kind of pointer type.
@@ -2515,7 +2576,7 @@ class alignas(8) Type : public ExtQualsTypeCommonBase {
/// the type parameters of the given declaration context in any type described
/// within that context, or an empty optional to indicate that no
/// substitution is required.
Optional<ArrayRef<QualType>>
std::optional<ArrayRef<QualType>>
getObjCSubstitutions(const DeclContext *dc) const;
/// Determines if this is an ObjC interface type that may accept type
@@ -2536,6 +2597,7 @@ class alignas(8) Type : public ExtQualsTypeCommonBase {
/// This will check for a TypedefType by removing any existing sugar
/// until it reaches a TypedefType or a non-sugared type.
template <> const TypedefType *Type::getAs() const;
template <> const UsingType *Type::getAs() const;
/// This will check for a TemplateSpecializationType by removing any
/// existing sugar until it reaches a TemplateSpecializationType or a
@@ -3873,7 +3935,10 @@ class FunctionType : public Type {
}
Qualifiers getFastTypeQuals() const {
if (isFunctionProtoType())
return Qualifiers::fromFastMask(FunctionTypeBits.FastTypeQuals);
return Qualifiers();
}
public:
@@ -4172,7 +4237,7 @@ class FunctionProtoType final
}
ArrayRef<QualType> getParamTypes() const {
return llvm::makeArrayRef(param_type_begin(), param_type_end());
return llvm::ArrayRef(param_type_begin(), param_type_end());
}
ExtProtoInfo getExtProtoInfo() const {
@@ -4317,10 +4382,9 @@ class FunctionProtoType final
}
using param_type_iterator = const QualType *;
using param_type_range = llvm::iterator_range<param_type_iterator>;
param_type_range param_types() const {
return param_type_range(param_type_begin(), param_type_end());
ArrayRef<QualType> param_types() const {
return llvm::ArrayRef(param_type_begin(), param_type_end());
}
param_type_iterator param_type_begin() const {
@@ -4334,7 +4398,7 @@ class FunctionProtoType final
using exception_iterator = const QualType *;
ArrayRef<QualType> exceptions() const {
return llvm::makeArrayRef(exception_begin(), exception_end());
return llvm::ArrayRef(exception_begin(), exception_end());
}
exception_iterator exception_begin() const {
@@ -4440,9 +4504,12 @@ class UnresolvedUsingType : public Type {
}
};
class UsingType : public Type, public llvm::FoldingSetNode {
class UsingType final : public Type,
public llvm::FoldingSetNode,
private llvm::TrailingObjects<UsingType, QualType> {
UsingShadowDecl *Found;
friend class ASTContext; // ASTContext creates these.
friend TrailingObjects;
UsingType(const UsingShadowDecl *Found, QualType Underlying, QualType Canon);
@@ -4451,21 +4518,31 @@ class UsingType : public Type, public llvm::FoldingSetNode {
QualType getUnderlyingType() const;
bool isSugared() const { return true; }
// This always has the 'same' type as declared, but not necessarily identical.
QualType desugar() const { return getUnderlyingType(); }
void Profile(llvm::FoldingSetNodeID &ID) { Profile(ID, Found); }
static void Profile(llvm::FoldingSetNodeID &ID,
const UsingShadowDecl *Found) {
// Internal helper, for debugging purposes.
bool typeMatchesDecl() const { return !UsingBits.hasTypeDifferentFromDecl; }
void Profile(llvm::FoldingSetNodeID &ID) {
Profile(ID, Found, typeMatchesDecl() ? QualType() : getUnderlyingType());
}
static void Profile(llvm::FoldingSetNodeID &ID, const UsingShadowDecl *Found,
QualType Underlying) {
ID.AddPointer(Found);
if (!Underlying.isNull())
Underlying.Profile(ID);
}
static bool classof(const Type *T) { return T->getTypeClass() == Using; }
};
class TypedefType : public Type {
class TypedefType final : public Type,
public llvm::FoldingSetNode,
private llvm::TrailingObjects<TypedefType, QualType> {
TypedefNameDecl *Decl;
private:
friend class ASTContext; // ASTContext creates these.
friend TrailingObjects;
TypedefType(TypeClass tc, const TypedefNameDecl *D, QualType underlying,
QualType can);
@@ -4474,8 +4551,23 @@ class TypedefType : public Type {
TypedefNameDecl *getDecl() const { return Decl; }
bool isSugared() const { return true; }
// This always has the 'same' type as declared, but not necessarily identical.
QualType desugar() const;
// Internal helper, for debugging purposes.
bool typeMatchesDecl() const { return !TypedefBits.hasTypeDifferentFromDecl; }
void Profile(llvm::FoldingSetNodeID &ID) {
Profile(ID, Decl, typeMatchesDecl() ? QualType() : desugar());
}
static void Profile(llvm::FoldingSetNodeID &ID, const TypedefNameDecl *Decl,
QualType Underlying) {
ID.AddPointer(Decl);
if (!Underlying.isNull())
Underlying.Profile(ID);
}
static bool classof(const Type *T) { return T->getTypeClass() == Typedef; }
};
@@ -4511,18 +4603,25 @@ class MacroQualifiedType : public Type {
}
};
/// Represents a `typeof` (or __typeof__) expression (a GCC extension).
/// Represents a `typeof` (or __typeof__) expression (a C2x feature and GCC
/// extension) or a `typeof_unqual` expression (a C2x feature).
class TypeOfExprType : public Type {
Expr *TOExpr;
protected:
friend class ASTContext; // ASTContext creates these.
TypeOfExprType(Expr *E, QualType can = QualType());
TypeOfExprType(Expr *E, TypeOfKind Kind, QualType Can = QualType());
public:
Expr *getUnderlyingExpr() const { return TOExpr; }
/// Returns the kind of 'typeof' type this is.
TypeOfKind getKind() const {
return TypeOfBits.IsUnqual ? TypeOfKind::Unqualified
: TypeOfKind::Qualified;
}
/// Remove a single level of sugar.
QualType desugar() const;
@@ -4543,37 +4642,52 @@ class DependentTypeOfExprType
const ASTContext &Context;
public:
DependentTypeOfExprType(const ASTContext &Context, Expr *E)
: TypeOfExprType(E), Context(Context) {}
DependentTypeOfExprType(const ASTContext &Context, Expr *E, TypeOfKind Kind)
: TypeOfExprType(E, Kind), Context(Context) {}
void Profile(llvm::FoldingSetNodeID &ID) {
Profile(ID, Context, getUnderlyingExpr());
Profile(ID, Context, getUnderlyingExpr(),
getKind() == TypeOfKind::Unqualified);
}
static void Profile(llvm::FoldingSetNodeID &ID, const ASTContext &Context,
Expr *E);
Expr *E, bool IsUnqual);
};
/// Represents `typeof(type)`, a GCC extension.
/// Represents `typeof(type)`, a C2x feature and GCC extension, or
/// `typeof_unqual(type), a C2x feature.
class TypeOfType : public Type {
friend class ASTContext; // ASTContext creates these.
QualType TOType;
TypeOfType(QualType T, QualType can)
: Type(TypeOf, can, T->getDependence()), TOType(T) {
assert(!isa<TypedefType>(can) && "Invalid canonical type");
TypeOfType(QualType T, QualType Can, TypeOfKind Kind)
: Type(TypeOf,
Kind == TypeOfKind::Unqualified ? Can.getAtomicUnqualifiedType()
: Can,
T->getDependence()),
TOType(T) {
TypeOfBits.IsUnqual = Kind == TypeOfKind::Unqualified;
}
public:
QualType getUnderlyingType() const { return TOType; }
QualType getUnmodifiedType() const { return TOType; }
/// Remove a single level of sugar.
QualType desugar() const { return getUnderlyingType(); }
QualType desugar() const {
QualType QT = getUnmodifiedType();
return TypeOfBits.IsUnqual ? QT.getAtomicUnqualifiedType() : QT;
}
/// Returns whether this type directly provides sugar.
bool isSugared() const { return true; }
/// Returns the kind of 'typeof' type this is.
TypeOfKind getKind() const {
return TypeOfBits.IsUnqual ? TypeOfKind::Unqualified
: TypeOfKind::Qualified;
}
static bool classof(const Type *T) { return T->getTypeClass() == TypeOf; }
};
@@ -4624,7 +4738,8 @@ class DependentDecltypeType : public DecltypeType, public llvm::FoldingSetNode {
class UnaryTransformType : public Type {
public:
enum UTTKind {
EnumUnderlyingType
#define TRANSFORM_TYPE_TRAIT_DEF(Enum, _) Enum,
#include "clang/Basic/TransformTypeTraits.def"
};
private:
@@ -4807,7 +4922,7 @@ class AttributedType : public Type, public llvm::FoldingSetNode {
bool isCallingConv() const;
llvm::Optional<NullabilityKind> getImmediateNullability() const;
std::optional<NullabilityKind> getImmediateNullability() const;
/// Retrieve the attribute kind corresponding to the given
/// nullability kind.
@@ -4837,7 +4952,7 @@ class AttributedType : public Type, public llvm::FoldingSetNode {
/// to the underlying modified type.
///
/// \returns the top-level nullability, if present.
static Optional<NullabilityKind> stripOuterNullability(QualType &T);
static std::optional<NullabilityKind> stripOuterNullability(QualType &T);
void Profile(llvm::FoldingSetNodeID &ID) {
Profile(ID, getAttrKind(), ModifiedType, EquivalentType);
@@ -4968,40 +5083,60 @@ class TemplateTypeParmType : public Type, public llvm::FoldingSetNode {
/// been replaced with these. They are used solely to record that a
/// type was originally written as a template type parameter;
/// therefore they are never canonical.
class SubstTemplateTypeParmType : public Type, public llvm::FoldingSetNode {
class SubstTemplateTypeParmType final
: public Type,
public llvm::FoldingSetNode,
private llvm::TrailingObjects<SubstTemplateTypeParmType, QualType> {
friend class ASTContext;
friend class llvm::TrailingObjects<SubstTemplateTypeParmType, QualType>;
// The original type parameter.
const TemplateTypeParmType *Replaced;
Decl *AssociatedDecl;
SubstTemplateTypeParmType(const TemplateTypeParmType *Param, QualType Canon)
: Type(SubstTemplateTypeParm, Canon, Canon->getDependence()),
Replaced(Param) {}
SubstTemplateTypeParmType(QualType Replacement, Decl *AssociatedDecl,
unsigned Index, std::optional<unsigned> PackIndex);
public:
/// Gets the template parameter that was substituted for.
const TemplateTypeParmType *getReplacedParameter() const {
return Replaced;
}
/// Gets the type that was substituted for the template
/// parameter.
QualType getReplacementType() const {
return getCanonicalTypeInternal();
return SubstTemplateTypeParmTypeBits.HasNonCanonicalUnderlyingType
? *getTrailingObjects<QualType>()
: getCanonicalTypeInternal();
}
/// A template-like entity which owns the whole pattern being substituted.
/// This will usually own a set of template parameters, or in some
/// cases might even be a template parameter itself.
Decl *getAssociatedDecl() const { return AssociatedDecl; }
/// Gets the template parameter declaration that was substituted for.
const TemplateTypeParmDecl *getReplacedParameter() const;
/// Returns the index of the replaced parameter in the associated declaration.
/// This should match the result of `getReplacedParameter()->getIndex()`.
unsigned getIndex() const { return SubstTemplateTypeParmTypeBits.Index; }
std::optional<unsigned> getPackIndex() const {
if (SubstTemplateTypeParmTypeBits.PackIndex == 0)
return std::nullopt;
return SubstTemplateTypeParmTypeBits.PackIndex - 1;
}
bool isSugared() const { return true; }
QualType desugar() const { return getReplacementType(); }
void Profile(llvm::FoldingSetNodeID &ID) {
Profile(ID, getReplacedParameter(), getReplacementType());
Profile(ID, getReplacementType(), getAssociatedDecl(), getIndex(),
getPackIndex());
}
static void Profile(llvm::FoldingSetNodeID &ID,
const TemplateTypeParmType *Replaced,
QualType Replacement) {
ID.AddPointer(Replaced);
ID.AddPointer(Replacement.getAsOpaquePtr());
static void Profile(llvm::FoldingSetNodeID &ID, QualType Replacement,
const Decl *AssociatedDecl, unsigned Index,
std::optional<unsigned> PackIndex) {
Replacement.Profile(ID);
ID.AddPointer(AssociatedDecl);
ID.AddInteger(Index);
ID.AddInteger(PackIndex ? *PackIndex - 1 : 0);
}
static bool classof(const Type *T) {
@@ -5024,24 +5159,33 @@ class SubstTemplateTypeParmType : public Type, public llvm::FoldingSetNode {
class SubstTemplateTypeParmPackType : public Type, public llvm::FoldingSetNode {
friend class ASTContext;
/// The original type parameter.
const TemplateTypeParmType *Replaced;
/// A pointer to the set of template arguments that this
/// parameter pack is instantiated with.
const TemplateArgument *Arguments;
SubstTemplateTypeParmPackType(const TemplateTypeParmType *Param,
QualType Canon,
llvm::PointerIntPair<Decl *, 1, bool> AssociatedDeclAndFinal;
SubstTemplateTypeParmPackType(QualType Canon, Decl *AssociatedDecl,
unsigned Index, bool Final,
const TemplateArgument &ArgPack);
public:
IdentifierInfo *getIdentifier() const { return Replaced->getIdentifier(); }
IdentifierInfo *getIdentifier() const;
/// Gets the template parameter that was substituted for.
const TemplateTypeParmType *getReplacedParameter() const {
return Replaced;
}
/// A template-like entity which owns the whole pattern being substituted.
/// This will usually own a set of template parameters, or in some
/// cases might even be a template parameter itself.
Decl *getAssociatedDecl() const;
/// Gets the template parameter declaration that was substituted for.
const TemplateTypeParmDecl *getReplacedParameter() const;
/// Returns the index of the replaced parameter in the associated declaration.
/// This should match the result of `getReplacedParameter()->getIndex()`.
unsigned getIndex() const { return SubstTemplateTypeParmPackTypeBits.Index; }
// When true the substitution will be 'Final' (subst node won't be placed).
bool getFinal() const;
unsigned getNumArgs() const {
return SubstTemplateTypeParmPackTypeBits.NumArgs;
@@ -5053,8 +5197,8 @@ class SubstTemplateTypeParmPackType : public Type, public llvm::FoldingSetNode {
TemplateArgument getArgumentPack() const;
void Profile(llvm::FoldingSetNodeID &ID);
static void Profile(llvm::FoldingSetNodeID &ID,
const TemplateTypeParmType *Replaced,
static void Profile(llvm::FoldingSetNodeID &ID, const Decl *AssociatedDecl,
unsigned Index, bool Final,
const TemplateArgument &ArgPack);
static bool classof(const Type *T) {
@@ -5113,29 +5257,10 @@ class alignas(8) AutoType : public DeducedType, public llvm::FoldingSetNode {
TypeDependence ExtraDependence, QualType Canon, ConceptDecl *CD,
ArrayRef<TemplateArgument> TypeConstraintArgs);
const TemplateArgument *getArgBuffer() const {
return reinterpret_cast<const TemplateArgument*>(this+1);
}
TemplateArgument *getArgBuffer() {
return reinterpret_cast<TemplateArgument*>(this+1);
}
public:
/// Retrieve the template arguments.
const TemplateArgument *getArgs() const {
return getArgBuffer();
}
/// Retrieve the number of template arguments.
unsigned getNumArgs() const {
return AutoTypeBits.NumArgs;
}
const TemplateArgument &getArg(unsigned Idx) const; // in TemplateBase.h
ArrayRef<TemplateArgument> getTypeConstraintArguments() const {
return {getArgs(), getNumArgs()};
return {reinterpret_cast<const TemplateArgument *>(this + 1),
AutoTypeBits.NumArgs};
}
ConceptDecl *getTypeConstraintConcept() const {
@@ -5158,11 +5283,7 @@ class alignas(8) AutoType : public DeducedType, public llvm::FoldingSetNode {
return (AutoTypeKeyword)AutoTypeBits.Keyword;
}
void Profile(llvm::FoldingSetNodeID &ID, const ASTContext &Context) {
Profile(ID, Context, getDeducedType(), getKeyword(), isDependentType(),
getTypeConstraintConcept(), getTypeConstraintArguments());
}
void Profile(llvm::FoldingSetNodeID &ID, const ASTContext &Context);
static void Profile(llvm::FoldingSetNodeID &ID, const ASTContext &Context,
QualType Deduced, AutoTypeKeyword Keyword,
bool IsDependent, ConceptDecl *CD,
@@ -5300,35 +5421,14 @@ class alignas(8) TemplateSpecializationType
/// Get the aliased type, if this is a specialization of a type alias
/// template.
QualType getAliasedType() const {
assert(isTypeAlias() && "not a type alias template specialization");
return *reinterpret_cast<const QualType*>(end());
}
using iterator = const TemplateArgument *;
iterator begin() const { return getArgs(); }
iterator end() const; // defined inline in TemplateBase.h
QualType getAliasedType() const;
/// Retrieve the name of the template that we are specializing.
TemplateName getTemplateName() const { return Template; }
/// Retrieve the template arguments.
const TemplateArgument *getArgs() const {
return reinterpret_cast<const TemplateArgument *>(this + 1);
}
/// Retrieve the number of template arguments.
unsigned getNumArgs() const {
return TemplateSpecializationTypeBits.NumArgs;
}
/// Retrieve a specific template argument as a type.
/// \pre \c isArgType(Arg)
const TemplateArgument &getArg(unsigned Idx) const; // in TemplateBase.h
ArrayRef<TemplateArgument> template_arguments() const {
return {getArgs(), getNumArgs()};
return {reinterpret_cast<const TemplateArgument *>(this + 1),
TemplateSpecializationTypeBits.NumArgs};
}
bool isSugared() const {
@@ -5339,12 +5439,7 @@ class alignas(8) TemplateSpecializationType
return isTypeAlias() ? getAliasedType() : getCanonicalTypeInternal();
}
void Profile(llvm::FoldingSetNodeID &ID, const ASTContext &Ctx) {
Profile(ID, Template, template_arguments(), Ctx);
if (isTypeAlias())
getAliasedType().Profile(ID);
}
void Profile(llvm::FoldingSetNodeID &ID, const ASTContext &Ctx);
static void Profile(llvm::FoldingSetNodeID &ID, TemplateName T,
ArrayRef<TemplateArgument> Args,
const ASTContext &Context);
@@ -5371,6 +5466,13 @@ void printTemplateArgumentList(raw_ostream &OS,
const PrintingPolicy &Policy,
const TemplateParameterList *TPL = nullptr);
/// Make a best-effort determination of whether the type T can be produced by
/// substituting Args into the default argument of Param.
bool isSubstitutedDefaultArgument(ASTContext &Ctx, TemplateArgument Arg,
const NamedDecl *Param,
ArrayRef<TemplateArgument> Args,
unsigned Depth);
/// The injected class name of a C++ class template or class
/// template partial specialization. Used to record that a type was
/// spelled with a bare identifier rather than as a template-id; the
@@ -5569,9 +5671,6 @@ class ElaboratedType final
ElaboratedTypeBits.HasOwnedTagDecl = true;
*getTrailingObjects<TagDecl *>() = OwnedTagDecl;
}
assert(!(Keyword == ETK_None && NNS == nullptr) &&
"ElaboratedType cannot have elaborated type keyword "
"and name qualifier both null.");
}
public:
@@ -5690,44 +5789,20 @@ class alignas(8) DependentTemplateSpecializationType
ArrayRef<TemplateArgument> Args,
QualType Canon);
const TemplateArgument *getArgBuffer() const {
return reinterpret_cast<const TemplateArgument*>(this+1);
}
TemplateArgument *getArgBuffer() {
return reinterpret_cast<TemplateArgument*>(this+1);
}
public:
NestedNameSpecifier *getQualifier() const { return NNS; }
const IdentifierInfo *getIdentifier() const { return Name; }
/// Retrieve the template arguments.
const TemplateArgument *getArgs() const {
return getArgBuffer();
}
/// Retrieve the number of template arguments.
unsigned getNumArgs() const {
return DependentTemplateSpecializationTypeBits.NumArgs;
}
const TemplateArgument &getArg(unsigned Idx) const; // in TemplateBase.h
ArrayRef<TemplateArgument> template_arguments() const {
return {getArgs(), getNumArgs()};
return {reinterpret_cast<const TemplateArgument *>(this + 1),
DependentTemplateSpecializationTypeBits.NumArgs};
}
using iterator = const TemplateArgument *;
iterator begin() const { return getArgs(); }
iterator end() const; // inline in TemplateBase.h
bool isSugared() const { return false; }
QualType desugar() const { return QualType(this, 0); }
void Profile(llvm::FoldingSetNodeID &ID, const ASTContext &Context) {
Profile(ID, Context, getKeyword(), NNS, Name, {getArgs(), getNumArgs()});
Profile(ID, Context, getKeyword(), NNS, Name, template_arguments());
}
static void Profile(llvm::FoldingSetNodeID &ID,
@@ -5771,7 +5846,7 @@ class PackExpansionType : public Type, public llvm::FoldingSetNode {
QualType Pattern;
PackExpansionType(QualType Pattern, QualType Canon,
Optional<unsigned> NumExpansions)
std::optional<unsigned> NumExpansions)
: Type(PackExpansion, Canon,
(Pattern->getDependence() | TypeDependence::Dependent |
TypeDependence::Instantiation) &
@@ -5789,10 +5864,10 @@ class PackExpansionType : public Type, public llvm::FoldingSetNode {
/// Retrieve the number of expansions that this pack expansion will
/// generate, if known.
Optional<unsigned> getNumExpansions() const {
std::optional<unsigned> getNumExpansions() const {
if (PackExpansionTypeBits.NumExpansions)
return PackExpansionTypeBits.NumExpansions - 1;
return None;
return std::nullopt;
}
bool isSugared() const { return false; }
@@ -5803,7 +5878,7 @@ class PackExpansionType : public Type, public llvm::FoldingSetNode {
}
static void Profile(llvm::FoldingSetNodeID &ID, QualType Pattern,
Optional<unsigned> NumExpansions) {
std::optional<unsigned> NumExpansions) {
ID.AddPointer(Pattern.getAsOpaquePtr());
ID.AddBoolean(NumExpansions.has_value());
if (NumExpansions)
@@ -6060,8 +6135,7 @@ class ObjCObjectType : public Type,
/// Retrieve the type arguments of this object type as they were
/// written.
ArrayRef<QualType> getTypeArgsAsWritten() const {
return llvm::makeArrayRef(getTypeArgStorage(),
ObjCObjectTypeBits.NumTypeArgs);
return llvm::ArrayRef(getTypeArgStorage(), ObjCObjectTypeBits.NumTypeArgs);
}
/// Whether this is a "__kindof" type as written.
@@ -6564,6 +6638,19 @@ inline const Type *QualType::getTypePtrOrNull() const {
return (isNull() ? nullptr : getCommonPtr()->BaseType);
}
inline bool QualType::isReferenceable() const {
// C++ [defns.referenceable]
// type that is either an object type, a function type that does not have
// cv-qualifiers or a ref-qualifier, or a reference type.
const Type &Self = **this;
if (Self.isObjectType() || Self.isReferenceType())
return true;
if (const auto *F = Self.getAs<FunctionProtoType>())
return F->getMethodQuals().empty() && F->getRefQualifier() == RQ_None;
return false;
}
inline SplitQualType QualType::split() const {
if (!hasLocalNonFastQualifiers())
return SplitQualType(getTypePtrUnsafe(),
@@ -7058,6 +7145,14 @@ inline bool Type::isOpenCLSpecificType() const {
isQueueT() || isReserveIDT() || isPipeType() || isOCLExtOpaqueType();
}
inline bool Type::isRVVType() const {
#define RVV_TYPE(Name, Id, SingletonId) \
isSpecificBuiltinType(BuiltinType::Id) ||
return
#include "clang/Basic/RISCVVTypes.def"
false; // end of boolean or operation.
}
inline bool Type::isTemplateTypeParmType() const {
return isa<TemplateTypeParmType>(CanonicalType);
}
@@ -814,7 +814,7 @@ class ObjCTypeParamTypeLoc : public ConcreteTypeLoc<UnqualTypeLoc,
}
ArrayRef<SourceLocation> getProtocolLocs() const {
return llvm::makeArrayRef(getProtocolLocArray(), getNumProtocols());
return llvm::ArrayRef(getProtocolLocArray(), getNumProtocols());
}
void initializeLocal(ASTContext &Context, SourceLocation Loc);
@@ -1020,7 +1020,7 @@ class ObjCObjectTypeLoc : public ConcreteTypeLoc<UnqualTypeLoc,
ArrayRef<SourceLocation> getProtocolLocs() const {
return llvm::makeArrayRef(getProtocolLocArray(), getNumProtocols());
return llvm::ArrayRef(getProtocolLocArray(), getNumProtocols());
}
bool hasBaseTypeAsWritten() const {
@@ -1447,7 +1447,7 @@ class FunctionTypeLoc : public ConcreteTypeLoc<UnqualTypeLoc,
}
ArrayRef<ParmVarDecl *> getParams() const {
return llvm::makeArrayRef(getParmArray(), getNumParams());
return llvm::ArrayRef(getParmArray(), getNumParams());
}
// ParmVarDecls* are stored after Info, one for each parameter.
@@ -1634,7 +1634,7 @@ class TemplateSpecializationTypeLoc :
}
unsigned getNumArgs() const {
return getTypePtr()->getNumArgs();
return getTypePtr()->template_arguments().size();
}
void setArgLocInfo(unsigned i, TemplateArgumentLocInfo AI) {
@@ -1646,7 +1646,8 @@ class TemplateSpecializationTypeLoc :
}
TemplateArgumentLoc getArgLoc(unsigned i) const {
return TemplateArgumentLoc(getTypePtr()->getArg(i), getArgLocInfo(i));
return TemplateArgumentLoc(getTypePtr()->template_arguments()[i],
getArgLocInfo(i));
}
SourceLocation getTemplateNameLoc() const {
@@ -1681,12 +1682,12 @@ class TemplateSpecializationTypeLoc :
setTemplateNameLoc(Loc);
setLAngleLoc(Loc);
setRAngleLoc(Loc);
initializeArgLocs(Context, getNumArgs(), getTypePtr()->getArgs(),
initializeArgLocs(Context, getTypePtr()->template_arguments(),
getArgInfos(), Loc);
}
static void initializeArgLocs(ASTContext &Context, unsigned NumArgs,
const TemplateArgument *Args,
static void initializeArgLocs(ASTContext &Context,
ArrayRef<TemplateArgument> Args,
TemplateArgumentLocInfo *ArgInfos,
SourceLocation Loc);
@@ -1934,7 +1935,7 @@ struct TypeOfExprTypeLocInfo : public TypeofLocInfo {
};
struct TypeOfTypeLocInfo : public TypeofLocInfo {
TypeSourceInfo* UnderlyingTInfo;
TypeSourceInfo *UnmodifiedTInfo;
};
template <class Derived, class TypeClass, class LocalData = TypeofLocInfo>
@@ -2002,16 +2003,16 @@ class TypeOfExprTypeLoc : public TypeofLikeTypeLoc<TypeOfExprTypeLoc,
class TypeOfTypeLoc
: public TypeofLikeTypeLoc<TypeOfTypeLoc, TypeOfType, TypeOfTypeLocInfo> {
public:
QualType getUnderlyingType() const {
return this->getTypePtr()->getUnderlyingType();
QualType getUnmodifiedType() const {
return this->getTypePtr()->getUnmodifiedType();
}
TypeSourceInfo* getUnderlyingTInfo() const {
return this->getLocalData()->UnderlyingTInfo;
TypeSourceInfo *getUnmodifiedTInfo() const {
return this->getLocalData()->UnmodifiedTInfo;
}
void setUnderlyingTInfo(TypeSourceInfo* TI) const {
this->getLocalData()->UnderlyingTInfo = TI;
void setUnmodifiedTInfo(TypeSourceInfo *TI) const {
this->getLocalData()->UnmodifiedTInfo = TI;
}
void initializeLocal(ASTContext &Context, SourceLocation Loc);
@@ -2188,7 +2189,7 @@ class AutoTypeLoc
}
unsigned getNumArgs() const {
return getTypePtr()->getNumArgs();
return getTypePtr()->getTypeConstraintArguments().size();
}
void setArgLocInfo(unsigned i, TemplateArgumentLocInfo AI) {
@@ -2263,22 +2264,31 @@ class ElaboratedTypeLoc : public ConcreteTypeLoc<UnqualTypeLoc,
ElaboratedLocInfo> {
public:
SourceLocation getElaboratedKeywordLoc() const {
return this->getLocalData()->ElaboratedKWLoc;
return !isEmpty() ? getLocalData()->ElaboratedKWLoc : SourceLocation();
}
void setElaboratedKeywordLoc(SourceLocation Loc) {
this->getLocalData()->ElaboratedKWLoc = Loc;
if (isEmpty()) {
assert(Loc.isInvalid());
return;
}
getLocalData()->ElaboratedKWLoc = Loc;
}
NestedNameSpecifierLoc getQualifierLoc() const {
return NestedNameSpecifierLoc(getTypePtr()->getQualifier(),
getLocalData()->QualifierData);
return !isEmpty() ? NestedNameSpecifierLoc(getTypePtr()->getQualifier(),
getLocalData()->QualifierData)
: NestedNameSpecifierLoc();
}
void setQualifierLoc(NestedNameSpecifierLoc QualifierLoc) {
assert(QualifierLoc.getNestedNameSpecifier()
== getTypePtr()->getQualifier() &&
assert(QualifierLoc.getNestedNameSpecifier() ==
getTypePtr()->getQualifier() &&
"Inconsistent nested-name-specifier pointer");
if (isEmpty()) {
assert(!QualifierLoc.hasQualifier());
return;
}
getLocalData()->QualifierData = QualifierLoc.getOpaqueData();
}
@@ -2295,12 +2305,24 @@ class ElaboratedTypeLoc : public ConcreteTypeLoc<UnqualTypeLoc,
void initializeLocal(ASTContext &Context, SourceLocation Loc);
TypeLoc getNamedTypeLoc() const {
return getInnerTypeLoc();
TypeLoc getNamedTypeLoc() const { return getInnerTypeLoc(); }
QualType getInnerType() const { return getTypePtr()->getNamedType(); }
bool isEmpty() const {
return getTypePtr()->getKeyword() == ElaboratedTypeKeyword::ETK_None &&
!getTypePtr()->getQualifier();
}
QualType getInnerType() const {
return getTypePtr()->getNamedType();
unsigned getLocalDataAlignment() const {
// FIXME: We want to return 1 here in the empty case, but
// there are bugs in how alignment is handled in TypeLocs
// that prevent this from working.
return ConcreteTypeLoc::getLocalDataAlignment();
}
unsigned getLocalDataSize() const {
return !isEmpty() ? ConcreteTypeLoc::getLocalDataSize() : 0;
}
void copy(ElaboratedTypeLoc Loc) {
@@ -2443,7 +2465,7 @@ class DependentTemplateSpecializationTypeLoc :
}
unsigned getNumArgs() const {
return getTypePtr()->getNumArgs();
return getTypePtr()->template_arguments().size();
}
void setArgLocInfo(unsigned i, TemplateArgumentLocInfo AI) {
@@ -2455,7 +2477,8 @@ class DependentTemplateSpecializationTypeLoc :
}
TemplateArgumentLoc getArgLoc(unsigned i) const {
return TemplateArgumentLoc(getTypePtr()->getArg(i), getArgLocInfo(i));
return TemplateArgumentLoc(getTypePtr()->template_arguments()[i],
getArgLocInfo(i));
}
SourceRange getLocalSourceRange() const {
@@ -379,16 +379,12 @@ let Class = TypedefType in {
def : Property<"declaration", DeclRef> {
let Read = [{ node->getDecl() }];
}
def : Property<"canonicalType", Optional<QualType>> {
let Read = [{ makeOptionalFromNullable(node->getCanonicalTypeInternal()) }];
def : Property<"underlyingType", QualType> {
let Read = [{ node->desugar() }];
}
def : Creator<[{
QualType finalCanonicalType =
canonicalType ? ctx.getCanonicalType(*canonicalType)
: QualType();
return ctx.getTypedefType(cast<TypedefNameDecl>(declaration),
finalCanonicalType);
return ctx.getTypedefType(cast<TypedefNameDecl>(declaration), underlyingType);
}]>;
}
@@ -397,18 +393,26 @@ let Class = TypeOfExprType in {
let Read = [{ node->getUnderlyingExpr() }];
}
def : Property<"kind", TypeOfKind> {
let Read = [{ node->getKind() }];
}
def : Creator<[{
return ctx.getTypeOfExprType(expression);
return ctx.getTypeOfExprType(expression, kind);
}]>;
}
let Class = TypeOfType in {
def : Property<"underlyingType", QualType> {
let Read = [{ node->getUnderlyingType() }];
def : Property<"unmodifiedType", QualType> {
let Read = [{ node->getUnmodifiedType() }];
}
def : Property<"kind", TypeOfKind> {
let Read = [{ node->getKind() }];
}
def : Creator<[{
return ctx.getTypeOfType(underlyingType);
return ctx.getTypeOfType(unmodifiedType, kind);
}]>;
}
@@ -662,10 +666,10 @@ let Class = TemplateSpecializationType in {
def : Property<"underlyingType", Optional<QualType>> {
let Read = [{
node->isTypeAlias()
? llvm::Optional<QualType>(node->getAliasedType())
? std::optional<QualType>(node->getAliasedType())
: node->isCanonicalUnqualified()
? llvm::None
: llvm::Optional<QualType>(node->getCanonicalTypeInternal())
? std::nullopt
: std::optional<QualType>(node->getCanonicalTypeInternal())
}];
}
@@ -728,18 +732,23 @@ let Class = TemplateTypeParmType in {
}
let Class = SubstTemplateTypeParmType in {
def : Property<"replacedParameter", QualType> {
let Read = [{ QualType(node->getReplacedParameter(), 0) }];
}
def : Property<"replacementType", QualType> {
let Read = [{ node->getReplacementType() }];
}
def : Property<"associatedDecl", DeclRef> {
let Read = [{ node->getAssociatedDecl() }];
}
def : Property<"Index", UInt32> {
let Read = [{ node->getIndex() }];
}
def : Property<"PackIndex", Optional<UInt32>> {
let Read = [{ node->getPackIndex() }];
}
def : Creator<[{
// The call to getCanonicalType here existed in ASTReader.cpp, too.
def : Creator<[{
return ctx.getSubstTemplateTypeParmType(
cast<TemplateTypeParmType>(replacedParameter),
ctx.getCanonicalType(replacementType));
replacementType, associatedDecl, Index, PackIndex);
}]>;
}
@@ -758,8 +767,14 @@ let Class = PackExpansionType in {
}
let Class = SubstTemplateTypeParmPackType in {
def : Property<"replacedParameter", QualType> {
let Read = [{ QualType(node->getReplacedParameter(), 0) }];
def : Property<"associatedDecl", DeclRef> {
let Read = [{ node->getAssociatedDecl() }];
}
def : Property<"Index", UInt32> {
let Read = [{ node->getIndex() }];
}
def : Property<"Final", Bool> {
let Read = [{ node->getFinal() }];
}
def : Property<"replacementPack", TemplateArgument> {
let Read = [{ node->getArgumentPack() }];
@@ -767,8 +782,7 @@ let Class = SubstTemplateTypeParmPackType in {
def : Creator<[{
return ctx.getSubstTemplateTypeParmPackType(
cast<TemplateTypeParmType>(replacedParameter),
replacementPack);
associatedDecl, Index, Final, replacementPack);
}]>;
}
@@ -820,8 +834,8 @@ let Class = DependentNameType in {
def : Property<"underlyingType", Optional<QualType>> {
let Read = [{
node->isCanonicalUnqualified()
? llvm::None
: llvm::Optional<QualType>(node->getCanonicalTypeInternal())
? std::nullopt
: std::optional<QualType>(node->getCanonicalTypeInternal())
}];
}
@@ -44,6 +44,7 @@
#include "llvm/ADT/SmallPtrSet.h"
#include "llvm/ADT/StringMap.h"
#include "llvm/Support/Timer.h"
#include <optional>
namespace clang {
@@ -115,7 +116,7 @@ class MatchFinder {
/// the result nodes. This API is temporary to facilitate
/// third parties porting existing code to the default
/// behavior of clang-tidy.
virtual llvm::Optional<TraversalKind> getCheckTraversalKind() const;
virtual std::optional<TraversalKind> getCheckTraversalKind() const;
};
/// Called when parsing is finished. Intended for testing only.
@@ -137,7 +138,7 @@ class MatchFinder {
/// Enables per-check timers.
///
/// It prints a report after match.
llvm::Optional<Profiling> CheckProfiling;
std::optional<Profiling> CheckProfiling;
};
MatchFinder(MatchFinderOptions Options = MatchFinderOptions());
@@ -289,8 +290,8 @@ class CollectMatchesCallback : public MatchFinder::MatchCallback {
Nodes.push_back(Result.Nodes);
}
llvm::Optional<TraversalKind> getCheckTraversalKind() const override {
return llvm::None;
std::optional<TraversalKind> getCheckTraversalKind() const override {
return std::nullopt;
}
SmallVector<BoundNodes, 1> Nodes;
@@ -90,6 +90,7 @@
#include <cstddef>
#include <iterator>
#include <limits>
#include <optional>
#include <string>
#include <utility>
#include <vector>
@@ -317,10 +318,10 @@ AST_POLYMORPHIC_MATCHER_P(isExpandedFromMacro,
// Verifies that the statement' beginning and ending are both expanded from
// the same instance of the given macro.
auto& Context = Finder->getASTContext();
llvm::Optional<SourceLocation> B =
std::optional<SourceLocation> B =
internal::getExpansionLocOfMacro(MacroName, Node.getBeginLoc(), Context);
if (!B) return false;
llvm::Optional<SourceLocation> E =
std::optional<SourceLocation> E =
internal::getExpansionLocOfMacro(MacroName, Node.getEndLoc(), Context);
if (!E) return false;
return *B == *E;
@@ -1101,9 +1102,9 @@ AST_POLYMORPHIC_MATCHER_P(
/// template<typename T> struct A {};
/// A<X> a;
/// \endcode
/// classTemplateSpecializationDecl(hasAnyTemplateArgument(
/// refersToType(class(hasName("X")))))
/// matches the specialization \c A<X>
/// classTemplateSpecializationDecl(hasAnyTemplateArgument(refersToType(
/// recordType(hasDeclaration(recordDecl(hasName("X")))))))
/// matches the specialization of \c struct A generated by \c A<X>.
AST_MATCHER_P(TemplateArgument, refersToType,
internal::Matcher<QualType>, InnerMatcher) {
if (Node.getKind() != TemplateArgument::Type)
@@ -3954,14 +3955,14 @@ AST_POLYMORPHIC_MATCHER_P_OVERLOAD(
///
/// \code
/// auto x = int(3);
/// \code
/// \endcode
/// cxxTemporaryObjectExpr(hasTypeLoc(loc(asString("int"))))
/// matches int(3)
///
/// \code
/// struct Foo { Foo(int, int); };
/// auto x = Foo(1, 2);
/// \code
/// \endcode
/// cxxFunctionalCastExpr(hasTypeLoc(loc(asString("struct Foo"))))
/// matches Foo(1, 2)
///
@@ -4175,7 +4176,7 @@ AST_MATCHER_P(DeclRefExpr, to, internal::Matcher<Decl>,
/// namespace a { class X{}; }
/// using a::X;
/// X x;
/// \code
/// \endcode
/// typeLoc(loc(usingType(throughUsingDecl(anything()))))
/// matches \c X
///
@@ -4722,7 +4723,7 @@ AST_MATCHER_P(LambdaExpr, hasAnyCapture, internal::Matcher<LambdaCapture>,
/// In the matcher
/// lambdaExpr(hasAnyCapture(lambdaCapture(capturesVar(hasName("x")))),
/// capturesVar(hasName("x")) matches `x` and `x = 1`.
AST_MATCHER_P(LambdaCapture, capturesVar, internal::Matcher<VarDecl>,
AST_MATCHER_P(LambdaCapture, capturesVar, internal::Matcher<ValueDecl>,
InnerMatcher) {
auto *capturedVar = Node.getCapturedVar();
return capturedVar && InnerMatcher.matches(*capturedVar, Finder, Builder);
@@ -5459,16 +5460,15 @@ AST_MATCHER_P(ArraySubscriptExpr, hasBase,
return false;
}
/// Matches a 'for', 'while', 'do while' statement or a function
/// definition that has a given body. Note that in case of functions
/// this matcher only matches the definition itself and not the other
/// declarations of the same function.
/// Matches a 'for', 'while', 'do' statement or a function definition that has
/// a given body. Note that in case of functions this matcher only matches the
/// definition itself and not the other declarations of the same function.
///
/// Given
/// \code
/// for (;;) {}
/// \endcode
/// hasBody(compoundStmt())
/// forStmt(hasBody(compoundStmt()))
/// matches 'for (;;) {}'
/// with compoundStmt()
/// matching '{}'
@@ -5478,12 +5478,11 @@ AST_MATCHER_P(ArraySubscriptExpr, hasBase,
/// void f();
/// void f() {}
/// \endcode
/// hasBody(functionDecl())
/// functionDecl(hasBody(compoundStmt()))
/// matches 'void f() {}'
/// with compoundStmt()
/// matching '{}'
/// but does not match 'void f();'
AST_POLYMORPHIC_MATCHER_P(hasBody,
AST_POLYMORPHIC_SUPPORTED_TYPES(DoStmt, ForStmt,
WhileStmt,
@@ -5630,7 +5629,7 @@ AST_POLYMORPHIC_MATCHER_P(
AST_POLYMORPHIC_SUPPORTED_TYPES(BinaryOperator, CXXOperatorCallExpr,
CXXRewrittenBinaryOperator, UnaryOperator),
std::string, Name) {
if (Optional<StringRef> OpName = internal::getOpName(Node))
if (std::optional<StringRef> OpName = internal::getOpName(Node))
return *OpName == Name;
return false;
}
@@ -5824,8 +5823,6 @@ AST_MATCHER_P(ExplicitCastExpr, hasDestinationType,
/// Matches implicit casts whose destination type matches a given
/// matcher.
///
/// FIXME: Unit test this matcher
AST_MATCHER_P(ImplicitCastExpr, hasImplicitDestinationType,
internal::Matcher<QualType>, InnerMatcher) {
return InnerMatcher.matches(Node.getType(), Finder, Builder);
@@ -7813,6 +7810,30 @@ AST_MATCHER(NamespaceDecl, isAnonymous) {
/// cxxRecordDecl(hasName("vector"), isInStdNamespace()) will match only #1.
AST_MATCHER(Decl, isInStdNamespace) { return Node.isInStdNamespace(); }
/// Matches declarations in an anonymous namespace.
///
/// Given
/// \code
/// class vector {};
/// namespace foo {
/// class vector {};
/// namespace {
/// class vector {}; // #1
/// }
/// }
/// namespace {
/// class vector {}; // #2
/// namespace foo {
/// class vector{}; // #3
/// }
/// }
/// \endcode
/// cxxRecordDecl(hasName("vector"), isInAnonymousNamespace()) will match
/// #1, #2 and #3.
AST_MATCHER(Decl, isInAnonymousNamespace) {
return Node.isInAnonymousNamespace();
}
/// If the given case statement does not use the GNU case range
/// extension, matches the constant given in the statement.
///
@@ -52,8 +52,6 @@
#include "llvm/ADT/APFloat.h"
#include "llvm/ADT/ArrayRef.h"
#include "llvm/ADT/IntrusiveRefCntPtr.h"
#include "llvm/ADT/None.h"
#include "llvm/ADT/Optional.h"
#include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/ADT/StringRef.h"
@@ -67,6 +65,7 @@
#include <cstdint>
#include <map>
#include <memory>
#include <optional>
#include <string>
#include <tuple>
#include <type_traits>
@@ -122,7 +121,7 @@ template <typename T> struct TypeListContainsSuperOf<EmptyTypeList, T> {
template <typename ResultT, typename ArgT,
ResultT (*Func)(ArrayRef<const ArgT *>)>
struct VariadicFunction {
ResultT operator()() const { return Func(None); }
ResultT operator()() const { return Func(std::nullopt); }
template <typename... ArgsT>
ResultT operator()(const ArgT &Arg1, const ArgsT &... Args) const {
@@ -351,8 +350,8 @@ class DynMatcherInterface
virtual bool dynMatches(const DynTypedNode &DynNode, ASTMatchFinder *Finder,
BoundNodesTreeBuilder *Builder) const = 0;
virtual llvm::Optional<clang::TraversalKind> TraversalKind() const {
return llvm::None;
virtual std::optional<clang::TraversalKind> TraversalKind() const {
return std::nullopt;
}
};
@@ -464,7 +463,7 @@ class DynTypedMatcher {
/// restricts the node types for \p Kind.
DynTypedMatcher dynCastTo(const ASTNodeKind Kind) const;
/// Return a matcher that that points to the same implementation, but sets the
/// Return a matcher that points to the same implementation, but sets the
/// traversal kind.
///
/// If the traversal kind is already set, then \c TK overrides it.
@@ -483,8 +482,8 @@ class DynTypedMatcher {
/// Bind the specified \p ID to the matcher.
/// \return A new matcher with the \p ID bound to it if this matcher supports
/// binding. Otherwise, returns an empty \c Optional<>.
llvm::Optional<DynTypedMatcher> tryBind(StringRef ID) const;
/// binding. Otherwise, returns an empty \c std::optional<>.
std::optional<DynTypedMatcher> tryBind(StringRef ID) const;
/// Returns a unique \p ID for the matcher.
///
@@ -536,8 +535,8 @@ class DynTypedMatcher {
/// Returns the \c TraversalKind respected by calls to `match()`, if any.
///
/// Most matchers will not have a traversal kind set, instead relying on the
/// surrounding context. For those, \c llvm::None is returned.
llvm::Optional<clang::TraversalKind> getTraversalKind() const {
/// surrounding context. For those, \c std::nullopt is returned.
std::optional<clang::TraversalKind> getTraversalKind() const {
return Implementation->TraversalKind();
}
@@ -649,7 +648,7 @@ class Matcher {
Builder);
}
llvm::Optional<clang::TraversalKind> TraversalKind() const override {
std::optional<clang::TraversalKind> TraversalKind() const override {
return this->InnerMatcher.getTraversalKind();
}
};
@@ -1396,20 +1395,6 @@ struct VariadicOperatorMatcherFunc {
}
};
template <typename F, typename Tuple, std::size_t... I>
constexpr auto applyMatcherImpl(F &&f, Tuple &&args,
std::index_sequence<I...>) {
return std::forward<F>(f)(std::get<I>(std::forward<Tuple>(args))...);
}
template <typename F, typename Tuple>
constexpr auto applyMatcher(F &&f, Tuple &&args) {
return applyMatcherImpl(
std::forward<F>(f), std::forward<Tuple>(args),
std::make_index_sequence<
std::tuple_size<typename std::decay<Tuple>::type>::value>());
}
template <typename T, bool IsBaseOf, typename Head, typename Tail>
struct GetCladeImpl {
using Type = Head;
@@ -1428,12 +1413,11 @@ struct MapAnyOfMatcherImpl {
template <typename... InnerMatchers>
BindableMatcher<CladeType>
operator()(InnerMatchers &&... InnerMatcher) const {
// TODO: Use std::apply from c++17
return VariadicAllOfMatcher<CladeType>()(applyMatcher(
return VariadicAllOfMatcher<CladeType>()(std::apply(
internal::VariadicOperatorMatcherFunc<
0, std::numeric_limits<unsigned>::max()>{
internal::DynTypedMatcher::VO_AnyOf},
applyMatcher(
std::apply(
[&](auto... Matcher) {
return std::make_tuple(Matcher(InnerMatcher...)...);
},
@@ -1531,7 +1515,7 @@ template <typename T> class TraversalMatcher : public MatcherInterface<T> {
Builder);
}
llvm::Optional<clang::TraversalKind> TraversalKind() const override {
std::optional<clang::TraversalKind> TraversalKind() const override {
if (auto NestedKind = this->InnerMatcher.getTraversalKind())
return NestedKind;
return Traversal;
@@ -1957,7 +1941,7 @@ getTemplateSpecializationArgs(const ClassTemplateSpecializationDecl &D) {
inline ArrayRef<TemplateArgument>
getTemplateSpecializationArgs(const TemplateSpecializationType &T) {
return llvm::makeArrayRef(T.getArgs(), T.getNumArgs());
return T.template_arguments();
}
inline ArrayRef<TemplateArgument>
@@ -1981,27 +1965,27 @@ template <typename Ty, typename Enable = void> struct GetBodyMatcher {
};
template <typename Ty>
struct GetBodyMatcher<Ty, typename std::enable_if<
std::is_base_of<FunctionDecl, Ty>::value>::type> {
struct GetBodyMatcher<
Ty, std::enable_if_t<std::is_base_of<FunctionDecl, Ty>::value>> {
static const Stmt *get(const Ty &Node) {
return Node.doesThisDeclarationHaveABody() ? Node.getBody() : nullptr;
}
};
template <typename NodeType>
inline Optional<BinaryOperatorKind>
inline std::optional<BinaryOperatorKind>
equivalentBinaryOperator(const NodeType &Node) {
return Node.getOpcode();
}
template <>
inline Optional<BinaryOperatorKind>
inline std::optional<BinaryOperatorKind>
equivalentBinaryOperator<CXXOperatorCallExpr>(const CXXOperatorCallExpr &Node) {
if (Node.getNumArgs() != 2)
return None;
return std::nullopt;
switch (Node.getOperator()) {
default:
return None;
return std::nullopt;
case OO_ArrowStar:
return BO_PtrMemI;
case OO_Star:
@@ -2070,20 +2054,20 @@ equivalentBinaryOperator<CXXOperatorCallExpr>(const CXXOperatorCallExpr &Node) {
}
template <typename NodeType>
inline Optional<UnaryOperatorKind>
inline std::optional<UnaryOperatorKind>
equivalentUnaryOperator(const NodeType &Node) {
return Node.getOpcode();
}
template <>
inline Optional<UnaryOperatorKind>
inline std::optional<UnaryOperatorKind>
equivalentUnaryOperator<CXXOperatorCallExpr>(const CXXOperatorCallExpr &Node) {
if (Node.getNumArgs() != 1 && Node.getOperator() != OO_PlusPlus &&
Node.getOperator() != OO_MinusMinus)
return None;
return std::nullopt;
switch (Node.getOperator()) {
default:
return None;
return std::nullopt;
case OO_Plus:
return UO_Plus;
case OO_Minus:
@@ -2099,13 +2083,13 @@ equivalentUnaryOperator<CXXOperatorCallExpr>(const CXXOperatorCallExpr &Node) {
case OO_PlusPlus: {
const auto *FD = Node.getDirectCallee();
if (!FD)
return None;
return std::nullopt;
return FD->getNumParams() > 0 ? UO_PostInc : UO_PreInc;
}
case OO_MinusMinus: {
const auto *FD = Node.getDirectCallee();
if (!FD)
return None;
return std::nullopt;
return FD->getNumParams() > 0 ? UO_PostDec : UO_PreDec;
}
case OO_Coawait:
@@ -2188,25 +2172,25 @@ CompoundStmtMatcher<StmtExpr>::get(const StmtExpr &Node) {
/// location (in the chain of expansions) at which \p MacroName was
/// expanded. Since the macro may have been expanded inside a series of
/// expansions, that location may itself be a MacroID.
llvm::Optional<SourceLocation>
getExpansionLocOfMacro(StringRef MacroName, SourceLocation Loc,
std::optional<SourceLocation> getExpansionLocOfMacro(StringRef MacroName,
SourceLocation Loc,
const ASTContext &Context);
inline Optional<StringRef> getOpName(const UnaryOperator &Node) {
inline std::optional<StringRef> getOpName(const UnaryOperator &Node) {
return Node.getOpcodeStr(Node.getOpcode());
}
inline Optional<StringRef> getOpName(const BinaryOperator &Node) {
inline std::optional<StringRef> getOpName(const BinaryOperator &Node) {
return Node.getOpcodeStr();
}
inline StringRef getOpName(const CXXRewrittenBinaryOperator &Node) {
return Node.getOpcodeStr();
}
inline Optional<StringRef> getOpName(const CXXOperatorCallExpr &Node) {
inline std::optional<StringRef> getOpName(const CXXOperatorCallExpr &Node) {
auto optBinaryOpcode = equivalentBinaryOperator(Node);
if (!optBinaryOpcode) {
auto optUnaryOpcode = equivalentUnaryOperator(Node);
if (!optUnaryOpcode)
return None;
return std::nullopt;
return UnaryOperator::getOpcodeStr(*optUnaryOpcode);
}
return BinaryOperator::getOpcodeStr(*optBinaryOpcode);
@@ -2232,26 +2216,26 @@ class HasAnyOperatorNameMatcher : public SingleNodeMatcherInterface<T> {
: SingleNodeMatcherInterface<T>(), Names(std::move(Names)) {}
bool matchesNode(const T &Node) const override {
Optional<StringRef> OptOpName = getOpName(Node);
std::optional<StringRef> OptOpName = getOpName(Node);
return OptOpName && llvm::is_contained(Names, *OptOpName);
}
private:
static Optional<StringRef> getOpName(const UnaryOperator &Node) {
static std::optional<StringRef> getOpName(const UnaryOperator &Node) {
return Node.getOpcodeStr(Node.getOpcode());
}
static Optional<StringRef> getOpName(const BinaryOperator &Node) {
static std::optional<StringRef> getOpName(const BinaryOperator &Node) {
return Node.getOpcodeStr();
}
static StringRef getOpName(const CXXRewrittenBinaryOperator &Node) {
return Node.getOpcodeStr();
}
static Optional<StringRef> getOpName(const CXXOperatorCallExpr &Node) {
static std::optional<StringRef> getOpName(const CXXOperatorCallExpr &Node) {
auto optBinaryOpcode = equivalentBinaryOperator(Node);
if (!optBinaryOpcode) {
auto optUnaryOpcode = equivalentUnaryOperator(Node);
if (!optUnaryOpcode)
return None;
return std::nullopt;
return UnaryOperator::getOpcodeStr(*optUnaryOpcode);
}
return BinaryOperator::getOpcodeStr(*optBinaryOpcode);
@@ -39,9 +39,9 @@
#include "clang/ASTMatchers/Dynamic/Registry.h"
#include "clang/ASTMatchers/Dynamic/VariantValue.h"
#include "llvm/ADT/ArrayRef.h"
#include "llvm/ADT/Optional.h"
#include "llvm/ADT/StringMap.h"
#include "llvm/ADT/StringRef.h"
#include <optional>
#include <utility>
#include <vector>
@@ -95,9 +95,9 @@ class Parser {
///
/// \param MatcherName The matcher name found by the parser.
///
/// \return The matcher constructor, or Optional<MatcherCtor>() if not
/// \return The matcher constructor, or std::optional<MatcherCtor>() if not
/// found.
virtual llvm::Optional<MatcherCtor>
virtual std::optional<MatcherCtor>
lookupMatcherCtor(StringRef MatcherName) = 0;
virtual bool isBuilderMatcher(MatcherCtor) const = 0;
@@ -138,7 +138,7 @@ class Parser {
public:
~RegistrySema() override;
llvm::Optional<MatcherCtor>
std::optional<MatcherCtor>
lookupMatcherCtor(StringRef MatcherName) override;
VariantMatcher actOnMatcherExpression(MatcherCtor Ctor,
@@ -180,14 +180,14 @@ class Parser {
/// Optional if an error occurred. In that case, \c Error will contain a
/// description of the error.
/// The caller takes ownership of the DynTypedMatcher object returned.
static llvm::Optional<DynTypedMatcher>
static std::optional<DynTypedMatcher>
parseMatcherExpression(StringRef &MatcherCode, Sema *S,
const NamedValueMap *NamedValues, Diagnostics *Error);
static llvm::Optional<DynTypedMatcher>
static std::optional<DynTypedMatcher>
parseMatcherExpression(StringRef &MatcherCode, Sema *S, Diagnostics *Error) {
return parseMatcherExpression(MatcherCode, S, nullptr, Error);
}
static llvm::Optional<DynTypedMatcher>
static std::optional<DynTypedMatcher>
parseMatcherExpression(StringRef &MatcherCode, Diagnostics *Error) {
return parseMatcherExpression(MatcherCode, nullptr, Error);
}
@@ -254,7 +254,7 @@ class Parser {
const TokenInfo &OpenToken, VariantValue *Value);
bool parseMatcherExpressionImpl(const TokenInfo &NameToken,
const TokenInfo &OpenToken,
llvm::Optional<MatcherCtor> Ctor,
std::optional<MatcherCtor> Ctor,
VariantValue *Value);
bool parseIdentifierPrefixImpl(VariantValue *Value);
@@ -19,8 +19,8 @@
#include "clang/ASTMatchers/Dynamic/Diagnostics.h"
#include "clang/ASTMatchers/Dynamic/VariantValue.h"
#include "llvm/ADT/ArrayRef.h"
#include "llvm/ADT/Optional.h"
#include "llvm/ADT/StringRef.h"
#include <optional>
#include <string>
#include <utility>
#include <vector>
@@ -94,8 +94,8 @@ class Registry {
/// Look up a matcher in the registry by name,
///
/// \return An opaque value which may be used to refer to the matcher
/// constructor, or Optional<MatcherCtor>() if not found.
static llvm::Optional<MatcherCtor> lookupMatcherCtor(StringRef MatcherName);
/// constructor, or std::optional<MatcherCtor>() if not found.
static std::optional<MatcherCtor> lookupMatcherCtor(StringRef MatcherName);
/// Compute the list of completion types for \p Context.
///
@@ -20,8 +20,8 @@
#include "clang/ASTMatchers/ASTMatchers.h"
#include "clang/ASTMatchers/ASTMatchersInternal.h"
#include "llvm/ADT/IntrusiveRefCntPtr.h"
#include "llvm/ADT/Optional.h"
#include <memory>
#include <optional>
#include <vector>
namespace clang {
@@ -117,8 +117,8 @@ class VariantMatcher {
/// Constructs a variadic typed matcher from \p InnerMatchers.
/// Will try to convert each inner matcher to the destination type and
/// return llvm::None if it fails to do so.
llvm::Optional<DynTypedMatcher>
/// return std::nullopt if it fails to do so.
std::optional<DynTypedMatcher>
constructVariadicOperator(DynTypedMatcher::VariadicOperator Op,
ArrayRef<VariantMatcher> InnerMatchers) const;
@@ -132,9 +132,9 @@ class VariantMatcher {
class Payload {
public:
virtual ~Payload();
virtual llvm::Optional<DynTypedMatcher> getSingleMatcher() const = 0;
virtual std::optional<DynTypedMatcher> getSingleMatcher() const = 0;
virtual std::string getTypeAsString() const = 0;
virtual llvm::Optional<DynTypedMatcher>
virtual std::optional<DynTypedMatcher>
getTypedMatcher(const MatcherOps &Ops) const = 0;
virtual bool isConvertibleTo(ASTNodeKind Kind,
unsigned *Specificity) const = 0;
@@ -171,7 +171,7 @@ class VariantMatcher {
/// \returns the matcher, if there is only one matcher. An empty Optional, if
/// the underlying matcher is a polymorphic matcher with more than one
/// representation.
llvm::Optional<DynTypedMatcher> getSingleMatcher() const;
std::optional<DynTypedMatcher> getSingleMatcher() const;
/// Determines if the contained matcher can be converted to
/// \c Matcher<T>.
@@ -18,7 +18,6 @@
#include "clang/Basic/LLVM.h"
#include "llvm/ADT/BitVector.h"
#include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/None.h"
#include "llvm/ADT/PostOrderIterator.h"
#include <utility>
#include <vector>
@@ -48,17 +47,18 @@ class PostOrderCFGView : public ManagedAnalysis {
/// Set the bit associated with a particular CFGBlock.
/// This is the important method for the SetType template parameter.
std::pair<llvm::NoneType, bool> insert(const CFGBlock *Block) {
std::pair<std::nullopt_t, bool> insert(const CFGBlock *Block) {
// Note that insert() is called by po_iterator, which doesn't check to
// make sure that Block is non-null. Moreover, the CFGBlock iterator will
// occasionally hand out null pointers for pruned edges, so we catch those
// here.
if (!Block)
return std::make_pair(None, false); // if an edge is trivially false.
return std::make_pair(std::nullopt,
false); // if an edge is trivially false.
if (VisitedBlockIDs.test(Block->getBlockID()))
return std::make_pair(None, false);
return std::make_pair(std::nullopt, false);
VisitedBlockIDs.set(Block->getBlockID());
return std::make_pair(None, true);
return std::make_pair(std::nullopt, true);
}
/// Check if the bit for a CFGBlock has been already set.
@@ -31,6 +31,7 @@
#include "clang/Basic/LLVM.h"
#include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/PointerIntPair.h"
#include "llvm/ADT/PointerUnion.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/Support/Casting.h"
#include <sstream>
@@ -354,7 +355,7 @@ class SExprBuilder {
const NamedDecl *AttrDecl;
// Implicit object argument -- e.g. 'this'
const Expr *SelfArg = nullptr;
llvm::PointerUnion<const Expr *, til::SExpr *> SelfArg = nullptr;
// Number of funArgs
unsigned NumArgs = 0;
@@ -378,10 +379,18 @@ class SExprBuilder {
// Translate a clang expression in an attribute to a til::SExpr.
// Constructs the context from D, DeclExp, and SelfDecl.
CapabilityExpr translateAttrExpr(const Expr *AttrExp, const NamedDecl *D,
const Expr *DeclExp, VarDecl *SelfD=nullptr);
const Expr *DeclExp,
til::SExpr *Self = nullptr);
CapabilityExpr translateAttrExpr(const Expr *AttrExp, CallingContext *Ctx);
// Translate a variable reference.
til::LiteralPtr *createVariable(const VarDecl *VD);
// Create placeholder for this: we don't know the VarDecl on construction yet.
std::pair<til::LiteralPtr *, StringRef>
createThisPlaceholder(const Expr *Exp);
// Translate a clang statement or expression to a TIL expression.
// Also performs substitution of variables; Ctx provides the context.
// Dispatches on the type of S.
@@ -50,8 +50,6 @@
#include "clang/Analysis/Analyses/ThreadSafetyUtil.h"
#include "clang/Basic/LLVM.h"
#include "llvm/ADT/ArrayRef.h"
#include "llvm/ADT/None.h"
#include "llvm/ADT/Optional.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/Support/Casting.h"
#include "llvm/Support/raw_ostream.h"
@@ -60,6 +58,7 @@
#include <cstddef>
#include <cstdint>
#include <iterator>
#include <optional>
#include <string>
#include <utility>
@@ -634,15 +633,14 @@ typename V::R_SExpr Literal::traverse(V &Vs, typename V::R_Ctx Ctx) {
/// At compile time, pointer literals are represented by symbolic names.
class LiteralPtr : public SExpr {
public:
LiteralPtr(const ValueDecl *D) : SExpr(COP_LiteralPtr), Cvdecl(D) {
assert(D && "ValueDecl must not be null");
}
LiteralPtr(const ValueDecl *D) : SExpr(COP_LiteralPtr), Cvdecl(D) {}
LiteralPtr(const LiteralPtr &) = default;
static bool classof(const SExpr *E) { return E->opcode() == COP_LiteralPtr; }
// The clang declaration for the value that this pointer points to.
const ValueDecl *clangDecl() const { return Cvdecl; }
void setClangDecl(const ValueDecl *VD) { Cvdecl = VD; }
template <class V>
typename V::R_SExpr traverse(V &Vs, typename V::R_Ctx Ctx) {
@@ -651,6 +649,8 @@ class LiteralPtr : public SExpr {
template <class C>
typename C::CType compare(const LiteralPtr* E, C& Cmp) const {
if (!Cvdecl || !E->Cvdecl)
return Cmp.comparePointers(this, E);
return Cmp.comparePointers(Cvdecl, E->Cvdecl);
}
@@ -957,7 +957,7 @@ class Project : public SExpr {
private:
SExpr* Rec;
mutable llvm::Optional<std::string> SlotName;
mutable std::optional<std::string> SlotName;
const ValueDecl *Cvdecl;
};
@@ -1430,9 +1430,7 @@ class Branch : public Terminator {
BasicBlock *elseBlock() { return Branches[1]; }
/// Return the list of basic blocks that this terminator can branch to.
ArrayRef<BasicBlock*> successors() {
return llvm::makeArrayRef(Branches);
}
ArrayRef<BasicBlock *> successors() { return llvm::ArrayRef(Branches); }
template <class V>
typename V::R_SExpr traverse(V &Vs, typename V::R_Ctx Ctx) {
@@ -1463,7 +1461,7 @@ class Return : public Terminator {
static bool classof(const SExpr *E) { return E->opcode() == COP_Return; }
/// Return an empty list.
ArrayRef<BasicBlock *> successors() { return None; }
ArrayRef<BasicBlock *> successors() { return std::nullopt; }
SExpr *returnValue() { return Retval; }
const SExpr *returnValue() const { return Retval; }
@@ -1489,7 +1487,7 @@ inline ArrayRef<BasicBlock*> Terminator::successors() {
case COP_Branch: return cast<Branch>(this)->successors();
case COP_Return: return cast<Return>(this)->successors();
default:
return None;
return std::nullopt;
}
}
@@ -623,7 +623,10 @@ class PrettyPrinter {
}
void printLiteralPtr(const LiteralPtr *E, StreamType &SS) {
SS << E->clangDecl()->getNameAsString();
if (const NamedDecl *D = E->clangDecl())
SS << D->getNameAsString();
else
SS << "<temporary>";
}
void printVariable(const Variable *V, StreamType &SS, bool IsVarDecl=false) {
@@ -204,11 +204,11 @@ template <class T> class SimpleArray {
}
llvm::iterator_range<reverse_iterator> reverse() {
return llvm::make_range(rbegin(), rend());
return llvm::reverse(*this);
}
llvm::iterator_range<const_reverse_iterator> reverse() const {
return llvm::make_range(rbegin(), rend());
return llvm::reverse(*this);
}
private:
@@ -0,0 +1,48 @@
//===- UnsafeBufferUsage.h - Replace pointers with modern C++ ---*- 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 analysis that aids replacing buffer accesses through
// raw pointers with safer C++ abstractions such as containers and views/spans.
//
//===----------------------------------------------------------------------===//
#ifndef LLVM_CLANG_ANALYSIS_ANALYSES_UNSAFEBUFFERUSAGE_H
#define LLVM_CLANG_ANALYSIS_ANALYSES_UNSAFEBUFFERUSAGE_H
#include "clang/AST/Decl.h"
#include "clang/AST/Stmt.h"
namespace clang {
/// The interface that lets the caller handle unsafe buffer usage analysis
/// results by overriding this class's handle... methods.
class UnsafeBufferUsageHandler {
public:
UnsafeBufferUsageHandler() = default;
virtual ~UnsafeBufferUsageHandler() = default;
/// This analyses produces large fixits that are organized into lists
/// of primitive fixits (individual insertions/removals/replacements).
using FixItList = llvm::SmallVectorImpl<FixItHint>;
/// Invoked when an unsafe operation over raw pointers is found.
virtual void handleUnsafeOperation(const Stmt *Operation,
bool IsRelatedToDecl) = 0;
/// Invoked when a fix is suggested against a variable.
virtual void handleFixableVariable(const VarDecl *Variable,
FixItList &&List) = 0;
};
// This function invokes the analysis and allows the caller to react to it
// through the handler class.
void checkUnsafeBufferUsage(const Decl *D, UnsafeBufferUsageHandler &Handler);
} // end namespace clang
#endif /* LLVM_CLANG_ANALYSIS_ANALYSES_UNSAFEBUFFERUSAGE_H */
@@ -0,0 +1,35 @@
//=- UnsafeBufferUsageGadgets.def - List of ways to use a buffer --*- 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
//
//===----------------------------------------------------------------------===//
/// A gadget is an individual operation in the code that may be of interest to
/// the UnsafeBufferUsage analysis.
#ifndef GADGET
#define GADGET(name)
#endif
/// Unsafe gadgets correspond to unsafe code patterns that warrant
/// an immediate warning.
#ifndef WARNING_GADGET
#define WARNING_GADGET(name) GADGET(name)
#endif
/// Safe gadgets correspond to code patterns that aren't unsafe but need to be
/// properly recognized in order to emit correct warnings and fixes over unsafe
/// gadgets.
#ifndef FIXABLE_GADGET
#define FIXABLE_GADGET(name) GADGET(name)
#endif
WARNING_GADGET(Increment)
WARNING_GADGET(Decrement)
WARNING_GADGET(ArraySubscript)
WARNING_GADGET(PointerArithmetic)
#undef FIXABLE_GADGET
#undef WARNING_GADGET
#undef GADGET
@@ -16,6 +16,7 @@
#include "clang/AST/Decl.h"
#include "clang/AST/ExprCXX.h"
#include "clang/AST/ExprObjC.h"
#include <optional>
namespace clang {
@@ -108,8 +109,8 @@ class AnyCall {
}
/// If @c E is a generic call (to ObjC method /function/block/etc),
/// return a constructed @c AnyCall object. Return None otherwise.
static Optional<AnyCall> forExpr(const Expr *E) {
/// return a constructed @c AnyCall object. Return std::nullopt otherwise.
static std::optional<AnyCall> forExpr(const Expr *E) {
if (const auto *ME = dyn_cast<ObjCMessageExpr>(E)) {
return AnyCall(ME);
} else if (const auto *CE = dyn_cast<CallExpr>(E)) {
@@ -123,26 +124,26 @@ class AnyCall {
} else if (const auto *CXCIE = dyn_cast<CXXInheritedCtorInitExpr>(E)) {
return AnyCall(CXCIE);
} else {
return None;
return std::nullopt;
}
}
/// If @c D is a callable (Objective-C method or a function), return
/// a constructed @c AnyCall object. Return None otherwise.
/// a constructed @c AnyCall object. Return std::nullopt otherwise.
// FIXME: block support.
static Optional<AnyCall> forDecl(const Decl *D) {
static std::optional<AnyCall> forDecl(const Decl *D) {
if (const auto *FD = dyn_cast<FunctionDecl>(D)) {
return AnyCall(FD);
} else if (const auto *MD = dyn_cast<ObjCMethodDecl>(D)) {
return AnyCall(MD);
}
return None;
return std::nullopt;
}
/// \returns formal parameters for direct calls (including virtual calls)
ArrayRef<ParmVarDecl *> parameters() const {
if (!D)
return None;
return std::nullopt;
if (const auto *FD = dyn_cast<FunctionDecl>(D)) {
return FD->parameters();
@@ -151,7 +152,7 @@ class AnyCall {
} else if (const auto *BD = dyn_cast<BlockDecl>(D)) {
return BD->parameters();
} else {
return None;
return std::nullopt;
}
}
@@ -17,7 +17,7 @@
#include "clang/AST/DeclBase.h"
#include "clang/Basic/LLVM.h"
#include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/Optional.h"
#include <optional>
namespace clang {
@@ -41,7 +41,7 @@ class BodyFarm {
BodyFarm(const BodyFarm &other) = delete;
private:
typedef llvm::DenseMap<const Decl *, Optional<Stmt *>> BodyMap;
typedef llvm::DenseMap<const Decl *, std::optional<Stmt *>> BodyMap;
ASTContext &C;
BodyMap Bodies;
@@ -21,8 +21,6 @@
#include "clang/Basic/LLVM.h"
#include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/GraphTraits.h"
#include "llvm/ADT/None.h"
#include "llvm/ADT/Optional.h"
#include "llvm/ADT/PointerIntPair.h"
#include "llvm/ADT/iterator_range.h"
#include "llvm/Support/Allocator.h"
@@ -32,6 +30,7 @@
#include <cstddef>
#include <iterator>
#include <memory>
#include <optional>
#include <vector>
namespace clang {
@@ -103,12 +102,11 @@ class CFGElement {
return t;
}
/// Convert to the specified CFGElement type, returning None if this
/// Convert to the specified CFGElement type, returning std::nullopt if this
/// CFGElement is not of the desired type.
template<typename T>
Optional<T> getAs() const {
template <typename T> std::optional<T> getAs() const {
if (!T::isKind(*this))
return None;
return std::nullopt;
T t;
CFGElement& e = t;
e = *this;
@@ -131,7 +129,7 @@ class CFGElement {
class CFGStmt : public CFGElement {
public:
explicit CFGStmt(Stmt *S, Kind K = Statement) : CFGElement(K, S) {
explicit CFGStmt(const Stmt *S, Kind K = Statement) : CFGElement(K, S) {
assert(isKind(*this));
}
@@ -155,7 +153,8 @@ class CFGStmt : public CFGElement {
/// this is only used by the analyzer's CFG.
class CFGConstructor : public CFGStmt {
public:
explicit CFGConstructor(CXXConstructExpr *CE, const ConstructionContext *C)
explicit CFGConstructor(const CXXConstructExpr *CE,
const ConstructionContext *C)
: CFGStmt(CE, Constructor) {
assert(C);
Data2.setPointer(const_cast<ConstructionContext *>(C));
@@ -185,7 +184,7 @@ class CFGCXXRecordTypedCall : public CFGStmt {
public:
/// Returns true when call expression \p CE needs to be represented
/// by CFGCXXRecordTypedCall, as opposed to a regular CFGStmt.
static bool isCXXRecordTypedCall(Expr *E) {
static bool isCXXRecordTypedCall(const Expr *E) {
assert(isa<CallExpr>(E) || isa<ObjCMessageExpr>(E));
// There is no such thing as reference-type expression. If the function
// returns a reference, it'll return the respective lvalue or xvalue
@@ -194,7 +193,7 @@ class CFGCXXRecordTypedCall : public CFGStmt {
E->getType().getCanonicalType()->getAsCXXRecordDecl();
}
explicit CFGCXXRecordTypedCall(Expr *E, const ConstructionContext *C)
explicit CFGCXXRecordTypedCall(const Expr *E, const ConstructionContext *C)
: CFGStmt(E, CXXRecordTypedCall) {
assert(isCXXRecordTypedCall(E));
assert(C && (isa<TemporaryObjectConstructionContext>(C) ||
@@ -225,7 +224,7 @@ class CFGCXXRecordTypedCall : public CFGStmt {
/// list.
class CFGInitializer : public CFGElement {
public:
explicit CFGInitializer(CXXCtorInitializer *initializer)
explicit CFGInitializer(const CXXCtorInitializer *initializer)
: CFGElement(Initializer, initializer) {}
CXXCtorInitializer* getInitializer() const {
@@ -264,7 +263,7 @@ class CFGNewAllocator : public CFGElement {
};
/// Represents the point where a loop ends.
/// This element is is only produced when building the CFG for the static
/// This element is only produced when building the CFG for the static
/// analyzer and hidden behind the 'cfg-loopexit' analyzer config flag.
///
/// Note: a loop exit element can be reached even when the loop body was never
@@ -482,7 +481,7 @@ class CFGMemberDtor : public CFGImplicitDtor {
/// expression for temporary object.
class CFGTemporaryDtor : public CFGImplicitDtor {
public:
CFGTemporaryDtor(CXXBindTemporaryExpr *expr)
CFGTemporaryDtor(const CXXBindTemporaryExpr *expr)
: CFGImplicitDtor(TemporaryDtor, expr, nullptr) {}
const CXXBindTemporaryExpr *getBindTemporaryExpr() const {
@@ -1399,7 +1398,7 @@ class CFG {
for (const_iterator I = begin(), E = end(); I != E; ++I)
for (CFGBlock::const_iterator BI = (*I)->begin(), BE = (*I)->end();
BI != BE; ++BI) {
if (Optional<CFGStmt> stmt = BI->getAs<CFGStmt>())
if (std::optional<CFGStmt> stmt = BI->getAs<CFGStmt>())
O(const_cast<Stmt *>(stmt->getStmt()));
}
}
@@ -1466,6 +1465,8 @@ class CFG {
llvm::DenseMap<const DeclStmt *, const DeclStmt *> SyntheticDeclStmts;
};
Expr *extractElementInitializerFromNestedAILE(const ArrayInitLoopExpr *AILE);
} // namespace clang
//===----------------------------------------------------------------------===//
@@ -260,7 +260,7 @@ class RecursiveCloneTypeIIHashConstraint {
///
/// Clones that aren't type II clones are moved into separate clone groups.
/// In contrast to the RecursiveCloneTypeIIHashConstraint, all clones in a clone
/// group are guaranteed to be be type II clones of each other, but it is too
/// group are guaranteed to be type II clones of each other, but it is too
/// slow to efficiently handle large amounts of clones.
class RecursiveCloneTypeIIVerifyConstraint {
public:
@@ -542,7 +542,7 @@ class SimpleTemporaryObjectConstructionContext
/// of being immediately copied by an elidable copy/move constructor.
/// For example, T t = T(123); includes a temporary T(123) that is immediately
/// copied to variable t. In such cases the elidable copy can (but not
/// necessarily should) be omitted ("elided") accodring to the rules of the
/// necessarily should) be omitted ("elided") according to the rules of the
/// language; the constructor would then construct variable t directly.
/// This construction context contains information of the elidable constructor
/// and its respective construction context.
@@ -0,0 +1,98 @@
//===---- CFGMatchSwitch.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 `CFGMatchSwitch` abstraction for building a "switch"
// statement for control flow graph elements. Each case of the switch is
// defined by an ASTMatcher which is applied on the AST node contained in the
// input `CFGElement`.
//
// Currently, the `CFGMatchSwitch` only handles `CFGElement`s of
// `Kind::Statement` and `Kind::Initializer`.
//
//===----------------------------------------------------------------------===//
#ifndef LLVM_CLANG_ANALYSIS_FLOWSENSITIVE_CFGMATCHSWITCH_H_
#define LLVM_CLANG_ANALYSIS_FLOWSENSITIVE_CFGMATCHSWITCH_H_
#include "clang/AST/ASTContext.h"
#include "clang/AST/Stmt.h"
#include "clang/Analysis/CFG.h"
#include "clang/Analysis/FlowSensitive/MatchSwitch.h"
#include <functional>
#include <utility>
namespace clang {
namespace dataflow {
template <typename State, typename Result = void>
using CFGMatchSwitch =
std::function<Result(const CFGElement &, 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 an AST node
/// contained in a CFG element.
template <typename State, typename Result = void> class CFGMatchSwitchBuilder {
public:
/// Registers an action `A` for `CFGStmt`s that will be triggered by the match
/// of the pattern `M` against the `Stmt` contained in the input `CFGStmt`.
///
/// Requirements:
///
/// `NodeT` should be derived from `Stmt`.
template <typename NodeT>
CFGMatchSwitchBuilder &&
CaseOfCFGStmt(MatchSwitchMatcher<Stmt> M,
MatchSwitchAction<NodeT, State, Result> A) && {
std::move(StmtBuilder).template CaseOf<NodeT>(M, A);
return std::move(*this);
}
/// Registers an action `A` for `CFGInitializer`s that will be triggered by
/// the match of the pattern `M` against the `CXXCtorInitializer` contained in
/// the input `CFGInitializer`.
///
/// Requirements:
///
/// `NodeT` should be derived from `CXXCtorInitializer`.
template <typename NodeT>
CFGMatchSwitchBuilder &&
CaseOfCFGInit(MatchSwitchMatcher<CXXCtorInitializer> M,
MatchSwitchAction<NodeT, State, Result> A) && {
std::move(InitBuilder).template CaseOf<NodeT>(M, A);
return std::move(*this);
}
CFGMatchSwitch<State, Result> Build() && {
return [StmtMS = std::move(StmtBuilder).Build(),
InitMS = std::move(InitBuilder).Build()](const CFGElement &Element,
ASTContext &Context,
State &S) -> Result {
switch (Element.getKind()) {
case CFGElement::Initializer:
return InitMS(*Element.castAs<CFGInitializer>().getInitializer(),
Context, S);
case CFGElement::Statement:
case CFGElement::Constructor:
case CFGElement::CXXRecordTypedCall:
return StmtMS(*Element.castAs<CFGStmt>().getStmt(), Context, S);
default:
// FIXME: Handle other kinds of CFGElement.
return Result();
}
};
}
private:
ASTMatchSwitchBuilder<Stmt, State, Result> StmtBuilder;
ASTMatchSwitchBuilder<CXXCtorInitializer, State, Result> InitBuilder;
};
} // namespace dataflow
} // namespace clang
#endif // LLVM_CLANG_ANALYSIS_FLOWSENSITIVE_CFGMATCHSWITCH_H_
@@ -30,9 +30,14 @@ namespace dataflow {
/// analysis.
class ControlFlowContext {
public:
/// Builds a ControlFlowContext from an AST node.
static llvm::Expected<ControlFlowContext> build(const Decl *D, Stmt *S,
ASTContext *C);
/// Builds a ControlFlowContext from an AST node. `D` is the function in which
/// `S` resides and must not be null.
static llvm::Expected<ControlFlowContext> build(const Decl *D, Stmt &S,
ASTContext &C);
/// Returns the `Decl` containing the statement used to construct the CFG, if
/// available.
const Decl *getDecl() const { return ContainingDecl; }
/// Returns the CFG that is stored in this context.
const CFG &getCFG() const { return *Cfg; }
@@ -43,10 +48,15 @@ class ControlFlowContext {
}
private:
ControlFlowContext(std::unique_ptr<CFG> Cfg,
// FIXME: Once the deprecated `build` method is removed, mark `D` as "must not
// be null" and add an assertion.
ControlFlowContext(const Decl *D, std::unique_ptr<CFG> Cfg,
llvm::DenseMap<const Stmt *, const CFGBlock *> StmtToBlock)
: Cfg(std::move(Cfg)), StmtToBlock(std::move(StmtToBlock)) {}
: ContainingDecl(D), Cfg(std::move(Cfg)),
StmtToBlock(std::move(StmtToBlock)) {}
/// The `Decl` containing the statement used to construct the CFG.
const Decl *ContainingDecl;
std::unique_ptr<CFG> Cfg;
llvm::DenseMap<const Stmt *, const CFGBlock *> StmtToBlock;
};
@@ -15,17 +15,18 @@
#define LLVM_CLANG_ANALYSIS_FLOWSENSITIVE_DATAFLOWANALYSIS_H
#include <iterator>
#include <optional>
#include <type_traits>
#include <utility>
#include <vector>
#include "clang/AST/ASTContext.h"
#include "clang/AST/Stmt.h"
#include "clang/Analysis/CFG.h"
#include "clang/Analysis/FlowSensitive/ControlFlowContext.h"
#include "clang/Analysis/FlowSensitive/DataflowEnvironment.h"
#include "clang/Analysis/FlowSensitive/DataflowLattice.h"
#include "clang/Analysis/FlowSensitive/TypeErasedDataflowAnalysis.h"
#include "llvm/ADT/Any.h"
#include "llvm/ADT/Optional.h"
#include "llvm/ADT/STLExtras.h"
#include "llvm/Support/Error.h"
@@ -40,8 +41,14 @@ namespace dataflow {
/// must provide the following public members:
/// * `LatticeT initialElement()` - returns a lattice element that models the
/// initial state of a basic block;
/// * `void transfer(const Stmt *, LatticeT &, Environment &)` - applies the
/// analysis transfer function for a given statement and lattice element.
/// * `void transfer(const CFGElement *, LatticeT &, Environment &)` - applies
/// the analysis transfer function for a given CFG element and lattice
/// element.
///
/// `Derived` can optionally provide the following members:
/// * `void transferBranch(bool Branch, const Stmt *Stmt, TypeErasedLattice &E,
/// Environment &Env)` - applies the analysis transfer
/// function for a given edge from a CFG block of a conditional statement.
///
/// `Derived` can optionally override the following members:
/// * `bool merge(QualType, const Value &, const Value &, Value &,
@@ -56,6 +63,15 @@ namespace dataflow {
/// made to it;
/// * `bool operator==(const LatticeT &) const` - returns true if and only if
/// the object is equal to the argument.
///
/// `LatticeT` can optionally provide the following members:
/// * `LatticeJoinEffect widen(const LatticeT &Previous)` - replaces the
/// lattice element with an approximation that can reach a fixed point more
/// quickly than iterated application of the transfer function alone. The
/// previous value is provided to inform the choice of widened value. The
/// function must also serve as a comparison operation, by indicating whether
/// the widened value is equivalent to the previous value with the returned
/// `LatticeJoinEffect`.
template <typename Derived, typename LatticeT>
class DataflowAnalysis : public TypeErasedDataflowAnalysis {
public:
@@ -66,7 +82,11 @@ class DataflowAnalysis : public TypeErasedDataflowAnalysis {
/// Deprecated. Use the `DataflowAnalysisOptions` constructor instead.
explicit DataflowAnalysis(ASTContext &Context, bool ApplyBuiltinTransfer)
: TypeErasedDataflowAnalysis(ApplyBuiltinTransfer), Context(Context) {}
: DataflowAnalysis(
Context,
{ApplyBuiltinTransfer
? DataflowAnalysisContext::Options{}
: std::optional<DataflowAnalysisContext::Options>()}) {}
explicit DataflowAnalysis(ASTContext &Context,
DataflowAnalysisOptions Options)
@@ -85,6 +105,13 @@ class DataflowAnalysis : public TypeErasedDataflowAnalysis {
return L1.join(L2);
}
LatticeJoinEffect widenTypeErased(TypeErasedLattice &Current,
const TypeErasedLattice &Previous) final {
Lattice &C = llvm::any_cast<Lattice &>(Current.Value);
const Lattice &P = llvm::any_cast<const Lattice &>(Previous.Value);
return widenInternal(Rank0{}, C, P);
}
bool isEqualTypeErased(const TypeErasedLattice &E1,
const TypeErasedLattice &E2) final {
const Lattice &L1 = llvm::any_cast<const Lattice &>(E1.Value);
@@ -92,13 +119,55 @@ class DataflowAnalysis : public TypeErasedDataflowAnalysis {
return L1 == L2;
}
void transferTypeErased(const Stmt *Stmt, TypeErasedLattice &E,
void transferTypeErased(const CFGElement *Element, TypeErasedLattice &E,
Environment &Env) final {
Lattice &L = llvm::any_cast<Lattice &>(E.Value);
static_cast<Derived *>(this)->transfer(Stmt, L, Env);
static_cast<Derived *>(this)->transfer(Element, L, Env);
}
void transferBranchTypeErased(bool Branch, const Stmt *Stmt,
TypeErasedLattice &E, Environment &Env) final {
transferBranchInternal(Rank0{}, *static_cast<Derived *>(this), Branch, Stmt,
E, Env);
}
private:
// These `Rank` structs are used for template metaprogramming to choose
// between overloads.
struct Rank1 {};
struct Rank0 : Rank1 {};
// The first-choice implementation: use `widen` when it is available.
template <typename T>
static auto widenInternal(Rank0, T &Current, const T &Prev)
-> decltype(Current.widen(Prev)) {
return Current.widen(Prev);
}
// The second-choice implementation: `widen` is unavailable. Widening is
// merged with equality checking, so when widening is unimplemented, we
// default to equality checking.
static LatticeJoinEffect widenInternal(Rank1, const Lattice &Current,
const Lattice &Prev) {
return Prev == Current ? LatticeJoinEffect::Unchanged
: LatticeJoinEffect::Changed;
}
// The first-choice implementation: `transferBranch` is implemented.
template <typename Analysis>
static auto transferBranchInternal(Rank0, Analysis &A, bool Branch,
const Stmt *Stmt, TypeErasedLattice &L,
Environment &Env)
-> std::void_t<decltype(A.transferBranch(
Branch, Stmt, std::declval<LatticeT &>(), Env))> {
A.transferBranch(Branch, Stmt, llvm::any_cast<Lattice &>(L.Value), Env);
}
// The second-choice implementation: `transferBranch` is unimplemented. No-op.
template <typename Analysis>
static void transferBranchInternal(Rank1, Analysis &A, bool, const Stmt *,
TypeErasedLattice &, Environment &) {}
ASTContext &Context;
};
@@ -116,43 +185,44 @@ template <typename LatticeT> struct DataflowAnalysisState {
/// 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
/// `PostVisitCFG` on each CFG element with the final analysis results at that
/// program point.
template <typename AnalysisT>
llvm::Expected<std::vector<
llvm::Optional<DataflowAnalysisState<typename AnalysisT::Lattice>>>>
std::optional<DataflowAnalysisState<typename AnalysisT::Lattice>>>>
runDataflowAnalysis(
const ControlFlowContext &CFCtx, AnalysisT &Analysis,
const Environment &InitEnv,
std::function<void(const Stmt *, const DataflowAnalysisState<
std::function<void(const CFGElement &, const DataflowAnalysisState<
typename AnalysisT::Lattice> &)>
PostVisitStmt = nullptr) {
std::function<void(const Stmt *, const TypeErasedDataflowAnalysisState &)>
PostVisitStmtClosure = nullptr;
if (PostVisitStmt != nullptr) {
PostVisitStmtClosure = [&PostVisitStmt](
const Stmt *Stmt,
PostVisitCFG = nullptr) {
std::function<void(const CFGElement &,
const TypeErasedDataflowAnalysisState &)>
PostVisitCFGClosure = nullptr;
if (PostVisitCFG) {
PostVisitCFGClosure = [&PostVisitCFG](
const CFGElement &Element,
const TypeErasedDataflowAnalysisState &State) {
auto *Lattice =
llvm::any_cast<typename AnalysisT::Lattice>(&State.Lattice.Value);
PostVisitStmt(Stmt, DataflowAnalysisState<typename AnalysisT::Lattice>{
PostVisitCFG(Element, DataflowAnalysisState<typename AnalysisT::Lattice>{
*Lattice, State.Env});
};
}
auto TypeErasedBlockStates = runTypeErasedDataflowAnalysis(
CFCtx, Analysis, InitEnv, PostVisitStmtClosure);
CFCtx, Analysis, InitEnv, PostVisitCFGClosure);
if (!TypeErasedBlockStates)
return TypeErasedBlockStates.takeError();
std::vector<
llvm::Optional<DataflowAnalysisState<typename AnalysisT::Lattice>>>
std::vector<std::optional<DataflowAnalysisState<typename AnalysisT::Lattice>>>
BlockStates;
BlockStates.reserve(TypeErasedBlockStates->size());
llvm::transform(std::move(*TypeErasedBlockStates),
std::back_inserter(BlockStates), [](auto &OptState) {
return std::move(OptState).map([](auto &&State) {
llvm::transform(
std::move(*TypeErasedBlockStates), std::back_inserter(BlockStates),
[](auto &OptState) {
return llvm::transformOptional(std::move(OptState), [](auto &&State) {
return DataflowAnalysisState<typename AnalysisT::Lattice>{
llvm::any_cast<typename AnalysisT::Lattice>(
std::move(State.Lattice.Value)),
@@ -167,8 +237,8 @@ runDataflowAnalysis(
/// 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;
/// Return value indicates whether the model processed the `Element`.
virtual bool transfer(const CFGElement *Element, Environment &Env) = 0;
};
} // namespace dataflow
@@ -18,6 +18,7 @@
#include "clang/AST/Decl.h"
#include "clang/AST/Expr.h"
#include "clang/AST/TypeOrdering.h"
#include "clang/Analysis/FlowSensitive/ControlFlowContext.h"
#include "clang/Analysis/FlowSensitive/Solver.h"
#include "clang/Analysis/FlowSensitive/StorageLocation.h"
#include "clang/Analysis/FlowSensitive/Value.h"
@@ -26,6 +27,7 @@
#include "llvm/Support/Compiler.h"
#include <cassert>
#include <memory>
#include <optional>
#include <type_traits>
#include <utility>
#include <vector>
@@ -49,18 +51,34 @@ const Stmt &ignoreCFGOmittedNodes(const Stmt &S);
/// Returns the set of all fields in the type.
llvm::DenseSet<const FieldDecl *> getObjectFields(QualType Type);
struct ContextSensitiveOptions {
/// The maximum depth to analyze. A value of zero is equivalent to disabling
/// context-sensitive analysis entirely.
unsigned Depth = 2;
};
/// Owns objects that encompass the state of a program and stores context that
/// is used during dataflow analysis.
class DataflowAnalysisContext {
public:
struct Options {
/// Options for analyzing function bodies when present in the translation
/// unit, or empty to disable context-sensitive analysis. Note that this is
/// fundamentally limited: some constructs, such as recursion, are
/// explicitly unsupported.
std::optional<ContextSensitiveOptions> ContextSensitiveOpts;
};
/// Constructs a dataflow analysis context.
///
/// Requirements:
///
/// `S` must not be null.
DataflowAnalysisContext(std::unique_ptr<Solver> S)
DataflowAnalysisContext(std::unique_ptr<Solver> S,
Options Opts = Options{
/*ContextSensitiveOpts=*/std::nullopt})
: S(std::move(S)), TrueVal(createAtomicBoolValue()),
FalseVal(createAtomicBoolValue()) {
FalseVal(createAtomicBoolValue()), Opts(Opts) {
assert(this->S != nullptr);
}
@@ -70,7 +88,7 @@ class DataflowAnalysisContext {
///
/// `Loc` must not be null.
template <typename T>
typename std::enable_if<std::is_base_of<StorageLocation, T>::value, T &>::type
std::enable_if_t<std::is_base_of<StorageLocation, T>::value, T &>
takeOwnership(std::unique_ptr<T> Loc) {
assert(Loc != nullptr);
Locs.push_back(std::move(Loc));
@@ -83,19 +101,17 @@ class DataflowAnalysisContext {
///
/// `Val` must not be null.
template <typename T>
typename std::enable_if<std::is_base_of<Value, T>::value, T &>::type
std::enable_if_t<std::is_base_of<Value, T>::value, T &>
takeOwnership(std::unique_ptr<T> Val) {
assert(Val != nullptr);
Vals.push_back(std::move(Val));
return *cast<T>(Vals.back().get());
}
/// Returns a stable storage location appropriate for `Type`.
/// Returns a new storage location appropriate for `Type`.
///
/// Requirements:
///
/// `Type` must not be null.
StorageLocation &getStableStorageLocation(QualType Type);
/// A null `Type` is interpreted as the pointee type of `std::nullptr_t`.
StorageLocation &createStorageLocation(QualType Type);
/// Returns a stable storage location for `D`.
StorageLocation &getStableStorageLocation(const VarDecl &D);
@@ -138,22 +154,6 @@ class DataflowAnalysisContext {
return It == ExprToLoc.end() ? nullptr : It->second;
}
/// Assigns `Loc` as the storage location of the `this` pointee.
///
/// Requirements:
///
/// The `this` pointee must not be assigned a storage location.
void setThisPointeeStorageLocation(StorageLocation &Loc) {
assert(ThisPointeeLoc == nullptr);
ThisPointeeLoc = &Loc;
}
/// Returns the storage location assigned to the `this` pointee or null if the
/// `this` pointee has no assigned storage location.
StorageLocation *getThisPointeeStorageLocation() const {
return ThisPointeeLoc;
}
/// Returns a pointer value that represents a null pointer. Calls with
/// `PointeeType` that are canonically equivalent will return the same result.
/// A null `PointeeType` can be used for the pointee of `std::nullptr_t`.
@@ -170,6 +170,18 @@ class DataflowAnalysisContext {
return takeOwnership(std::make_unique<AtomicBoolValue>());
}
/// Creates a Top value for booleans. Each instance is unique and can be
/// assigned a distinct truth value during solving.
///
/// FIXME: `Top iff Top` is true when both Tops are identical (by pointer
/// equality), but not when they are distinct values. We should improve the
/// implementation so that `Top iff Top` has a consistent meaning, regardless
/// of the identity of `Top`. Moreover, I think the meaning should be
/// `false`.
TopBoolValue &createTopBoolValue() {
return takeOwnership(std::make_unique<TopBoolValue>());
}
/// Returns a boolean value that represents the conjunction of `LHS` and
/// `RHS`. Subsequent calls with the same arguments, regardless of their
/// order, will return the same result. If the given boolean values represent
@@ -254,7 +266,15 @@ class DataflowAnalysisContext {
LLVM_DUMP_METHOD void dumpFlowCondition(AtomicBoolValue &Token);
/// Returns the `ControlFlowContext` registered for `F`, if any. Otherwise,
/// returns null.
const ControlFlowContext *getControlFlowContext(const FunctionDecl *F);
const Options &getOptions() { return Opts; }
private:
friend class Environment;
struct NullableQualTypeDenseMapInfo : private llvm::DenseMapInfo<QualType> {
static QualType getEmptyKey() {
// Allow a NULL `QualType` by using a different value as the empty key.
@@ -266,6 +286,13 @@ class DataflowAnalysisContext {
using DenseMapInfo::isEqual;
};
// Extends the set of modeled field declarations.
void addModeledFields(const llvm::DenseSet<const FieldDecl *> &Fields);
/// Returns the fields of `Type`, limited to the set of fields modeled by this
/// context.
llvm::DenseSet<const FieldDecl *> getReferencedFields(QualType Type);
/// 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
@@ -319,8 +346,6 @@ class DataflowAnalysisContext {
llvm::DenseMap<const ValueDecl *, StorageLocation *> DeclToLoc;
llvm::DenseMap<const Expr *, StorageLocation *> ExprToLoc;
StorageLocation *ThisPointeeLoc = nullptr;
// Null pointer values, keyed by the canonical pointee type.
//
// FIXME: The pointer values are indexed by the pointee types which are
@@ -333,6 +358,8 @@ class DataflowAnalysisContext {
AtomicBoolValue &TrueVal;
AtomicBoolValue &FalseVal;
Options Opts;
// Indices that are used to avoid recreating the same composite boolean
// values.
llvm::DenseMap<std::pair<BoolValue *, BoolValue *>, ConjunctionValue *>
@@ -360,6 +387,11 @@ class DataflowAnalysisContext {
llvm::DenseMap<AtomicBoolValue *, llvm::DenseSet<AtomicBoolValue *>>
FlowConditionDeps;
llvm::DenseMap<AtomicBoolValue *, BoolValue *> FlowConditionConstraints;
llvm::DenseMap<const FunctionDecl *, ControlFlowContext> FunctionContexts;
// Fields modeled by environments covered by this context.
llvm::DenseSet<const FieldDecl *> ModeledFields;
};
} // namespace dataflow
@@ -19,12 +19,14 @@
#include "clang/AST/DeclBase.h"
#include "clang/AST/Expr.h"
#include "clang/AST/Type.h"
#include "clang/Analysis/FlowSensitive/ControlFlowContext.h"
#include "clang/Analysis/FlowSensitive/DataflowAnalysisContext.h"
#include "clang/Analysis/FlowSensitive/DataflowLattice.h"
#include "clang/Analysis/FlowSensitive/StorageLocation.h"
#include "clang/Analysis/FlowSensitive/Value.h"
#include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/DenseSet.h"
#include "llvm/Support/ErrorHandling.h"
#include <memory>
#include <type_traits>
#include <utility>
@@ -47,6 +49,13 @@ enum class SkipPast {
ReferenceThenPointer,
};
/// Indicates the result of a tentative comparison.
enum class ComparisonResult {
Same,
Different,
Unknown,
};
/// 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
@@ -61,7 +70,11 @@ class Environment {
public:
virtual ~ValueModel() = default;
/// Returns true if and only if `Val1` is equivalent to `Val2`.
/// Returns:
/// `Same`: `Val1` is equivalent to `Val2`, according to the model.
/// `Different`: `Val1` is distinct from `Val2`, according to the model.
/// `Unknown`: The model can't determine a relationship between `Val1` and
/// `Val2`.
///
/// Requirements:
///
@@ -71,16 +84,12 @@ class Environment {
///
/// `Val1` and `Val2` must be assigned to the same storage location in
/// `Env1` and `Env2` respectively.
virtual bool compareEquivalent(QualType Type, const Value &Val1,
virtual ComparisonResult compare(QualType Type, const Value &Val1,
const Environment &Env1, const Value &Val2,
const Environment &Env2) {
// FIXME: Consider adding QualType to StructValue and removing the Type
// argument here.
//
// 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;
return ComparisonResult::Unknown;
}
/// Modifies `MergedVal` to approximate both `Val1` and `Val2`. This could
@@ -106,6 +115,46 @@ class Environment {
Environment &MergedEnv) {
return true;
}
/// This function may widen the current value -- replace it with an
/// approximation that can reach a fixed point more quickly than iterated
/// application of the transfer function alone. The previous value is
/// provided to inform the choice of widened value. The function must also
/// serve as a comparison operation, by indicating whether the widened value
/// is equivalent to the previous value.
///
/// Returns either:
///
/// `nullptr`, if this value is not of interest to the model, or
///
/// `&Prev`, if the widened value is equivalent to `Prev`, or
///
/// A non-null value that approximates `Current`. `Prev` is available to
/// inform the chosen approximation.
///
/// `PrevEnv` and `CurrentEnv` can be used to query child values and path
/// condition implications of `Prev` and `Current`, respectively.
///
/// Requirements:
///
/// `Prev` and `Current` must model values of type `Type`.
///
/// `Prev` and `Current` must be assigned to the same storage location in
/// `PrevEnv` and `CurrentEnv`, respectively.
virtual Value *widen(QualType Type, Value &Prev, const Environment &PrevEnv,
Value &Current, Environment &CurrentEnv) {
// The default implementation reduces to just comparison, since comparison
// is required by the API, even if no widening is performed.
switch (compare(Type, Prev, PrevEnv, Current, CurrentEnv)) {
case ComparisonResult::Same:
return &Prev;
case ComparisonResult::Different:
return &Current;
case ComparisonResult::Unknown:
return nullptr;
}
llvm_unreachable("all cases in switch covered");
}
};
/// Creates an environment that uses `DACtx` to store objects that encompass
@@ -128,20 +177,27 @@ class Environment {
/// with a symbolic representation of the `this` pointee.
Environment(DataflowAnalysisContext &DACtx, const DeclContext &DeclCtx);
const DataflowAnalysisContext::Options &getAnalysisOptions() {
return DACtx->getOptions();
}
/// Creates and returns an environment to use for an inline analysis of the
/// callee. Uses the storage location from each argument in the `Call` as the
/// storage location for the corresponding parameter in the callee.
///
/// Requirements:
///
/// The callee of `Call` must be a `FunctionDecl` with a body.
/// The callee of `Call` must be a `FunctionDecl`.
///
/// The body of the callee must not reference globals.
///
/// The arguments of `Call` must map 1:1 to the callee's parameters.
///
/// Each argument of `Call` must already have a `StorageLocation`.
Environment pushCall(const CallExpr *Call) const;
Environment pushCall(const CXXConstructExpr *Call) const;
/// Moves gathered information back into `this` from a `CalleeEnv` created via
/// `pushCall`.
void popCall(const Environment &CalleeEnv);
/// Returns true if and only if the environment is equivalent to `Other`, i.e
/// the two environments:
@@ -167,6 +223,17 @@ class Environment {
LatticeJoinEffect join(const Environment &Other,
Environment::ValueModel &Model);
/// Widens the environment point-wise, using `PrevEnv` as needed to inform the
/// approximation.
///
/// Requirements:
///
/// `PrevEnv` must be the immediate previous version of the environment.
/// `PrevEnv` and `this` must use the same `DataflowAnalysisContext`.
LatticeJoinEffect widen(const Environment &PrevEnv,
Environment::ValueModel &Model);
// FIXME: Rename `createOrGetStorageLocation` to `getOrCreateStorageLocation`,
// `getStableStorageLocation`, or something more appropriate.
@@ -217,6 +284,9 @@ class Environment {
/// in the environment.
StorageLocation *getThisPointeeStorageLocation() const;
/// Returns the storage location of the return value or null, if unset.
StorageLocation *getReturnStorageLocation() 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);
@@ -253,7 +323,7 @@ class Environment {
///
/// `Loc` must not be null.
template <typename T>
typename std::enable_if<std::is_base_of<StorageLocation, T>::value, T &>::type
std::enable_if_t<std::is_base_of<StorageLocation, T>::value, T &>
takeOwnership(std::unique_ptr<T> Loc) {
return DACtx->takeOwnership(std::move(Loc));
}
@@ -265,7 +335,7 @@ class Environment {
///
/// `Val` must not be null.
template <typename T>
typename std::enable_if<std::is_base_of<Value, T>::value, T &>::type
std::enable_if_t<std::is_base_of<Value, T>::value, T &>
takeOwnership(std::unique_ptr<T> Val) {
return DACtx->takeOwnership(std::move(Val));
}
@@ -281,6 +351,11 @@ class Environment {
return DACtx->createAtomicBoolValue();
}
/// Returns a unique instance of boolean Top.
BoolValue &makeTopBoolValue() const {
return DACtx->createTopBoolValue();
}
/// 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
@@ -339,7 +414,23 @@ class Environment {
/// imply that `Val` is true.
bool flowConditionImplies(BoolValue &Val) const;
/// Returns the `DeclContext` of the block being analysed, if any. Otherwise,
/// returns null.
const DeclContext *getDeclCtx() const { return CallStack.back(); }
/// Returns whether this `Environment` can be extended to analyze the given
/// `Callee` (i.e. if `pushCall` can be used), with recursion disallowed and a
/// given `MaxDepth`.
bool canDescend(unsigned MaxDepth, const DeclContext *Callee) const;
/// Returns the `ControlFlowContext` registered for `F`, if any. Otherwise,
/// returns null.
const ControlFlowContext *getControlFlowContext(const FunctionDecl *F) {
return DACtx->getControlFlowContext(F);
}
LLVM_DUMP_METHOD void dump() const;
LLVM_DUMP_METHOD void dump(raw_ostream &OS) const;
private:
/// Creates a value appropriate for `Type`, if `Type` is supported, otherwise
@@ -360,9 +451,33 @@ class Environment {
StorageLocation &skip(StorageLocation &Loc, SkipPast SP) const;
const StorageLocation &skip(const StorageLocation &Loc, SkipPast SP) const;
/// Shared implementation of `pushCall` overloads. Note that unlike
/// `pushCall`, this member is invoked on the environment of the callee, not
/// of the caller.
void pushCallInternal(const FunctionDecl *FuncDecl,
ArrayRef<const Expr *> Args);
/// Assigns storage locations and values to all variables in `Vars`.
void initVars(llvm::DenseSet<const VarDecl *> Vars);
// `DACtx` is not null and not owned by this object.
DataflowAnalysisContext *DACtx;
// FIXME: move the fields `CallStack`, `ReturnLoc` and `ThisPointeeLoc` into a
// separate call-context object, shared between environments in the same call.
// https://github.com/llvm/llvm-project/issues/59005
// `DeclContext` of the block being analysed if provided.
std::vector<const DeclContext *> CallStack;
// In a properly initialized `Environment`, `ReturnLoc` should only be null if
// its `DeclContext` could not be cast to a `FunctionDecl`.
StorageLocation *ReturnLoc = nullptr;
// The storage location of the `this` pointee. Should only be null if the
// function being analyzed is only a function and not a method.
StorageLocation *ThisPointeeLoc = nullptr;
// Maps from program declarations and statements to storage locations that are
// assigned to them. Unlike the maps in `DataflowAnalysisContext`, these
// include only storage locations that are in scope for a particular basic
@@ -18,6 +18,8 @@ namespace clang {
namespace dataflow {
/// Effect indicating whether a lattice join operation resulted in a new value.
// FIXME: Rename to `LatticeEffect` since `widen` uses it as well, and we are
// likely removing it from `join`.
enum class LatticeJoinEffect {
Unchanged,
Changed,
@@ -134,7 +134,7 @@ class DataflowValues {
/// getBlockDataMap - Retrieves the internal map between CFGBlocks and
/// dataflow values. If the dataflow analysis operates in the forward
/// direction, the values correspond to the dataflow values at the start
/// of the block. Otherwise, for a backward analysis, the values correpsond
/// of the block. Otherwise, for a backward analysis, the values correspond
/// to the dataflow values at the end of the block.
BlockDataMapTy& getBlockDataMap() { return BlockDataMap; }
const BlockDataMapTy& getBlockDataMap() const { return BlockDataMap; }
@@ -20,15 +20,19 @@
#include "clang/Analysis/FlowSensitive/Solver.h"
#include "clang/Analysis/FlowSensitive/Value.h"
#include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/StringRef.h"
namespace clang {
namespace dataflow {
/// Returns a string representation of a value kind.
llvm::StringRef debugString(Value::Kind Kind);
/// Returns a string representation of a boolean assignment to true or false.
std::string debugString(Solver::Result::Assignment Assignment);
llvm::StringRef debugString(Solver::Result::Assignment Assignment);
/// Returns a string representation of the result status of a SAT check.
std::string debugString(Solver::Result::Status Status);
llvm::StringRef debugString(Solver::Result::Status Status);
/// Returns a string representation for the boolean value `B`.
///
@@ -16,6 +16,9 @@
// library may be generalized and moved to ASTMatchers.
//
//===----------------------------------------------------------------------===//
//
// FIXME: Rename to ASTMatchSwitch.h and update documentation when all usages of
// `MatchSwitch` are updated to `ASTMatchSwitch<Stmt>`
#ifndef LLVM_CLANG_ANALYSIS_FLOWSENSITIVE_MATCHSWITCH_H_
#define LLVM_CLANG_ANALYSIS_FLOWSENSITIVE_MATCHSWITCH_H_
@@ -28,6 +31,7 @@
#include "llvm/ADT/StringRef.h"
#include <functional>
#include <string>
#include <type_traits>
#include <utility>
#include <vector>
@@ -44,23 +48,45 @@ template <typename LatticeT> struct TransferState {
Environment &Env;
};
/// Matches against `Stmt` and, based on its structure, dispatches to an
/// appropriate handler.
/// A read-only version of TransferState.
template <typename LatticeT> struct TransferStateForDiagnostics {
TransferStateForDiagnostics(const LatticeT &Lattice, const Environment &Env)
: Lattice(Lattice), Env(Env) {}
/// Current lattice element.
const LatticeT &Lattice;
const Environment &Env;
};
template <typename T>
using MatchSwitchMatcher = ast_matchers::internal::Matcher<T>;
template <typename T, typename State, typename Result = void>
using MatchSwitchAction = std::function<Result(
const T *, const ast_matchers::MatchFinder::MatchResult &, State &)>;
template <typename BaseT, typename State, typename Result = void>
using ASTMatchSwitch =
std::function<Result(const BaseT &, ASTContext &, State &)>;
// FIXME: Remove this alias when all usages of `MatchSwitch` are updated to
// `ASTMatchSwitch<Stmt>`.
template <typename State, typename Result = void>
using MatchSwitch = std::function<Result(const Stmt &, ASTContext &, State &)>;
using MatchSwitch = ASTMatchSwitch<Stmt, State, Result>;
/// Collects cases of a "match switch": a collection of matchers paired with
/// callbacks, which together define a switch that can be applied to a
/// `Stmt`. This structure can simplify the definition of `transfer` functions
/// that rely on pattern-matching.
/// callbacks, which together define a switch that can be applied to a node
/// whose type derives from `BaseT`. 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.
/// can define the `ASTMatchSwitch` 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>>()
/// ASTMatchSwitch<Stmt, TransferState<MyLattice> BuildSwitch() {
/// return ASTMatchSwitchBuilder<TransferState<MyLattice>>()
/// .CaseOf(callExpr(callee(functionDecl(hasName("foo")))), TransferFooCall)
/// .CaseOf(callExpr(argumentCountIs(2),
/// callee(functionDecl(hasName("bar")))),
@@ -68,35 +94,35 @@ using MatchSwitch = std::function<Result(const Stmt &, ASTContext &, State &)>;
/// .Build();
/// }
/// \endcode
template <typename State, typename Result = void> class MatchSwitchBuilder {
template <typename BaseT, typename State, typename Result = void>
class ASTMatchSwitchBuilder {
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) && {
/// `NodeT` should be derived from `BaseT`.
template <typename NodeT>
ASTMatchSwitchBuilder &&CaseOf(MatchSwitchMatcher<BaseT> M,
MatchSwitchAction<NodeT, State, Result> A) && {
static_assert(std::is_base_of<BaseT, NodeT>::value,
"NodeT must be derived from BaseT.");
Matchers.push_back(std::move(M));
Actions.push_back(
[A = std::move(A)](const Stmt *Stmt,
[A = std::move(A)](const BaseT *Node,
const ast_matchers::MatchFinder::MatchResult &R,
State &S) { return A(cast<Node>(Stmt), R, S); });
State &S) { return A(cast<NodeT>(Node), R, S); });
return std::move(*this);
}
MatchSwitch<State, Result> Build() && {
ASTMatchSwitch<BaseT, 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())
const BaseT &Node, ASTContext &Context, State &S) -> Result {
auto Results = ast_matchers::matchDynamic(Matcher, Node, 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()) {
@@ -105,7 +131,7 @@ template <typename State, typename Result = void> class MatchSwitchBuilder {
if (ID.consume_front("Tag") && !ID.getAsInteger(10, Index) &&
Index < Actions.size()) {
return Actions[Index](
&Stmt,
&Node,
ast_matchers::MatchFinder::MatchResult(Results[0], &Context), S);
}
}
@@ -137,15 +163,19 @@ template <typename State, typename Result = void> class MatchSwitchBuilder {
// 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>(),
DynTypedMatcher::VO_AnyOf, ASTNodeKind::getFromNodeKind<BaseT>(),
std::move(Matchers));
}
std::vector<ast_matchers::internal::DynTypedMatcher> Matchers;
std::vector<std::function<Result(
const Stmt *, const ast_matchers::MatchFinder::MatchResult &, State &)>>
Actions;
std::vector<MatchSwitchAction<BaseT, State, Result>> Actions;
};
// FIXME: Remove this alias when all usages of `MatchSwitchBuilder` are updated
// to `ASTMatchSwitchBuilder<Stmt>`.
template <typename State, typename Result = void>
using MatchSwitchBuilder = ASTMatchSwitchBuilder<Stmt, State, Result>;
} // namespace dataflow
} // namespace clang
#endif // LLVM_CLANG_ANALYSIS_FLOWSENSITIVE_MATCHSWITCH_H_
@@ -26,7 +26,7 @@ namespace dataflow {
class ChromiumCheckModel : public DataflowModel {
public:
ChromiumCheckModel() = default;
bool transfer(const Stmt *Stmt, Environment &Env) override;
bool transfer(const CFGElement *Element, Environment &Env) override;
private:
/// Declarations for `::logging::CheckError::.*Check`, lazily initialized.
@@ -15,10 +15,10 @@
#define CLANG_ANALYSIS_FLOWSENSITIVE_MODELS_UNCHECKEDOPTIONALACCESSMODEL_H
#include "clang/AST/ASTContext.h"
#include "clang/AST/Stmt.h"
#include "clang/Analysis/CFG.h"
#include "clang/Analysis/FlowSensitive/CFGMatchSwitch.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>
@@ -30,11 +30,12 @@ namespace dataflow {
// 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[]`.
/// In generating diagnostics, 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;
};
@@ -44,17 +45,16 @@ struct UncheckedOptionalAccessModelOptions {
class UncheckedOptionalAccessModel
: public DataflowAnalysis<UncheckedOptionalAccessModel, NoopLattice> {
public:
UncheckedOptionalAccessModel(
ASTContext &AstContext, UncheckedOptionalAccessModelOptions Options = {});
UncheckedOptionalAccessModel(ASTContext &Ctx);
/// 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);
void transfer(const CFGElement *Elt, NoopLattice &L, Environment &Env);
bool compareEquivalent(QualType Type, const Value &Val1,
ComparisonResult compare(QualType Type, const Value &Val1,
const Environment &Env1, const Value &Val2,
const Environment &Env2) override;
@@ -62,8 +62,11 @@ class UncheckedOptionalAccessModel
const Value &Val2, const Environment &Env2, Value &MergedVal,
Environment &MergedEnv) override;
Value *widen(QualType Type, Value &Prev, const Environment &PrevEnv,
Value &Current, Environment &CurrentEnv) override;
private:
MatchSwitch<TransferState<NoopLattice>> TransferMatchSwitch;
CFGMatchSwitch<TransferState<NoopLattice>> TransferMatchSwitch;
};
class UncheckedOptionalAccessDiagnoser {
@@ -71,11 +74,11 @@ class UncheckedOptionalAccessDiagnoser {
UncheckedOptionalAccessDiagnoser(
UncheckedOptionalAccessModelOptions Options = {});
std::vector<SourceLocation> diagnose(ASTContext &Context, const Stmt *Stmt,
std::vector<SourceLocation> diagnose(ASTContext &Ctx, const CFGElement *Elt,
const Environment &Env);
private:
MatchSwitch<const Environment, std::vector<SourceLocation>>
CFGMatchSwitch<const Environment, std::vector<SourceLocation>>
DiagnoseMatchSwitch;
};
@@ -14,7 +14,7 @@
#define LLVM_CLANG_ANALYSIS_FLOWSENSITIVE_NOOPANALYSIS_H
#include "clang/AST/ASTContext.h"
#include "clang/AST/Stmt.h"
#include "clang/Analysis/CFG.h"
#include "clang/Analysis/FlowSensitive/DataflowAnalysis.h"
#include "clang/Analysis/FlowSensitive/DataflowEnvironment.h"
#include "clang/Analysis/FlowSensitive/NoopLattice.h"
@@ -38,7 +38,7 @@ class NoopAnalysis : public DataflowAnalysis<NoopAnalysis, NoopLattice> {
static NoopLattice initialElement() { return {}; }
void transfer(const Stmt *S, NoopLattice &E, Environment &Env) {}
void transfer(const CFGElement *E, NoopLattice &L, Environment &Env) {}
};
} // namespace dataflow
@@ -17,7 +17,7 @@
#include "clang/Analysis/FlowSensitive/Value.h"
#include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/DenseSet.h"
#include "llvm/ADT/Optional.h"
#include <optional>
namespace clang {
namespace dataflow {
@@ -64,7 +64,7 @@ class Solver {
/// Returns a truth assignment to boolean values that satisfies the queried
/// boolean formula if available. Otherwise, an empty optional is returned.
llvm::Optional<llvm::DenseMap<AtomicBoolValue *, Assignment>>
std::optional<llvm::DenseMap<AtomicBoolValue *, Assignment>>
getSolution() const {
return Solution;
}
@@ -72,11 +72,11 @@ class Solver {
private:
Result(
enum Status SATCheckStatus,
llvm::Optional<llvm::DenseMap<AtomicBoolValue *, Assignment>> Solution)
std::optional<llvm::DenseMap<AtomicBoolValue *, Assignment>> Solution)
: SATCheckStatus(SATCheckStatus), Solution(std::move(Solution)) {}
Status SATCheckStatus;
llvm::Optional<llvm::DenseMap<AtomicBoolValue *, Assignment>> Solution;
std::optional<llvm::DenseMap<AtomicBoolValue *, Assignment>> Solution;
};
virtual ~Solver() = default;
@@ -65,6 +65,9 @@ class ScalarStorageLocation final : public StorageLocation {
/// 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.
/// FIXME: Currently, the storage location of unions is modelled the same way as
/// that of structs or classes. Eventually, we need to change this modelling so
/// that all of the members of a given union have the same storage location.
class AggregateStorageLocation final : public StorageLocation {
public:
explicit AggregateStorageLocation(QualType Type)
@@ -15,17 +15,12 @@
#define LLVM_CLANG_ANALYSIS_FLOWSENSITIVE_TRANSFER_H
#include "clang/AST/Stmt.h"
#include "clang/Analysis/FlowSensitive/DataflowAnalysisContext.h"
#include "clang/Analysis/FlowSensitive/DataflowEnvironment.h"
namespace clang {
namespace dataflow {
struct TransferOptions {
/// Determines whether to analyze function bodies when present in the
/// translation unit.
bool ContextSensitive = false;
};
/// Maps statements to the environments of basic blocks that contain them.
class StmtToEnvMap {
public:
@@ -42,8 +37,7 @@ class StmtToEnvMap {
/// Requirements:
///
/// `S` must not be `ParenExpr` or `ExprWithCleanups`.
void transfer(const StmtToEnvMap &StmtToEnv, const Stmt &S, Environment &Env,
TransferOptions Options);
void transfer(const StmtToEnvMap &StmtToEnv, const Stmt &S, Environment &Env);
} // namespace dataflow
} // namespace clang
@@ -14,6 +14,7 @@
#ifndef LLVM_CLANG_ANALYSIS_FLOWSENSITIVE_TYPEERASEDDATAFLOWANALYSIS_H
#define LLVM_CLANG_ANALYSIS_FLOWSENSITIVE_TYPEERASEDDATAFLOWANALYSIS_H
#include <optional>
#include <utility>
#include <vector>
@@ -21,25 +22,22 @@
#include "clang/AST/Stmt.h"
#include "clang/Analysis/CFG.h"
#include "clang/Analysis/FlowSensitive/ControlFlowContext.h"
#include "clang/Analysis/FlowSensitive/DataflowAnalysisContext.h"
#include "clang/Analysis/FlowSensitive/DataflowEnvironment.h"
#include "clang/Analysis/FlowSensitive/DataflowLattice.h"
#include "clang/Analysis/FlowSensitive/Transfer.h"
#include "llvm/ADT/Any.h"
#include "llvm/ADT/Optional.h"
#include "llvm/Support/Error.h"
namespace clang {
namespace dataflow {
struct DataflowAnalysisOptions {
/// Determines whether to apply the built-in transfer functions.
/// Options for the built-in model, or empty to not apply them.
// FIXME: Remove this option once the framework supports composing analyses
// (at which point the built-in transfer functions can be simply a standalone
// analysis).
bool ApplyBuiltinTransfer = true;
/// Only has an effect if `ApplyBuiltinTransfer` is true.
TransferOptions BuiltinTransferOptions;
std::optional<DataflowAnalysisContext::Options> BuiltinOpts =
DataflowAnalysisContext::Options{};
};
/// Type-erased lattice element container.
@@ -59,10 +57,6 @@ class TypeErasedDataflowAnalysis : public Environment::ValueModel {
public:
TypeErasedDataflowAnalysis() : Options({}) {}
/// Deprecated. Use the `DataflowAnalysisOptions` constructor instead.
TypeErasedDataflowAnalysis(bool ApplyBuiltinTransfer)
: Options({ApplyBuiltinTransfer, TransferOptions{}}) {}
TypeErasedDataflowAnalysis(DataflowAnalysisOptions Options)
: Options(Options) {}
@@ -81,23 +75,43 @@ class TypeErasedDataflowAnalysis : public Environment::ValueModel {
virtual LatticeJoinEffect joinTypeErased(TypeErasedLattice &,
const TypeErasedLattice &) = 0;
/// Chooses a lattice element that approximates the current element at a
/// program point, given the previous element at that point. Places the
/// widened result in the current element (`Current`). Widening is optional --
/// it is only needed to either accelerate convergence (for lattices with
/// non-trivial height) or guarantee convergence (for lattices with infinite
/// height).
///
/// Returns an indication of whether any changes were made to `Current` in
/// order to widen. This saves a separate call to `isEqualTypeErased` after
/// the widening.
virtual LatticeJoinEffect
widenTypeErased(TypeErasedLattice &Current,
const TypeErasedLattice &Previous) = 0;
/// Returns true if and only if the two given type-erased lattice elements are
/// equal.
virtual bool isEqualTypeErased(const TypeErasedLattice &,
const TypeErasedLattice &) = 0;
/// Applies the analysis transfer function for a given statement and
/// type-erased lattice element.
virtual void transferTypeErased(const Stmt *, TypeErasedLattice &,
/// Applies the analysis transfer function for a given control flow graph
/// element and type-erased lattice element.
virtual void transferTypeErased(const CFGElement *, TypeErasedLattice &,
Environment &) = 0;
/// Determines whether to apply the built-in transfer functions, which model
/// the heap and stack in the `Environment`.
bool applyBuiltinTransfer() const { return Options.ApplyBuiltinTransfer; }
/// Applies the analysis transfer function for a given edge from a CFG block
/// of a conditional statement.
/// @param Stmt The condition which is responsible for the split in the CFG.
/// @param Branch True if the edge goes to the basic block where the
/// condition is true.
virtual void transferBranchTypeErased(bool Branch, const Stmt *,
TypeErasedLattice &, Environment &) = 0;
/// Returns the options to be passed to the built-in transfer functions.
TransferOptions builtinTransferOptions() const {
return Options.BuiltinTransferOptions;
/// If the built-in model is enabled, returns the options to be passed to
/// them. Otherwise returns empty.
const std::optional<DataflowAnalysisContext::Options> &
builtinOptions() const {
return Options.BuiltinOpts;
}
};
@@ -113,37 +127,38 @@ struct TypeErasedDataflowAnalysisState {
: Lattice(std::move(Lattice)), Env(std::move(Env)) {}
};
/// Transfers the state of a basic block by evaluating each of its statements in
/// Transfers the state of a basic block by evaluating each of its elements in
/// the context of `Analysis` and the states of its predecessors that are
/// available in `BlockStates`. `HandleTransferredStmt` (if provided) will be
/// applied to each statement in the block, after it is evaluated.
/// available in `BlockStates`. `PostVisitCFG` (if provided) will be applied to
/// each element in the block, after it is evaluated.
///
/// Requirements:
///
/// All predecessors of `Block` except those with loop back edges must have
/// already been transferred. States in `BlockStates` that are set to
/// `llvm::None` represent basic blocks that are not evaluated yet.
/// `std::nullopt` represent basic blocks that are not evaluated yet.
TypeErasedDataflowAnalysisState transferBlock(
const ControlFlowContext &CFCtx,
std::vector<llvm::Optional<TypeErasedDataflowAnalysisState>> &BlockStates,
llvm::ArrayRef<std::optional<TypeErasedDataflowAnalysisState>> BlockStates,
const CFGBlock &Block, const Environment &InitEnv,
TypeErasedDataflowAnalysis &Analysis,
std::function<void(const CFGStmt &,
std::function<void(const CFGElement &,
const TypeErasedDataflowAnalysisState &)>
HandleTransferredStmt = nullptr);
PostVisitCFG = 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. Otherwise, calls
/// `PostVisitStmt` on each statement with the final analysis results at that
/// `PostVisitCFG` on each CFG element with the final analysis results at that
/// program point.
llvm::Expected<std::vector<llvm::Optional<TypeErasedDataflowAnalysisState>>>
llvm::Expected<std::vector<std::optional<TypeErasedDataflowAnalysisState>>>
runTypeErasedDataflowAnalysis(
const ControlFlowContext &CFCtx, TypeErasedDataflowAnalysis &Analysis,
const Environment &InitEnv,
std::function<void(const Stmt *, const TypeErasedDataflowAnalysisState &)>
PostVisitStmt = nullptr);
std::function<void(const CFGElement &,
const TypeErasedDataflowAnalysisState &)>
PostVisitCFG = nullptr);
} // namespace dataflow
} // namespace clang
@@ -19,6 +19,7 @@
#include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/StringMap.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/Support/raw_ostream.h"
#include <cassert>
#include <utility>
@@ -38,6 +39,7 @@ class Value {
Struct,
// Synthetic boolean values are either atomic values or logical connectives.
TopBool,
AtomicBool,
Conjunction,
Disjunction,
@@ -76,13 +78,25 @@ class Value {
llvm::StringMap<Value *> Properties;
};
/// An equivalence relation for values. It obeys reflexivity, symmetry and
/// transitivity. It does *not* include comparison of `Properties`.
///
/// Computes equivalence for these subclasses:
/// * ReferenceValue, PointerValue -- pointee locations are equal. Does not
/// compute deep equality of `Value` at said location.
/// * TopBoolValue -- both are `TopBoolValue`s.
///
/// Otherwise, falls back to pointer equality.
bool areEquivalentValues(const Value &Val1, const Value &Val2);
/// 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 ||
return Val->getKind() == Kind::TopBool ||
Val->getKind() == Kind::AtomicBool ||
Val->getKind() == Kind::Conjunction ||
Val->getKind() == Kind::Disjunction ||
Val->getKind() == Kind::Negation ||
@@ -91,6 +105,17 @@ class BoolValue : public Value {
}
};
/// Models the trivially true formula, which is Top in the lattice of boolean
/// formulas.
class TopBoolValue final : public BoolValue {
public:
TopBoolValue() : BoolValue(Kind::TopBool) {}
static bool classof(const Value *Val) {
return Val->getKind() == Kind::TopBool;
}
};
/// Models an atomic boolean.
class AtomicBoolValue : public BoolValue {
public:
@@ -286,6 +311,8 @@ class StructValue final : public Value {
llvm::DenseMap<const ValueDecl *, Value *> Children;
};
raw_ostream &operator<<(raw_ostream &OS, const Value &Val);
} // namespace dataflow
} // namespace clang
@@ -13,9 +13,9 @@
#include "clang/Basic/SourceLocation.h"
#include "clang/Lex/Preprocessor.h"
#include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/Optional.h"
#include "llvm/ADT/SmallString.h"
#include "llvm/ADT/SmallVector.h"
#include <optional>
namespace clang {
@@ -85,14 +85,16 @@ class MacroExpansionContext {
/// \param MacroExpansionLoc Must be the expansion location of a macro.
/// \return The textual representation of the token sequence which was
/// substituted in place of the macro after the preprocessing.
/// If no macro was expanded at that location, returns llvm::None.
Optional<StringRef> getExpandedText(SourceLocation MacroExpansionLoc) const;
/// If no macro was expanded at that location, returns std::nullopt.
std::optional<StringRef>
getExpandedText(SourceLocation MacroExpansionLoc) const;
/// \param MacroExpansionLoc Must be the expansion location of a macro.
/// \return The text from the original source code which were substituted by
/// the macro expansion chain from the given location.
/// If no macro was expanded at that location, returns llvm::None.
Optional<StringRef> getOriginalText(SourceLocation MacroExpansionLoc) const;
/// If no macro was expanded at that location, returns std::nullopt.
std::optional<StringRef>
getOriginalText(SourceLocation MacroExpansionLoc) const;
LLVM_DUMP_METHOD void dumpExpansionRangesToStream(raw_ostream &OS) const;
LLVM_DUMP_METHOD void dumpExpandedTextsToStream(raw_ostream &OS) const;
@@ -19,7 +19,6 @@
#include "clang/Basic/SourceLocation.h"
#include "llvm/ADT/ArrayRef.h"
#include "llvm/ADT/FoldingSet.h"
#include "llvm/ADT/Optional.h"
#include "llvm/ADT/PointerUnion.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/ADT/StringRef.h"
@@ -30,6 +29,7 @@
#include <list>
#include <map>
#include <memory>
#include <optional>
#include <set>
#include <string>
#include <utility>
@@ -73,7 +73,7 @@ struct PathDiagnosticConsumerOptions {
bool ShouldSerializeStats = false;
/// If the consumer intends to produce multiple output files, should it
/// use a pseudo-random file name name or a human-readable file name.
/// use a pseudo-random file name or a human-readable file name.
bool ShouldWriteVerboseReportFilename = false;
/// Whether the consumer should treat consumed diagnostics as hard errors.
@@ -532,7 +532,7 @@ class PathDiagnosticSpotPiece : public PathDiagnosticPiece {
};
class PathDiagnosticEventPiece : public PathDiagnosticSpotPiece {
Optional<bool> IsPrunable;
std::optional<bool> IsPrunable;
public:
PathDiagnosticEventPiece(const PathDiagnosticLocation &pos,

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