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:
@@ -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
|
||||
|
||||
@@ -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);
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
|
||||
@@ -2853,10 +2866,12 @@ class ASTContext : public RefCountedBase<ASTContext> {
|
||||
bool canBindObjCObjectType(QualType To, QualType From);
|
||||
|
||||
// Functions for calculating composite types
|
||||
QualType mergeTypes(QualType, QualType, bool OfBlockPointer=false,
|
||||
bool Unqualified = false, bool BlockReturnType = false);
|
||||
QualType mergeFunctionTypes(QualType, QualType, bool OfBlockPointer=false,
|
||||
bool Unqualified = false, bool AllowCXX = false);
|
||||
QualType mergeTypes(QualType, QualType, bool OfBlockPointer = false,
|
||||
bool Unqualified = false, bool BlockReturnType = false,
|
||||
bool IsConditionalOperator = false);
|
||||
QualType mergeFunctionTypes(QualType, QualType, bool OfBlockPointer = 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);
|
||||
}
|
||||
|
||||
@@ -430,7 +430,7 @@ class ConcreteTypeLoc : public Base {
|
||||
unsigned size = sizeof(LocalData);
|
||||
unsigned extraAlign = asDerived()->getExtraLocalDataAlignment();
|
||||
size = llvm::alignTo(size, extraAlign);
|
||||
return reinterpret_cast<char*>(Base::Data) + size;
|
||||
return reinterpret_cast<char *>(Base::Data) + size;
|
||||
}
|
||||
|
||||
void *getNonLocalData() const {
|
||||
@@ -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 */
|
||||
+35
@@ -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_
|
||||
+15
-5
@@ -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;
|
||||
};
|
||||
|
||||
+95
-25
@@ -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
|
||||
|
||||
+59
-27
@@ -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
|
||||
|
||||
+127
-12
@@ -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_
|
||||
|
||||
+1
-1
@@ -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.
|
||||
|
||||
+17
-14
@@ -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
|
||||
|
||||
+46
-31
@@ -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
Reference in New Issue
Block a user