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;
|
# xargs -n1 | sort | uniq -d;
|
||||||
# done
|
# 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
|
# 20230614: caroot bundle updated
|
||||||
OLD_FILES+=usr/share/certs/trusted/Cybertrust_Global_Root.pem
|
OLD_FILES+=usr/share/certs/trusted/Cybertrust_Global_Root.pem
|
||||||
OLD_FILES+=usr/share/certs/trusted/DST_Root_CA_X3.pem
|
OLD_FILES+=usr/share/certs/trusted/DST_Root_CA_X3.pem
|
||||||
|
|||||||
@@ -7,6 +7,7 @@
|
|||||||
.gitignore
|
.gitignore
|
||||||
.mailmap
|
.mailmap
|
||||||
CONTRIBUTING.md
|
CONTRIBUTING.md
|
||||||
|
LICENSE.TXT
|
||||||
README.md
|
README.md
|
||||||
SECURITY.md
|
SECURITY.md
|
||||||
bolt/
|
bolt/
|
||||||
@@ -15,7 +16,7 @@ clang/.clang-format
|
|||||||
clang/.clang-tidy
|
clang/.clang-tidy
|
||||||
clang/.gitignore
|
clang/.gitignore
|
||||||
clang/CMakeLists.txt
|
clang/CMakeLists.txt
|
||||||
clang/CODE_OWNERS.TXT
|
clang/CodeOwners.rst
|
||||||
clang/INSTALL.txt
|
clang/INSTALL.txt
|
||||||
clang/ModuleInfo.txt
|
clang/ModuleInfo.txt
|
||||||
clang/NOTES.txt
|
clang/NOTES.txt
|
||||||
@@ -31,6 +32,7 @@ clang/include/clang/Basic/Version.inc.in
|
|||||||
clang/include/clang/CMakeLists.txt
|
clang/include/clang/CMakeLists.txt
|
||||||
clang/include/clang/Config/
|
clang/include/clang/Config/
|
||||||
clang/include/clang/Driver/CMakeLists.txt
|
clang/include/clang/Driver/CMakeLists.txt
|
||||||
|
clang/include/clang/Format/.clang-format
|
||||||
clang/include/clang/Parse/CMakeLists.txt
|
clang/include/clang/Parse/CMakeLists.txt
|
||||||
clang/include/clang/Sema/CMakeLists.txt
|
clang/include/clang/Sema/CMakeLists.txt
|
||||||
clang/include/clang/Serialization/CMakeLists.txt
|
clang/include/clang/Serialization/CMakeLists.txt
|
||||||
@@ -57,6 +59,7 @@ clang/lib/DirectoryWatcher/CMakeLists.txt
|
|||||||
clang/lib/Driver/CMakeLists.txt
|
clang/lib/Driver/CMakeLists.txt
|
||||||
clang/lib/Edit/CMakeLists.txt
|
clang/lib/Edit/CMakeLists.txt
|
||||||
clang/lib/ExtractAPI/CMakeLists.txt
|
clang/lib/ExtractAPI/CMakeLists.txt
|
||||||
|
clang/lib/Format/.clang-format
|
||||||
clang/lib/Format/CMakeLists.txt
|
clang/lib/Format/CMakeLists.txt
|
||||||
clang/lib/Frontend/CMakeLists.txt
|
clang/lib/Frontend/CMakeLists.txt
|
||||||
clang/lib/Frontend/Rewrite/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/CMakeLists.txt
|
||||||
clang/lib/Tooling/DumpTool/generate_cxx_src_locs.py
|
clang/lib/Tooling/DumpTool/generate_cxx_src_locs.py
|
||||||
clang/lib/Tooling/Inclusions/CMakeLists.txt
|
clang/lib/Tooling/Inclusions/CMakeLists.txt
|
||||||
|
clang/lib/Tooling/Inclusions/Stdlib/CMakeLists.txt
|
||||||
clang/lib/Tooling/Refactoring/CMakeLists.txt
|
clang/lib/Tooling/Refactoring/CMakeLists.txt
|
||||||
clang/lib/Tooling/Syntax/CMakeLists.txt
|
clang/lib/Tooling/Syntax/CMakeLists.txt
|
||||||
clang/lib/Tooling/Transformer/CMakeLists.txt
|
clang/lib/Tooling/Transformer/CMakeLists.txt
|
||||||
@@ -99,6 +103,7 @@ clang/tools/clang-check/
|
|||||||
clang/tools/clang-diff/
|
clang/tools/clang-diff/
|
||||||
clang/tools/clang-extdef-mapping/
|
clang/tools/clang-extdef-mapping/
|
||||||
clang/tools/clang-format-vs/
|
clang/tools/clang-format-vs/
|
||||||
|
clang/tools/clang-format/.clang-format
|
||||||
clang/tools/clang-format/CMakeLists.txt
|
clang/tools/clang-format/CMakeLists.txt
|
||||||
clang/tools/clang-format/clang-format-bbedit.applescript
|
clang/tools/clang-format/clang-format-bbedit.applescript
|
||||||
clang/tools/clang-format/clang-format-diff.py
|
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-fuzzer/
|
||||||
clang/tools/clang-import-test/
|
clang/tools/clang-import-test/
|
||||||
clang/tools/clang-linker-wrapper/
|
clang/tools/clang-linker-wrapper/
|
||||||
clang/tools/clang-nvlink-wrapper/
|
|
||||||
clang/tools/clang-offload-bundler/
|
clang/tools/clang-offload-bundler/
|
||||||
clang/tools/clang-offload-packager/
|
clang/tools/clang-offload-packager/
|
||||||
clang/tools/clang-offload-wrapper/
|
|
||||||
clang/tools/clang-refactor/
|
clang/tools/clang-refactor/
|
||||||
clang/tools/clang-rename/
|
clang/tools/clang-rename/
|
||||||
clang/tools/clang-repl/CMakeLists.txt
|
clang/tools/clang-repl/CMakeLists.txt
|
||||||
@@ -126,6 +129,7 @@ clang/tools/driver/CMakeLists.txt
|
|||||||
clang/tools/driver/Info.plist.in
|
clang/tools/driver/Info.plist.in
|
||||||
clang/tools/include-mapping/
|
clang/tools/include-mapping/
|
||||||
clang/tools/libclang/
|
clang/tools/libclang/
|
||||||
|
clang/tools/nvptx-arch/CMakeLists.txt
|
||||||
clang/tools/scan-build-py/
|
clang/tools/scan-build-py/
|
||||||
clang/tools/scan-build/
|
clang/tools/scan-build/
|
||||||
clang/tools/scan-view/
|
clang/tools/scan-view/
|
||||||
@@ -201,7 +205,9 @@ compiler-rt/lib/msan/.clang-format
|
|||||||
compiler-rt/lib/msan/CMakeLists.txt
|
compiler-rt/lib/msan/CMakeLists.txt
|
||||||
compiler-rt/lib/msan/tests/
|
compiler-rt/lib/msan/tests/
|
||||||
compiler-rt/lib/orc/CMakeLists.txt
|
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/profile/CMakeLists.txt
|
||||||
compiler-rt/lib/safestack/.clang-format
|
compiler-rt/lib/safestack/.clang-format
|
||||||
compiler-rt/lib/safestack/CMakeLists.txt
|
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/CMakeLists.txt
|
||||||
compiler-rt/lib/sanitizer_common/scripts/
|
compiler-rt/lib/sanitizer_common/scripts/
|
||||||
compiler-rt/lib/sanitizer_common/tests/
|
compiler-rt/lib/sanitizer_common/tests/
|
||||||
compiler-rt/lib/scudo/CMakeLists.txt
|
|
||||||
compiler-rt/lib/scudo/standalone/CMakeLists.txt
|
compiler-rt/lib/scudo/standalone/CMakeLists.txt
|
||||||
compiler-rt/lib/scudo/standalone/benchmarks/
|
compiler-rt/lib/scudo/standalone/benchmarks/
|
||||||
compiler-rt/lib/scudo/standalone/fuzz/CMakeLists.txt
|
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/dd/CMakeLists.txt
|
||||||
compiler-rt/lib/tsan/go/build.bat
|
compiler-rt/lib/tsan/go/build.bat
|
||||||
compiler-rt/lib/tsan/go/buildgo.sh
|
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/rtl/CMakeLists.txt
|
||||||
compiler-rt/lib/tsan/tests/
|
compiler-rt/lib/tsan/tests/
|
||||||
compiler-rt/lib/ubsan/CMakeLists.txt
|
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/ARM/CMakeLists.txt
|
||||||
lldb/source/Plugins/Instruction/ARM64/CMakeLists.txt
|
lldb/source/Plugins/Instruction/ARM64/CMakeLists.txt
|
||||||
lldb/source/Plugins/Instruction/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/MIPS/CMakeLists.txt
|
||||||
lldb/source/Plugins/Instruction/MIPS64/CMakeLists.txt
|
lldb/source/Plugins/Instruction/MIPS64/CMakeLists.txt
|
||||||
lldb/source/Plugins/Instruction/PPC64/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/ASan/CMakeLists.txt
|
||||||
lldb/source/Plugins/InstrumentationRuntime/CMakeLists.txt
|
lldb/source/Plugins/InstrumentationRuntime/CMakeLists.txt
|
||||||
lldb/source/Plugins/InstrumentationRuntime/MainThreadChecker/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/MemoryHistory/asan/CMakeLists.txt
|
||||||
lldb/source/Plugins/ObjectContainer/BSD-Archive/CMakeLists.txt
|
lldb/source/Plugins/ObjectContainer/BSD-Archive/CMakeLists.txt
|
||||||
lldb/source/Plugins/ObjectContainer/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/ObjectContainer/Universal-Mach-O/
|
||||||
lldb/source/Plugins/ObjectFile/Breakpad/CMakeLists.txt
|
lldb/source/Plugins/ObjectFile/Breakpad/CMakeLists.txt
|
||||||
lldb/source/Plugins/ObjectFile/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/IR/CMakeLists.txt
|
||||||
llvm/include/llvm/Support/CMakeLists.txt
|
llvm/include/llvm/Support/CMakeLists.txt
|
||||||
llvm/include/llvm/Support/LICENSE.TXT
|
llvm/include/llvm/Support/LICENSE.TXT
|
||||||
|
llvm/include/llvm/TargetParser/CMakeLists.txt
|
||||||
llvm/lib/Analysis/CMakeLists.txt
|
llvm/lib/Analysis/CMakeLists.txt
|
||||||
llvm/lib/Analysis/README.txt
|
llvm/lib/Analysis/README.txt
|
||||||
llvm/lib/Analysis/models/
|
llvm/lib/Analysis/models/
|
||||||
@@ -518,11 +526,13 @@ llvm/lib/CodeGen/MIRParser/CMakeLists.txt
|
|||||||
llvm/lib/CodeGen/README.txt
|
llvm/lib/CodeGen/README.txt
|
||||||
llvm/lib/CodeGen/SelectionDAG/CMakeLists.txt
|
llvm/lib/CodeGen/SelectionDAG/CMakeLists.txt
|
||||||
llvm/lib/DWARFLinker/CMakeLists.txt
|
llvm/lib/DWARFLinker/CMakeLists.txt
|
||||||
|
llvm/lib/DWARFLinkerParallel/CMakeLists.txt
|
||||||
llvm/lib/DWP/CMakeLists.txt
|
llvm/lib/DWP/CMakeLists.txt
|
||||||
llvm/lib/DebugInfo/CMakeLists.txt
|
llvm/lib/DebugInfo/CMakeLists.txt
|
||||||
llvm/lib/DebugInfo/CodeView/CMakeLists.txt
|
llvm/lib/DebugInfo/CodeView/CMakeLists.txt
|
||||||
llvm/lib/DebugInfo/DWARF/CMakeLists.txt
|
llvm/lib/DebugInfo/DWARF/CMakeLists.txt
|
||||||
llvm/lib/DebugInfo/GSYM/CMakeLists.txt
|
llvm/lib/DebugInfo/GSYM/CMakeLists.txt
|
||||||
|
llvm/lib/DebugInfo/LogicalView/CMakeLists.txt
|
||||||
llvm/lib/DebugInfo/MSF/CMakeLists.txt
|
llvm/lib/DebugInfo/MSF/CMakeLists.txt
|
||||||
llvm/lib/DebugInfo/PDB/CMakeLists.txt
|
llvm/lib/DebugInfo/PDB/CMakeLists.txt
|
||||||
llvm/lib/DebugInfo/Symbolize/CMakeLists.txt
|
llvm/lib/DebugInfo/Symbolize/CMakeLists.txt
|
||||||
@@ -542,11 +552,13 @@ llvm/lib/ExecutionEngine/RuntimeDyld/CMakeLists.txt
|
|||||||
llvm/lib/Extensions/
|
llvm/lib/Extensions/
|
||||||
llvm/lib/FileCheck/CMakeLists.txt
|
llvm/lib/FileCheck/CMakeLists.txt
|
||||||
llvm/lib/Frontend/CMakeLists.txt
|
llvm/lib/Frontend/CMakeLists.txt
|
||||||
|
llvm/lib/Frontend/HLSL/CMakeLists.txt
|
||||||
llvm/lib/Frontend/OpenACC/CMakeLists.txt
|
llvm/lib/Frontend/OpenACC/CMakeLists.txt
|
||||||
llvm/lib/Frontend/OpenMP/CMakeLists.txt
|
llvm/lib/Frontend/OpenMP/CMakeLists.txt
|
||||||
llvm/lib/FuzzMutate/CMakeLists.txt
|
llvm/lib/FuzzMutate/CMakeLists.txt
|
||||||
llvm/lib/Fuzzer/
|
llvm/lib/Fuzzer/
|
||||||
llvm/lib/IR/CMakeLists.txt
|
llvm/lib/IR/CMakeLists.txt
|
||||||
|
llvm/lib/IRPrinter/CMakeLists.txt
|
||||||
llvm/lib/IRReader/CMakeLists.txt
|
llvm/lib/IRReader/CMakeLists.txt
|
||||||
llvm/lib/InterfaceStub/CMakeLists.txt
|
llvm/lib/InterfaceStub/CMakeLists.txt
|
||||||
llvm/lib/LTO/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/CSKY/TargetInfo/CMakeLists.txt
|
||||||
llvm/lib/Target/DirectX/CMakeLists.txt
|
llvm/lib/Target/DirectX/CMakeLists.txt
|
||||||
llvm/lib/Target/DirectX/DXILWriter/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/MCTargetDesc/CMakeLists.txt
|
||||||
llvm/lib/Target/DirectX/TargetInfo/CMakeLists.txt
|
llvm/lib/Target/DirectX/TargetInfo/CMakeLists.txt
|
||||||
llvm/lib/Target/Hexagon/AsmParser/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/AsmParser/CMakeLists.txt
|
||||||
llvm/lib/Target/RISCV/CMakeLists.txt
|
llvm/lib/Target/RISCV/CMakeLists.txt
|
||||||
llvm/lib/Target/RISCV/Disassembler/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/MCTargetDesc/CMakeLists.txt
|
||||||
llvm/lib/Target/RISCV/TargetInfo/CMakeLists.txt
|
llvm/lib/Target/RISCV/TargetInfo/CMakeLists.txt
|
||||||
llvm/lib/Target/SPIRV/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/MCTargetDesc/CMakeLists.txt
|
||||||
llvm/lib/Target/XCore/README.txt
|
llvm/lib/Target/XCore/README.txt
|
||||||
llvm/lib/Target/XCore/TargetInfo/CMakeLists.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/CMakeLists.txt
|
||||||
llvm/lib/Testing/Support/CMakeLists.txt
|
llvm/lib/Testing/Support/CMakeLists.txt
|
||||||
llvm/lib/TextAPI/CMakeLists.txt
|
llvm/lib/TextAPI/CMakeLists.txt
|
||||||
@@ -749,7 +770,9 @@ llvm/tools/llvm-cvtres/
|
|||||||
llvm/tools/llvm-cxxdump/CMakeLists.txt
|
llvm/tools/llvm-cxxdump/CMakeLists.txt
|
||||||
llvm/tools/llvm-cxxfilt/CMakeLists.txt
|
llvm/tools/llvm-cxxfilt/CMakeLists.txt
|
||||||
llvm/tools/llvm-cxxmap/CMakeLists.txt
|
llvm/tools/llvm-cxxmap/CMakeLists.txt
|
||||||
|
llvm/tools/llvm-debuginfo-analyzer/CMakeLists.txt
|
||||||
llvm/tools/llvm-debuginfod-find/
|
llvm/tools/llvm-debuginfod-find/
|
||||||
|
llvm/tools/llvm-debuginfod/
|
||||||
llvm/tools/llvm-diff/CMakeLists.txt
|
llvm/tools/llvm-diff/CMakeLists.txt
|
||||||
llvm/tools/llvm-diff/lib/CMakeLists.txt
|
llvm/tools/llvm-diff/lib/CMakeLists.txt
|
||||||
llvm/tools/llvm-dis-fuzzer/
|
llvm/tools/llvm-dis-fuzzer/
|
||||||
@@ -758,10 +781,10 @@ llvm/tools/llvm-dlang-demangle-fuzzer/
|
|||||||
llvm/tools/llvm-driver/
|
llvm/tools/llvm-driver/
|
||||||
llvm/tools/llvm-dwarfdump/CMakeLists.txt
|
llvm/tools/llvm-dwarfdump/CMakeLists.txt
|
||||||
llvm/tools/llvm-dwarfdump/fuzzer/
|
llvm/tools/llvm-dwarfdump/fuzzer/
|
||||||
|
llvm/tools/llvm-dwarfutil/CMakeLists.txt
|
||||||
llvm/tools/llvm-dwp/CMakeLists.txt
|
llvm/tools/llvm-dwp/CMakeLists.txt
|
||||||
llvm/tools/llvm-exegesis/
|
llvm/tools/llvm-exegesis/
|
||||||
llvm/tools/llvm-extract/CMakeLists.txt
|
llvm/tools/llvm-extract/CMakeLists.txt
|
||||||
llvm/tools/llvm-go/
|
|
||||||
llvm/tools/llvm-gsymutil/
|
llvm/tools/llvm-gsymutil/
|
||||||
llvm/tools/llvm-ifs/
|
llvm/tools/llvm-ifs/
|
||||||
llvm/tools/llvm-isel-fuzzer/
|
llvm/tools/llvm-isel-fuzzer/
|
||||||
@@ -793,6 +816,7 @@ llvm/tools/llvm-rc/
|
|||||||
llvm/tools/llvm-readobj/CMakeLists.txt
|
llvm/tools/llvm-readobj/CMakeLists.txt
|
||||||
llvm/tools/llvm-reduce/
|
llvm/tools/llvm-reduce/
|
||||||
llvm/tools/llvm-remark-size-diff/
|
llvm/tools/llvm-remark-size-diff/
|
||||||
|
llvm/tools/llvm-remarkutil/CMakeLists.txt
|
||||||
llvm/tools/llvm-rtdyld/CMakeLists.txt
|
llvm/tools/llvm-rtdyld/CMakeLists.txt
|
||||||
llvm/tools/llvm-rust-demangle-fuzzer/
|
llvm/tools/llvm-rust-demangle-fuzzer/
|
||||||
llvm/tools/llvm-shlib/
|
llvm/tools/llvm-shlib/
|
||||||
@@ -816,7 +840,6 @@ llvm/tools/opt/CMakeLists.txt
|
|||||||
llvm/tools/remarks-shlib/
|
llvm/tools/remarks-shlib/
|
||||||
llvm/tools/sancov/
|
llvm/tools/sancov/
|
||||||
llvm/tools/sanstats/
|
llvm/tools/sanstats/
|
||||||
llvm/tools/split-file/
|
|
||||||
llvm/tools/verify-uselistorder/
|
llvm/tools/verify-uselistorder/
|
||||||
llvm/tools/vfabi-demangle-fuzzer/
|
llvm/tools/vfabi-demangle-fuzzer/
|
||||||
llvm/tools/xcode-toolchain/
|
llvm/tools/xcode-toolchain/
|
||||||
@@ -834,6 +857,7 @@ llvm/utils/PerfectShuffle/
|
|||||||
llvm/utils/Reviewing/
|
llvm/utils/Reviewing/
|
||||||
llvm/utils/TableGen/CMakeLists.txt
|
llvm/utils/TableGen/CMakeLists.txt
|
||||||
llvm/utils/TableGen/GlobalISel/CMakeLists.txt
|
llvm/utils/TableGen/GlobalISel/CMakeLists.txt
|
||||||
|
llvm/utils/TableGen/jupyter/
|
||||||
llvm/utils/TableGen/tdtags
|
llvm/utils/TableGen/tdtags
|
||||||
llvm/utils/Target/
|
llvm/utils/Target/
|
||||||
llvm/utils/UnicodeData/
|
llvm/utils/UnicodeData/
|
||||||
@@ -853,7 +877,6 @@ llvm/utils/codegen-diff
|
|||||||
llvm/utils/collect_and_build_with_pgo.py
|
llvm/utils/collect_and_build_with_pgo.py
|
||||||
llvm/utils/convert-constraint-log-to-z3.py
|
llvm/utils/convert-constraint-log-to-z3.py
|
||||||
llvm/utils/count/
|
llvm/utils/count/
|
||||||
llvm/utils/countloc.sh
|
|
||||||
llvm/utils/create_ladder_graph.py
|
llvm/utils/create_ladder_graph.py
|
||||||
llvm/utils/crosstool/
|
llvm/utils/crosstool/
|
||||||
llvm/utils/demangle_tree.py
|
llvm/utils/demangle_tree.py
|
||||||
@@ -862,12 +885,12 @@ llvm/utils/emacs/
|
|||||||
llvm/utils/extract-section.py
|
llvm/utils/extract-section.py
|
||||||
llvm/utils/extract_symbols.py
|
llvm/utils/extract_symbols.py
|
||||||
llvm/utils/extract_vplan.py
|
llvm/utils/extract_vplan.py
|
||||||
|
llvm/utils/filecheck_lint/
|
||||||
llvm/utils/findmisopt
|
llvm/utils/findmisopt
|
||||||
llvm/utils/findoptdiff
|
llvm/utils/findoptdiff
|
||||||
llvm/utils/findsym.pl
|
llvm/utils/findsym.pl
|
||||||
llvm/utils/fpcmp/
|
llvm/utils/fpcmp/
|
||||||
llvm/utils/gdb-scripts/
|
llvm/utils/gdb-scripts/
|
||||||
llvm/utils/getsrcs.sh
|
|
||||||
llvm/utils/git/
|
llvm/utils/git/
|
||||||
llvm/utils/gn/
|
llvm/utils/gn/
|
||||||
llvm/utils/indirect_calls.py
|
llvm/utils/indirect_calls.py
|
||||||
@@ -884,14 +907,14 @@ llvm/utils/llvm-mca-compare.py
|
|||||||
llvm/utils/llvm-native-gxx
|
llvm/utils/llvm-native-gxx
|
||||||
llvm/utils/llvm-original-di-preservation.py
|
llvm/utils/llvm-original-di-preservation.py
|
||||||
llvm/utils/llvm.grm
|
llvm/utils/llvm.grm
|
||||||
llvm/utils/llvmdo
|
|
||||||
llvm/utils/llvmgrep
|
|
||||||
llvm/utils/merge-stats.py
|
llvm/utils/merge-stats.py
|
||||||
llvm/utils/not/
|
llvm/utils/not/
|
||||||
|
llvm/utils/phabricator/
|
||||||
llvm/utils/pipeline.py
|
llvm/utils/pipeline.py
|
||||||
llvm/utils/prepare-code-coverage-artifact.py
|
llvm/utils/prepare-code-coverage-artifact.py
|
||||||
llvm/utils/reduce_pipeline.py
|
llvm/utils/reduce_pipeline.py
|
||||||
llvm/utils/reduce_pipeline_test/
|
llvm/utils/reduce_pipeline_test/
|
||||||
|
llvm/utils/relative_lines.py
|
||||||
llvm/utils/release/
|
llvm/utils/release/
|
||||||
llvm/utils/remote-exec.py
|
llvm/utils/remote-exec.py
|
||||||
llvm/utils/revert_checker.py
|
llvm/utils/revert_checker.py
|
||||||
@@ -903,12 +926,14 @@ llvm/utils/schedcover.py
|
|||||||
llvm/utils/shuffle_fuzz.py
|
llvm/utils/shuffle_fuzz.py
|
||||||
llvm/utils/shuffle_select_fuzz_tester.py
|
llvm/utils/shuffle_select_fuzz_tester.py
|
||||||
llvm/utils/sort_includes.py
|
llvm/utils/sort_includes.py
|
||||||
|
llvm/utils/split-file/.clang-tidy
|
||||||
|
llvm/utils/split-file/CMakeLists.txt
|
||||||
llvm/utils/sysroot.py
|
llvm/utils/sysroot.py
|
||||||
llvm/utils/testgen/
|
llvm/utils/testgen/
|
||||||
llvm/utils/textmate/
|
llvm/utils/textmate/
|
||||||
llvm/utils/unicode-case-fold.py
|
llvm/utils/unicode-case-fold.py
|
||||||
llvm/utils/unittest/
|
|
||||||
llvm/utils/update_analyze_test_checks.py
|
llvm/utils/update_analyze_test_checks.py
|
||||||
|
llvm/utils/update_any_test_checks.py
|
||||||
llvm/utils/update_cc_test_checks.py
|
llvm/utils/update_cc_test_checks.py
|
||||||
llvm/utils/update_llc_test_checks.py
|
llvm/utils/update_llc_test_checks.py
|
||||||
llvm/utils/update_mca_test_checks.py
|
llvm/utils/update_mca_test_checks.py
|
||||||
@@ -935,6 +960,7 @@ openmp/runtime/README.txt
|
|||||||
openmp/runtime/cmake/
|
openmp/runtime/cmake/
|
||||||
openmp/runtime/doc/
|
openmp/runtime/doc/
|
||||||
openmp/runtime/src/CMakeLists.txt
|
openmp/runtime/src/CMakeLists.txt
|
||||||
|
openmp/runtime/src/exports_test_so.txt
|
||||||
openmp/runtime/test/
|
openmp/runtime/test/
|
||||||
openmp/runtime/tools/
|
openmp/runtime/tools/
|
||||||
openmp/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
|
#ifndef LLVM_CLANG_C_DOCUMENTATION_H
|
||||||
#define LLVM_CLANG_C_DOCUMENTATION_H
|
#define LLVM_CLANG_C_DOCUMENTATION_H
|
||||||
|
|
||||||
|
#include "clang-c/CXErrorCode.h"
|
||||||
#include "clang-c/ExternC.h"
|
#include "clang-c/ExternC.h"
|
||||||
#include "clang-c/Index.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);
|
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
|
#ifndef LLVM_CLANG_C_INDEX_H
|
||||||
#define LLVM_CLANG_C_INDEX_H
|
#define LLVM_CLANG_C_INDEX_H
|
||||||
|
|
||||||
#include <time.h>
|
|
||||||
|
|
||||||
#include "clang-c/BuildSystem.h"
|
#include "clang-c/BuildSystem.h"
|
||||||
|
#include "clang-c/CXDiagnostic.h"
|
||||||
#include "clang-c/CXErrorCode.h"
|
#include "clang-c/CXErrorCode.h"
|
||||||
|
#include "clang-c/CXFile.h"
|
||||||
|
#include "clang-c/CXSourceLocation.h"
|
||||||
#include "clang-c/CXString.h"
|
#include "clang-c/CXString.h"
|
||||||
#include "clang-c/ExternC.h"
|
#include "clang-c/ExternC.h"
|
||||||
#include "clang-c/Platform.h"
|
#include "clang-c/Platform.h"
|
||||||
@@ -341,45 +342,6 @@ CINDEX_LINKAGE unsigned clang_CXIndex_getGlobalOptions(CXIndex);
|
|||||||
CINDEX_LINKAGE void
|
CINDEX_LINKAGE void
|
||||||
clang_CXIndex_setInvocationEmissionPathOption(CXIndex, const char *Path);
|
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
|
* Determine whether the given header is guarded against
|
||||||
* multiple inclusions, either with the conventional
|
* 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,
|
CINDEX_LINKAGE const char *clang_getFileContents(CXTranslationUnit tu,
|
||||||
CXFile file, size_t *size);
|
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
|
* Retrieves the source location associated with a given file/line/column
|
||||||
* in a particular translation unit.
|
* in a particular translation unit.
|
||||||
@@ -501,204 +393,6 @@ CINDEX_LINKAGE CXSourceLocation clang_getLocationForOffset(CXTranslationUnit tu,
|
|||||||
CXFile file,
|
CXFile file,
|
||||||
unsigned offset);
|
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.
|
* Retrieve all ranges that were skipped by the preprocessor.
|
||||||
*
|
*
|
||||||
@@ -718,142 +412,6 @@ CINDEX_LINKAGE CXSourceRangeList *clang_getSkippedRanges(CXTranslationUnit tu,
|
|||||||
CINDEX_LINKAGE CXSourceRangeList *
|
CINDEX_LINKAGE CXSourceRangeList *
|
||||||
clang_getAllSkippedRanges(CXTranslationUnit tu);
|
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
|
* Determine the number of diagnostics produced for the given
|
||||||
* translation unit.
|
* translation unit.
|
||||||
@@ -881,232 +439,6 @@ CINDEX_LINKAGE CXDiagnostic clang_getDiagnostic(CXTranslationUnit Unit,
|
|||||||
CINDEX_LINKAGE CXDiagnosticSet
|
CINDEX_LINKAGE CXDiagnosticSet
|
||||||
clang_getDiagnosticSetFromTU(CXTranslationUnit Unit);
|
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
|
* \defgroup CINDEX_TRANSLATION_UNIT Translation unit manipulation
|
||||||
*
|
*
|
||||||
@@ -2199,7 +1531,13 @@ enum CXCursorKind {
|
|||||||
*/
|
*/
|
||||||
CXCursor_RequiresExpr = 154,
|
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 */
|
/* Statements */
|
||||||
CXCursor_FirstStmt = 200,
|
CXCursor_FirstStmt = 200,
|
||||||
@@ -2646,7 +1984,11 @@ enum CXCursorKind {
|
|||||||
*/
|
*/
|
||||||
CXCursor_OMPParallelMaskedTaskLoopSimdDirective = 304,
|
CXCursor_OMPParallelMaskedTaskLoopSimdDirective = 304,
|
||||||
|
|
||||||
CXCursor_LastStmt = CXCursor_OMPParallelMaskedTaskLoopSimdDirective,
|
/** OpenMP error directive.
|
||||||
|
*/
|
||||||
|
CXCursor_OMPErrorDirective = 305,
|
||||||
|
|
||||||
|
CXCursor_LastStmt = CXCursor_OMPErrorDirective,
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Cursor that represents the translation unit itself.
|
* 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
|
* Returns the number of template args of a function, struct, or class decl
|
||||||
* template specialization.
|
* representing a template specialization.
|
||||||
*
|
*
|
||||||
* If the argument cursor cannot be converted into a template function
|
* If the argument cursor cannot be converted into a template function
|
||||||
* declaration, -1 is returned.
|
* 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.
|
* Retrieve the kind of the I'th template argument of the CXCursor C.
|
||||||
*
|
*
|
||||||
* If the argument CXCursor does not represent a FunctionDecl, an invalid
|
* If the argument CXCursor does not represent a FunctionDecl, StructDecl, or
|
||||||
* template argument kind is returned.
|
* ClassTemplatePartialSpecialization, an invalid template argument kind is
|
||||||
|
* returned.
|
||||||
*
|
*
|
||||||
* For example, for the following declaration and specialization:
|
* For example, for the following declaration and specialization:
|
||||||
* template <typename T, int kInt, bool kBool>
|
* 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
|
* Retrieve a CXType representing the type of a TemplateArgument of a
|
||||||
* function decl representing a template specialization.
|
* function decl representing a template specialization.
|
||||||
*
|
*
|
||||||
* If the argument CXCursor does not represent a FunctionDecl whose I'th
|
* If the argument CXCursor does not represent a FunctionDecl, StructDecl,
|
||||||
* template argument has a kind of CXTemplateArgKind_Integral, an invalid type
|
* ClassDecl or ClassTemplatePartialSpecialization whose I'th template argument
|
||||||
* is returned.
|
* has a kind of CXTemplateArgKind_Integral, an invalid type is returned.
|
||||||
*
|
*
|
||||||
* For example, for the following declaration and specialization:
|
* For example, for the following declaration and specialization:
|
||||||
* template <typename T, int kInt, bool kBool>
|
* 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.
|
* 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
|
* 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:
|
* For example, for the following declaration and specialization:
|
||||||
* template <typename T, int kInt, bool kBool>
|
* 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.
|
* 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
|
* 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:
|
* For example, for the following declaration and specialization:
|
||||||
* template <typename T, int kInt, bool kBool>
|
* 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);
|
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.
|
* 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);
|
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
|
* Determine if a C++ member function or member function template is
|
||||||
* pure virtual.
|
* pure virtual.
|
||||||
@@ -4895,6 +4293,56 @@ CINDEX_LINKAGE unsigned clang_CXXMethod_isStatic(CXCursor C);
|
|||||||
*/
|
*/
|
||||||
CINDEX_LINKAGE unsigned clang_CXXMethod_isVirtual(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
|
* Determine if a C++ record is abstract, i.e. whether a class or struct
|
||||||
* has a pure virtual member function.
|
* has a pure virtual member function.
|
||||||
|
|||||||
@@ -10,11 +10,15 @@
|
|||||||
#define LLVM_CLANG_APINOTES_TYPES_H
|
#define LLVM_CLANG_APINOTES_TYPES_H
|
||||||
|
|
||||||
#include "clang/Basic/Specifiers.h"
|
#include "clang/Basic/Specifiers.h"
|
||||||
#include "llvm/ADT/Optional.h"
|
|
||||||
#include "llvm/ADT/StringRef.h"
|
#include "llvm/ADT/StringRef.h"
|
||||||
#include <climits>
|
#include <climits>
|
||||||
|
#include <optional>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
|
namespace llvm {
|
||||||
|
class raw_ostream;
|
||||||
|
} // namespace llvm
|
||||||
|
|
||||||
namespace clang {
|
namespace clang {
|
||||||
namespace api_notes {
|
namespace api_notes {
|
||||||
enum class RetainCountConventionKind {
|
enum class RetainCountConventionKind {
|
||||||
@@ -70,12 +74,12 @@ class CommonEntityInfo {
|
|||||||
: Unavailable(0), UnavailableInSwift(0), SwiftPrivateSpecified(0),
|
: Unavailable(0), UnavailableInSwift(0), SwiftPrivateSpecified(0),
|
||||||
SwiftPrivate(0) {}
|
SwiftPrivate(0) {}
|
||||||
|
|
||||||
llvm::Optional<bool> isSwiftPrivate() const {
|
std::optional<bool> isSwiftPrivate() const {
|
||||||
return SwiftPrivateSpecified ? llvm::Optional<bool>(SwiftPrivate)
|
return SwiftPrivateSpecified ? std::optional<bool>(SwiftPrivate)
|
||||||
: llvm::None;
|
: std::nullopt;
|
||||||
}
|
}
|
||||||
|
|
||||||
void setSwiftPrivate(llvm::Optional<bool> Private) {
|
void setSwiftPrivate(std::optional<bool> Private) {
|
||||||
SwiftPrivateSpecified = Private.has_value();
|
SwiftPrivateSpecified = Private.has_value();
|
||||||
SwiftPrivate = Private.value_or(0);
|
SwiftPrivate = Private.value_or(0);
|
||||||
}
|
}
|
||||||
@@ -127,39 +131,39 @@ class CommonTypeInfo : public CommonEntityInfo {
|
|||||||
/// The Swift type to which a given type is bridged.
|
/// The Swift type to which a given type is bridged.
|
||||||
///
|
///
|
||||||
/// Reflects the swift_bridge attribute.
|
/// Reflects the swift_bridge attribute.
|
||||||
llvm::Optional<std::string> SwiftBridge;
|
std::optional<std::string> SwiftBridge;
|
||||||
|
|
||||||
/// The NS error domain for this type.
|
/// The NS error domain for this type.
|
||||||
llvm::Optional<std::string> NSErrorDomain;
|
std::optional<std::string> NSErrorDomain;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
CommonTypeInfo() {}
|
CommonTypeInfo() {}
|
||||||
|
|
||||||
const llvm::Optional<std::string> &getSwiftBridge() const {
|
const std::optional<std::string> &getSwiftBridge() const {
|
||||||
return SwiftBridge;
|
return SwiftBridge;
|
||||||
}
|
}
|
||||||
|
|
||||||
void setSwiftBridge(const llvm::Optional<std::string> &SwiftType) {
|
void setSwiftBridge(const std::optional<std::string> &SwiftType) {
|
||||||
SwiftBridge = SwiftType;
|
SwiftBridge = SwiftType;
|
||||||
}
|
}
|
||||||
|
|
||||||
void setSwiftBridge(const llvm::Optional<llvm::StringRef> &SwiftType) {
|
void setSwiftBridge(const std::optional<llvm::StringRef> &SwiftType) {
|
||||||
SwiftBridge = SwiftType
|
SwiftBridge = SwiftType
|
||||||
? llvm::Optional<std::string>(std::string(*SwiftType))
|
? std::optional<std::string>(std::string(*SwiftType))
|
||||||
: llvm::None;
|
: std::nullopt;
|
||||||
}
|
}
|
||||||
|
|
||||||
const llvm::Optional<std::string> &getNSErrorDomain() const {
|
const std::optional<std::string> &getNSErrorDomain() const {
|
||||||
return NSErrorDomain;
|
return NSErrorDomain;
|
||||||
}
|
}
|
||||||
|
|
||||||
void setNSErrorDomain(const llvm::Optional<std::string> &Domain) {
|
void setNSErrorDomain(const std::optional<std::string> &Domain) {
|
||||||
NSErrorDomain = Domain;
|
NSErrorDomain = Domain;
|
||||||
}
|
}
|
||||||
|
|
||||||
void setNSErrorDomain(const llvm::Optional<llvm::StringRef> &Domain) {
|
void setNSErrorDomain(const std::optional<llvm::StringRef> &Domain) {
|
||||||
NSErrorDomain =
|
NSErrorDomain = Domain ? std::optional<std::string>(std::string(*Domain))
|
||||||
Domain ? llvm::Optional<std::string>(std::string(*Domain)) : llvm::None;
|
: std::nullopt;
|
||||||
}
|
}
|
||||||
|
|
||||||
friend bool operator==(const CommonTypeInfo &, const CommonTypeInfo &);
|
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
|
/// Determine the default nullability for properties and methods of this
|
||||||
/// class.
|
/// class.
|
||||||
///
|
///
|
||||||
/// eturns the default nullability, if implied, or None if there is no
|
/// Returns the default nullability, if implied, or std::nullopt if there is
|
||||||
llvm::Optional<NullabilityKind> getDefaultNullability() const {
|
/// none.
|
||||||
|
std::optional<NullabilityKind> getDefaultNullability() const {
|
||||||
return HasDefaultNullability
|
return HasDefaultNullability
|
||||||
? llvm::Optional<NullabilityKind>(
|
? std::optional<NullabilityKind>(
|
||||||
static_cast<NullabilityKind>(DefaultNullability))
|
static_cast<NullabilityKind>(DefaultNullability))
|
||||||
: llvm::None;
|
: std::nullopt;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Set the default nullability for properties and methods of this class.
|
/// Set the default nullability for properties and methods of this class.
|
||||||
@@ -232,21 +237,21 @@ class ObjCContextInfo : public CommonTypeInfo {
|
|||||||
bool hasDesignatedInits() const { return HasDesignatedInits; }
|
bool hasDesignatedInits() const { return HasDesignatedInits; }
|
||||||
void setHasDesignatedInits(bool Value) { HasDesignatedInits = Value; }
|
void setHasDesignatedInits(bool Value) { HasDesignatedInits = Value; }
|
||||||
|
|
||||||
llvm::Optional<bool> getSwiftImportAsNonGeneric() const {
|
std::optional<bool> getSwiftImportAsNonGeneric() const {
|
||||||
return SwiftImportAsNonGenericSpecified
|
return SwiftImportAsNonGenericSpecified
|
||||||
? llvm::Optional<bool>(SwiftImportAsNonGeneric)
|
? std::optional<bool>(SwiftImportAsNonGeneric)
|
||||||
: llvm::None;
|
: std::nullopt;
|
||||||
}
|
}
|
||||||
void setSwiftImportAsNonGeneric(llvm::Optional<bool> Value) {
|
void setSwiftImportAsNonGeneric(std::optional<bool> Value) {
|
||||||
SwiftImportAsNonGenericSpecified = Value.has_value();
|
SwiftImportAsNonGenericSpecified = Value.has_value();
|
||||||
SwiftImportAsNonGeneric = Value.value_or(false);
|
SwiftImportAsNonGeneric = Value.value_or(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
llvm::Optional<bool> getSwiftObjCMembers() const {
|
std::optional<bool> getSwiftObjCMembers() const {
|
||||||
return SwiftObjCMembersSpecified ? llvm::Optional<bool>(SwiftObjCMembers)
|
return SwiftObjCMembersSpecified ? std::optional<bool>(SwiftObjCMembers)
|
||||||
: llvm::None;
|
: std::nullopt;
|
||||||
}
|
}
|
||||||
void setSwiftObjCMembers(llvm::Optional<bool> Value) {
|
void setSwiftObjCMembers(std::optional<bool> Value) {
|
||||||
SwiftObjCMembersSpecified = Value.has_value();
|
SwiftObjCMembersSpecified = Value.has_value();
|
||||||
SwiftObjCMembers = Value.value_or(false);
|
SwiftObjCMembers = Value.value_or(false);
|
||||||
}
|
}
|
||||||
@@ -310,10 +315,10 @@ class VariableInfo : public CommonEntityInfo {
|
|||||||
public:
|
public:
|
||||||
VariableInfo() : NullabilityAudited(false), Nullable(0) {}
|
VariableInfo() : NullabilityAudited(false), Nullable(0) {}
|
||||||
|
|
||||||
llvm::Optional<NullabilityKind> getNullability() const {
|
std::optional<NullabilityKind> getNullability() const {
|
||||||
return NullabilityAudited ? llvm::Optional<NullabilityKind>(
|
return NullabilityAudited ? std::optional<NullabilityKind>(
|
||||||
static_cast<NullabilityKind>(Nullable))
|
static_cast<NullabilityKind>(Nullable))
|
||||||
: llvm::None;
|
: std::nullopt;
|
||||||
}
|
}
|
||||||
|
|
||||||
void setNullabilityAudited(NullabilityKind kind) {
|
void setNullabilityAudited(NullabilityKind kind) {
|
||||||
@@ -359,12 +364,12 @@ class ObjCPropertyInfo : public VariableInfo {
|
|||||||
ObjCPropertyInfo()
|
ObjCPropertyInfo()
|
||||||
: SwiftImportAsAccessorsSpecified(false), SwiftImportAsAccessors(false) {}
|
: SwiftImportAsAccessorsSpecified(false), SwiftImportAsAccessors(false) {}
|
||||||
|
|
||||||
llvm::Optional<bool> getSwiftImportAsAccessors() const {
|
std::optional<bool> getSwiftImportAsAccessors() const {
|
||||||
return SwiftImportAsAccessorsSpecified
|
return SwiftImportAsAccessorsSpecified
|
||||||
? llvm::Optional<bool>(SwiftImportAsAccessors)
|
? std::optional<bool>(SwiftImportAsAccessors)
|
||||||
: llvm::None;
|
: std::nullopt;
|
||||||
}
|
}
|
||||||
void setSwiftImportAsAccessors(llvm::Optional<bool> Value) {
|
void setSwiftImportAsAccessors(std::optional<bool> Value) {
|
||||||
SwiftImportAsAccessorsSpecified = Value.has_value();
|
SwiftImportAsAccessorsSpecified = Value.has_value();
|
||||||
SwiftImportAsAccessors = Value.value_or(false);
|
SwiftImportAsAccessors = Value.value_or(false);
|
||||||
}
|
}
|
||||||
@@ -423,23 +428,23 @@ class ParamInfo : public VariableInfo {
|
|||||||
ParamInfo()
|
ParamInfo()
|
||||||
: NoEscapeSpecified(false), NoEscape(false), RawRetainCountConvention() {}
|
: NoEscapeSpecified(false), NoEscape(false), RawRetainCountConvention() {}
|
||||||
|
|
||||||
llvm::Optional<bool> isNoEscape() const {
|
std::optional<bool> isNoEscape() const {
|
||||||
if (!NoEscapeSpecified)
|
if (!NoEscapeSpecified)
|
||||||
return llvm::None;
|
return std::nullopt;
|
||||||
return NoEscape;
|
return NoEscape;
|
||||||
}
|
}
|
||||||
void setNoEscape(llvm::Optional<bool> Value) {
|
void setNoEscape(std::optional<bool> Value) {
|
||||||
NoEscapeSpecified = Value.has_value();
|
NoEscapeSpecified = Value.has_value();
|
||||||
NoEscape = Value.value_or(false);
|
NoEscape = Value.value_or(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
llvm::Optional<RetainCountConventionKind> getRetainCountConvention() const {
|
std::optional<RetainCountConventionKind> getRetainCountConvention() const {
|
||||||
if (!RawRetainCountConvention)
|
if (!RawRetainCountConvention)
|
||||||
return llvm::None;
|
return std::nullopt;
|
||||||
return static_cast<RetainCountConventionKind>(RawRetainCountConvention - 1);
|
return static_cast<RetainCountConventionKind>(RawRetainCountConvention - 1);
|
||||||
}
|
}
|
||||||
void
|
void
|
||||||
setRetainCountConvention(llvm::Optional<RetainCountConventionKind> Value) {
|
setRetainCountConvention(std::optional<RetainCountConventionKind> Value) {
|
||||||
RawRetainCountConvention = Value ? static_cast<unsigned>(*Value) + 1 : 0;
|
RawRetainCountConvention = Value ? static_cast<unsigned>(*Value) + 1 : 0;
|
||||||
assert(getRetainCountConvention() == Value && "bitfield too small");
|
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.
|
/// API notes for a function or method.
|
||||||
class FunctionInfo : public CommonEntityInfo {
|
class FunctionInfo : public CommonEntityInfo {
|
||||||
private:
|
private:
|
||||||
static constexpr const unsigned NullabilityKindMask = 0x3;
|
static constexpr const uint64_t NullabilityKindMask = 0x3;
|
||||||
static constexpr const unsigned NullabilityKindSize = 2;
|
static constexpr const unsigned NullabilityKindSize = 2;
|
||||||
|
|
||||||
static constexpr const unsigned ReturnInfoIndex = 0;
|
static constexpr const unsigned ReturnInfoIndex = 0;
|
||||||
@@ -551,13 +556,13 @@ class FunctionInfo : public CommonEntityInfo {
|
|||||||
|
|
||||||
NullabilityKind getReturnTypeInfo() const { return getTypeInfo(0); }
|
NullabilityKind getReturnTypeInfo() const { return getTypeInfo(0); }
|
||||||
|
|
||||||
llvm::Optional<RetainCountConventionKind> getRetainCountConvention() const {
|
std::optional<RetainCountConventionKind> getRetainCountConvention() const {
|
||||||
if (!RawRetainCountConvention)
|
if (!RawRetainCountConvention)
|
||||||
return llvm::None;
|
return std::nullopt;
|
||||||
return static_cast<RetainCountConventionKind>(RawRetainCountConvention - 1);
|
return static_cast<RetainCountConventionKind>(RawRetainCountConvention - 1);
|
||||||
}
|
}
|
||||||
void
|
void
|
||||||
setRetainCountConvention(llvm::Optional<RetainCountConventionKind> Value) {
|
setRetainCountConvention(std::optional<RetainCountConventionKind> Value) {
|
||||||
RawRetainCountConvention = Value ? static_cast<unsigned>(*Value) + 1 : 0;
|
RawRetainCountConvention = Value ? static_cast<unsigned>(*Value) + 1 : 0;
|
||||||
assert(getRetainCountConvention() == Value && "bitfield too small");
|
assert(getRetainCountConvention() == Value && "bitfield too small");
|
||||||
}
|
}
|
||||||
@@ -654,16 +659,16 @@ class TagInfo : public CommonTypeInfo {
|
|||||||
unsigned IsFlagEnum : 1;
|
unsigned IsFlagEnum : 1;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
llvm::Optional<EnumExtensibilityKind> EnumExtensibility;
|
std::optional<EnumExtensibilityKind> EnumExtensibility;
|
||||||
|
|
||||||
TagInfo() : HasFlagEnum(0), IsFlagEnum(0) {}
|
TagInfo() : HasFlagEnum(0), IsFlagEnum(0) {}
|
||||||
|
|
||||||
llvm::Optional<bool> isFlagEnum() const {
|
std::optional<bool> isFlagEnum() const {
|
||||||
if (HasFlagEnum)
|
if (HasFlagEnum)
|
||||||
return IsFlagEnum;
|
return IsFlagEnum;
|
||||||
return llvm::None;
|
return std::nullopt;
|
||||||
}
|
}
|
||||||
void setFlagEnum(llvm::Optional<bool> Value) {
|
void setFlagEnum(std::optional<bool> Value) {
|
||||||
HasFlagEnum = Value.has_value();
|
HasFlagEnum = Value.has_value();
|
||||||
IsFlagEnum = Value.value_or(false);
|
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.
|
/// Describes API notes data for a typedef.
|
||||||
class TypedefInfo : public CommonTypeInfo {
|
class TypedefInfo : public CommonTypeInfo {
|
||||||
public:
|
public:
|
||||||
llvm::Optional<SwiftNewTypeKind> SwiftWrapper;
|
std::optional<SwiftNewTypeKind> SwiftWrapper;
|
||||||
|
|
||||||
TypedefInfo() {}
|
TypedefInfo() {}
|
||||||
|
|
||||||
|
|||||||
@@ -43,7 +43,7 @@ class MigrateSourceAction : public ASTFrontendAction {
|
|||||||
class MigrateAction : public WrapperFrontendAction {
|
class MigrateAction : public WrapperFrontendAction {
|
||||||
std::string MigrateDir;
|
std::string MigrateDir;
|
||||||
std::string PlistOut;
|
std::string PlistOut;
|
||||||
bool EmitPremigrationARCErros;
|
bool EmitPremigrationARCErrors;
|
||||||
protected:
|
protected:
|
||||||
bool BeginInvocation(CompilerInstance &CI) override;
|
bool BeginInvocation(CompilerInstance &CI) override;
|
||||||
|
|
||||||
|
|||||||
@@ -238,7 +238,7 @@ class APValue {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
class LValuePathSerializationHelper {
|
class LValuePathSerializationHelper {
|
||||||
const void *ElemTy;
|
const void *Ty;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
ArrayRef<LValuePathEntry> Path;
|
ArrayRef<LValuePathEntry> Path;
|
||||||
|
|||||||
@@ -44,6 +44,7 @@ class ConstraintSatisfaction : public llvm::FoldingSetNode {
|
|||||||
using Detail = llvm::PointerUnion<Expr *, SubstitutionDiagnostic *>;
|
using Detail = llvm::PointerUnion<Expr *, SubstitutionDiagnostic *>;
|
||||||
|
|
||||||
bool IsSatisfied = false;
|
bool IsSatisfied = false;
|
||||||
|
bool ContainsErrors = false;
|
||||||
|
|
||||||
/// \brief Pairs of unsatisfied atomic constraint expressions along with the
|
/// \brief Pairs of unsatisfied atomic constraint expressions along with the
|
||||||
/// substituted constraint expr, if the template arguments could be
|
/// 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,
|
static void Profile(llvm::FoldingSetNodeID &ID, const ASTContext &C,
|
||||||
const NamedDecl *ConstraintOwner,
|
const NamedDecl *ConstraintOwner,
|
||||||
ArrayRef<TemplateArgument> TemplateArgs);
|
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
|
/// Pairs of unsatisfied atomic constraint expressions along with the
|
||||||
@@ -78,6 +86,7 @@ struct ASTConstraintSatisfaction final :
|
|||||||
UnsatisfiedConstraintRecord> {
|
UnsatisfiedConstraintRecord> {
|
||||||
std::size_t NumRecords;
|
std::size_t NumRecords;
|
||||||
bool IsSatisfied : 1;
|
bool IsSatisfied : 1;
|
||||||
|
bool ContainsErrors : 1;
|
||||||
|
|
||||||
const UnsatisfiedConstraintRecord *begin() const {
|
const UnsatisfiedConstraintRecord *begin() const {
|
||||||
return getTrailingObjects<UnsatisfiedConstraintRecord>();
|
return getTrailingObjects<UnsatisfiedConstraintRecord>();
|
||||||
@@ -89,9 +98,13 @@ struct ASTConstraintSatisfaction final :
|
|||||||
|
|
||||||
ASTConstraintSatisfaction(const ASTContext &C,
|
ASTConstraintSatisfaction(const ASTContext &C,
|
||||||
const ConstraintSatisfaction &Satisfaction);
|
const ConstraintSatisfaction &Satisfaction);
|
||||||
|
ASTConstraintSatisfaction(const ASTContext &C,
|
||||||
|
const ASTConstraintSatisfaction &Satisfaction);
|
||||||
|
|
||||||
static ASTConstraintSatisfaction *
|
static ASTConstraintSatisfaction *
|
||||||
Create(const ASTContext &C, const ConstraintSatisfaction &Satisfaction);
|
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
|
/// \brief Common data class for constructs that reference concepts with
|
||||||
|
|||||||
@@ -76,7 +76,7 @@ class ASTConsumer {
|
|||||||
virtual void HandleTagDeclRequiredDefinition(const TagDecl *D) {}
|
virtual void HandleTagDeclRequiredDefinition(const TagDecl *D) {}
|
||||||
|
|
||||||
/// Invoked when a function is implicitly instantiated.
|
/// 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
|
/// instantiated at the end of the translation unit and passed to
|
||||||
/// HandleTopLevelDecl.
|
/// HandleTopLevelDecl.
|
||||||
virtual void HandleCXXImplicitFunctionInstantiation(FunctionDecl *D) {}
|
virtual void HandleCXXImplicitFunctionInstantiation(FunctionDecl *D) {}
|
||||||
|
|||||||
@@ -14,65 +14,38 @@
|
|||||||
#ifndef LLVM_CLANG_AST_ASTCONTEXT_H
|
#ifndef LLVM_CLANG_AST_ASTCONTEXT_H
|
||||||
#define LLVM_CLANG_AST_ASTCONTEXT_H
|
#define LLVM_CLANG_AST_ASTCONTEXT_H
|
||||||
|
|
||||||
#include "clang/AST/ASTContextAllocate.h"
|
|
||||||
#include "clang/AST/ASTFwd.h"
|
#include "clang/AST/ASTFwd.h"
|
||||||
#include "clang/AST/CanonicalType.h"
|
#include "clang/AST/CanonicalType.h"
|
||||||
#include "clang/AST/CommentCommandTraits.h"
|
#include "clang/AST/CommentCommandTraits.h"
|
||||||
#include "clang/AST/ComparisonCategories.h"
|
#include "clang/AST/ComparisonCategories.h"
|
||||||
#include "clang/AST/Decl.h"
|
#include "clang/AST/Decl.h"
|
||||||
#include "clang/AST/DeclBase.h"
|
|
||||||
#include "clang/AST/DeclarationName.h"
|
#include "clang/AST/DeclarationName.h"
|
||||||
#include "clang/AST/ExternalASTSource.h"
|
#include "clang/AST/ExternalASTSource.h"
|
||||||
#include "clang/AST/NestedNameSpecifier.h"
|
#include "clang/AST/NestedNameSpecifier.h"
|
||||||
#include "clang/AST/PrettyPrinter.h"
|
#include "clang/AST/PrettyPrinter.h"
|
||||||
#include "clang/AST/RawCommentList.h"
|
#include "clang/AST/RawCommentList.h"
|
||||||
#include "clang/AST/TemplateName.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/IdentifierTable.h"
|
||||||
#include "clang/Basic/LLVM.h"
|
#include "clang/Basic/LLVM.h"
|
||||||
#include "clang/Basic/LangOptions.h"
|
#include "clang/Basic/LangOptions.h"
|
||||||
#include "clang/Basic/Linkage.h"
|
|
||||||
#include "clang/Basic/NoSanitizeList.h"
|
#include "clang/Basic/NoSanitizeList.h"
|
||||||
#include "clang/Basic/OperatorKinds.h"
|
|
||||||
#include "clang/Basic/PartialDiagnostic.h"
|
#include "clang/Basic/PartialDiagnostic.h"
|
||||||
#include "clang/Basic/ProfileList.h"
|
#include "clang/Basic/ProfileList.h"
|
||||||
#include "clang/Basic/SourceLocation.h"
|
#include "clang/Basic/SourceLocation.h"
|
||||||
#include "clang/Basic/Specifiers.h"
|
|
||||||
#include "clang/Basic/TargetCXXABI.h"
|
|
||||||
#include "clang/Basic/XRayLists.h"
|
#include "clang/Basic/XRayLists.h"
|
||||||
#include "llvm/ADT/APSInt.h"
|
|
||||||
#include "llvm/ADT/ArrayRef.h"
|
|
||||||
#include "llvm/ADT/DenseMap.h"
|
#include "llvm/ADT/DenseMap.h"
|
||||||
#include "llvm/ADT/DenseSet.h"
|
#include "llvm/ADT/DenseSet.h"
|
||||||
#include "llvm/ADT/FoldingSet.h"
|
#include "llvm/ADT/FoldingSet.h"
|
||||||
#include "llvm/ADT/IntrusiveRefCntPtr.h"
|
#include "llvm/ADT/IntrusiveRefCntPtr.h"
|
||||||
#include "llvm/ADT/MapVector.h"
|
#include "llvm/ADT/MapVector.h"
|
||||||
#include "llvm/ADT/None.h"
|
|
||||||
#include "llvm/ADT/Optional.h"
|
|
||||||
#include "llvm/ADT/PointerIntPair.h"
|
#include "llvm/ADT/PointerIntPair.h"
|
||||||
#include "llvm/ADT/PointerUnion.h"
|
#include "llvm/ADT/PointerUnion.h"
|
||||||
#include "llvm/ADT/SmallVector.h"
|
#include "llvm/ADT/SmallVector.h"
|
||||||
#include "llvm/ADT/StringMap.h"
|
#include "llvm/ADT/StringMap.h"
|
||||||
#include "llvm/ADT/StringRef.h"
|
#include "llvm/ADT/StringRef.h"
|
||||||
#include "llvm/ADT/TinyPtrVector.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 "llvm/Support/TypeSize.h"
|
||||||
#include <cassert>
|
#include <optional>
|
||||||
#include <cstddef>
|
|
||||||
#include <cstdint>
|
|
||||||
#include <iterator>
|
|
||||||
#include <memory>
|
|
||||||
#include <string>
|
|
||||||
#include <type_traits>
|
|
||||||
#include <utility>
|
|
||||||
#include <vector>
|
|
||||||
|
|
||||||
namespace llvm {
|
namespace llvm {
|
||||||
|
|
||||||
@@ -246,6 +219,7 @@ class ASTContext : public RefCountedBase<ASTContext> {
|
|||||||
TemplateSpecializationTypes;
|
TemplateSpecializationTypes;
|
||||||
mutable llvm::FoldingSet<ParenType> ParenTypes{GeneralTypesLog2InitSize};
|
mutable llvm::FoldingSet<ParenType> ParenTypes{GeneralTypesLog2InitSize};
|
||||||
mutable llvm::FoldingSet<UsingType> UsingTypes;
|
mutable llvm::FoldingSet<UsingType> UsingTypes;
|
||||||
|
mutable llvm::FoldingSet<TypedefType> TypedefTypes;
|
||||||
mutable llvm::FoldingSet<ElaboratedType> ElaboratedTypes{
|
mutable llvm::FoldingSet<ElaboratedType> ElaboratedTypes{
|
||||||
GeneralTypesLog2InitSize};
|
GeneralTypesLog2InitSize};
|
||||||
mutable llvm::FoldingSet<DependentNameType> DependentNameTypes;
|
mutable llvm::FoldingSet<DependentNameType> DependentNameTypes;
|
||||||
@@ -639,9 +613,6 @@ class ASTContext : public RefCountedBase<ASTContext> {
|
|||||||
std::unique_ptr<CXXABI> ABI;
|
std::unique_ptr<CXXABI> ABI;
|
||||||
CXXABI *createCXXABI(const TargetInfo &T);
|
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 space map mangling must be used with language specific
|
||||||
/// address spaces (e.g. OpenCL/CUDA)
|
/// address spaces (e.g. OpenCL/CUDA)
|
||||||
bool AddrSpaceMapMangling;
|
bool AddrSpaceMapMangling;
|
||||||
@@ -1366,6 +1337,9 @@ class ASTContext : public RefCountedBase<ASTContext> {
|
|||||||
CanQualType getDecayedType(CanQualType T) const {
|
CanQualType getDecayedType(CanQualType T) const {
|
||||||
return CanQualType::CreateUnsafe(getDecayedType((QualType) T));
|
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
|
/// Return the uniqued reference to the atomic type for the specified
|
||||||
/// type.
|
/// type.
|
||||||
@@ -1613,10 +1587,12 @@ class ASTContext : public RefCountedBase<ASTContext> {
|
|||||||
QualType getBTFTagAttributedType(const BTFTypeTagAttr *BTFAttr,
|
QualType getBTFTagAttributedType(const BTFTypeTagAttr *BTFAttr,
|
||||||
QualType Wrapped);
|
QualType Wrapped);
|
||||||
|
|
||||||
QualType getSubstTemplateTypeParmType(const TemplateTypeParmType *Replaced,
|
QualType
|
||||||
QualType Replacement) const;
|
getSubstTemplateTypeParmType(QualType Replacement, Decl *AssociatedDecl,
|
||||||
QualType getSubstTemplateTypeParmPackType(
|
unsigned Index,
|
||||||
const TemplateTypeParmType *Replaced,
|
std::optional<unsigned> PackIndex) const;
|
||||||
|
QualType getSubstTemplateTypeParmPackType(Decl *AssociatedDecl,
|
||||||
|
unsigned Index, bool Final,
|
||||||
const TemplateArgument &ArgPack);
|
const TemplateArgument &ArgPack);
|
||||||
|
|
||||||
QualType
|
QualType
|
||||||
@@ -1633,7 +1609,7 @@ class ASTContext : public RefCountedBase<ASTContext> {
|
|||||||
ArrayRef<TemplateArgument> Args) const;
|
ArrayRef<TemplateArgument> Args) const;
|
||||||
|
|
||||||
QualType getTemplateSpecializationType(TemplateName T,
|
QualType getTemplateSpecializationType(TemplateName T,
|
||||||
const TemplateArgumentListInfo &Args,
|
ArrayRef<TemplateArgumentLoc> Args,
|
||||||
QualType Canon = QualType()) const;
|
QualType Canon = QualType()) const;
|
||||||
|
|
||||||
TypeSourceInfo *
|
TypeSourceInfo *
|
||||||
@@ -1654,10 +1630,9 @@ class ASTContext : public RefCountedBase<ASTContext> {
|
|||||||
const IdentifierInfo *Name,
|
const IdentifierInfo *Name,
|
||||||
QualType Canon = QualType()) const;
|
QualType Canon = QualType()) const;
|
||||||
|
|
||||||
QualType getDependentTemplateSpecializationType(ElaboratedTypeKeyword Keyword,
|
QualType getDependentTemplateSpecializationType(
|
||||||
NestedNameSpecifier *NNS,
|
ElaboratedTypeKeyword Keyword, NestedNameSpecifier *NNS,
|
||||||
const IdentifierInfo *Name,
|
const IdentifierInfo *Name, ArrayRef<TemplateArgumentLoc> Args) const;
|
||||||
const TemplateArgumentListInfo &Args) const;
|
|
||||||
QualType getDependentTemplateSpecializationType(
|
QualType getDependentTemplateSpecializationType(
|
||||||
ElaboratedTypeKeyword Keyword, NestedNameSpecifier *NNS,
|
ElaboratedTypeKeyword Keyword, NestedNameSpecifier *NNS,
|
||||||
const IdentifierInfo *Name, ArrayRef<TemplateArgument> Args) const;
|
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
|
/// elsewhere, such as if the pattern contains a placeholder type or
|
||||||
/// if this is the canonical type of another pack expansion type.
|
/// if this is the canonical type of another pack expansion type.
|
||||||
QualType getPackExpansionType(QualType Pattern,
|
QualType getPackExpansionType(QualType Pattern,
|
||||||
Optional<unsigned> NumExpansions,
|
std::optional<unsigned> NumExpansions,
|
||||||
bool ExpectPackInType = true);
|
bool ExpectPackInType = true);
|
||||||
|
|
||||||
QualType getObjCInterfaceType(const ObjCInterfaceDecl *Decl,
|
QualType getObjCInterfaceType(const ObjCInterfaceDecl *Decl,
|
||||||
@@ -1710,9 +1685,9 @@ class ASTContext : public RefCountedBase<ASTContext> {
|
|||||||
/// Return a ObjCObjectPointerType type for the given ObjCObjectType.
|
/// Return a ObjCObjectPointerType type for the given ObjCObjectType.
|
||||||
QualType getObjCObjectPointerType(QualType OIT) const;
|
QualType getObjCObjectPointerType(QualType OIT) const;
|
||||||
|
|
||||||
/// GCC extension.
|
/// C2x feature and GCC extension.
|
||||||
QualType getTypeOfExprType(Expr *e) const;
|
QualType getTypeOfExprType(Expr *E, TypeOfKind Kind) const;
|
||||||
QualType getTypeOfType(QualType t) const;
|
QualType getTypeOfType(QualType QT, TypeOfKind Kind) const;
|
||||||
|
|
||||||
QualType getReferenceQualifiedType(const Expr *e) const;
|
QualType getReferenceQualifiedType(const Expr *e) const;
|
||||||
|
|
||||||
@@ -2197,10 +2172,14 @@ class ASTContext : public RefCountedBase<ASTContext> {
|
|||||||
const IdentifierInfo *Name) const;
|
const IdentifierInfo *Name) const;
|
||||||
TemplateName getDependentTemplateName(NestedNameSpecifier *NNS,
|
TemplateName getDependentTemplateName(NestedNameSpecifier *NNS,
|
||||||
OverloadedOperatorKind Operator) const;
|
OverloadedOperatorKind Operator) const;
|
||||||
TemplateName getSubstTemplateTemplateParm(TemplateTemplateParmDecl *param,
|
TemplateName
|
||||||
TemplateName replacement) const;
|
getSubstTemplateTemplateParm(TemplateName replacement, Decl *AssociatedDecl,
|
||||||
TemplateName getSubstTemplateTemplateParmPack(TemplateTemplateParmDecl *Param,
|
unsigned Index,
|
||||||
const TemplateArgument &ArgPack) const;
|
std::optional<unsigned> PackIndex) const;
|
||||||
|
TemplateName getSubstTemplateTemplateParmPack(const TemplateArgument &ArgPack,
|
||||||
|
Decl *AssociatedDecl,
|
||||||
|
unsigned Index,
|
||||||
|
bool Final) const;
|
||||||
|
|
||||||
enum GetBuiltinTypeError {
|
enum GetBuiltinTypeError {
|
||||||
/// No error
|
/// No error
|
||||||
@@ -2310,13 +2289,13 @@ class ASTContext : public RefCountedBase<ASTContext> {
|
|||||||
CharUnits getTypeSizeInChars(QualType T) const;
|
CharUnits getTypeSizeInChars(QualType T) const;
|
||||||
CharUnits getTypeSizeInChars(const Type *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())
|
if (Ty->isIncompleteType() || Ty->isDependentType())
|
||||||
return None;
|
return std::nullopt;
|
||||||
return getTypeSizeInChars(Ty);
|
return getTypeSizeInChars(Ty);
|
||||||
}
|
}
|
||||||
|
|
||||||
Optional<CharUnits> getTypeSizeInCharsIfKnown(const Type *Ty) const {
|
std::optional<CharUnits> getTypeSizeInCharsIfKnown(const Type *Ty) const {
|
||||||
return getTypeSizeInCharsIfKnown(QualType(Ty, 0));
|
return getTypeSizeInCharsIfKnown(QualType(Ty, 0));
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2372,6 +2351,9 @@ class ASTContext : public RefCountedBase<ASTContext> {
|
|||||||
bool isAlignmentRequired(const Type *T) const;
|
bool isAlignmentRequired(const Type *T) const;
|
||||||
bool isAlignmentRequired(QualType 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
|
/// Return the "preferred" alignment of the specified type \p T for
|
||||||
/// the current target, in bits.
|
/// the current target, in bits.
|
||||||
///
|
///
|
||||||
@@ -2537,6 +2519,9 @@ class ASTContext : public RefCountedBase<ASTContext> {
|
|||||||
return getCanonicalType(T1) == getCanonicalType(T2);
|
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,
|
/// Return this type as a completely-unqualified array type,
|
||||||
/// capturing the qualifiers in \p Quals.
|
/// capturing the qualifiers in \p Quals.
|
||||||
///
|
///
|
||||||
@@ -2561,8 +2546,8 @@ class ASTContext : public RefCountedBase<ASTContext> {
|
|||||||
|
|
||||||
bool hasSameNullabilityTypeQualifier(QualType SubT, QualType SuperT,
|
bool hasSameNullabilityTypeQualifier(QualType SubT, QualType SuperT,
|
||||||
bool IsParam) const {
|
bool IsParam) const {
|
||||||
auto SubTnullability = SubT->getNullability(*this);
|
auto SubTnullability = SubT->getNullability();
|
||||||
auto SuperTnullability = SuperT->getNullability(*this);
|
auto SuperTnullability = SuperT->getNullability();
|
||||||
if (SubTnullability.has_value() == SuperTnullability.has_value()) {
|
if (SubTnullability.has_value() == SuperTnullability.has_value()) {
|
||||||
// Neither has nullability; return true
|
// Neither has nullability; return true
|
||||||
if (!SubTnullability)
|
if (!SubTnullability)
|
||||||
@@ -2662,6 +2647,11 @@ class ASTContext : public RefCountedBase<ASTContext> {
|
|||||||
/// template.
|
/// template.
|
||||||
bool hasSameTemplateName(const TemplateName &X, const TemplateName &Y) const;
|
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.
|
/// Determine whether the two declarations refer to the same entity.
|
||||||
bool isSameEntity(const NamedDecl *X, const NamedDecl *Y) const;
|
bool isSameEntity(const NamedDecl *X, const NamedDecl *Y) const;
|
||||||
|
|
||||||
@@ -2730,6 +2720,10 @@ class ASTContext : public RefCountedBase<ASTContext> {
|
|||||||
/// Return number of constant array elements.
|
/// Return number of constant array elements.
|
||||||
uint64_t getConstantArrayElementCount(const ConstantArrayType *CA) const;
|
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.
|
/// Perform adjustment on the parameter type of a function.
|
||||||
///
|
///
|
||||||
/// This routine adjusts the given parameter type @p T to the actual
|
/// 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).
|
/// long double and double on AArch64 will return 0).
|
||||||
int getFloatingTypeSemanticOrder(QualType LHS, QualType RHS) const;
|
int getFloatingTypeSemanticOrder(QualType LHS, QualType RHS) const;
|
||||||
|
|
||||||
unsigned getTargetAddressSpace(QualType T) const;
|
|
||||||
|
|
||||||
unsigned getTargetAddressSpace(Qualifiers Q) const;
|
|
||||||
|
|
||||||
unsigned getTargetAddressSpace(LangAS AS) const;
|
unsigned getTargetAddressSpace(LangAS AS) const;
|
||||||
|
|
||||||
LangAS getLangASForBuiltinAddressSpace(unsigned AS) const;
|
LangAS getLangASForBuiltinAddressSpace(unsigned AS) const;
|
||||||
@@ -2803,6 +2793,23 @@ class ASTContext : public RefCountedBase<ASTContext> {
|
|||||||
return AddrSpaceMapMangling || isTargetAddressSpace(AS);
|
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:
|
private:
|
||||||
// Helper for integer ordering
|
// Helper for integer ordering
|
||||||
unsigned getIntegerRank(const Type *T) const;
|
unsigned getIntegerRank(const Type *T) const;
|
||||||
@@ -2820,14 +2827,20 @@ class ASTContext : public RefCountedBase<ASTContext> {
|
|||||||
bool typesAreBlockPointerCompatible(QualType, QualType);
|
bool typesAreBlockPointerCompatible(QualType, QualType);
|
||||||
|
|
||||||
bool isObjCIdType(QualType T) const {
|
bool isObjCIdType(QualType T) const {
|
||||||
|
if (const auto *ET = dyn_cast<ElaboratedType>(T))
|
||||||
|
T = ET->getNamedType();
|
||||||
return T == getObjCIdType();
|
return T == getObjCIdType();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool isObjCClassType(QualType T) const {
|
bool isObjCClassType(QualType T) const {
|
||||||
|
if (const auto *ET = dyn_cast<ElaboratedType>(T))
|
||||||
|
T = ET->getNamedType();
|
||||||
return T == getObjCClassType();
|
return T == getObjCClassType();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool isObjCSelType(QualType T) const {
|
bool isObjCSelType(QualType T) const {
|
||||||
|
if (const auto *ET = dyn_cast<ElaboratedType>(T))
|
||||||
|
T = ET->getNamedType();
|
||||||
return T == getObjCSelType();
|
return T == getObjCSelType();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2853,10 +2866,12 @@ class ASTContext : public RefCountedBase<ASTContext> {
|
|||||||
bool canBindObjCObjectType(QualType To, QualType From);
|
bool canBindObjCObjectType(QualType To, QualType From);
|
||||||
|
|
||||||
// Functions for calculating composite types
|
// Functions for calculating composite types
|
||||||
QualType mergeTypes(QualType, QualType, bool OfBlockPointer=false,
|
QualType mergeTypes(QualType, QualType, bool OfBlockPointer = false,
|
||||||
bool Unqualified = false, bool BlockReturnType = false);
|
bool Unqualified = false, bool BlockReturnType = false,
|
||||||
QualType mergeFunctionTypes(QualType, QualType, bool OfBlockPointer=false,
|
bool IsConditionalOperator = false);
|
||||||
bool Unqualified = false, bool AllowCXX = false);
|
QualType mergeFunctionTypes(QualType, QualType, bool OfBlockPointer = false,
|
||||||
|
bool Unqualified = false, bool AllowCXX = false,
|
||||||
|
bool IsConditionalOperator = false);
|
||||||
QualType mergeFunctionParameterTypes(QualType, QualType,
|
QualType mergeFunctionParameterTypes(QualType, QualType,
|
||||||
bool OfBlockPointer = false,
|
bool OfBlockPointer = false,
|
||||||
bool Unqualified = false);
|
bool Unqualified = false);
|
||||||
@@ -3104,6 +3119,9 @@ class ASTContext : public RefCountedBase<ASTContext> {
|
|||||||
/// valid feature names.
|
/// valid feature names.
|
||||||
ParsedTargetAttr filterFunctionTargetAttrs(const TargetAttr *TD) const;
|
ParsedTargetAttr filterFunctionTargetAttrs(const TargetAttr *TD) const;
|
||||||
|
|
||||||
|
std::vector<std::string>
|
||||||
|
filterFunctionTargetVersionAttrs(const TargetVersionAttr *TV) const;
|
||||||
|
|
||||||
void getFunctionFeatureMap(llvm::StringMap<bool> &FeatureMap,
|
void getFunctionFeatureMap(llvm::StringMap<bool> &FeatureMap,
|
||||||
const FunctionDecl *) const;
|
const FunctionDecl *) const;
|
||||||
void getFunctionFeatureMap(llvm::StringMap<bool> &FeatureMap,
|
void getFunctionFeatureMap(llvm::StringMap<bool> &FeatureMap,
|
||||||
@@ -3196,11 +3214,11 @@ OPT_LIST(V)
|
|||||||
|
|
||||||
#undef OPT_LIST
|
#undef OPT_LIST
|
||||||
|
|
||||||
LLVM_NODISCARD ObjCEncOptions keepingOnly(ObjCEncOptions Mask) const {
|
[[nodiscard]] ObjCEncOptions keepingOnly(ObjCEncOptions Mask) const {
|
||||||
return Bits & Mask.Bits;
|
return Bits & Mask.Bits;
|
||||||
}
|
}
|
||||||
|
|
||||||
LLVM_NODISCARD ObjCEncOptions forComponentType() const {
|
[[nodiscard]] ObjCEncOptions forComponentType() const {
|
||||||
ObjCEncOptions Mask = ObjCEncOptions()
|
ObjCEncOptions Mask = ObjCEncOptions()
|
||||||
.setIsOutermostType()
|
.setIsOutermostType()
|
||||||
.setIsStructField();
|
.setIsStructField();
|
||||||
|
|||||||
@@ -32,6 +32,7 @@ class ASTDumper : public ASTNodeTraverser<ASTDumper, TextNodeDumper> {
|
|||||||
|
|
||||||
TextNodeDumper &doGetNodeDelegate() { return NodeDumper; }
|
TextNodeDumper &doGetNodeDelegate() { return NodeDumper; }
|
||||||
|
|
||||||
|
void dumpInvalidDeclContext(const DeclContext *DC);
|
||||||
void dumpLookups(const DeclContext *DC, bool DumpDecls);
|
void dumpLookups(const DeclContext *DC, bool DumpDecls);
|
||||||
|
|
||||||
template <typename SpecializationDecl>
|
template <typename SpecializationDecl>
|
||||||
|
|||||||
@@ -27,8 +27,8 @@
|
|||||||
#include "clang/Basic/SourceLocation.h"
|
#include "clang/Basic/SourceLocation.h"
|
||||||
#include "llvm/ADT/DenseMap.h"
|
#include "llvm/ADT/DenseMap.h"
|
||||||
#include "llvm/ADT/DenseSet.h"
|
#include "llvm/ADT/DenseSet.h"
|
||||||
#include "llvm/ADT/Optional.h"
|
|
||||||
#include "llvm/ADT/SmallVector.h"
|
#include "llvm/ADT/SmallVector.h"
|
||||||
|
#include <optional>
|
||||||
#include <utility>
|
#include <utility>
|
||||||
|
|
||||||
namespace clang {
|
namespace clang {
|
||||||
@@ -304,7 +304,7 @@ class TypeSourceInfo;
|
|||||||
/// \param From Object to import.
|
/// \param From Object to import.
|
||||||
/// \return Error information (success or error).
|
/// \return Error information (success or error).
|
||||||
template <typename ImportT>
|
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);
|
auto ToOrErr = Import(From);
|
||||||
if (ToOrErr)
|
if (ToOrErr)
|
||||||
To = *ToOrErr;
|
To = *ToOrErr;
|
||||||
@@ -367,7 +367,7 @@ class TypeSourceInfo;
|
|||||||
/// in the "to" context was imported. If it was not imported or of the wrong
|
/// in the "to" context was imported. If it was not imported or of the wrong
|
||||||
/// type a null value is returned.
|
/// type a null value is returned.
|
||||||
template <typename DeclT>
|
template <typename DeclT>
|
||||||
llvm::Optional<DeclT *> getImportedFromDecl(const DeclT *ToD) const {
|
std::optional<DeclT *> getImportedFromDecl(const DeclT *ToD) const {
|
||||||
auto FromI = ImportedFromDecls.find(ToD);
|
auto FromI = ImportedFromDecls.find(ToD);
|
||||||
if (FromI == ImportedFromDecls.end())
|
if (FromI == ImportedFromDecls.end())
|
||||||
return {};
|
return {};
|
||||||
@@ -482,7 +482,7 @@ class TypeSourceInfo;
|
|||||||
|
|
||||||
/// Import the definition of the given declaration, including all of
|
/// Import the definition of the given declaration, including all of
|
||||||
/// the declarations it contains.
|
/// 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
|
/// Cope with a name conflict when importing a declaration into the
|
||||||
/// given context.
|
/// given context.
|
||||||
@@ -564,7 +564,7 @@ class TypeSourceInfo;
|
|||||||
/// Return if import of the given declaration has failed and if yes
|
/// 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 kind of the problem. This gives the first error encountered with
|
||||||
/// the node.
|
/// the node.
|
||||||
llvm::Optional<ASTImportError> getImportDeclErrorIfAny(Decl *FromD) const;
|
std::optional<ASTImportError> getImportDeclErrorIfAny(Decl *FromD) const;
|
||||||
|
|
||||||
/// Mark (newly) imported declaration with error.
|
/// Mark (newly) imported declaration with error.
|
||||||
void setImportDeclError(Decl *From, ASTImportError Error);
|
void setImportDeclError(Decl *From, ASTImportError Error);
|
||||||
@@ -577,8 +577,8 @@ class TypeSourceInfo;
|
|||||||
/// Determine the index of a field in its parent record.
|
/// Determine the index of a field in its parent record.
|
||||||
/// F should be a field (or indirect field) declaration.
|
/// F should be a field (or indirect field) declaration.
|
||||||
/// \returns The index of the field in its parent context (starting from 0).
|
/// \returns The index of the field in its parent context (starting from 0).
|
||||||
/// On error `None` is returned (parent context is non-record).
|
/// On error `std::nullopt` is returned (parent context is non-record).
|
||||||
static llvm::Optional<unsigned> getFieldIndex(Decl *F);
|
static std::optional<unsigned> getFieldIndex(Decl *F);
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace clang
|
} // namespace clang
|
||||||
|
|||||||
@@ -18,6 +18,7 @@
|
|||||||
#include "clang/AST/ASTImporterLookupTable.h"
|
#include "clang/AST/ASTImporterLookupTable.h"
|
||||||
#include "clang/AST/Decl.h"
|
#include "clang/AST/Decl.h"
|
||||||
#include "llvm/ADT/DenseMap.h"
|
#include "llvm/ADT/DenseMap.h"
|
||||||
|
#include <optional>
|
||||||
|
|
||||||
namespace clang {
|
namespace clang {
|
||||||
|
|
||||||
@@ -65,12 +66,12 @@ class ASTImporterSharedState {
|
|||||||
LookupTable->remove(ND);
|
LookupTable->remove(ND);
|
||||||
}
|
}
|
||||||
|
|
||||||
llvm::Optional<ASTImportError> getImportDeclErrorIfAny(Decl *ToD) const {
|
std::optional<ASTImportError> getImportDeclErrorIfAny(Decl *ToD) const {
|
||||||
auto Pos = ImportErrors.find(ToD);
|
auto Pos = ImportErrors.find(ToD);
|
||||||
if (Pos != ImportErrors.end())
|
if (Pos != ImportErrors.end())
|
||||||
return Pos->second;
|
return Pos->second;
|
||||||
else
|
else
|
||||||
return Optional<ASTImportError>();
|
return std::nullopt;
|
||||||
}
|
}
|
||||||
|
|
||||||
void setImportDeclError(Decl *To, ASTImportError Error) {
|
void setImportDeclError(Decl *To, ASTImportError Error) {
|
||||||
|
|||||||
@@ -246,7 +246,7 @@ class ASTNodeTraverser
|
|||||||
.getTypeConstraint()
|
.getTypeConstraint()
|
||||||
->getImmediatelyDeclaredConstraint());
|
->getImmediatelyDeclaredConstraint());
|
||||||
} else if (auto *NR = dyn_cast<concepts::NestedRequirement>(R)) {
|
} else if (auto *NR = dyn_cast<concepts::NestedRequirement>(R)) {
|
||||||
if (!NR->isSubstitutionFailure())
|
if (!NR->hasInvalidConstraint())
|
||||||
Visit(NR->getConstraintExpr());
|
Visit(NR->getConstraintExpr());
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@@ -389,16 +389,13 @@ class ASTNodeTraverser
|
|||||||
void VisitBTFTagAttributedType(const BTFTagAttributedType *T) {
|
void VisitBTFTagAttributedType(const BTFTagAttributedType *T) {
|
||||||
Visit(T->getWrappedType());
|
Visit(T->getWrappedType());
|
||||||
}
|
}
|
||||||
void VisitSubstTemplateTypeParmType(const SubstTemplateTypeParmType *T) {
|
void VisitSubstTemplateTypeParmType(const SubstTemplateTypeParmType *) {}
|
||||||
Visit(T->getReplacedParameter());
|
|
||||||
}
|
|
||||||
void
|
void
|
||||||
VisitSubstTemplateTypeParmPackType(const SubstTemplateTypeParmPackType *T) {
|
VisitSubstTemplateTypeParmPackType(const SubstTemplateTypeParmPackType *T) {
|
||||||
Visit(T->getReplacedParameter());
|
|
||||||
Visit(T->getArgumentPack());
|
Visit(T->getArgumentPack());
|
||||||
}
|
}
|
||||||
void VisitTemplateSpecializationType(const TemplateSpecializationType *T) {
|
void VisitTemplateSpecializationType(const TemplateSpecializationType *T) {
|
||||||
for (const auto &Arg : *T)
|
for (const auto &Arg : T->template_arguments())
|
||||||
Visit(Arg);
|
Visit(Arg);
|
||||||
}
|
}
|
||||||
void VisitObjCObjectPointerType(const ObjCObjectPointerType *T) {
|
void VisitObjCObjectPointerType(const ObjCObjectPointerType *T) {
|
||||||
@@ -479,6 +476,8 @@ class ASTNodeTraverser
|
|||||||
Visit(D->getAsmString());
|
Visit(D->getAsmString());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void VisitTopLevelStmtDecl(const TopLevelStmtDecl *D) { Visit(D->getStmt()); }
|
||||||
|
|
||||||
void VisitCapturedDecl(const CapturedDecl *D) { Visit(D->getBody()); }
|
void VisitCapturedDecl(const CapturedDecl *D) { Visit(D->getBody()); }
|
||||||
|
|
||||||
void VisitOMPThreadPrivateDecl(const OMPThreadPrivateDecl *D) {
|
void VisitOMPThreadPrivateDecl(const OMPThreadPrivateDecl *D) {
|
||||||
@@ -626,7 +625,14 @@ class ASTNodeTraverser
|
|||||||
Visit(D->getConstraintExpr());
|
Visit(D->getConstraintExpr());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void VisitImplicitConceptSpecializationDecl(
|
||||||
|
const ImplicitConceptSpecializationDecl *CSD) {
|
||||||
|
for (const TemplateArgument &Arg : CSD->getTemplateArguments())
|
||||||
|
Visit(Arg);
|
||||||
|
}
|
||||||
|
|
||||||
void VisitConceptSpecializationExpr(const ConceptSpecializationExpr *CSE) {
|
void VisitConceptSpecializationExpr(const ConceptSpecializationExpr *CSE) {
|
||||||
|
Visit(CSE->getSpecializationDecl());
|
||||||
if (CSE->hasExplicitTemplateArgs())
|
if (CSE->hasExplicitTemplateArgs())
|
||||||
for (const auto &ArgLoc : CSE->getTemplateArgsAsWritten()->arguments())
|
for (const auto &ArgLoc : CSE->getTemplateArgsAsWritten()->arguments())
|
||||||
dumpTemplateArgumentLoc(ArgLoc);
|
dumpTemplateArgumentLoc(ArgLoc);
|
||||||
@@ -638,9 +644,16 @@ class ASTNodeTraverser
|
|||||||
}
|
}
|
||||||
|
|
||||||
void VisitFriendDecl(const FriendDecl *D) {
|
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());
|
Visit(D->getFriendDecl());
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void VisitObjCMethodDecl(const ObjCMethodDecl *D) {
|
void VisitObjCMethodDecl(const ObjCMethodDecl *D) {
|
||||||
if (D->isThisDeclarationADefinition())
|
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 VisitBlockExpr(const BlockExpr *Node) { Visit(Node->getBlockDecl()); }
|
||||||
|
|
||||||
void VisitOpaqueValueExpr(const OpaqueValueExpr *Node) {
|
void VisitOpaqueValueExpr(const OpaqueValueExpr *Node) {
|
||||||
|
|||||||
@@ -17,7 +17,7 @@
|
|||||||
#include "clang/AST/DeclBase.h"
|
#include "clang/AST/DeclBase.h"
|
||||||
#include "llvm/ADT/DenseMap.h"
|
#include "llvm/ADT/DenseMap.h"
|
||||||
#include "llvm/ADT/DenseSet.h"
|
#include "llvm/ADT/DenseSet.h"
|
||||||
#include "llvm/ADT/Optional.h"
|
#include <optional>
|
||||||
#include <queue>
|
#include <queue>
|
||||||
#include <utility>
|
#include <utility>
|
||||||
|
|
||||||
@@ -114,7 +114,7 @@ struct StructuralEquivalenceContext {
|
|||||||
///
|
///
|
||||||
/// FIXME: This is needed by ASTImporter and ASTStructureEquivalence. It
|
/// FIXME: This is needed by ASTImporter and ASTStructureEquivalence. It
|
||||||
/// probably makes more sense in some other common place then here.
|
/// probably makes more sense in some other common place then here.
|
||||||
static llvm::Optional<unsigned>
|
static std::optional<unsigned>
|
||||||
findUntaggedStructOrUnionIndex(RecordDecl *Anon);
|
findUntaggedStructOrUnionIndex(RecordDecl *Anon);
|
||||||
|
|
||||||
// If ErrorOnTagTypeMismatch is set, return the error, otherwise get the
|
// If ErrorOnTagTypeMismatch is set, return the error, otherwise get the
|
||||||
|
|||||||
@@ -51,11 +51,10 @@ enum TraversalKind {
|
|||||||
class ASTNodeKind {
|
class ASTNodeKind {
|
||||||
public:
|
public:
|
||||||
/// Empty identifier. It matches nothing.
|
/// Empty identifier. It matches nothing.
|
||||||
ASTNodeKind() : KindId(NKI_None) {}
|
constexpr ASTNodeKind() : KindId(NKI_None) {}
|
||||||
|
|
||||||
/// Construct an identifier for T.
|
/// Construct an identifier for T.
|
||||||
template <class T>
|
template <class T> static constexpr ASTNodeKind getFromNodeKind() {
|
||||||
static ASTNodeKind getFromNodeKind() {
|
|
||||||
return ASTNodeKind(KindToKindId<T>::Id);
|
return ASTNodeKind(KindToKindId<T>::Id);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -71,12 +70,12 @@ class ASTNodeKind {
|
|||||||
/// \}
|
/// \}
|
||||||
|
|
||||||
/// Returns \c true if \c this and \c Other represent the same kind.
|
/// 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;
|
return KindId != NKI_None && KindId == Other.KindId;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns \c true only for the default \c ASTNodeKind()
|
/// 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.
|
/// 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
|
/// \param Distance If non-null, used to return the distance between \c this
|
||||||
@@ -87,7 +86,7 @@ class ASTNodeKind {
|
|||||||
StringRef asStringRef() const;
|
StringRef asStringRef() const;
|
||||||
|
|
||||||
/// Strict weak ordering for ASTNodeKind.
|
/// Strict weak ordering for ASTNodeKind.
|
||||||
bool operator<(const ASTNodeKind &Other) const {
|
constexpr bool operator<(const ASTNodeKind &Other) const {
|
||||||
return KindId < Other.KindId;
|
return KindId < Other.KindId;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -121,7 +120,7 @@ class ASTNodeKind {
|
|||||||
|
|
||||||
/// Check if the given ASTNodeKind identifies a type that offers pointer
|
/// Check if the given ASTNodeKind identifies a type that offers pointer
|
||||||
/// identity. This is useful for the fast path in DynTypedNode.
|
/// identity. This is useful for the fast path in DynTypedNode.
|
||||||
bool hasPointerIdentity() const {
|
constexpr bool hasPointerIdentity() const {
|
||||||
return KindId > NKI_LastKindWithoutPointerIdentity;
|
return KindId > NKI_LastKindWithoutPointerIdentity;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -165,7 +164,7 @@ class ASTNodeKind {
|
|||||||
};
|
};
|
||||||
|
|
||||||
/// Use getFromNodeKind<T>() to construct the kind.
|
/// 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
|
/// Returns \c true if \c Base is a base kind of (or same as) \c
|
||||||
/// Derived.
|
/// Derived.
|
||||||
|
|||||||
@@ -69,7 +69,12 @@ class ASTUnresolvedSet {
|
|||||||
return false;
|
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(); }
|
void clear() { Decls.clear(); }
|
||||||
|
|
||||||
|
|||||||
@@ -10,17 +10,17 @@
|
|||||||
#define LLVM_CLANG_AST_ABSTRACTBASICREADER_H
|
#define LLVM_CLANG_AST_ABSTRACTBASICREADER_H
|
||||||
|
|
||||||
#include "clang/AST/DeclTemplate.h"
|
#include "clang/AST/DeclTemplate.h"
|
||||||
|
#include <optional>
|
||||||
|
|
||||||
namespace clang {
|
namespace clang {
|
||||||
namespace serialization {
|
namespace serialization {
|
||||||
|
|
||||||
template <class T>
|
template <class T>
|
||||||
inline T makeNullableFromOptional(const Optional<T> &value) {
|
inline T makeNullableFromOptional(const std::optional<T> &value) {
|
||||||
return (value ? *value : T());
|
return (value ? *value : T());
|
||||||
}
|
}
|
||||||
|
|
||||||
template <class T>
|
template <class T> inline T *makePointerFromOptional(std::optional<T *> value) {
|
||||||
inline T *makePointerFromOptional(Optional<T *> value) {
|
|
||||||
return value.value_or(nullptr);
|
return value.value_or(nullptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -49,7 +49,7 @@ inline T *makePointerFromOptional(Optional<T *> value) {
|
|||||||
// type-specific readers for all the enum types.
|
// type-specific readers for all the enum types.
|
||||||
//
|
//
|
||||||
// template <class ValueType>
|
// template <class ValueType>
|
||||||
// Optional<ValueType> writeOptional();
|
// std::optional<ValueType> writeOptional();
|
||||||
//
|
//
|
||||||
// Reads an optional value from the current property.
|
// Reads an optional value from the current property.
|
||||||
//
|
//
|
||||||
@@ -157,7 +157,7 @@ class DataStreamBasicReader : public BasicReaderBase<Impl> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
template <class T, class... Args>
|
template <class T, class... Args>
|
||||||
llvm::Optional<T> readOptional(Args &&...args) {
|
std::optional<T> readOptional(Args &&...args) {
|
||||||
return UnpackOptionalValue<T>::unpack(
|
return UnpackOptionalValue<T>::unpack(
|
||||||
ReadDispatcher<T>::read(asImpl(), std::forward<Args>(args)...));
|
ReadDispatcher<T>::read(asImpl(), std::forward<Args>(args)...));
|
||||||
}
|
}
|
||||||
@@ -190,7 +190,8 @@ class DataStreamBasicReader : public BasicReaderBase<Impl> {
|
|||||||
|
|
||||||
APValue::LValuePathSerializationHelper readLValuePathSerializationHelper(
|
APValue::LValuePathSerializationHelper readLValuePathSerializationHelper(
|
||||||
SmallVectorImpl<APValue::LValuePathEntry> &path) {
|
SmallVectorImpl<APValue::LValuePathEntry> &path) {
|
||||||
auto elemTy = asImpl().readQualType();
|
auto origTy = asImpl().readQualType();
|
||||||
|
auto elemTy = origTy;
|
||||||
unsigned pathLength = asImpl().readUInt32();
|
unsigned pathLength = asImpl().readUInt32();
|
||||||
for (unsigned i = 0; i < pathLength; ++i) {
|
for (unsigned i = 0; i < pathLength; ++i) {
|
||||||
if (elemTy->template getAs<RecordType>()) {
|
if (elemTy->template getAs<RecordType>()) {
|
||||||
@@ -208,7 +209,7 @@ class DataStreamBasicReader : public BasicReaderBase<Impl> {
|
|||||||
APValue::LValuePathEntry::ArrayIndex(asImpl().readUInt32()));
|
APValue::LValuePathEntry::ArrayIndex(asImpl().readUInt32()));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return APValue::LValuePathSerializationHelper(path, elemTy);
|
return APValue::LValuePathSerializationHelper(path, origTy);
|
||||||
}
|
}
|
||||||
|
|
||||||
Qualifiers readQualifiers() {
|
Qualifiers readQualifiers() {
|
||||||
|
|||||||
@@ -11,20 +11,18 @@
|
|||||||
|
|
||||||
#include "clang/AST/ASTContext.h"
|
#include "clang/AST/ASTContext.h"
|
||||||
#include "clang/AST/DeclTemplate.h"
|
#include "clang/AST/DeclTemplate.h"
|
||||||
|
#include <optional>
|
||||||
|
|
||||||
namespace clang {
|
namespace clang {
|
||||||
namespace serialization {
|
namespace serialization {
|
||||||
|
|
||||||
template <class T>
|
template <class T>
|
||||||
inline llvm::Optional<T> makeOptionalFromNullable(const T &value) {
|
inline std::optional<T> makeOptionalFromNullable(const T &value) {
|
||||||
return (value.isNull()
|
return (value.isNull() ? std::optional<T>() : std::optional<T>(value));
|
||||||
? llvm::Optional<T>()
|
|
||||||
: llvm::Optional<T>(value));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
template <class T>
|
template <class T> inline std::optional<T *> makeOptionalFromPointer(T *value) {
|
||||||
inline llvm::Optional<T*> makeOptionalFromPointer(T *value) {
|
return (value ? std::optional<T *>(value) : std::optional<T *>());
|
||||||
return (value ? llvm::Optional<T*>(value) : llvm::Optional<T*>());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// PropertyWriter is a class concept that requires the following method:
|
// 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.
|
// type-specific writers for all the enum types.
|
||||||
//
|
//
|
||||||
// template <class ValueType>
|
// template <class ValueType>
|
||||||
// void writeOptional(Optional<ValueType> value);
|
// void writeOptional(std::optional<ValueType> value);
|
||||||
//
|
//
|
||||||
// Writes an optional value as the current property.
|
// Writes an optional value as the current property.
|
||||||
//
|
//
|
||||||
@@ -148,8 +146,7 @@ class DataStreamBasicWriter : public BasicWriterBase<Impl> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
template <class T>
|
template <class T> void writeOptional(std::optional<T> value) {
|
||||||
void writeOptional(llvm::Optional<T> value) {
|
|
||||||
WriteDispatcher<T>::write(asImpl(), PackOptionalValue<T>::pack(value));
|
WriteDispatcher<T>::write(asImpl(), PackOptionalValue<T>::pack(value));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -24,7 +24,6 @@
|
|||||||
#include "clang/Basic/OpenMPKinds.h"
|
#include "clang/Basic/OpenMPKinds.h"
|
||||||
#include "clang/Basic/Sanitizers.h"
|
#include "clang/Basic/Sanitizers.h"
|
||||||
#include "clang/Basic/SourceLocation.h"
|
#include "clang/Basic/SourceLocation.h"
|
||||||
#include "llvm/ADT/StringSwitch.h"
|
|
||||||
#include "llvm/Support/ErrorHandling.h"
|
#include "llvm/Support/ErrorHandling.h"
|
||||||
#include "llvm/Support/VersionTuple.h"
|
#include "llvm/Support/VersionTuple.h"
|
||||||
#include "llvm/Support/raw_ostream.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
|
/// A parameter attribute which changes the argument-passing ABI rule
|
||||||
/// for the parameter.
|
/// for the parameter.
|
||||||
class ParameterABIAttr : public InheritableParamAttr {
|
class ParameterABIAttr : public InheritableParamAttr {
|
||||||
@@ -347,24 +362,6 @@ class ParamIdx {
|
|||||||
static_assert(sizeof(ParamIdx) == sizeof(ParamIdx::SerialType),
|
static_assert(sizeof(ParamIdx) == sizeof(ParamIdx::SerialType),
|
||||||
"ParamIdx does not fit its serialization type");
|
"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"
|
#include "clang/AST/Attrs.inc"
|
||||||
|
|
||||||
inline const StreamingDiagnostic &operator<<(const StreamingDiagnostic &DB,
|
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, hasSignedIntegerRepresentation)
|
||||||
LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, hasUnsignedIntegerRepresentation)
|
LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, hasUnsignedIntegerRepresentation)
|
||||||
LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, hasFloatingRepresentation)
|
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, isSignedIntegerType)
|
||||||
LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isUnsignedIntegerType)
|
LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isUnsignedIntegerType)
|
||||||
LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isSignedIntegerOrEnumerationType)
|
LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isSignedIntegerOrEnumerationType)
|
||||||
@@ -529,7 +528,7 @@ struct CanProxyAdaptor<FunctionProtoType>
|
|||||||
|
|
||||||
template<>
|
template<>
|
||||||
struct CanProxyAdaptor<TypeOfType> : public CanProxyBase<TypeOfType> {
|
struct CanProxyAdaptor<TypeOfType> : public CanProxyBase<TypeOfType> {
|
||||||
LLVM_CLANG_CANPROXY_TYPE_ACCESSOR(getUnderlyingType)
|
LLVM_CLANG_CANPROXY_TYPE_ACCESSOR(getUnmodifiedType)
|
||||||
};
|
};
|
||||||
|
|
||||||
template<>
|
template<>
|
||||||
|
|||||||
@@ -64,6 +64,12 @@ namespace clang {
|
|||||||
return CharUnits(Quantity);
|
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.
|
// Compound assignment.
|
||||||
CharUnits& operator+= (const CharUnits &Other) {
|
CharUnits& operator+= (const CharUnits &Other) {
|
||||||
Quantity += Other.Quantity;
|
Quantity += Other.Quantity;
|
||||||
@@ -183,7 +189,8 @@ namespace clang {
|
|||||||
llvm::Align getAsAlign() const { return llvm::Align(Quantity); }
|
llvm::Align getAsAlign() const { return llvm::Align(Quantity); }
|
||||||
|
|
||||||
/// getAsMaybeAlign - Returns Quantity as a valid llvm::Align or
|
/// 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 {
|
llvm::MaybeAlign getAsMaybeAlign() const {
|
||||||
return llvm::MaybeAlign(Quantity);
|
return llvm::MaybeAlign(Quantity);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -80,7 +80,7 @@ class Sema {
|
|||||||
ArrayRef<T> copyArray(ArrayRef<T> Source) {
|
ArrayRef<T> copyArray(ArrayRef<T> Source) {
|
||||||
if (!Source.empty())
|
if (!Source.empty())
|
||||||
return Source.copy(Allocator);
|
return Source.copy(Allocator);
|
||||||
return None;
|
return std::nullopt;
|
||||||
}
|
}
|
||||||
|
|
||||||
ParagraphComment *actOnParagraphComment(
|
ParagraphComment *actOnParagraphComment(
|
||||||
|
|||||||
@@ -19,6 +19,7 @@
|
|||||||
#include "llvm/ADT/DenseMap.h"
|
#include "llvm/ADT/DenseMap.h"
|
||||||
#include <array>
|
#include <array>
|
||||||
#include <cassert>
|
#include <cassert>
|
||||||
|
#include <optional>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
namespace llvm {
|
namespace llvm {
|
||||||
@@ -58,7 +59,8 @@ inline ComparisonCategoryType commonComparisonType(ComparisonCategoryType A,
|
|||||||
|
|
||||||
/// Get the comparison category that should be used when comparing values of
|
/// Get the comparison category that should be used when comparing values of
|
||||||
/// type \c T.
|
/// type \c T.
|
||||||
Optional<ComparisonCategoryType> getComparisonCategoryForBuiltinCmp(QualType T);
|
std::optional<ComparisonCategoryType>
|
||||||
|
getComparisonCategoryForBuiltinCmp(QualType T);
|
||||||
|
|
||||||
/// An enumeration representing the possible results of a three-way
|
/// An enumeration representing the possible results of a three-way
|
||||||
/// comparison. These values map onto instances of comparison category types
|
/// comparison. These values map onto instances of comparison category types
|
||||||
|
|||||||
@@ -79,6 +79,7 @@ class CXXUnresolvedConstructExpr;
|
|||||||
class CXXDependentScopeMemberExpr;
|
class CXXDependentScopeMemberExpr;
|
||||||
class MaterializeTemporaryExpr;
|
class MaterializeTemporaryExpr;
|
||||||
class CXXFoldExpr;
|
class CXXFoldExpr;
|
||||||
|
class CXXParenListInitExpr;
|
||||||
class TypeTraitExpr;
|
class TypeTraitExpr;
|
||||||
class ConceptSpecializationExpr;
|
class ConceptSpecializationExpr;
|
||||||
class SYCLUniqueStableNameExpr;
|
class SYCLUniqueStableNameExpr;
|
||||||
@@ -168,6 +169,7 @@ ExprDependence computeDependence(CXXUnresolvedConstructExpr *E);
|
|||||||
ExprDependence computeDependence(CXXDependentScopeMemberExpr *E);
|
ExprDependence computeDependence(CXXDependentScopeMemberExpr *E);
|
||||||
ExprDependence computeDependence(MaterializeTemporaryExpr *E);
|
ExprDependence computeDependence(MaterializeTemporaryExpr *E);
|
||||||
ExprDependence computeDependence(CXXFoldExpr *E);
|
ExprDependence computeDependence(CXXFoldExpr *E);
|
||||||
|
ExprDependence computeDependence(CXXParenListInitExpr *E);
|
||||||
ExprDependence computeDependence(TypeTraitExpr *E);
|
ExprDependence computeDependence(TypeTraitExpr *E);
|
||||||
ExprDependence computeDependence(ConceptSpecializationExpr *E,
|
ExprDependence computeDependence(ConceptSpecializationExpr *E,
|
||||||
bool ValueDependent);
|
bool ValueDependent);
|
||||||
|
|||||||
@@ -35,7 +35,6 @@
|
|||||||
#include "clang/Basic/Visibility.h"
|
#include "clang/Basic/Visibility.h"
|
||||||
#include "llvm/ADT/APSInt.h"
|
#include "llvm/ADT/APSInt.h"
|
||||||
#include "llvm/ADT/ArrayRef.h"
|
#include "llvm/ADT/ArrayRef.h"
|
||||||
#include "llvm/ADT/Optional.h"
|
|
||||||
#include "llvm/ADT/PointerIntPair.h"
|
#include "llvm/ADT/PointerIntPair.h"
|
||||||
#include "llvm/ADT/PointerUnion.h"
|
#include "llvm/ADT/PointerUnion.h"
|
||||||
#include "llvm/ADT/StringRef.h"
|
#include "llvm/ADT/StringRef.h"
|
||||||
@@ -46,6 +45,7 @@
|
|||||||
#include <cassert>
|
#include <cassert>
|
||||||
#include <cstddef>
|
#include <cstddef>
|
||||||
#include <cstdint>
|
#include <cstdint>
|
||||||
|
#include <optional>
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <utility>
|
#include <utility>
|
||||||
|
|
||||||
@@ -291,7 +291,9 @@ class NamedDecl : public Decl {
|
|||||||
|
|
||||||
/// Pretty-print the unqualified name of this declaration. Can be overloaded
|
/// Pretty-print the unqualified name of this declaration. Can be overloaded
|
||||||
/// by derived classes to provide a more user-friendly name when appropriate.
|
/// 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
|
/// Get the actual, stored name of the declaration, which may be a special
|
||||||
/// name.
|
/// name.
|
||||||
@@ -435,7 +437,7 @@ class NamedDecl : public Decl {
|
|||||||
|
|
||||||
/// If visibility was explicitly specified for this
|
/// If visibility was explicitly specified for this
|
||||||
/// declaration, return that visibility.
|
/// declaration, return that visibility.
|
||||||
Optional<Visibility>
|
std::optional<Visibility>
|
||||||
getExplicitVisibility(ExplicitVisibilityKind kind) const;
|
getExplicitVisibility(ExplicitVisibilityKind kind) const;
|
||||||
|
|
||||||
/// True if the computed linkage is valid. Used for consistency
|
/// True if the computed linkage is valid. Used for consistency
|
||||||
@@ -540,6 +542,9 @@ class LabelDecl : public NamedDecl {
|
|||||||
class NamespaceDecl : public NamedDecl, public DeclContext,
|
class NamespaceDecl : public NamedDecl, public DeclContext,
|
||||||
public Redeclarable<NamespaceDecl>
|
public Redeclarable<NamespaceDecl>
|
||||||
{
|
{
|
||||||
|
|
||||||
|
enum Flags : unsigned { F_Inline = 1 << 0, F_Nested = 1 << 1 };
|
||||||
|
|
||||||
/// The starting location of the source range, pointing
|
/// The starting location of the source range, pointing
|
||||||
/// to either the namespace or the inline keyword.
|
/// to either the namespace or the inline keyword.
|
||||||
SourceLocation LocStart;
|
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
|
/// 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
|
/// only when this is not the first in the chain), along with a
|
||||||
/// boolean value indicating whether this is an inline namespace.
|
/// 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,
|
NamespaceDecl(ASTContext &C, DeclContext *DC, bool Inline,
|
||||||
SourceLocation StartLoc, SourceLocation IdLoc,
|
SourceLocation StartLoc, SourceLocation IdLoc,
|
||||||
IdentifierInfo *Id, NamespaceDecl *PrevDecl);
|
IdentifierInfo *Id, NamespaceDecl *PrevDecl, bool Nested);
|
||||||
|
|
||||||
using redeclarable_base = Redeclarable<NamespaceDecl>;
|
using redeclarable_base = Redeclarable<NamespaceDecl>;
|
||||||
|
|
||||||
@@ -567,10 +573,10 @@ class NamespaceDecl : public NamedDecl, public DeclContext,
|
|||||||
friend class ASTDeclReader;
|
friend class ASTDeclReader;
|
||||||
friend class ASTDeclWriter;
|
friend class ASTDeclWriter;
|
||||||
|
|
||||||
static NamespaceDecl *Create(ASTContext &C, DeclContext *DC,
|
static NamespaceDecl *Create(ASTContext &C, DeclContext *DC, bool Inline,
|
||||||
bool Inline, SourceLocation StartLoc,
|
SourceLocation StartLoc, SourceLocation IdLoc,
|
||||||
SourceLocation IdLoc, IdentifierInfo *Id,
|
IdentifierInfo *Id, NamespaceDecl *PrevDecl,
|
||||||
NamespaceDecl *PrevDecl);
|
bool Nested);
|
||||||
|
|
||||||
static NamespaceDecl *CreateDeserialized(ASTContext &C, unsigned ID);
|
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.
|
/// Returns true if this is an inline namespace declaration.
|
||||||
bool isInline() const {
|
bool isInline() const {
|
||||||
return AnonOrFirstNamespaceAndInline.getInt();
|
return AnonOrFirstNamespaceAndFlags.getInt() & F_Inline;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Set whether this is an inline namespace declaration.
|
/// Set whether this is an inline namespace declaration.
|
||||||
void setInline(bool Inline) {
|
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.
|
/// 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,
|
/// Retrieve the anonymous namespace nested inside this namespace,
|
||||||
/// if any.
|
/// if any.
|
||||||
NamespaceDecl *getAnonymousNamespace() const {
|
NamespaceDecl *getAnonymousNamespace() const {
|
||||||
return getOriginalNamespace()->AnonOrFirstNamespaceAndInline.getPointer();
|
return getOriginalNamespace()->AnonOrFirstNamespaceAndFlags.getPointer();
|
||||||
}
|
}
|
||||||
|
|
||||||
void setAnonymousNamespace(NamespaceDecl *D) {
|
void setAnonymousNamespace(NamespaceDecl *D) {
|
||||||
getOriginalNamespace()->AnonOrFirstNamespaceAndInline.setPointer(D);
|
getOriginalNamespace()->AnonOrFirstNamespaceAndFlags.setPointer(D);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Retrieves the canonical declaration of this namespace.
|
/// 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
|
/// 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 lvalue) a function (in which case it is a function designator) or
|
||||||
/// an enum constant.
|
/// an enum constant.
|
||||||
@@ -689,6 +718,18 @@ class ValueDecl : public NamedDecl {
|
|||||||
/// or declared with the weak or weak-ref attr.
|
/// or declared with the weak or weak-ref attr.
|
||||||
bool isWeak() const;
|
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.
|
// Implement isa/cast/dyncast/etc.
|
||||||
static bool classof(const Decl *D) { return classofKind(D->getKind()); }
|
static bool classof(const Decl *D) { return classofKind(D->getKind()); }
|
||||||
static bool classofKind(Kind K) { return K >= firstValue && K <= lastValue; }
|
static bool classofKind(Kind K) { return K >= firstValue && K <= lastValue; }
|
||||||
@@ -882,7 +923,10 @@ class VarDecl : public DeclaratorDecl, public Redeclarable<VarDecl> {
|
|||||||
CallInit,
|
CallInit,
|
||||||
|
|
||||||
/// Direct list-initialization (C++11)
|
/// Direct list-initialization (C++11)
|
||||||
ListInit
|
ListInit,
|
||||||
|
|
||||||
|
/// Parenthesized list-initialization (C++20)
|
||||||
|
ParenListInit
|
||||||
};
|
};
|
||||||
|
|
||||||
/// Kinds of thread-local storage.
|
/// Kinds of thread-local storage.
|
||||||
@@ -1853,7 +1897,8 @@ enum class MultiVersionKind {
|
|||||||
Target,
|
Target,
|
||||||
CPUSpecific,
|
CPUSpecific,
|
||||||
CPUDispatch,
|
CPUDispatch,
|
||||||
TargetClones
|
TargetClones,
|
||||||
|
TargetVersion
|
||||||
};
|
};
|
||||||
|
|
||||||
/// Represents a function declaration or definition.
|
/// Represents a function declaration or definition.
|
||||||
@@ -1936,6 +1981,8 @@ class FunctionDecl : public DeclaratorDecl,
|
|||||||
/// EndRangeLoc.
|
/// EndRangeLoc.
|
||||||
SourceLocation EndRangeLoc;
|
SourceLocation EndRangeLoc;
|
||||||
|
|
||||||
|
SourceLocation DefaultKWLoc;
|
||||||
|
|
||||||
/// The template or declaration that this declaration
|
/// The template or declaration that this declaration
|
||||||
/// describes or was instantiated from, respectively.
|
/// describes or was instantiated from, respectively.
|
||||||
///
|
///
|
||||||
@@ -2242,6 +2289,16 @@ class FunctionDecl : public DeclaratorDecl,
|
|||||||
FunctionDeclBits.IsExplicitlyDefaulted = ED;
|
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
|
/// True if this method is user-declared and was not
|
||||||
/// deleted or defaulted on its first declaration.
|
/// deleted or defaulted on its first declaration.
|
||||||
bool isUserProvided() const {
|
bool isUserProvided() const {
|
||||||
@@ -2414,7 +2471,7 @@ class FunctionDecl : public DeclaratorDecl,
|
|||||||
/// If this function is an allocation/deallocation function that takes
|
/// If this function is an allocation/deallocation function that takes
|
||||||
/// the `std::nothrow_t` tag, return true through IsNothrow,
|
/// the `std::nothrow_t` tag, return true through IsNothrow,
|
||||||
bool isReplaceableGlobalAllocationFunction(
|
bool isReplaceableGlobalAllocationFunction(
|
||||||
Optional<unsigned> *AlignmentParam = nullptr,
|
std::optional<unsigned> *AlignmentParam = nullptr,
|
||||||
bool *IsNothrow = nullptr) const;
|
bool *IsNothrow = nullptr) const;
|
||||||
|
|
||||||
/// Determine if this function provides an inline implementation of a builtin.
|
/// Determine if this function provides an inline implementation of a builtin.
|
||||||
@@ -2466,6 +2523,19 @@ class FunctionDecl : public DeclaratorDecl,
|
|||||||
getCanonicalDecl()->FunctionDeclBits.IsMultiVersion = V;
|
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
|
/// 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
|
/// this can return a value even if the function is not multiversion, such as
|
||||||
/// the case of 'target'.
|
/// the case of 'target'.
|
||||||
@@ -3144,7 +3214,7 @@ class IndirectFieldDecl : public ValueDecl,
|
|||||||
using chain_iterator = ArrayRef<NamedDecl *>::const_iterator;
|
using chain_iterator = ArrayRef<NamedDecl *>::const_iterator;
|
||||||
|
|
||||||
ArrayRef<NamedDecl *> chain() const {
|
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_begin() const { return chain().begin(); }
|
||||||
chain_iterator chain_end() const { return chain().end(); }
|
chain_iterator chain_end() const { return chain().end(); }
|
||||||
@@ -3621,6 +3691,8 @@ class TagDecl : public TypeDecl,
|
|||||||
return getExtInfo()->TemplParamLists[i];
|
return getExtInfo()->TemplParamLists[i];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void printName(raw_ostream &OS, const PrintingPolicy &Policy) const override;
|
||||||
|
|
||||||
void setTemplateParameterListsInfo(ASTContext &Context,
|
void setTemplateParameterListsInfo(ASTContext &Context,
|
||||||
ArrayRef<TemplateParameterList *> TPLists);
|
ArrayRef<TemplateParameterList *> TPLists);
|
||||||
|
|
||||||
@@ -3839,6 +3911,11 @@ class EnumDecl : public TagDecl {
|
|||||||
/// -101 1001011 8
|
/// -101 1001011 8
|
||||||
unsigned getNumNegativeBits() const { return EnumDeclBits.NumNegativeBits; }
|
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.
|
/// Returns true if this is a C++11 scoped enumeration.
|
||||||
bool isScoped() const { return EnumDeclBits.IsScoped; }
|
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.
|
// to save some space. Use the provided accessors to access it.
|
||||||
public:
|
public:
|
||||||
friend class DeclContext;
|
friend class DeclContext;
|
||||||
|
friend class ASTDeclReader;
|
||||||
/// Enum that represents the different ways arguments are passed to and
|
/// Enum that represents the different ways arguments are passed to and
|
||||||
/// returned from function calls. This takes into account the target-specific
|
/// returned from function calls. This takes into account the target-specific
|
||||||
/// and version-specific rules along with the rules determined by the
|
/// 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.
|
/// nullptr is returned if no named data member exists.
|
||||||
const FieldDecl *findFirstNamedDataMember() const;
|
const FieldDecl *findFirstNamedDataMember() const;
|
||||||
|
|
||||||
|
/// Get precomputed ODRHash or add a new one.
|
||||||
|
unsigned getODRHash();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
/// Deserialize just the fields.
|
/// Deserialize just the fields.
|
||||||
void LoadFieldsFromExternalStorage() const;
|
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 {
|
class FileScopeAsmDecl : public Decl {
|
||||||
@@ -4210,6 +4295,34 @@ class FileScopeAsmDecl : public Decl {
|
|||||||
static bool classofKind(Kind K) { return K == FileScopeAsm; }
|
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
|
/// Represents a block literal declaration, which is like an
|
||||||
/// unnamed FunctionDecl. For example:
|
/// unnamed FunctionDecl. For example:
|
||||||
/// ^{ statement-body } or ^(int arg1, float arg2){ statement-body }
|
/// ^{ 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; }
|
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
|
/// Insertion operator for diagnostics. This allows sending NamedDecl's
|
||||||
/// into a diagnostic with <<.
|
/// into a diagnostic with <<.
|
||||||
inline const StreamingDiagnostic &operator<<(const StreamingDiagnostic &PD,
|
inline const StreamingDiagnostic &operator<<(const StreamingDiagnostic &PD,
|
||||||
|
|||||||
@@ -447,6 +447,14 @@ class alignas(8) Decl {
|
|||||||
return const_cast<Decl*>(this)->getDeclContext();
|
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,
|
/// Find the innermost non-closure ancestor of this declaration,
|
||||||
/// walking up through blocks, lambdas, etc. If that ancestor is
|
/// walking up through blocks, lambdas, etc. If that ancestor is
|
||||||
/// not a code context (!isFunctionOrMethod()), returns null.
|
/// not a code context (!isFunctionOrMethod()), returns null.
|
||||||
@@ -466,6 +474,9 @@ class alignas(8) Decl {
|
|||||||
|
|
||||||
bool isInStdNamespace() const;
|
bool isInStdNamespace() const;
|
||||||
|
|
||||||
|
// Return true if this is a FileContext Decl.
|
||||||
|
bool isFileContextDecl() const;
|
||||||
|
|
||||||
ASTContext &getASTContext() const LLVM_READONLY;
|
ASTContext &getASTContext() const LLVM_READONLY;
|
||||||
|
|
||||||
/// Helper to get the language options from the ASTContext.
|
/// 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.
|
/// Determine whether this is a block-scope declaration with linkage.
|
||||||
/// This will either be a local variable declaration declared 'extern', or a
|
/// This will either be a local variable declaration declared 'extern', or a
|
||||||
/// local function declaration.
|
/// local function declaration.
|
||||||
bool isLocalExternDecl() {
|
bool isLocalExternDecl() const {
|
||||||
return IdentifierNamespace & IDNS_LocalExtern;
|
return IdentifierNamespace & IDNS_LocalExtern;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1566,10 +1577,14 @@ class DeclContext {
|
|||||||
|
|
||||||
/// Indicates whether this struct has had its field layout randomized.
|
/// Indicates whether this struct has had its field layout randomized.
|
||||||
uint64_t IsRandomized : 1;
|
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.
|
/// Number of non-inherited bits in RecordDeclBitfields.
|
||||||
enum { NumRecordDeclBits = 15 };
|
enum { NumRecordDeclBits = 41 };
|
||||||
|
|
||||||
/// Stores the bits used by OMPDeclareReductionDecl.
|
/// Stores the bits used by OMPDeclareReductionDecl.
|
||||||
/// If modified NumOMPDeclareReductionDeclBits and the accessor
|
/// If modified NumOMPDeclareReductionDeclBits and the accessor
|
||||||
@@ -1656,10 +1671,14 @@ class DeclContext {
|
|||||||
|
|
||||||
/// Indicates if the function uses Floating Point Constrained Intrinsics
|
/// Indicates if the function uses Floating Point Constrained Intrinsics
|
||||||
uint64_t UsesFPIntrin : 1;
|
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.
|
/// Number of non-inherited bits in FunctionDeclBitfields.
|
||||||
enum { NumFunctionDeclBits = 28 };
|
enum { NumFunctionDeclBits = 29 };
|
||||||
|
|
||||||
/// Stores the bits used by CXXConstructorDecl. If modified
|
/// Stores the bits used by CXXConstructorDecl. If modified
|
||||||
/// NumCXXConstructorDeclBits and the accessor
|
/// NumCXXConstructorDeclBits and the accessor
|
||||||
@@ -1671,12 +1690,12 @@ class DeclContext {
|
|||||||
/// For the bits in FunctionDeclBitfields.
|
/// For the bits in FunctionDeclBitfields.
|
||||||
uint64_t : NumFunctionDeclBits;
|
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
|
/// Note that this makes CXXConstructorDeclBitfields take
|
||||||
/// exactly 64 bits and thus the width of NumCtorInitializers
|
/// exactly 64 bits and thus the width of NumCtorInitializers
|
||||||
/// will need to be shrunk if some bit is added to NumDeclContextBitfields,
|
/// will need to be shrunk if some bit is added to NumDeclContextBitfields,
|
||||||
/// NumFunctionDeclBitfields or CXXConstructorDeclBitfields.
|
/// NumFunctionDeclBitfields or CXXConstructorDeclBitfields.
|
||||||
uint64_t NumCtorInitializers : 20;
|
uint64_t NumCtorInitializers : 19;
|
||||||
uint64_t IsInheritingConstructor : 1;
|
uint64_t IsInheritingConstructor : 1;
|
||||||
|
|
||||||
/// Whether this constructor has a trail-allocated explicit specifier.
|
/// Whether this constructor has a trail-allocated explicit specifier.
|
||||||
@@ -1894,6 +1913,10 @@ class DeclContext {
|
|||||||
public:
|
public:
|
||||||
~DeclContext();
|
~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 {
|
Decl::Kind getDeclKind() const {
|
||||||
return static_cast<Decl::Kind>(DeclContextBits.DeclKind);
|
return static_cast<Decl::Kind>(DeclContextBits.DeclKind);
|
||||||
}
|
}
|
||||||
@@ -2009,7 +2032,7 @@ class DeclContext {
|
|||||||
/// Here, E is a transparent context, so its enumerator (Val1) will
|
/// Here, E is a transparent context, so its enumerator (Val1) will
|
||||||
/// appear (semantically) that it is in the same context of E.
|
/// appear (semantically) that it is in the same context of E.
|
||||||
/// Examples of transparent contexts include: enumerations (except for
|
/// 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;
|
bool isTransparentContext() const;
|
||||||
|
|
||||||
/// Determines whether this context or some of its ancestors is a
|
/// 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 Decl *D);
|
||||||
static bool classof(const DeclContext *D) { return true; }
|
static bool classof(const DeclContext *D) { return true; }
|
||||||
|
|
||||||
|
void dumpAsDecl() const;
|
||||||
|
void dumpAsDecl(const ASTContext *Ctx) const;
|
||||||
void dumpDeclContext() const;
|
void dumpDeclContext() const;
|
||||||
void dumpLookups() const;
|
void dumpLookups() const;
|
||||||
void dumpLookups(llvm::raw_ostream &OS, bool DumpDecls = false,
|
void dumpLookups(llvm::raw_ostream &OS, bool DumpDecls = false,
|
||||||
|
|||||||
@@ -260,6 +260,7 @@ class CXXRecordDecl : public RecordDecl {
|
|||||||
friend class ASTWriter;
|
friend class ASTWriter;
|
||||||
friend class DeclContext;
|
friend class DeclContext;
|
||||||
friend class LambdaExpr;
|
friend class LambdaExpr;
|
||||||
|
friend class ODRDiagsEmitter;
|
||||||
|
|
||||||
friend void FunctionDecl::setPure(bool);
|
friend void FunctionDecl::setPure(bool);
|
||||||
friend void TagDecl::startDefinition();
|
friend void TagDecl::startDefinition();
|
||||||
@@ -356,11 +357,11 @@ class CXXRecordDecl : public RecordDecl {
|
|||||||
}
|
}
|
||||||
|
|
||||||
ArrayRef<CXXBaseSpecifier> bases() const {
|
ArrayRef<CXXBaseSpecifier> bases() const {
|
||||||
return llvm::makeArrayRef(getBases(), NumBases);
|
return llvm::ArrayRef(getBases(), NumBases);
|
||||||
}
|
}
|
||||||
|
|
||||||
ArrayRef<CXXBaseSpecifier> vbases() const {
|
ArrayRef<CXXBaseSpecifier> vbases() const {
|
||||||
return llvm::makeArrayRef(getVBases(), NumVBases);
|
return llvm::ArrayRef(getVBases(), NumVBases);
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
@@ -409,9 +410,11 @@ class CXXRecordDecl : public RecordDecl {
|
|||||||
/// or within a data member initializer.
|
/// or within a data member initializer.
|
||||||
LazyDeclPtr ContextDecl;
|
LazyDeclPtr ContextDecl;
|
||||||
|
|
||||||
/// The list of captures, both explicit and implicit, for this
|
/// The lists of captures, both explicit and implicit, for this
|
||||||
/// lambda.
|
/// lambda. One list is provided for each merged copy of the lambda.
|
||||||
Capture *Captures = nullptr;
|
/// 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.
|
/// The type of the call method.
|
||||||
TypeSourceInfo *MethodTyInfo;
|
TypeSourceInfo *MethodTyInfo;
|
||||||
@@ -429,6 +432,9 @@ class CXXRecordDecl : public RecordDecl {
|
|||||||
Aggregate = false;
|
Aggregate = false;
|
||||||
PlainOldData = false;
|
PlainOldData = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Add a list of captures.
|
||||||
|
void AddCaptureList(ASTContext &Ctx, Capture *CaptureList);
|
||||||
};
|
};
|
||||||
|
|
||||||
struct DefinitionData *dataPtr() const {
|
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
|
/// \note No entries will be added for init-captures, as they do not capture
|
||||||
/// variables.
|
/// 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;
|
FieldDecl *&ThisCapture) const;
|
||||||
|
|
||||||
using capture_const_iterator = const LambdaCapture *;
|
using capture_const_iterator = const LambdaCapture *;
|
||||||
@@ -1068,7 +1080,9 @@ class CXXRecordDecl : public RecordDecl {
|
|||||||
}
|
}
|
||||||
|
|
||||||
capture_const_iterator captures_begin() const {
|
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 {
|
capture_const_iterator captures_end() const {
|
||||||
@@ -1170,7 +1184,7 @@ class CXXRecordDecl : public RecordDecl {
|
|||||||
|
|
||||||
/// Determine whether this class has a pure virtual function.
|
/// 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
|
/// a pure virtual function or inherits a pure virtual function that is
|
||||||
/// not overridden.
|
/// not overridden.
|
||||||
bool isAbstract() const { return data().Abstract; }
|
bool isAbstract() const { return data().Abstract; }
|
||||||
@@ -1916,7 +1930,7 @@ class CXXDeductionGuideDecl : public FunctionDecl {
|
|||||||
ExplicitSpecifier getExplicitSpecifier() { return ExplicitSpec; }
|
ExplicitSpecifier getExplicitSpecifier() { return ExplicitSpec; }
|
||||||
const ExplicitSpecifier getExplicitSpecifier() const { 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(); }
|
bool isExplicit() const { return ExplicitSpec.isExplicit(); }
|
||||||
|
|
||||||
/// Get the template for which this guide performs deduction.
|
/// Get the template for which this guide performs deduction.
|
||||||
@@ -2512,7 +2526,7 @@ class CXXConstructorDecl final
|
|||||||
return getCanonicalDecl()->getExplicitSpecifierInternal();
|
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(); }
|
bool isExplicit() const { return getExplicitSpecifier().isExplicit(); }
|
||||||
|
|
||||||
/// Iterates through the member/base initializer list.
|
/// Iterates through the member/base initializer list.
|
||||||
@@ -2796,7 +2810,7 @@ class CXXConversionDecl : public CXXMethodDecl {
|
|||||||
return getCanonicalDecl()->ExplicitSpec;
|
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(); }
|
bool isExplicit() const { return getExplicitSpecifier().isExplicit(); }
|
||||||
void setExplicitSpecifier(ExplicitSpecifier ES) { ExplicitSpec = ES; }
|
void setExplicitSpecifier(ExplicitSpecifier ES) { ExplicitSpec = ES; }
|
||||||
|
|
||||||
@@ -3612,17 +3626,15 @@ class ConstructorUsingShadowDecl final : public UsingShadowDecl {
|
|||||||
class UsingEnumDecl : public BaseUsingDecl, public Mergeable<UsingEnumDecl> {
|
class UsingEnumDecl : public BaseUsingDecl, public Mergeable<UsingEnumDecl> {
|
||||||
/// The source location of the 'using' keyword itself.
|
/// The source location of the 'using' keyword itself.
|
||||||
SourceLocation UsingLocation;
|
SourceLocation UsingLocation;
|
||||||
|
/// The source location of the 'enum' keyword.
|
||||||
/// Location of the 'enum' keyword.
|
|
||||||
SourceLocation EnumLocation;
|
SourceLocation EnumLocation;
|
||||||
|
/// 'qual::SomeEnum' as an EnumType, possibly with Elaborated/Typedef sugar.
|
||||||
/// The enum
|
TypeSourceInfo *EnumType;
|
||||||
EnumDecl *Enum;
|
|
||||||
|
|
||||||
UsingEnumDecl(DeclContext *DC, DeclarationName DN, SourceLocation UL,
|
UsingEnumDecl(DeclContext *DC, DeclarationName DN, SourceLocation UL,
|
||||||
SourceLocation EL, SourceLocation NL, EnumDecl *ED)
|
SourceLocation EL, SourceLocation NL, TypeSourceInfo *EnumType)
|
||||||
: BaseUsingDecl(UsingEnum, DC, NL, DN), UsingLocation(UL),
|
: BaseUsingDecl(UsingEnum, DC, NL, DN), UsingLocation(UL), EnumLocation(EL),
|
||||||
EnumLocation(EL), Enum(ED) {}
|
EnumType(EnumType){}
|
||||||
|
|
||||||
void anchor() override;
|
void anchor() override;
|
||||||
|
|
||||||
@@ -3637,13 +3649,29 @@ class UsingEnumDecl : public BaseUsingDecl, public Mergeable<UsingEnumDecl> {
|
|||||||
/// The source location of the 'enum' keyword.
|
/// The source location of the 'enum' keyword.
|
||||||
SourceLocation getEnumLoc() const { return EnumLocation; }
|
SourceLocation getEnumLoc() const { return EnumLocation; }
|
||||||
void setEnumLoc(SourceLocation L) { EnumLocation = L; }
|
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:
|
public:
|
||||||
EnumDecl *getEnumDecl() const { return Enum; }
|
EnumDecl *getEnumDecl() const { return cast<EnumDecl>(EnumType->getType()->getAsTagDecl()); }
|
||||||
|
|
||||||
static UsingEnumDecl *Create(ASTContext &C, DeclContext *DC,
|
static UsingEnumDecl *Create(ASTContext &C, DeclContext *DC,
|
||||||
SourceLocation UsingL, SourceLocation EnumL,
|
SourceLocation UsingL, SourceLocation EnumL,
|
||||||
SourceLocation NameL, EnumDecl *ED);
|
SourceLocation NameL, TypeSourceInfo *EnumType);
|
||||||
|
|
||||||
static UsingEnumDecl *CreateDeserialized(ASTContext &C, unsigned ID);
|
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
|
/// Get the set of using declarations that this pack expanded into. Note that
|
||||||
/// some of these may still be unresolved.
|
/// some of these may still be unresolved.
|
||||||
ArrayRef<NamedDecl *> expansions() const {
|
ArrayRef<NamedDecl *> expansions() const {
|
||||||
return llvm::makeArrayRef(getTrailingObjects<NamedDecl *>(), NumExpansions);
|
return llvm::ArrayRef(getTrailingObjects<NamedDecl *>(), NumExpansions);
|
||||||
}
|
}
|
||||||
|
|
||||||
static UsingPackDecl *Create(ASTContext &C, DeclContext *DC,
|
static UsingPackDecl *Create(ASTContext &C, DeclContext *DC,
|
||||||
@@ -4081,10 +4109,10 @@ class DecompositionDecl final
|
|||||||
unsigned NumBindings);
|
unsigned NumBindings);
|
||||||
|
|
||||||
ArrayRef<BindingDecl *> bindings() const {
|
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 classof(const Decl *D) { return classofKind(D->getKind()); }
|
||||||
static bool classofKind(Kind K) { return K == Decomposition; }
|
static bool classofKind(Kind K) { return K == Decomposition; }
|
||||||
@@ -4197,7 +4225,8 @@ class MSGuidDecl : public ValueDecl,
|
|||||||
|
|
||||||
public:
|
public:
|
||||||
/// Print this UUID in a human-readable format.
|
/// 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.
|
/// Get the decomposed parts of this declaration.
|
||||||
Parts getParts() const { return PartVal; }
|
Parts getParts() const { return PartVal; }
|
||||||
@@ -4250,7 +4279,8 @@ class UnnamedGlobalConstantDecl : public ValueDecl,
|
|||||||
|
|
||||||
public:
|
public:
|
||||||
/// Print this in a human-readable format.
|
/// 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; }
|
const APValue &getValue() const { return Value; }
|
||||||
|
|
||||||
|
|||||||
@@ -23,7 +23,6 @@
|
|||||||
#include "clang/Basic/LLVM.h"
|
#include "clang/Basic/LLVM.h"
|
||||||
#include "clang/Basic/SourceLocation.h"
|
#include "clang/Basic/SourceLocation.h"
|
||||||
#include "llvm/ADT/ArrayRef.h"
|
#include "llvm/ADT/ArrayRef.h"
|
||||||
#include "llvm/ADT/None.h"
|
|
||||||
#include "llvm/ADT/PointerUnion.h"
|
#include "llvm/ADT/PointerUnion.h"
|
||||||
#include "llvm/Support/Casting.h"
|
#include "llvm/Support/Casting.h"
|
||||||
#include "llvm/Support/Compiler.h"
|
#include "llvm/Support/Compiler.h"
|
||||||
@@ -108,11 +107,10 @@ class FriendDecl final
|
|||||||
friend class ASTNodeImporter;
|
friend class ASTNodeImporter;
|
||||||
friend TrailingObjects;
|
friend TrailingObjects;
|
||||||
|
|
||||||
static FriendDecl *Create(ASTContext &C, DeclContext *DC,
|
static FriendDecl *
|
||||||
SourceLocation L, FriendUnion Friend_,
|
Create(ASTContext &C, DeclContext *DC, SourceLocation L, FriendUnion Friend_,
|
||||||
SourceLocation FriendL,
|
SourceLocation FriendL,
|
||||||
ArrayRef<TemplateParameterList*> FriendTypeTPLists
|
ArrayRef<TemplateParameterList *> FriendTypeTPLists = std::nullopt);
|
||||||
= None);
|
|
||||||
static FriendDecl *CreateDeserialized(ASTContext &C, unsigned ID,
|
static FriendDecl *CreateDeserialized(ASTContext &C, unsigned ID,
|
||||||
unsigned FriendTypeNumTPLists);
|
unsigned FriendTypeNumTPLists);
|
||||||
|
|
||||||
|
|||||||
@@ -25,9 +25,8 @@
|
|||||||
#include "clang/Basic/SourceLocation.h"
|
#include "clang/Basic/SourceLocation.h"
|
||||||
#include "clang/Basic/Specifiers.h"
|
#include "clang/Basic/Specifiers.h"
|
||||||
#include "llvm/ADT/ArrayRef.h"
|
#include "llvm/ADT/ArrayRef.h"
|
||||||
#include "llvm/ADT/DenseMap.h"
|
|
||||||
#include "llvm/ADT/DenseSet.h"
|
#include "llvm/ADT/DenseSet.h"
|
||||||
#include "llvm/ADT/None.h"
|
#include "llvm/ADT/MapVector.h"
|
||||||
#include "llvm/ADT/PointerIntPair.h"
|
#include "llvm/ADT/PointerIntPair.h"
|
||||||
#include "llvm/ADT/STLExtras.h"
|
#include "llvm/ADT/STLExtras.h"
|
||||||
#include "llvm/ADT/StringRef.h"
|
#include "llvm/ADT/StringRef.h"
|
||||||
@@ -374,8 +373,7 @@ class ObjCMethodDecl : public NamedDecl, public DeclContext {
|
|||||||
// ArrayRef access to formal parameters. This should eventually
|
// ArrayRef access to formal parameters. This should eventually
|
||||||
// replace the iterator interface above.
|
// replace the iterator interface above.
|
||||||
ArrayRef<ParmVarDecl*> parameters() const {
|
ArrayRef<ParmVarDecl*> parameters() const {
|
||||||
return llvm::makeArrayRef(const_cast<ParmVarDecl**>(getParams()),
|
return llvm::ArrayRef(const_cast<ParmVarDecl **>(getParams()), NumParams);
|
||||||
NumParams);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ParmVarDecl *getParamDecl(unsigned Idx) {
|
ParmVarDecl *getParamDecl(unsigned Idx) {
|
||||||
@@ -389,9 +387,8 @@ class ObjCMethodDecl : public NamedDecl, public DeclContext {
|
|||||||
/// Sets the method's parameters and selector source locations.
|
/// Sets the method's parameters and selector source locations.
|
||||||
/// If the method is implicit (not coming from source) \p SelLocs is
|
/// If the method is implicit (not coming from source) \p SelLocs is
|
||||||
/// ignored.
|
/// ignored.
|
||||||
void setMethodParams(ASTContext &C,
|
void setMethodParams(ASTContext &C, ArrayRef<ParmVarDecl *> Params,
|
||||||
ArrayRef<ParmVarDecl*> Params,
|
ArrayRef<SourceLocation> SelLocs = std::nullopt);
|
||||||
ArrayRef<SourceLocation> SelLocs = llvm::None);
|
|
||||||
|
|
||||||
// Iterator access to parameter types.
|
// Iterator access to parameter types.
|
||||||
struct GetTypeFn {
|
struct GetTypeFn {
|
||||||
@@ -1079,7 +1076,7 @@ class ObjCContainerDecl : public NamedDecl, public DeclContext {
|
|||||||
ObjCPropertyQueryKind QueryKind) const;
|
ObjCPropertyQueryKind QueryKind) const;
|
||||||
|
|
||||||
using PropertyMap =
|
using PropertyMap =
|
||||||
llvm::DenseMap<std::pair<IdentifierInfo *, unsigned/*isClassProperty*/>,
|
llvm::MapVector<std::pair<IdentifierInfo *, unsigned /*isClassProperty*/>,
|
||||||
ObjCPropertyDecl *>;
|
ObjCPropertyDecl *>;
|
||||||
using ProtocolPropertySet = llvm::SmallDenseSet<const ObjCProtocolDecl *, 8>;
|
using ProtocolPropertySet = llvm::SmallDenseSet<const ObjCProtocolDecl *, 8>;
|
||||||
using PropertyDeclOrder = llvm::SmallVector<ObjCPropertyDecl *, 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 routine collects list of properties to be implemented in the class.
|
||||||
/// This includes, class's and its conforming protocols' properties.
|
/// This includes, class's and its conforming protocols' properties.
|
||||||
/// Note, the superclass's properties are not included in the list.
|
/// Note, the superclass's properties are not included in the list.
|
||||||
virtual void collectPropertiesToImplement(PropertyMap &PM,
|
virtual void collectPropertiesToImplement(PropertyMap &PM) const {}
|
||||||
PropertyDeclOrder &PO) const {}
|
|
||||||
|
|
||||||
SourceLocation getAtStartLoc() const { return ObjCContainerDeclBits.AtStart; }
|
SourceLocation getAtStartLoc() const { return ObjCContainerDeclBits.AtStart; }
|
||||||
|
|
||||||
@@ -1150,6 +1146,7 @@ class ObjCContainerDecl : public NamedDecl, public DeclContext {
|
|||||||
class ObjCInterfaceDecl : public ObjCContainerDecl
|
class ObjCInterfaceDecl : public ObjCContainerDecl
|
||||||
, public Redeclarable<ObjCInterfaceDecl> {
|
, public Redeclarable<ObjCInterfaceDecl> {
|
||||||
friend class ASTContext;
|
friend class ASTContext;
|
||||||
|
friend class ODRDiagsEmitter;
|
||||||
|
|
||||||
/// TypeForDecl - This indicates the Type object that represents this
|
/// TypeForDecl - This indicates the Type object that represents this
|
||||||
/// TypeDecl. It is a cache maintained by ASTContext::getObjCInterfaceType
|
/// TypeDecl. It is a cache maintained by ASTContext::getObjCInterfaceType
|
||||||
@@ -1207,6 +1204,12 @@ class ObjCInterfaceDecl : public ObjCContainerDecl
|
|||||||
/// One of the \c InheritedDesignatedInitializersState enumeratos.
|
/// One of the \c InheritedDesignatedInitializersState enumeratos.
|
||||||
mutable unsigned InheritedDesignatedInitializers : 2;
|
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 location of the last location in this declaration, before
|
||||||
/// the properties/methods. For example, this will be the '>', '}', or
|
/// the properties/methods. For example, this will be the '>', '}', or
|
||||||
/// identifier,
|
/// identifier,
|
||||||
@@ -1215,7 +1218,7 @@ class ObjCInterfaceDecl : public ObjCContainerDecl
|
|||||||
DefinitionData()
|
DefinitionData()
|
||||||
: ExternallyCompleted(false), IvarListMissingImplementation(true),
|
: ExternallyCompleted(false), IvarListMissingImplementation(true),
|
||||||
HasDesignatedInitializers(false),
|
HasDesignatedInitializers(false),
|
||||||
InheritedDesignatedInitializers(IDI_Unknown) {}
|
InheritedDesignatedInitializers(IDI_Unknown), HasODRHash(false) {}
|
||||||
};
|
};
|
||||||
|
|
||||||
/// The type parameters associated with this class, if any.
|
/// 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).
|
/// a forward declaration (\@class) to a definition (\@interface).
|
||||||
void startDefinition();
|
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.
|
/// Retrieve the superclass type.
|
||||||
const ObjCObjectType *getSuperClassType() const {
|
const ObjCObjectType *getSuperClassType() const {
|
||||||
if (TypeSourceInfo *TInfo = getSuperClassTInfo())
|
if (TypeSourceInfo *TInfo = getSuperClassTInfo())
|
||||||
@@ -1780,8 +1790,7 @@ class ObjCInterfaceDecl : public ObjCContainerDecl
|
|||||||
*FindPropertyVisibleInPrimaryClass(IdentifierInfo *PropertyId,
|
*FindPropertyVisibleInPrimaryClass(IdentifierInfo *PropertyId,
|
||||||
ObjCPropertyQueryKind QueryKind) const;
|
ObjCPropertyQueryKind QueryKind) const;
|
||||||
|
|
||||||
void collectPropertiesToImplement(PropertyMap &PM,
|
void collectPropertiesToImplement(PropertyMap &PM) const override;
|
||||||
PropertyDeclOrder &PO) const override;
|
|
||||||
|
|
||||||
/// isSuperClassOf - Return true if this class is the specified class or is a
|
/// isSuperClassOf - Return true if this class is the specified class or is a
|
||||||
/// super class of the specified interface class.
|
/// super class of the specified interface class.
|
||||||
@@ -1897,10 +1906,17 @@ class ObjCInterfaceDecl : public ObjCContainerDecl
|
|||||||
const Type *getTypeForDecl() const { return TypeForDecl; }
|
const Type *getTypeForDecl() const { return TypeForDecl; }
|
||||||
void setTypeForDecl(const Type *TD) const { TypeForDecl = TD; }
|
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 classof(const Decl *D) { return classofKind(D->getKind()); }
|
||||||
static bool classofKind(Kind K) { return K == ObjCInterface; }
|
static bool classofKind(Kind K) { return K == ObjCInterface; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
/// True if a valid hash is stored in ODRHash.
|
||||||
|
bool hasODRHash() const;
|
||||||
|
void setHasODRHash(bool HasHash);
|
||||||
|
|
||||||
const ObjCInterfaceDecl *findInterfaceWithDesignatedInitializers() const;
|
const ObjCInterfaceDecl *findInterfaceWithDesignatedInitializers() const;
|
||||||
bool inheritsDesignatedInitializers() const;
|
bool inheritsDesignatedInitializers() const;
|
||||||
};
|
};
|
||||||
@@ -2057,6 +2073,12 @@ class ObjCProtocolDecl : public ObjCContainerDecl,
|
|||||||
|
|
||||||
/// Referenced protocols
|
/// Referenced protocols
|
||||||
ObjCProtocolList ReferencedProtocols;
|
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,
|
/// Contains a pointer to the data associated with this class,
|
||||||
@@ -2093,10 +2115,15 @@ class ObjCProtocolDecl : public ObjCContainerDecl,
|
|||||||
return getMostRecentDecl();
|
return getMostRecentDecl();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// True if a valid hash is stored in ODRHash.
|
||||||
|
bool hasODRHash() const;
|
||||||
|
void setHasODRHash(bool HasHash);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
friend class ASTDeclReader;
|
friend class ASTDeclReader;
|
||||||
friend class ASTDeclWriter;
|
friend class ASTDeclWriter;
|
||||||
friend class ASTReader;
|
friend class ASTReader;
|
||||||
|
friend class ODRDiagsEmitter;
|
||||||
|
|
||||||
static ObjCProtocolDecl *Create(ASTContext &C, DeclContext *DC,
|
static ObjCProtocolDecl *Create(ASTContext &C, DeclContext *DC,
|
||||||
IdentifierInfo *Id,
|
IdentifierInfo *Id,
|
||||||
@@ -2221,6 +2248,13 @@ class ObjCProtocolDecl : public ObjCContainerDecl,
|
|||||||
/// Starts the definition of this Objective-C protocol.
|
/// Starts the definition of this Objective-C protocol.
|
||||||
void startDefinition();
|
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
|
/// Produce a name to be used for protocol's metadata. It comes either via
|
||||||
/// objc_runtime_name attribute or protocol name.
|
/// objc_runtime_name attribute or protocol name.
|
||||||
StringRef getObjCRuntimeNameAsString() const;
|
StringRef getObjCRuntimeNameAsString() const;
|
||||||
@@ -2246,13 +2280,15 @@ class ObjCProtocolDecl : public ObjCContainerDecl,
|
|||||||
ObjCProtocolDecl *getCanonicalDecl() override { return getFirstDecl(); }
|
ObjCProtocolDecl *getCanonicalDecl() override { return getFirstDecl(); }
|
||||||
const ObjCProtocolDecl *getCanonicalDecl() const { return getFirstDecl(); }
|
const ObjCProtocolDecl *getCanonicalDecl() const { return getFirstDecl(); }
|
||||||
|
|
||||||
void collectPropertiesToImplement(PropertyMap &PM,
|
void collectPropertiesToImplement(PropertyMap &PM) const override;
|
||||||
PropertyDeclOrder &PO) const override;
|
|
||||||
|
|
||||||
void collectInheritedProtocolProperties(const ObjCPropertyDecl *Property,
|
void collectInheritedProtocolProperties(const ObjCPropertyDecl *Property,
|
||||||
ProtocolPropertySet &PS,
|
ProtocolPropertySet &PS,
|
||||||
PropertyDeclOrder &PO) const;
|
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 classof(const Decl *D) { return classofKind(D->getKind()); }
|
||||||
static bool classofKind(Kind K) { return K == ObjCProtocol; }
|
static bool classofKind(Kind K) { return K == ObjCProtocol; }
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -34,7 +34,7 @@ template <typename U> class OMPDeclarativeDirective : public U {
|
|||||||
/// Get the clauses storage.
|
/// Get the clauses storage.
|
||||||
MutableArrayRef<OMPClause *> getClauses() {
|
MutableArrayRef<OMPClause *> getClauses() {
|
||||||
if (!Data)
|
if (!Data)
|
||||||
return llvm::None;
|
return std::nullopt;
|
||||||
return Data->getClauses();
|
return Data->getClauses();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -90,7 +90,7 @@ template <typename U> class OMPDeclarativeDirective : public U {
|
|||||||
|
|
||||||
ArrayRef<OMPClause *> clauses() const {
|
ArrayRef<OMPClause *> clauses() const {
|
||||||
if (!Data)
|
if (!Data)
|
||||||
return llvm::None;
|
return std::nullopt;
|
||||||
return Data->getClauses();
|
return Data->getClauses();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@@ -118,12 +118,12 @@ class OMPThreadPrivateDecl final : public OMPDeclarativeDirective<Decl> {
|
|||||||
|
|
||||||
ArrayRef<const Expr *> getVars() const {
|
ArrayRef<const Expr *> getVars() const {
|
||||||
auto **Storage = reinterpret_cast<Expr **>(Data->getChildren().data());
|
auto **Storage = reinterpret_cast<Expr **>(Data->getChildren().data());
|
||||||
return llvm::makeArrayRef(Storage, Data->getNumChildren());
|
return llvm::ArrayRef(Storage, Data->getNumChildren());
|
||||||
}
|
}
|
||||||
|
|
||||||
MutableArrayRef<Expr *> getVars() {
|
MutableArrayRef<Expr *> getVars() {
|
||||||
auto **Storage = reinterpret_cast<Expr **>(Data->getChildren().data());
|
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);
|
void setVars(ArrayRef<Expr *> VL);
|
||||||
@@ -481,12 +481,12 @@ class OMPAllocateDecl final : public OMPDeclarativeDirective<Decl> {
|
|||||||
|
|
||||||
ArrayRef<const Expr *> getVars() const {
|
ArrayRef<const Expr *> getVars() const {
|
||||||
auto **Storage = reinterpret_cast<Expr **>(Data->getChildren().data());
|
auto **Storage = reinterpret_cast<Expr **>(Data->getChildren().data());
|
||||||
return llvm::makeArrayRef(Storage, Data->getNumChildren());
|
return llvm::ArrayRef(Storage, Data->getNumChildren());
|
||||||
}
|
}
|
||||||
|
|
||||||
MutableArrayRef<Expr *> getVars() {
|
MutableArrayRef<Expr *> getVars() {
|
||||||
auto **Storage = reinterpret_cast<Expr **>(Data->getChildren().data());
|
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);
|
void setVars(ArrayRef<Expr *> VL);
|
||||||
|
|||||||
@@ -39,6 +39,7 @@
|
|||||||
#include <cstddef>
|
#include <cstddef>
|
||||||
#include <cstdint>
|
#include <cstdint>
|
||||||
#include <iterator>
|
#include <iterator>
|
||||||
|
#include <optional>
|
||||||
#include <utility>
|
#include <utility>
|
||||||
|
|
||||||
namespace clang {
|
namespace clang {
|
||||||
@@ -129,11 +130,9 @@ class TemplateParameterList final
|
|||||||
|
|
||||||
unsigned size() const { return NumParams; }
|
unsigned size() const { return NumParams; }
|
||||||
|
|
||||||
ArrayRef<NamedDecl*> asArray() {
|
ArrayRef<NamedDecl *> asArray() { return llvm::ArrayRef(begin(), end()); }
|
||||||
return llvm::makeArrayRef(begin(), end());
|
|
||||||
}
|
|
||||||
ArrayRef<const NamedDecl*> asArray() const {
|
ArrayRef<const NamedDecl*> asArray() const {
|
||||||
return llvm::makeArrayRef(begin(), size());
|
return llvm::ArrayRef(begin(), size());
|
||||||
}
|
}
|
||||||
|
|
||||||
NamedDecl* getParam(unsigned Idx) {
|
NamedDecl* getParam(unsigned Idx) {
|
||||||
@@ -274,8 +273,7 @@ class TemplateArgumentList final
|
|||||||
///
|
///
|
||||||
/// This operation assumes that the input argument list outlives it.
|
/// This operation assumes that the input argument list outlives it.
|
||||||
/// This takes the list as a pointer to avoid looking like a copy
|
/// This takes the list as a pointer to avoid looking like a copy
|
||||||
/// constructor, since this really really isn't safe to use that
|
/// constructor, since this really isn't safe to use that way.
|
||||||
/// way.
|
|
||||||
explicit TemplateArgumentList(const TemplateArgumentList *Other)
|
explicit TemplateArgumentList(const TemplateArgumentList *Other)
|
||||||
: Arguments(Other->data()), NumArguments(Other->size()) {}
|
: Arguments(Other->data()), NumArguments(Other->size()) {}
|
||||||
|
|
||||||
@@ -290,7 +288,7 @@ class TemplateArgumentList final
|
|||||||
|
|
||||||
/// Produce this as an array ref.
|
/// Produce this as an array ref.
|
||||||
ArrayRef<TemplateArgument> asArray() const {
|
ArrayRef<TemplateArgument> asArray() const {
|
||||||
return llvm::makeArrayRef(data(), size());
|
return llvm::ArrayRef(data(), size());
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Retrieve the number of template arguments in this
|
/// Retrieve the number of template arguments in this
|
||||||
@@ -440,6 +438,9 @@ class TemplateDecl : public NamedDecl {
|
|||||||
/// Get the underlying, templated declaration.
|
/// Get the underlying, templated declaration.
|
||||||
NamedDecl *getTemplatedDecl() const { return TemplatedDecl; }
|
NamedDecl *getTemplatedDecl() const { return TemplatedDecl; }
|
||||||
|
|
||||||
|
// Should a specialization behave like an alias for another type.
|
||||||
|
bool isTypeAlias() const;
|
||||||
|
|
||||||
// Implement isa/cast/dyncast/etc.
|
// Implement isa/cast/dyncast/etc.
|
||||||
static bool classof(const Decl *D) { return classofKind(D->getKind()); }
|
static bool classof(const Decl *D) { return classofKind(D->getKind()); }
|
||||||
|
|
||||||
@@ -456,18 +457,17 @@ class TemplateDecl : public NamedDecl {
|
|||||||
NamedDecl *TemplatedDecl;
|
NamedDecl *TemplatedDecl;
|
||||||
TemplateParameterList *TemplateParams;
|
TemplateParameterList *TemplateParams;
|
||||||
|
|
||||||
|
public:
|
||||||
void setTemplateParameters(TemplateParameterList *TParams) {
|
void setTemplateParameters(TemplateParameterList *TParams) {
|
||||||
TemplateParams = TParams;
|
TemplateParams = TParams;
|
||||||
}
|
}
|
||||||
|
|
||||||
public:
|
/// Initialize the underlying templated declaration.
|
||||||
/// Initialize the underlying templated declaration and
|
void init(NamedDecl *NewTemplatedDecl) {
|
||||||
/// template parameters.
|
if (TemplatedDecl)
|
||||||
void init(NamedDecl *templatedDecl, TemplateParameterList* templateParams) {
|
assert(TemplatedDecl == NewTemplatedDecl && "Inconsistent TemplatedDecl");
|
||||||
assert(!TemplatedDecl && "TemplatedDecl already set!");
|
else
|
||||||
assert(!TemplateParams && "TemplateParams already set!");
|
TemplatedDecl = NewTemplatedDecl;
|
||||||
TemplatedDecl = templatedDecl;
|
|
||||||
TemplateParams = templateParams;
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -740,7 +740,7 @@ class DependentFunctionTemplateSpecializationInfo final
|
|||||||
unsigned getNumTemplateArgs() const { return NumArgs; }
|
unsigned getNumTemplateArgs() const { return NumArgs; }
|
||||||
|
|
||||||
llvm::ArrayRef<TemplateArgumentLoc> arguments() const {
|
llvm::ArrayRef<TemplateArgumentLoc> arguments() const {
|
||||||
return llvm::makeArrayRef(getTemplateArgs(), getNumTemplateArgs());
|
return llvm::ArrayRef(getTemplateArgs(), getNumTemplateArgs());
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns the nth template argument.
|
/// 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
|
/// The first value in the array is the number of specializations/partial
|
||||||
/// specializations that follow.
|
/// specializations that follow.
|
||||||
uint32_t *LazySpecializations = nullptr;
|
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
|
/// Pointer to the common data shared by all declarations of this
|
||||||
@@ -952,6 +961,14 @@ class RedeclarableTemplateDecl : public TemplateDecl,
|
|||||||
getCommonPtr()->InstantiatedFromMember.setPointer(TD);
|
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_range = redeclarable_base::redecl_range;
|
||||||
using redecl_iterator = redeclarable_base::redecl_iterator;
|
using redecl_iterator = redeclarable_base::redecl_iterator;
|
||||||
|
|
||||||
@@ -996,15 +1013,6 @@ class FunctionTemplateDecl : public RedeclarableTemplateDecl {
|
|||||||
/// template, including explicit specializations and instantiations.
|
/// template, including explicit specializations and instantiations.
|
||||||
llvm::FoldingSetVector<FunctionTemplateSpecializationInfo> Specializations;
|
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;
|
Common() = default;
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -1104,15 +1112,6 @@ class FunctionTemplateDecl : public RedeclarableTemplateDecl {
|
|||||||
return makeSpecIterator(getSpecializations(), true);
|
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,
|
/// Return whether this function template is an abbreviated function template,
|
||||||
/// e.g. `void foo(auto x)` or `template<typename T> void foo(auto x)`
|
/// e.g. `void foo(auto x)` or `template<typename T> void foo(auto x)`
|
||||||
bool isAbbreviated() const {
|
bool isAbbreviated() const {
|
||||||
@@ -1223,7 +1222,7 @@ class TemplateTypeParmDecl final : public TypeDecl,
|
|||||||
/// type constraint.
|
/// type constraint.
|
||||||
bool TypeConstraintInitialized : 1;
|
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
|
/// parameter pack, meaning that its type is a pack expansion and we
|
||||||
/// already know the set of types that expansion expands to.
|
/// already know the set of types that expansion expands to.
|
||||||
bool ExpandedParameterPack : 1;
|
bool ExpandedParameterPack : 1;
|
||||||
@@ -1238,21 +1237,19 @@ class TemplateTypeParmDecl final : public TypeDecl,
|
|||||||
|
|
||||||
TemplateTypeParmDecl(DeclContext *DC, SourceLocation KeyLoc,
|
TemplateTypeParmDecl(DeclContext *DC, SourceLocation KeyLoc,
|
||||||
SourceLocation IdLoc, IdentifierInfo *Id, bool Typename,
|
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),
|
: TypeDecl(TemplateTypeParm, DC, IdLoc, Id, KeyLoc), Typename(Typename),
|
||||||
HasTypeConstraint(HasTypeConstraint), TypeConstraintInitialized(false),
|
HasTypeConstraint(HasTypeConstraint), TypeConstraintInitialized(false),
|
||||||
ExpandedParameterPack(NumExpanded),
|
ExpandedParameterPack(NumExpanded),
|
||||||
NumExpanded(NumExpanded.value_or(0)) {}
|
NumExpanded(NumExpanded.value_or(0)) {}
|
||||||
|
|
||||||
public:
|
public:
|
||||||
static TemplateTypeParmDecl *Create(const ASTContext &C, DeclContext *DC,
|
static TemplateTypeParmDecl *
|
||||||
SourceLocation KeyLoc,
|
Create(const ASTContext &C, DeclContext *DC, SourceLocation KeyLoc,
|
||||||
SourceLocation NameLoc,
|
SourceLocation NameLoc, unsigned D, unsigned P, IdentifierInfo *Id,
|
||||||
unsigned D, unsigned P,
|
bool Typename, bool ParameterPack, bool HasTypeConstraint = false,
|
||||||
IdentifierInfo *Id, bool Typename,
|
std::optional<unsigned> NumExpanded = std::nullopt);
|
||||||
bool ParameterPack,
|
|
||||||
bool HasTypeConstraint = false,
|
|
||||||
Optional<unsigned> NumExpanded = None);
|
|
||||||
static TemplateTypeParmDecl *CreateDeserialized(const ASTContext &C,
|
static TemplateTypeParmDecl *CreateDeserialized(const ASTContext &C,
|
||||||
unsigned ID);
|
unsigned ID);
|
||||||
static TemplateTypeParmDecl *CreateDeserialized(const ASTContext &C,
|
static TemplateTypeParmDecl *CreateDeserialized(const ASTContext &C,
|
||||||
@@ -1388,7 +1385,7 @@ class TemplateTypeParmDecl final : public TypeDecl,
|
|||||||
/// \brief Get the associated-constraints of this template parameter.
|
/// \brief Get the associated-constraints of this template parameter.
|
||||||
/// This will either be the immediately-introduced constraint or empty.
|
/// 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.
|
/// accept an ArrayRef of constraint expressions.
|
||||||
void getAssociatedConstraints(llvm::SmallVectorImpl<const Expr *> &AC) const {
|
void getAssociatedConstraints(llvm::SmallVectorImpl<const Expr *> &AC) const {
|
||||||
if (HasTypeConstraint)
|
if (HasTypeConstraint)
|
||||||
@@ -2929,6 +2926,14 @@ class VarTemplateSpecializationDecl : public VarDecl,
|
|||||||
return ExplicitInfo ? ExplicitInfo->TemplateKeywordLoc : SourceLocation();
|
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 {
|
void Profile(llvm::FoldingSetNodeID &ID) const {
|
||||||
Profile(ID, TemplateArgs->asArray(), getASTContext());
|
Profile(ID, TemplateArgs->asArray(), getASTContext());
|
||||||
}
|
}
|
||||||
@@ -3086,6 +3091,14 @@ class VarTemplatePartialSpecializationDecl
|
|||||||
return First->InstantiatedFromMember.setInt(true);
|
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 {
|
void Profile(llvm::FoldingSetNodeID &ID) const {
|
||||||
Profile(ID, getTemplateArgs().asArray(), getTemplateParameters(),
|
Profile(ID, getTemplateArgs().asArray(), getTemplateParameters(),
|
||||||
getASTContext());
|
getASTContext());
|
||||||
@@ -3258,7 +3271,7 @@ class VarTemplateDecl : public RedeclarableTemplateDecl {
|
|||||||
static bool classofKind(Kind K) { return K == VarTemplate; }
|
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> {
|
class ConceptDecl : public TemplateDecl, public Mergeable<ConceptDecl> {
|
||||||
protected:
|
protected:
|
||||||
Expr *ConstraintExpr;
|
Expr *ConstraintExpr;
|
||||||
@@ -3303,6 +3316,40 @@ class ConceptDecl : public TemplateDecl, public Mergeable<ConceptDecl> {
|
|||||||
friend class ASTDeclWriter;
|
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.
|
/// A template parameter object.
|
||||||
///
|
///
|
||||||
/// Template parameter objects represent values of class type used as template
|
/// Template parameter objects represent values of class type used as template
|
||||||
@@ -3340,7 +3387,8 @@ class TemplateParamObjectDecl : public ValueDecl,
|
|||||||
|
|
||||||
public:
|
public:
|
||||||
/// Print this template parameter object in a human-readable format.
|
/// 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.
|
/// Print this object as an equivalent expression.
|
||||||
void printAsExpr(llvm::raw_ostream &OS) const;
|
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
|
/// 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.
|
/// 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 (const auto *TTP = dyn_cast<TemplateTypeParmDecl>(Param)) {
|
||||||
if (TTP->isExpandedParameterPack())
|
if (TTP->isExpandedParameterPack())
|
||||||
return TTP->getNumExpansionParameters();
|
return TTP->getNumExpansionParameters();
|
||||||
@@ -3418,9 +3466,13 @@ inline Optional<unsigned> getExpandedPackSize(const NamedDecl *Param) {
|
|||||||
return TTP->getNumExpansionTemplateParameters();
|
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
|
} // namespace clang
|
||||||
|
|
||||||
#endif // LLVM_CLANG_AST_DECLTEMPLATE_H
|
#endif // LLVM_CLANG_AST_DECLTEMPLATE_H
|
||||||
|
|||||||
@@ -941,7 +941,7 @@ class AssumedTemplateStorage : public UncommonTemplateNameStorage {
|
|||||||
friend class ASTContext;
|
friend class ASTContext;
|
||||||
|
|
||||||
AssumedTemplateStorage(DeclarationName Name)
|
AssumedTemplateStorage(DeclarationName Name)
|
||||||
: UncommonTemplateNameStorage(Assumed, 0), Name(Name) {}
|
: UncommonTemplateNameStorage(Assumed, 0, 0), Name(Name) {}
|
||||||
DeclarationName Name;
|
DeclarationName Name;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|||||||
@@ -36,6 +36,7 @@
|
|||||||
#include "llvm/Support/AtomicOrdering.h"
|
#include "llvm/Support/AtomicOrdering.h"
|
||||||
#include "llvm/Support/Compiler.h"
|
#include "llvm/Support/Compiler.h"
|
||||||
#include "llvm/Support/TrailingObjects.h"
|
#include "llvm/Support/TrailingObjects.h"
|
||||||
|
#include <optional>
|
||||||
|
|
||||||
namespace clang {
|
namespace clang {
|
||||||
class APValue;
|
class APValue;
|
||||||
@@ -523,14 +524,24 @@ class Expr : public ValueStmt {
|
|||||||
/// semantically correspond to a bool.
|
/// semantically correspond to a bool.
|
||||||
bool isKnownToHaveBooleanValue(bool Semantic = true) const;
|
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
|
/// isIntegerConstantExpr - Return the value if this expression is a valid
|
||||||
/// integer constant expression. If not a valid i-c-e, return None and fill
|
/// integer constant expression. If not a valid i-c-e, return std::nullopt
|
||||||
/// in Loc (if specified) with the location of the invalid expression.
|
/// 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
|
/// Note: This does not perform the implicit conversions required by C++11
|
||||||
/// [expr.const]p5.
|
/// [expr.const]p5.
|
||||||
Optional<llvm::APSInt> getIntegerConstantExpr(const ASTContext &Ctx,
|
std::optional<llvm::APSInt>
|
||||||
SourceLocation *Loc = nullptr,
|
getIntegerConstantExpr(const ASTContext &Ctx, SourceLocation *Loc = nullptr,
|
||||||
bool isEvaluated = true) const;
|
bool isEvaluated = true) const;
|
||||||
bool isIntegerConstantExpr(const ASTContext &Ctx,
|
bool isIntegerConstantExpr(const ASTContext &Ctx,
|
||||||
SourceLocation *Loc = nullptr) const;
|
SourceLocation *Loc = nullptr) const;
|
||||||
@@ -1972,7 +1983,7 @@ class PredefinedExpr final
|
|||||||
LFunction, // Same as Function, but as wide string.
|
LFunction, // Same as Function, but as wide string.
|
||||||
FuncDName,
|
FuncDName,
|
||||||
FuncSig,
|
FuncSig,
|
||||||
LFuncSig, // Same as FuncSig, but as as wide string
|
LFuncSig, // Same as FuncSig, but as wide string
|
||||||
PrettyFunction,
|
PrettyFunction,
|
||||||
/// The same as PrettyFunction, except that the
|
/// The same as PrettyFunction, except that the
|
||||||
/// 'virtual' keyword is omitted for virtual member functions.
|
/// 'virtual' keyword is omitted for virtual member functions.
|
||||||
@@ -3009,7 +3020,7 @@ class CallExpr : public Expr {
|
|||||||
/// Compute and set dependence bits.
|
/// Compute and set dependence bits.
|
||||||
void computeDependence() {
|
void computeDependence() {
|
||||||
setDependence(clang::computeDependence(
|
setDependence(clang::computeDependence(
|
||||||
this, llvm::makeArrayRef(
|
this, llvm::ArrayRef(
|
||||||
reinterpret_cast<Expr **>(getTrailingStmts() + PREARGS_START),
|
reinterpret_cast<Expr **>(getTrailingStmts() + PREARGS_START),
|
||||||
getNumPreArgs())));
|
getNumPreArgs())));
|
||||||
}
|
}
|
||||||
@@ -3056,14 +3067,10 @@ class CallExpr : public Expr {
|
|||||||
/// interface. This provides efficient reverse iteration of the
|
/// interface. This provides efficient reverse iteration of the
|
||||||
/// subexpressions. This is currently used for CFG construction.
|
/// subexpressions. This is currently used for CFG construction.
|
||||||
ArrayRef<Stmt *> getRawSubExprs() {
|
ArrayRef<Stmt *> getRawSubExprs() {
|
||||||
return llvm::makeArrayRef(getTrailingStmts(),
|
return llvm::ArrayRef(getTrailingStmts(),
|
||||||
PREARGS_START + getNumPreArgs() + getNumArgs());
|
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.
|
/// Get FPOptionsOverride from trailing storage.
|
||||||
FPOptionsOverride getStoredFPFeatures() const {
|
FPOptionsOverride getStoredFPFeatures() const {
|
||||||
assert(hasStoredFPFeatures());
|
assert(hasStoredFPFeatures());
|
||||||
@@ -4008,7 +4015,7 @@ class BinaryOperator : public Expr {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// This is used in ASTImporter
|
// This is used in ASTImporter
|
||||||
FPOptionsOverride getFPFeatures(const LangOptions &LO) const {
|
FPOptionsOverride getFPFeatures() const {
|
||||||
if (BinaryOperatorBits.HasFPFeatures)
|
if (BinaryOperatorBits.HasFPFeatures)
|
||||||
return getStoredFPFeatures();
|
return getStoredFPFeatures();
|
||||||
return FPOptionsOverride();
|
return FPOptionsOverride();
|
||||||
@@ -4827,12 +4834,10 @@ class InitListExpr : public Expr {
|
|||||||
return reinterpret_cast<Expr * const *>(InitExprs.data());
|
return reinterpret_cast<Expr * const *>(InitExprs.data());
|
||||||
}
|
}
|
||||||
|
|
||||||
ArrayRef<Expr *> inits() {
|
ArrayRef<Expr *> inits() { return llvm::ArrayRef(getInits(), getNumInits()); }
|
||||||
return llvm::makeArrayRef(getInits(), getNumInits());
|
|
||||||
}
|
|
||||||
|
|
||||||
ArrayRef<Expr *> inits() const {
|
ArrayRef<Expr *> inits() const {
|
||||||
return llvm::makeArrayRef(getInits(), getNumInits());
|
return llvm::ArrayRef(getInits(), getNumInits());
|
||||||
}
|
}
|
||||||
|
|
||||||
const Expr *getInit(unsigned Init) const {
|
const Expr *getInit(unsigned Init) const {
|
||||||
@@ -5574,9 +5579,7 @@ class ParenListExpr final
|
|||||||
return reinterpret_cast<Expr **>(getTrailingObjects<Stmt *>());
|
return reinterpret_cast<Expr **>(getTrailingObjects<Stmt *>());
|
||||||
}
|
}
|
||||||
|
|
||||||
ArrayRef<Expr *> exprs() {
|
ArrayRef<Expr *> exprs() { return llvm::ArrayRef(getExprs(), getNumExprs()); }
|
||||||
return llvm::makeArrayRef(getExprs(), getNumExprs());
|
|
||||||
}
|
|
||||||
|
|
||||||
SourceLocation getLParenLoc() const { return LParenLoc; }
|
SourceLocation getLParenLoc() const { return LParenLoc; }
|
||||||
SourceLocation getRParenLoc() const { return RParenLoc; }
|
SourceLocation getRParenLoc() const { return RParenLoc; }
|
||||||
@@ -6427,7 +6430,7 @@ class RecoveryExpr final : public Expr,
|
|||||||
|
|
||||||
ArrayRef<Expr *> subExpressions() {
|
ArrayRef<Expr *> subExpressions() {
|
||||||
auto *B = getTrailingObjects<Expr *>();
|
auto *B = getTrailingObjects<Expr *>();
|
||||||
return llvm::makeArrayRef(B, B + NumExprs);
|
return llvm::ArrayRef(B, B + NumExprs);
|
||||||
}
|
}
|
||||||
|
|
||||||
ArrayRef<const Expr *> subExpressions() const {
|
ArrayRef<const Expr *> subExpressions() const {
|
||||||
|
|||||||
@@ -40,8 +40,6 @@
|
|||||||
#include "clang/Basic/Specifiers.h"
|
#include "clang/Basic/Specifiers.h"
|
||||||
#include "clang/Basic/TypeTraits.h"
|
#include "clang/Basic/TypeTraits.h"
|
||||||
#include "llvm/ADT/ArrayRef.h"
|
#include "llvm/ADT/ArrayRef.h"
|
||||||
#include "llvm/ADT/None.h"
|
|
||||||
#include "llvm/ADT/Optional.h"
|
|
||||||
#include "llvm/ADT/PointerUnion.h"
|
#include "llvm/ADT/PointerUnion.h"
|
||||||
#include "llvm/ADT/StringRef.h"
|
#include "llvm/ADT/StringRef.h"
|
||||||
#include "llvm/ADT/iterator_range.h"
|
#include "llvm/ADT/iterator_range.h"
|
||||||
@@ -52,6 +50,7 @@
|
|||||||
#include <cstddef>
|
#include <cstddef>
|
||||||
#include <cstdint>
|
#include <cstdint>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
|
#include <optional>
|
||||||
|
|
||||||
namespace clang {
|
namespace clang {
|
||||||
|
|
||||||
@@ -730,6 +729,11 @@ class CXXBoolLiteralExpr : public Expr {
|
|||||||
explicit CXXBoolLiteralExpr(EmptyShell Empty)
|
explicit CXXBoolLiteralExpr(EmptyShell Empty)
|
||||||
: Expr(CXXBoolLiteralExprClass, 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; }
|
bool getValue() const { return CXXBoolLiteralExprBits.Value; }
|
||||||
void setValue(bool V) { CXXBoolLiteralExprBits.Value = V; }
|
void setValue(bool V) { CXXBoolLiteralExprBits.Value = V; }
|
||||||
|
|
||||||
@@ -756,6 +760,8 @@ class CXXBoolLiteralExpr : public Expr {
|
|||||||
/// The null pointer literal (C++11 [lex.nullptr])
|
/// The null pointer literal (C++11 [lex.nullptr])
|
||||||
///
|
///
|
||||||
/// Introduced in C++11, the only literal of type \c nullptr_t is \c 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 {
|
class CXXNullPtrLiteralExpr : public Expr {
|
||||||
public:
|
public:
|
||||||
CXXNullPtrLiteralExpr(QualType Ty, SourceLocation Loc)
|
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
|
/// This wraps up a function call argument that was created from the
|
||||||
/// corresponding parameter's default argument, when the call did not
|
/// corresponding parameter's default argument, when the call did not
|
||||||
/// explicitly supply arguments for all of the parameters.
|
/// 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 ASTStmtReader;
|
||||||
|
friend class ASTReader;
|
||||||
|
friend TrailingObjects;
|
||||||
|
|
||||||
/// The parameter whose default is being used.
|
/// The parameter whose default is being used.
|
||||||
ParmVarDecl *Param;
|
ParmVarDecl *Param;
|
||||||
@@ -1248,7 +1258,7 @@ class CXXDefaultArgExpr final : public Expr {
|
|||||||
DeclContext *UsedContext;
|
DeclContext *UsedContext;
|
||||||
|
|
||||||
CXXDefaultArgExpr(StmtClass SC, SourceLocation Loc, ParmVarDecl *Param,
|
CXXDefaultArgExpr(StmtClass SC, SourceLocation Loc, ParmVarDecl *Param,
|
||||||
DeclContext *UsedContext)
|
Expr *RewrittenExpr, DeclContext *UsedContext)
|
||||||
: Expr(SC,
|
: Expr(SC,
|
||||||
Param->hasUnparsedDefaultArg()
|
Param->hasUnparsedDefaultArg()
|
||||||
? Param->getType().getNonReferenceType()
|
? Param->getType().getNonReferenceType()
|
||||||
@@ -1257,28 +1267,54 @@ class CXXDefaultArgExpr final : public Expr {
|
|||||||
Param->getDefaultArg()->getObjectKind()),
|
Param->getDefaultArg()->getObjectKind()),
|
||||||
Param(Param), UsedContext(UsedContext) {
|
Param(Param), UsedContext(UsedContext) {
|
||||||
CXXDefaultArgExprBits.Loc = Loc;
|
CXXDefaultArgExprBits.Loc = Loc;
|
||||||
|
CXXDefaultArgExprBits.HasRewrittenInit = RewrittenExpr != nullptr;
|
||||||
|
if (RewrittenExpr)
|
||||||
|
*getTrailingObjects<Expr *>() = RewrittenExpr;
|
||||||
setDependence(computeDependence(this));
|
setDependence(computeDependence(this));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
CXXDefaultArgExpr(EmptyShell Empty, bool HasRewrittenInit)
|
||||||
|
: Expr(CXXDefaultArgExprClass, Empty) {
|
||||||
|
CXXDefaultArgExprBits.HasRewrittenInit = HasRewrittenInit;
|
||||||
|
}
|
||||||
|
|
||||||
public:
|
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
|
// \p Param is the parameter whose default argument is used by this
|
||||||
// expression.
|
// expression.
|
||||||
static CXXDefaultArgExpr *Create(const ASTContext &C, SourceLocation Loc,
|
static CXXDefaultArgExpr *Create(const ASTContext &C, SourceLocation Loc,
|
||||||
ParmVarDecl *Param,
|
ParmVarDecl *Param, Expr *RewrittenExpr,
|
||||||
DeclContext *UsedContext) {
|
DeclContext *UsedContext);
|
||||||
return new (C)
|
|
||||||
CXXDefaultArgExpr(CXXDefaultArgExprClass, Loc, Param, UsedContext);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Retrieve the parameter that the argument was created from.
|
// Retrieve the parameter that the argument was created from.
|
||||||
const ParmVarDecl *getParam() const { return Param; }
|
const ParmVarDecl *getParam() const { return Param; }
|
||||||
ParmVarDecl *getParam() { return Param; }
|
ParmVarDecl *getParam() { return Param; }
|
||||||
|
|
||||||
// Retrieve the actual argument to the function call.
|
bool hasRewrittenInit() const {
|
||||||
const Expr *getExpr() const { return getParam()->getDefaultArg(); }
|
return CXXDefaultArgExprBits.HasRewrittenInit;
|
||||||
Expr *getExpr() { return getParam()->getDefaultArg(); }
|
}
|
||||||
|
|
||||||
|
// 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; }
|
const DeclContext *getUsedContext() const { return UsedContext; }
|
||||||
DeclContext *getUsedContext() { 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
|
/// is implicitly used in a mem-initializer-list in a constructor
|
||||||
/// (C++11 [class.base.init]p8) or in aggregate initialization
|
/// (C++11 [class.base.init]p8) or in aggregate initialization
|
||||||
/// (C++1y [dcl.init.aggr]p7).
|
/// (C++1y [dcl.init.aggr]p7).
|
||||||
class CXXDefaultInitExpr : public Expr {
|
class CXXDefaultInitExpr final
|
||||||
friend class ASTReader;
|
: public Expr,
|
||||||
friend class ASTStmtReader;
|
private llvm::TrailingObjects<CXXDefaultInitExpr, Expr *> {
|
||||||
|
|
||||||
|
friend class ASTStmtReader;
|
||||||
|
friend class ASTReader;
|
||||||
|
friend TrailingObjects;
|
||||||
/// The field whose default is being used.
|
/// The field whose default is being used.
|
||||||
FieldDecl *Field;
|
FieldDecl *Field;
|
||||||
|
|
||||||
@@ -1326,16 +1365,25 @@ class CXXDefaultInitExpr : public Expr {
|
|||||||
DeclContext *UsedContext;
|
DeclContext *UsedContext;
|
||||||
|
|
||||||
CXXDefaultInitExpr(const ASTContext &Ctx, SourceLocation Loc,
|
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:
|
public:
|
||||||
|
static CXXDefaultInitExpr *CreateEmpty(const ASTContext &C,
|
||||||
|
bool HasRewrittenInit);
|
||||||
/// \p Field is the non-static data member whose default initializer is used
|
/// \p Field is the non-static data member whose default initializer is used
|
||||||
/// by this expression.
|
/// by this expression.
|
||||||
static CXXDefaultInitExpr *Create(const ASTContext &Ctx, SourceLocation Loc,
|
static CXXDefaultInitExpr *Create(const ASTContext &Ctx, SourceLocation Loc,
|
||||||
FieldDecl *Field, DeclContext *UsedContext) {
|
FieldDecl *Field, DeclContext *UsedContext,
|
||||||
return new (Ctx) CXXDefaultInitExpr(Ctx, Loc, Field, Field->getType(), UsedContext);
|
Expr *RewrittenInitExpr);
|
||||||
|
|
||||||
|
bool hasRewrittenInit() const {
|
||||||
|
return CXXDefaultInitExprBits.HasRewrittenInit;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Get the field whose initializer will be used.
|
/// Get the field whose initializer will be used.
|
||||||
@@ -1343,13 +1391,23 @@ class CXXDefaultInitExpr : public Expr {
|
|||||||
const FieldDecl *getField() const { return Field; }
|
const FieldDecl *getField() const { return Field; }
|
||||||
|
|
||||||
/// Get the initialization expression that will be used.
|
/// Get the initialization expression that will be used.
|
||||||
|
Expr *getExpr();
|
||||||
const Expr *getExpr() const {
|
const Expr *getExpr() const {
|
||||||
assert(Field->getInClassInitializer() && "initializer hasn't been parsed");
|
return const_cast<CXXDefaultInitExpr *>(this)->getExpr();
|
||||||
return Field->getInClassInitializer();
|
|
||||||
}
|
}
|
||||||
Expr *getExpr() {
|
|
||||||
assert(Field->getInClassInitializer() && "initializer hasn't been parsed");
|
/// Retrieve the initializing expression with evaluated immediate calls, if
|
||||||
return Field->getInClassInitializer();
|
/// 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; }
|
const DeclContext *getUsedContext() const { return UsedContext; }
|
||||||
@@ -2204,7 +2262,7 @@ class CXXNewExpr final
|
|||||||
CXXNewExpr(bool IsGlobalNew, FunctionDecl *OperatorNew,
|
CXXNewExpr(bool IsGlobalNew, FunctionDecl *OperatorNew,
|
||||||
FunctionDecl *OperatorDelete, bool ShouldPassAlignment,
|
FunctionDecl *OperatorDelete, bool ShouldPassAlignment,
|
||||||
bool UsualArrayDeleteWantsSize, ArrayRef<Expr *> PlacementArgs,
|
bool UsualArrayDeleteWantsSize, ArrayRef<Expr *> PlacementArgs,
|
||||||
SourceRange TypeIdParens, Optional<Expr *> ArraySize,
|
SourceRange TypeIdParens, std::optional<Expr *> ArraySize,
|
||||||
InitializationStyle InitializationStyle, Expr *Initializer,
|
InitializationStyle InitializationStyle, Expr *Initializer,
|
||||||
QualType Ty, TypeSourceInfo *AllocatedTypeInfo, SourceRange Range,
|
QualType Ty, TypeSourceInfo *AllocatedTypeInfo, SourceRange Range,
|
||||||
SourceRange DirectInitRange);
|
SourceRange DirectInitRange);
|
||||||
@@ -2219,7 +2277,7 @@ class CXXNewExpr final
|
|||||||
Create(const ASTContext &Ctx, bool IsGlobalNew, FunctionDecl *OperatorNew,
|
Create(const ASTContext &Ctx, bool IsGlobalNew, FunctionDecl *OperatorNew,
|
||||||
FunctionDecl *OperatorDelete, bool ShouldPassAlignment,
|
FunctionDecl *OperatorDelete, bool ShouldPassAlignment,
|
||||||
bool UsualArrayDeleteWantsSize, ArrayRef<Expr *> PlacementArgs,
|
bool UsualArrayDeleteWantsSize, ArrayRef<Expr *> PlacementArgs,
|
||||||
SourceRange TypeIdParens, Optional<Expr *> ArraySize,
|
SourceRange TypeIdParens, std::optional<Expr *> ArraySize,
|
||||||
InitializationStyle InitializationStyle, Expr *Initializer,
|
InitializationStyle InitializationStyle, Expr *Initializer,
|
||||||
QualType Ty, TypeSourceInfo *AllocatedTypeInfo, SourceRange Range,
|
QualType Ty, TypeSourceInfo *AllocatedTypeInfo, SourceRange Range,
|
||||||
SourceRange DirectInitRange);
|
SourceRange DirectInitRange);
|
||||||
@@ -2261,32 +2319,32 @@ class CXXNewExpr final
|
|||||||
|
|
||||||
bool isArray() const { return CXXNewExprBits.IsArray; }
|
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.
|
/// since there might not be an array size expression.
|
||||||
/// If the result is not-None, it will never wrap a nullptr.
|
/// If the result is not-None, it will never wrap a nullptr.
|
||||||
Optional<Expr *> getArraySize() {
|
std::optional<Expr *> getArraySize() {
|
||||||
if (!isArray())
|
if (!isArray())
|
||||||
return None;
|
return std::nullopt;
|
||||||
|
|
||||||
if (auto *Result =
|
if (auto *Result =
|
||||||
cast_or_null<Expr>(getTrailingObjects<Stmt *>()[arraySizeOffset()]))
|
cast_or_null<Expr>(getTrailingObjects<Stmt *>()[arraySizeOffset()]))
|
||||||
return Result;
|
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.
|
/// since there might not be an array size expression.
|
||||||
/// If the result is not-None, it will never wrap a nullptr.
|
/// If the result is not-None, it will never wrap a nullptr.
|
||||||
Optional<const Expr *> getArraySize() const {
|
std::optional<const Expr *> getArraySize() const {
|
||||||
if (!isArray())
|
if (!isArray())
|
||||||
return None;
|
return std::nullopt;
|
||||||
|
|
||||||
if (auto *Result =
|
if (auto *Result =
|
||||||
cast_or_null<Expr>(getTrailingObjects<Stmt *>()[arraySizeOffset()]))
|
cast_or_null<Expr>(getTrailingObjects<Stmt *>()[arraySizeOffset()]))
|
||||||
return Result;
|
return Result;
|
||||||
|
|
||||||
return None;
|
return std::nullopt;
|
||||||
}
|
}
|
||||||
|
|
||||||
unsigned getNumPlacementArgs() const {
|
unsigned getNumPlacementArgs() const {
|
||||||
@@ -2738,8 +2796,7 @@ class TypeTraitExpr final
|
|||||||
|
|
||||||
/// Retrieve the argument types.
|
/// Retrieve the argument types.
|
||||||
ArrayRef<TypeSourceInfo *> getArgs() const {
|
ArrayRef<TypeSourceInfo *> getArgs() const {
|
||||||
return llvm::makeArrayRef(getTrailingObjects<TypeSourceInfo *>(),
|
return llvm::ArrayRef(getTrailingObjects<TypeSourceInfo *>(), getNumArgs());
|
||||||
getNumArgs());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
SourceLocation getBeginLoc() const LLVM_READONLY { return Loc; }
|
SourceLocation getBeginLoc() const LLVM_READONLY { return Loc; }
|
||||||
@@ -3385,8 +3442,7 @@ class ExprWithCleanups final
|
|||||||
ArrayRef<CleanupObject> objects);
|
ArrayRef<CleanupObject> objects);
|
||||||
|
|
||||||
ArrayRef<CleanupObject> getObjects() const {
|
ArrayRef<CleanupObject> getObjects() const {
|
||||||
return llvm::makeArrayRef(getTrailingObjects<CleanupObject>(),
|
return llvm::ArrayRef(getTrailingObjects<CleanupObject>(), getNumObjects());
|
||||||
getNumObjects());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
unsigned getNumObjects() const { return ExprWithCleanupsBits.NumObjects; }
|
unsigned getNumObjects() const { return ExprWithCleanupsBits.NumObjects; }
|
||||||
@@ -4082,7 +4138,7 @@ class PackExpansionExpr : public Expr {
|
|||||||
|
|
||||||
public:
|
public:
|
||||||
PackExpansionExpr(QualType T, Expr *Pattern, SourceLocation EllipsisLoc,
|
PackExpansionExpr(QualType T, Expr *Pattern, SourceLocation EllipsisLoc,
|
||||||
Optional<unsigned> NumExpansions)
|
std::optional<unsigned> NumExpansions)
|
||||||
: Expr(PackExpansionExprClass, T, Pattern->getValueKind(),
|
: Expr(PackExpansionExprClass, T, Pattern->getValueKind(),
|
||||||
Pattern->getObjectKind()),
|
Pattern->getObjectKind()),
|
||||||
EllipsisLoc(EllipsisLoc),
|
EllipsisLoc(EllipsisLoc),
|
||||||
@@ -4105,11 +4161,11 @@ class PackExpansionExpr : public Expr {
|
|||||||
|
|
||||||
/// Determine the number of expansions that will be produced when
|
/// Determine the number of expansions that will be produced when
|
||||||
/// this pack expansion is instantiated, if already known.
|
/// this pack expansion is instantiated, if already known.
|
||||||
Optional<unsigned> getNumExpansions() const {
|
std::optional<unsigned> getNumExpansions() const {
|
||||||
if (NumExpansions)
|
if (NumExpansions)
|
||||||
return NumExpansions - 1;
|
return NumExpansions - 1;
|
||||||
|
|
||||||
return None;
|
return std::nullopt;
|
||||||
}
|
}
|
||||||
|
|
||||||
SourceLocation getBeginLoc() const LLVM_READONLY {
|
SourceLocation getBeginLoc() const LLVM_READONLY {
|
||||||
@@ -4176,7 +4232,7 @@ class SizeOfPackExpr final
|
|||||||
/// the given parameter pack.
|
/// the given parameter pack.
|
||||||
SizeOfPackExpr(QualType SizeType, SourceLocation OperatorLoc, NamedDecl *Pack,
|
SizeOfPackExpr(QualType SizeType, SourceLocation OperatorLoc, NamedDecl *Pack,
|
||||||
SourceLocation PackLoc, SourceLocation RParenLoc,
|
SourceLocation PackLoc, SourceLocation RParenLoc,
|
||||||
Optional<unsigned> Length,
|
std::optional<unsigned> Length,
|
||||||
ArrayRef<TemplateArgument> PartialArgs)
|
ArrayRef<TemplateArgument> PartialArgs)
|
||||||
: Expr(SizeOfPackExprClass, SizeType, VK_PRValue, OK_Ordinary),
|
: Expr(SizeOfPackExprClass, SizeType, VK_PRValue, OK_Ordinary),
|
||||||
OperatorLoc(OperatorLoc), PackLoc(PackLoc), RParenLoc(RParenLoc),
|
OperatorLoc(OperatorLoc), PackLoc(PackLoc), RParenLoc(RParenLoc),
|
||||||
@@ -4194,11 +4250,11 @@ class SizeOfPackExpr final
|
|||||||
: Expr(SizeOfPackExprClass, Empty), Length(NumPartialArgs) {}
|
: Expr(SizeOfPackExprClass, Empty), Length(NumPartialArgs) {}
|
||||||
|
|
||||||
public:
|
public:
|
||||||
static SizeOfPackExpr *Create(ASTContext &Context, SourceLocation OperatorLoc,
|
static SizeOfPackExpr *
|
||||||
NamedDecl *Pack, SourceLocation PackLoc,
|
Create(ASTContext &Context, SourceLocation OperatorLoc, NamedDecl *Pack,
|
||||||
SourceLocation RParenLoc,
|
SourceLocation PackLoc, SourceLocation RParenLoc,
|
||||||
Optional<unsigned> Length = None,
|
std::optional<unsigned> Length = std::nullopt,
|
||||||
ArrayRef<TemplateArgument> PartialArgs = None);
|
ArrayRef<TemplateArgument> PartialArgs = std::nullopt);
|
||||||
static SizeOfPackExpr *CreateDeserialized(ASTContext &Context,
|
static SizeOfPackExpr *CreateDeserialized(ASTContext &Context,
|
||||||
unsigned NumPartialArgs);
|
unsigned NumPartialArgs);
|
||||||
|
|
||||||
@@ -4237,7 +4293,7 @@ class SizeOfPackExpr final
|
|||||||
ArrayRef<TemplateArgument> getPartialArguments() const {
|
ArrayRef<TemplateArgument> getPartialArguments() const {
|
||||||
assert(isPartiallySubstituted());
|
assert(isPartiallySubstituted());
|
||||||
const auto *Args = getTrailingObjects<TemplateArgument>();
|
const auto *Args = getTrailingObjects<TemplateArgument>();
|
||||||
return llvm::makeArrayRef(Args, Args + Length);
|
return llvm::ArrayRef(Args, Args + Length);
|
||||||
}
|
}
|
||||||
|
|
||||||
SourceLocation getBeginLoc() const LLVM_READONLY { return OperatorLoc; }
|
SourceLocation getBeginLoc() const LLVM_READONLY { return OperatorLoc; }
|
||||||
@@ -4263,24 +4319,30 @@ class SubstNonTypeTemplateParmExpr : public Expr {
|
|||||||
friend class ASTReader;
|
friend class ASTReader;
|
||||||
friend class ASTStmtReader;
|
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.
|
/// The replacement expression.
|
||||||
Stmt *Replacement;
|
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)
|
explicit SubstNonTypeTemplateParmExpr(EmptyShell Empty)
|
||||||
: Expr(SubstNonTypeTemplateParmExprClass, Empty) {}
|
: Expr(SubstNonTypeTemplateParmExprClass, Empty) {}
|
||||||
|
|
||||||
public:
|
public:
|
||||||
SubstNonTypeTemplateParmExpr(QualType Ty, ExprValueKind ValueKind,
|
SubstNonTypeTemplateParmExpr(QualType Ty, ExprValueKind ValueKind,
|
||||||
SourceLocation Loc,
|
SourceLocation Loc, Expr *Replacement,
|
||||||
NonTypeTemplateParmDecl *Param, bool RefParam,
|
Decl *AssociatedDecl, unsigned Index,
|
||||||
Expr *Replacement)
|
std::optional<unsigned> PackIndex, bool RefParam)
|
||||||
: Expr(SubstNonTypeTemplateParmExprClass, Ty, ValueKind, OK_Ordinary),
|
: 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;
|
SubstNonTypeTemplateParmExprBits.NameLoc = Loc;
|
||||||
setDependence(computeDependence(this));
|
setDependence(computeDependence(this));
|
||||||
}
|
}
|
||||||
@@ -4293,11 +4355,23 @@ class SubstNonTypeTemplateParmExpr : public Expr {
|
|||||||
|
|
||||||
Expr *getReplacement() const { return cast<Expr>(Replacement); }
|
Expr *getReplacement() const { return cast<Expr>(Replacement); }
|
||||||
|
|
||||||
NonTypeTemplateParmDecl *getParameter() const {
|
/// A template-like entity which owns the whole pattern being substituted.
|
||||||
return ParamAndRef.getPointer();
|
/// 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.
|
/// Determine the substituted type of the template parameter.
|
||||||
QualType getParameterType(const ASTContext &Ctx) const;
|
QualType getParameterType(const ASTContext &Ctx) const;
|
||||||
@@ -4331,14 +4405,16 @@ class SubstNonTypeTemplateParmPackExpr : public Expr {
|
|||||||
friend class ASTStmtReader;
|
friend class ASTStmtReader;
|
||||||
|
|
||||||
/// The non-type template parameter pack itself.
|
/// The non-type template parameter pack itself.
|
||||||
NonTypeTemplateParmDecl *Param;
|
Decl *AssociatedDecl;
|
||||||
|
|
||||||
/// A pointer to the set of template arguments that this
|
/// A pointer to the set of template arguments that this
|
||||||
/// parameter pack is instantiated with.
|
/// parameter pack is instantiated with.
|
||||||
const TemplateArgument *Arguments;
|
const TemplateArgument *Arguments;
|
||||||
|
|
||||||
/// The number of template arguments in \c 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.
|
/// The location of the non-type template parameter pack reference.
|
||||||
SourceLocation NameLoc;
|
SourceLocation NameLoc;
|
||||||
@@ -4347,14 +4423,21 @@ class SubstNonTypeTemplateParmPackExpr : public Expr {
|
|||||||
: Expr(SubstNonTypeTemplateParmPackExprClass, Empty) {}
|
: Expr(SubstNonTypeTemplateParmPackExprClass, Empty) {}
|
||||||
|
|
||||||
public:
|
public:
|
||||||
SubstNonTypeTemplateParmPackExpr(QualType T,
|
SubstNonTypeTemplateParmPackExpr(QualType T, ExprValueKind ValueKind,
|
||||||
ExprValueKind ValueKind,
|
|
||||||
NonTypeTemplateParmDecl *Param,
|
|
||||||
SourceLocation NameLoc,
|
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.
|
/// 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.
|
/// Retrieve the location of the parameter pack name.
|
||||||
SourceLocation getParameterPackLocation() const { return NameLoc; }
|
SourceLocation getParameterPackLocation() const { return NameLoc; }
|
||||||
@@ -4607,7 +4690,7 @@ class CXXFoldExpr : public Expr {
|
|||||||
CXXFoldExpr(QualType T, UnresolvedLookupExpr *Callee,
|
CXXFoldExpr(QualType T, UnresolvedLookupExpr *Callee,
|
||||||
SourceLocation LParenLoc, Expr *LHS, BinaryOperatorKind Opcode,
|
SourceLocation LParenLoc, Expr *LHS, BinaryOperatorKind Opcode,
|
||||||
SourceLocation EllipsisLoc, Expr *RHS, SourceLocation RParenLoc,
|
SourceLocation EllipsisLoc, Expr *RHS, SourceLocation RParenLoc,
|
||||||
Optional<unsigned> NumExpansions)
|
std::optional<unsigned> NumExpansions)
|
||||||
: Expr(CXXFoldExprClass, T, VK_PRValue, OK_Ordinary),
|
: Expr(CXXFoldExprClass, T, VK_PRValue, OK_Ordinary),
|
||||||
LParenLoc(LParenLoc), EllipsisLoc(EllipsisLoc), RParenLoc(RParenLoc),
|
LParenLoc(LParenLoc), EllipsisLoc(EllipsisLoc), RParenLoc(RParenLoc),
|
||||||
NumExpansions(NumExpansions ? *NumExpansions + 1 : 0), Opcode(Opcode) {
|
NumExpansions(NumExpansions ? *NumExpansions + 1 : 0), Opcode(Opcode) {
|
||||||
@@ -4644,10 +4727,10 @@ class CXXFoldExpr : public Expr {
|
|||||||
SourceLocation getEllipsisLoc() const { return EllipsisLoc; }
|
SourceLocation getEllipsisLoc() const { return EllipsisLoc; }
|
||||||
BinaryOperatorKind getOperator() const { return Opcode; }
|
BinaryOperatorKind getOperator() const { return Opcode; }
|
||||||
|
|
||||||
Optional<unsigned> getNumExpansions() const {
|
std::optional<unsigned> getNumExpansions() const {
|
||||||
if (NumExpansions)
|
if (NumExpansions)
|
||||||
return NumExpansions - 1;
|
return NumExpansions - 1;
|
||||||
return None;
|
return std::nullopt;
|
||||||
}
|
}
|
||||||
|
|
||||||
SourceLocation getBeginLoc() const LLVM_READONLY {
|
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;
|
/// Represents an expression that might suspend coroutine execution;
|
||||||
/// either a co_await or co_yield expression.
|
/// either a co_await or co_yield expression.
|
||||||
///
|
///
|
||||||
|
|||||||
@@ -24,6 +24,7 @@
|
|||||||
#include "clang/AST/TemplateBase.h"
|
#include "clang/AST/TemplateBase.h"
|
||||||
#include "clang/AST/Type.h"
|
#include "clang/AST/Type.h"
|
||||||
#include "clang/Basic/SourceLocation.h"
|
#include "clang/Basic/SourceLocation.h"
|
||||||
|
#include "llvm/Support/ErrorHandling.h"
|
||||||
#include "llvm/Support/TrailingObjects.h"
|
#include "llvm/Support/TrailingObjects.h"
|
||||||
#include <utility>
|
#include <utility>
|
||||||
#include <string>
|
#include <string>
|
||||||
@@ -37,18 +38,17 @@ class ASTStmtWriter;
|
|||||||
///
|
///
|
||||||
/// According to C++2a [expr.prim.id]p3 an id-expression that denotes the
|
/// 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.
|
/// specialization of a concept results in a prvalue of type bool.
|
||||||
class ConceptSpecializationExpr final : public Expr, public ConceptReference,
|
class ConceptSpecializationExpr final : public Expr, public ConceptReference {
|
||||||
private llvm::TrailingObjects<ConceptSpecializationExpr,
|
friend class ASTReader;
|
||||||
TemplateArgument> {
|
|
||||||
friend class ASTStmtReader;
|
friend class ASTStmtReader;
|
||||||
friend TrailingObjects;
|
|
||||||
public:
|
public:
|
||||||
using SubstitutionDiagnostic = std::pair<SourceLocation, std::string>;
|
using SubstitutionDiagnostic = std::pair<SourceLocation, std::string>;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
/// \brief The number of template arguments in the tail-allocated list of
|
/// \brief The Implicit Concept Specialization Decl, which holds the template
|
||||||
/// converted template arguments.
|
/// arguments for this specialization.
|
||||||
unsigned NumTemplateArgs;
|
ImplicitConceptSpecializationDecl *SpecDecl;
|
||||||
|
|
||||||
/// \brief Information about the satisfaction of the named concept with the
|
/// \brief Information about the satisfaction of the named concept with the
|
||||||
/// given arguments. If this expression is value dependent, this is to be
|
/// 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,
|
DeclarationNameInfo ConceptNameInfo,
|
||||||
NamedDecl *FoundDecl, ConceptDecl *NamedConcept,
|
NamedDecl *FoundDecl, ConceptDecl *NamedConcept,
|
||||||
const ASTTemplateArgumentListInfo *ArgsAsWritten,
|
const ASTTemplateArgumentListInfo *ArgsAsWritten,
|
||||||
ArrayRef<TemplateArgument> ConvertedArgs,
|
ImplicitConceptSpecializationDecl *SpecDecl,
|
||||||
const ConstraintSatisfaction *Satisfaction);
|
const ConstraintSatisfaction *Satisfaction);
|
||||||
|
|
||||||
ConceptSpecializationExpr(const ASTContext &C, ConceptDecl *NamedConcept,
|
ConceptSpecializationExpr(const ASTContext &C, ConceptDecl *NamedConcept,
|
||||||
ArrayRef<TemplateArgument> ConvertedArgs,
|
ImplicitConceptSpecializationDecl *SpecDecl,
|
||||||
const ConstraintSatisfaction *Satisfaction,
|
const ConstraintSatisfaction *Satisfaction,
|
||||||
bool Dependent,
|
bool Dependent,
|
||||||
bool ContainsUnexpandedParameterPack);
|
bool ContainsUnexpandedParameterPack);
|
||||||
|
ConceptSpecializationExpr(EmptyShell Empty);
|
||||||
ConceptSpecializationExpr(EmptyShell Empty, unsigned NumTemplateArgs);
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
static ConceptSpecializationExpr *
|
static ConceptSpecializationExpr *
|
||||||
Create(const ASTContext &C, NestedNameSpecifierLoc NNS,
|
Create(const ASTContext &C, NestedNameSpecifierLoc NNS,
|
||||||
SourceLocation TemplateKWLoc, DeclarationNameInfo ConceptNameInfo,
|
SourceLocation TemplateKWLoc, DeclarationNameInfo ConceptNameInfo,
|
||||||
NamedDecl *FoundDecl, ConceptDecl *NamedConcept,
|
NamedDecl *FoundDecl, ConceptDecl *NamedConcept,
|
||||||
const ASTTemplateArgumentListInfo *ArgsAsWritten,
|
const ASTTemplateArgumentListInfo *ArgsAsWritten,
|
||||||
ArrayRef<TemplateArgument> ConvertedArgs,
|
ImplicitConceptSpecializationDecl *SpecDecl,
|
||||||
const ConstraintSatisfaction *Satisfaction);
|
const ConstraintSatisfaction *Satisfaction);
|
||||||
|
|
||||||
static ConceptSpecializationExpr *
|
static ConceptSpecializationExpr *
|
||||||
Create(const ASTContext &C, ConceptDecl *NamedConcept,
|
Create(const ASTContext &C, ConceptDecl *NamedConcept,
|
||||||
ArrayRef<TemplateArgument> ConvertedArgs,
|
ImplicitConceptSpecializationDecl *SpecDecl,
|
||||||
const ConstraintSatisfaction *Satisfaction,
|
const ConstraintSatisfaction *Satisfaction, bool Dependent,
|
||||||
bool Dependent,
|
|
||||||
bool ContainsUnexpandedParameterPack);
|
bool ContainsUnexpandedParameterPack);
|
||||||
|
|
||||||
static ConceptSpecializationExpr *
|
|
||||||
Create(ASTContext &C, EmptyShell Empty, unsigned NumTemplateArgs);
|
|
||||||
|
|
||||||
ArrayRef<TemplateArgument> getTemplateArguments() const {
|
ArrayRef<TemplateArgument> getTemplateArguments() const {
|
||||||
return ArrayRef<TemplateArgument>(getTrailingObjects<TemplateArgument>(),
|
return SpecDecl->getTemplateArguments();
|
||||||
NumTemplateArgs);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// \brief Set new template arguments for this concept specialization.
|
const ImplicitConceptSpecializationDecl *getSpecializationDecl() const {
|
||||||
void setTemplateArguments(ArrayRef<TemplateArgument> Converted);
|
assert(SpecDecl && "Template Argument Decl not initialized");
|
||||||
|
return SpecDecl;
|
||||||
|
}
|
||||||
|
|
||||||
/// \brief Whether or not the concept with the given arguments was satisfied
|
/// \brief Whether or not the concept with the given arguments was satisfied
|
||||||
/// when the expression was created.
|
/// when the expression was created.
|
||||||
/// The expression must not be dependent.
|
/// The expression must not be dependent.
|
||||||
bool isSatisfied() const {
|
bool isSatisfied() const {
|
||||||
assert(!isValueDependent()
|
assert(!isValueDependent() &&
|
||||||
&& "isSatisfied called on a dependent ConceptSpecializationExpr");
|
"isSatisfied called on a dependent ConceptSpecializationExpr");
|
||||||
return Satisfaction->IsSatisfied;
|
return Satisfaction->IsSatisfied;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -112,8 +107,8 @@ class ConceptSpecializationExpr final : public Expr, public ConceptReference,
|
|||||||
/// satisfaction of the named concept.
|
/// satisfaction of the named concept.
|
||||||
/// The expression must not be dependent.
|
/// The expression must not be dependent.
|
||||||
const ASTConstraintSatisfaction &getSatisfaction() const {
|
const ASTConstraintSatisfaction &getSatisfaction() const {
|
||||||
assert(!isValueDependent()
|
assert(!isValueDependent() &&
|
||||||
&& "getSatisfaction called on dependent ConceptSpecializationExpr");
|
"getSatisfaction called on dependent ConceptSpecializationExpr");
|
||||||
return *Satisfaction;
|
return *Satisfaction;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -407,57 +402,61 @@ class ExprRequirement : public Requirement {
|
|||||||
/// \brief A requires-expression requirement which is satisfied when a general
|
/// \brief A requires-expression requirement which is satisfied when a general
|
||||||
/// constraint expression is satisfied ('nested' requirements).
|
/// constraint expression is satisfied ('nested' requirements).
|
||||||
class NestedRequirement : public Requirement {
|
class NestedRequirement : public Requirement {
|
||||||
llvm::PointerUnion<Expr *, SubstitutionDiagnostic *> Value;
|
Expr *Constraint = nullptr;
|
||||||
const ASTConstraintSatisfaction *Satisfaction = nullptr;
|
const ASTConstraintSatisfaction *Satisfaction = nullptr;
|
||||||
|
bool HasInvalidConstraint = false;
|
||||||
|
StringRef InvalidConstraintEntity;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
friend ASTStmtReader;
|
friend ASTStmtReader;
|
||||||
friend ASTStmtWriter;
|
friend ASTStmtWriter;
|
||||||
|
|
||||||
NestedRequirement(SubstitutionDiagnostic *SubstDiag) :
|
NestedRequirement(Expr *Constraint)
|
||||||
Requirement(RK_Nested, /*IsDependent=*/false,
|
: Requirement(RK_Nested, /*IsDependent=*/true,
|
||||||
/*ContainsUnexpandedParameterPack*/false,
|
|
||||||
/*IsSatisfied=*/false), Value(SubstDiag) {}
|
|
||||||
|
|
||||||
NestedRequirement(Expr *Constraint) :
|
|
||||||
Requirement(RK_Nested, /*IsDependent=*/true,
|
|
||||||
Constraint->containsUnexpandedParameterPack()),
|
Constraint->containsUnexpandedParameterPack()),
|
||||||
Value(Constraint) {
|
Constraint(Constraint) {
|
||||||
assert(Constraint->isInstantiationDependent() &&
|
assert(Constraint->isInstantiationDependent() &&
|
||||||
"Nested requirement with non-dependent constraint must be "
|
"Nested requirement with non-dependent constraint must be "
|
||||||
"constructed with a ConstraintSatisfaction object");
|
"constructed with a ConstraintSatisfaction object");
|
||||||
}
|
}
|
||||||
|
|
||||||
NestedRequirement(ASTContext &C, Expr *Constraint,
|
NestedRequirement(ASTContext &C, Expr *Constraint,
|
||||||
const ConstraintSatisfaction &Satisfaction) :
|
const ConstraintSatisfaction &Satisfaction)
|
||||||
Requirement(RK_Nested, Constraint->isInstantiationDependent(),
|
: Requirement(RK_Nested, Constraint->isInstantiationDependent(),
|
||||||
Constraint->containsUnexpandedParameterPack(),
|
Constraint->containsUnexpandedParameterPack(),
|
||||||
Satisfaction.IsSatisfied),
|
Satisfaction.IsSatisfied),
|
||||||
Value(Constraint),
|
Constraint(Constraint),
|
||||||
Satisfaction(ASTConstraintSatisfaction::Create(C, Satisfaction)) {}
|
Satisfaction(ASTConstraintSatisfaction::Create(C, Satisfaction)) {}
|
||||||
|
|
||||||
bool isSubstitutionFailure() const {
|
NestedRequirement(StringRef InvalidConstraintEntity,
|
||||||
return Value.is<SubstitutionDiagnostic *>();
|
const ASTConstraintSatisfaction *Satisfaction)
|
||||||
}
|
: Requirement(RK_Nested,
|
||||||
|
/*IsDependent=*/false,
|
||||||
|
/*ContainsUnexpandedParameterPack*/ false,
|
||||||
|
Satisfaction->IsSatisfied),
|
||||||
|
Satisfaction(Satisfaction), HasInvalidConstraint(true),
|
||||||
|
InvalidConstraintEntity(InvalidConstraintEntity) {}
|
||||||
|
|
||||||
SubstitutionDiagnostic *getSubstitutionDiagnostic() const {
|
NestedRequirement(ASTContext &C, StringRef InvalidConstraintEntity,
|
||||||
assert(isSubstitutionFailure() &&
|
const ConstraintSatisfaction &Satisfaction)
|
||||||
"getSubstitutionDiagnostic() may not be called when there was no "
|
: NestedRequirement(InvalidConstraintEntity,
|
||||||
"substitution failure.");
|
ASTConstraintSatisfaction::Create(C, Satisfaction)) {}
|
||||||
return Value.get<SubstitutionDiagnostic *>();
|
|
||||||
|
bool hasInvalidConstraint() const { return HasInvalidConstraint; }
|
||||||
|
|
||||||
|
StringRef getInvalidConstraintEntity() {
|
||||||
|
assert(hasInvalidConstraint());
|
||||||
|
return InvalidConstraintEntity;
|
||||||
}
|
}
|
||||||
|
|
||||||
Expr *getConstraintExpr() const {
|
Expr *getConstraintExpr() const {
|
||||||
assert(!isSubstitutionFailure() && "getConstraintExpr() may not be called "
|
assert(!hasInvalidConstraint() &&
|
||||||
"on nested requirements with "
|
"getConstraintExpr() may not be called "
|
||||||
"substitution failures.");
|
"on nested requirements with invalid constraint.");
|
||||||
return Value.get<Expr *>();
|
return Constraint;
|
||||||
}
|
}
|
||||||
|
|
||||||
const ASTConstraintSatisfaction &getConstraintSatisfaction() const {
|
const ASTConstraintSatisfaction &getConstraintSatisfaction() const {
|
||||||
assert(!isSubstitutionFailure() && "getConstraintSatisfaction() may not be "
|
|
||||||
"called on nested requirements with "
|
|
||||||
"substitution failures.");
|
|
||||||
return *Satisfaction;
|
return *Satisfaction;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -529,6 +528,12 @@ class RequiresExpr final : public Expr,
|
|||||||
return RequiresExprBits.IsSatisfied;
|
return RequiresExprBits.IsSatisfied;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void setSatisfied(bool IsSatisfied) {
|
||||||
|
assert(!isValueDependent() &&
|
||||||
|
"setSatisfied called on a dependent RequiresExpr");
|
||||||
|
RequiresExprBits.IsSatisfied = IsSatisfied;
|
||||||
|
}
|
||||||
|
|
||||||
SourceLocation getRequiresKWLoc() const {
|
SourceLocation getRequiresKWLoc() const {
|
||||||
return RequiresExprBits.RequiresKWLoc;
|
return RequiresExprBits.RequiresKWLoc;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -27,8 +27,6 @@
|
|||||||
#include "clang/Basic/SourceLocation.h"
|
#include "clang/Basic/SourceLocation.h"
|
||||||
#include "clang/Basic/Specifiers.h"
|
#include "clang/Basic/Specifiers.h"
|
||||||
#include "llvm/ADT/ArrayRef.h"
|
#include "llvm/ADT/ArrayRef.h"
|
||||||
#include "llvm/ADT/None.h"
|
|
||||||
#include "llvm/ADT/Optional.h"
|
|
||||||
#include "llvm/ADT/PointerIntPair.h"
|
#include "llvm/ADT/PointerIntPair.h"
|
||||||
#include "llvm/ADT/PointerUnion.h"
|
#include "llvm/ADT/PointerUnion.h"
|
||||||
#include "llvm/ADT/StringRef.h"
|
#include "llvm/ADT/StringRef.h"
|
||||||
@@ -41,6 +39,7 @@
|
|||||||
#include <cassert>
|
#include <cassert>
|
||||||
#include <cstddef>
|
#include <cstddef>
|
||||||
#include <cstdint>
|
#include <cstdint>
|
||||||
|
#include <optional>
|
||||||
|
|
||||||
namespace clang {
|
namespace clang {
|
||||||
|
|
||||||
@@ -272,7 +271,7 @@ struct ObjCDictionaryElement {
|
|||||||
|
|
||||||
/// The number of elements this pack expansion will expand to, if
|
/// The number of elements this pack expansion will expand to, if
|
||||||
/// this is a pack expansion and is known.
|
/// this is a pack expansion and is known.
|
||||||
Optional<unsigned> NumExpansions;
|
std::optional<unsigned> NumExpansions;
|
||||||
|
|
||||||
/// Determines whether this dictionary element is a pack expansion.
|
/// Determines whether this dictionary element is a pack expansion.
|
||||||
bool isPackExpansion() const { return EllipsisLoc.isValid(); }
|
bool isPackExpansion() const { return EllipsisLoc.isValid(); }
|
||||||
@@ -362,7 +361,8 @@ class ObjCDictionaryLiteral final
|
|||||||
ObjCDictionaryElement getKeyValueElement(unsigned Index) const {
|
ObjCDictionaryElement getKeyValueElement(unsigned Index) const {
|
||||||
assert((Index < NumElements) && "Arg access out of range!");
|
assert((Index < NumElements) && "Arg access out of range!");
|
||||||
const KeyValuePair &KV = getTrailingObjects<KeyValuePair>()[Index];
|
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) {
|
if (HasPackExpansions) {
|
||||||
const ExpansionData &Expansion =
|
const ExpansionData &Expansion =
|
||||||
getTrailingObjects<ExpansionData>()[Index];
|
getTrailingObjects<ExpansionData>()[Index];
|
||||||
@@ -1415,10 +1415,9 @@ class ObjCMessageExpr final
|
|||||||
SourceLocation getSelectorLoc(unsigned Index) const {
|
SourceLocation getSelectorLoc(unsigned Index) const {
|
||||||
assert(Index < getNumSelectorLocs() && "Index out of range!");
|
assert(Index < getNumSelectorLocs() && "Index out of range!");
|
||||||
if (hasStandardSelLocs())
|
if (hasStandardSelLocs())
|
||||||
return getStandardSelectorLoc(Index, getSelector(),
|
return getStandardSelectorLoc(
|
||||||
getSelLocsKind() == SelLoc_StandardWithSpace,
|
Index, getSelector(), getSelLocsKind() == SelLoc_StandardWithSpace,
|
||||||
llvm::makeArrayRef(const_cast<Expr**>(getArgs()),
|
llvm::ArrayRef(const_cast<Expr **>(getArgs()), getNumArgs()),
|
||||||
getNumArgs()),
|
|
||||||
RBracLoc);
|
RBracLoc);
|
||||||
return getStoredSelLocs()[Index];
|
return getStoredSelLocs()[Index];
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -202,12 +202,12 @@ class OMPArrayShapingExpr final
|
|||||||
|
|
||||||
/// Fetches the dimensions for array shaping expression.
|
/// Fetches the dimensions for array shaping expression.
|
||||||
ArrayRef<Expr *> getDimensions() const {
|
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.
|
/// Fetches source ranges for the brackets os the array shaping expression.
|
||||||
ArrayRef<SourceRange> getBracketsRanges() const {
|
ArrayRef<SourceRange> getBracketsRanges() const {
|
||||||
return llvm::makeArrayRef(getTrailingObjects<SourceRange>(), NumDims);
|
return llvm::ArrayRef(getTrailingObjects<SourceRange>(), NumDims);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Fetches base expression of array shaping expression.
|
/// 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
|
/// Asks all connected ASTImporters if any of them imported the given
|
||||||
/// declaration. If any ASTImporter did import the given declaration,
|
/// declaration. If any ASTImporter did import the given declaration,
|
||||||
/// then this function returns the declaration that D was imported from.
|
/// 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);
|
Decl *FindOriginalDecl(Decl *D);
|
||||||
|
|
||||||
/// Add a set of ASTContexts as possible origins.
|
/// Add a set of ASTContexts as possible origins.
|
||||||
|
|||||||
@@ -20,7 +20,6 @@
|
|||||||
#include "llvm/ADT/ArrayRef.h"
|
#include "llvm/ADT/ArrayRef.h"
|
||||||
#include "llvm/ADT/DenseMap.h"
|
#include "llvm/ADT/DenseMap.h"
|
||||||
#include "llvm/ADT/IntrusiveRefCntPtr.h"
|
#include "llvm/ADT/IntrusiveRefCntPtr.h"
|
||||||
#include "llvm/ADT/Optional.h"
|
|
||||||
#include "llvm/ADT/PointerUnion.h"
|
#include "llvm/ADT/PointerUnion.h"
|
||||||
#include "llvm/ADT/STLExtras.h"
|
#include "llvm/ADT/STLExtras.h"
|
||||||
#include "llvm/ADT/SmallVector.h"
|
#include "llvm/ADT/SmallVector.h"
|
||||||
@@ -30,6 +29,7 @@
|
|||||||
#include <cstddef>
|
#include <cstddef>
|
||||||
#include <cstdint>
|
#include <cstdint>
|
||||||
#include <iterator>
|
#include <iterator>
|
||||||
|
#include <optional>
|
||||||
#include <utility>
|
#include <utility>
|
||||||
|
|
||||||
namespace clang {
|
namespace clang {
|
||||||
@@ -160,7 +160,7 @@ class ExternalASTSource : public RefCountedBase<ExternalASTSource> {
|
|||||||
virtual Module *getModule(unsigned ID) { return nullptr; }
|
virtual Module *getModule(unsigned ID) { return nullptr; }
|
||||||
|
|
||||||
/// Return a descriptor for the corresponding module, if one exists.
|
/// 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 };
|
enum ExtKind { EK_Always, EK_Never, EK_ReplyHazy };
|
||||||
|
|
||||||
|
|||||||
@@ -19,6 +19,7 @@
|
|||||||
#define LLVM_CLANG_AST_FORMATSTRING_H
|
#define LLVM_CLANG_AST_FORMATSTRING_H
|
||||||
|
|
||||||
#include "clang/AST/CanonicalType.h"
|
#include "clang/AST/CanonicalType.h"
|
||||||
|
#include <optional>
|
||||||
|
|
||||||
namespace clang {
|
namespace clang {
|
||||||
|
|
||||||
@@ -127,8 +128,12 @@ class ConversionSpecifier {
|
|||||||
dArg,
|
dArg,
|
||||||
DArg, // Apple extension
|
DArg, // Apple extension
|
||||||
iArg,
|
iArg,
|
||||||
|
// C23 conversion specifiers.
|
||||||
|
bArg,
|
||||||
|
BArg,
|
||||||
|
|
||||||
IntArgBeg = dArg,
|
IntArgBeg = dArg,
|
||||||
IntArgEnd = iArg,
|
IntArgEnd = BArg,
|
||||||
|
|
||||||
oArg,
|
oArg,
|
||||||
OArg, // Apple extension
|
OArg, // Apple extension
|
||||||
@@ -237,7 +242,7 @@ class ConversionSpecifier {
|
|||||||
|
|
||||||
bool isPrintfKind() const { return IsPrintf; }
|
bool isPrintfKind() const { return IsPrintf; }
|
||||||
|
|
||||||
Optional<ConversionSpecifier> getStandardSpecifier() const;
|
std::optional<ConversionSpecifier> getStandardSpecifier() const;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
bool IsPrintf;
|
bool IsPrintf;
|
||||||
@@ -257,8 +262,14 @@ class ArgType {
|
|||||||
/// instance, "%d" and float.
|
/// instance, "%d" and float.
|
||||||
NoMatch = 0,
|
NoMatch = 0,
|
||||||
/// The conversion specifier and the argument type are compatible. For
|
/// The conversion specifier and the argument type are compatible. For
|
||||||
/// instance, "%d" and _Bool.
|
/// instance, "%d" and int.
|
||||||
Match = 1,
|
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
|
/// The conversion specifier and the argument type are disallowed by the C
|
||||||
/// standard, but are in practice harmless. For instance, "%p" and int*.
|
/// standard, but are in practice harmless. For instance, "%p" and int*.
|
||||||
NoMatchPedantic,
|
NoMatchPedantic,
|
||||||
@@ -456,7 +467,7 @@ class FormatSpecifier {
|
|||||||
|
|
||||||
bool hasStandardLengthModifier() const;
|
bool hasStandardLengthModifier() const;
|
||||||
|
|
||||||
Optional<LengthModifier> getCorrectedLengthModifier() const;
|
std::optional<LengthModifier> getCorrectedLengthModifier() const;
|
||||||
|
|
||||||
bool hasStandardConversionSpecifier(const LangOptions &LangOpt) const;
|
bool hasStandardConversionSpecifier(const LangOptions &LangOpt) const;
|
||||||
|
|
||||||
|
|||||||
@@ -209,6 +209,7 @@ class JSONNodeDumper
|
|||||||
void Visit(const APValue &Value, QualType Ty);
|
void Visit(const APValue &Value, QualType Ty);
|
||||||
|
|
||||||
void VisitTypedefType(const TypedefType *TT);
|
void VisitTypedefType(const TypedefType *TT);
|
||||||
|
void VisitUsingType(const UsingType *TT);
|
||||||
void VisitFunctionType(const FunctionType *T);
|
void VisitFunctionType(const FunctionType *T);
|
||||||
void VisitFunctionProtoType(const FunctionProtoType *T);
|
void VisitFunctionProtoType(const FunctionProtoType *T);
|
||||||
void VisitRValueReferenceType(const ReferenceType *RT);
|
void VisitRValueReferenceType(const ReferenceType *RT);
|
||||||
@@ -220,6 +221,9 @@ class JSONNodeDumper
|
|||||||
void VisitUnaryTransformType(const UnaryTransformType *UTT);
|
void VisitUnaryTransformType(const UnaryTransformType *UTT);
|
||||||
void VisitTagType(const TagType *TT);
|
void VisitTagType(const TagType *TT);
|
||||||
void VisitTemplateTypeParmType(const TemplateTypeParmType *TTPT);
|
void VisitTemplateTypeParmType(const TemplateTypeParmType *TTPT);
|
||||||
|
void VisitSubstTemplateTypeParmType(const SubstTemplateTypeParmType *STTPT);
|
||||||
|
void
|
||||||
|
VisitSubstTemplateTypeParmPackType(const SubstTemplateTypeParmPackType *T);
|
||||||
void VisitAutoType(const AutoType *AT);
|
void VisitAutoType(const AutoType *AT);
|
||||||
void VisitTemplateSpecializationType(const TemplateSpecializationType *TST);
|
void VisitTemplateSpecializationType(const TemplateSpecializationType *TST);
|
||||||
void VisitInjectedClassNameType(const InjectedClassNameType *ICNT);
|
void VisitInjectedClassNameType(const InjectedClassNameType *ICNT);
|
||||||
@@ -245,6 +249,7 @@ class JSONNodeDumper
|
|||||||
void VisitEnumConstantDecl(const EnumConstantDecl *ECD);
|
void VisitEnumConstantDecl(const EnumConstantDecl *ECD);
|
||||||
void VisitRecordDecl(const RecordDecl *RD);
|
void VisitRecordDecl(const RecordDecl *RD);
|
||||||
void VisitCXXRecordDecl(const CXXRecordDecl *RD);
|
void VisitCXXRecordDecl(const CXXRecordDecl *RD);
|
||||||
|
void VisitHLSLBufferDecl(const HLSLBufferDecl *D);
|
||||||
void VisitTemplateTypeParmDecl(const TemplateTypeParmDecl *D);
|
void VisitTemplateTypeParmDecl(const TemplateTypeParmDecl *D);
|
||||||
void VisitNonTypeTemplateParmDecl(const NonTypeTemplateParmDecl *D);
|
void VisitNonTypeTemplateParmDecl(const NonTypeTemplateParmDecl *D);
|
||||||
void VisitTemplateTemplateParmDecl(const TemplateTemplateParmDecl *D);
|
void VisitTemplateTemplateParmDecl(const TemplateTemplateParmDecl *D);
|
||||||
@@ -380,7 +385,7 @@ class JSONDumper : public ASTNodeTraverser<JSONDumper, JSONNodeDumper> {
|
|||||||
case TSK_ExplicitInstantiationDefinition:
|
case TSK_ExplicitInstantiationDefinition:
|
||||||
if (!DumpExplicitInst)
|
if (!DumpExplicitInst)
|
||||||
break;
|
break;
|
||||||
LLVM_FALLTHROUGH;
|
[[fallthrough]];
|
||||||
case TSK_Undeclared:
|
case TSK_Undeclared:
|
||||||
case TSK_ImplicitInstantiation:
|
case TSK_ImplicitInstantiation:
|
||||||
if (DumpRefOnly)
|
if (DumpRefOnly)
|
||||||
|
|||||||
@@ -71,7 +71,7 @@ class LambdaCapture {
|
|||||||
/// capture that is a pack expansion, or an invalid source
|
/// capture that is a pack expansion, or an invalid source
|
||||||
/// location to indicate that this is not a pack expansion.
|
/// location to indicate that this is not a pack expansion.
|
||||||
LambdaCapture(SourceLocation Loc, bool Implicit, LambdaCaptureKind Kind,
|
LambdaCapture(SourceLocation Loc, bool Implicit, LambdaCaptureKind Kind,
|
||||||
VarDecl *Var = nullptr,
|
ValueDecl *Var = nullptr,
|
||||||
SourceLocation EllipsisLoc = SourceLocation());
|
SourceLocation EllipsisLoc = SourceLocation());
|
||||||
|
|
||||||
/// Determine the kind of capture.
|
/// Determine the kind of capture.
|
||||||
@@ -86,7 +86,7 @@ class LambdaCapture {
|
|||||||
|
|
||||||
/// Determine whether this capture handles a variable.
|
/// Determine whether this capture handles a variable.
|
||||||
bool capturesVariable() const {
|
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
|
/// 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
|
/// This operation is only valid if this capture is a variable capture
|
||||||
/// (other than a capture of \c this).
|
/// (other than a capture of \c this).
|
||||||
VarDecl *getCapturedVar() const {
|
ValueDecl *getCapturedVar() const {
|
||||||
assert(capturesVariable() && "No variable available for capture");
|
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
|
/// Determine whether this was an implicit capture (not
|
||||||
|
|||||||
@@ -19,6 +19,7 @@
|
|||||||
#include "clang/Basic/ABI.h"
|
#include "clang/Basic/ABI.h"
|
||||||
#include "llvm/ADT/DenseMap.h"
|
#include "llvm/ADT/DenseMap.h"
|
||||||
#include "llvm/Support/Casting.h"
|
#include "llvm/Support/Casting.h"
|
||||||
|
#include <optional>
|
||||||
|
|
||||||
namespace llvm {
|
namespace llvm {
|
||||||
class raw_ostream;
|
class raw_ostream;
|
||||||
@@ -61,6 +62,7 @@ class MangleContext {
|
|||||||
llvm::DenseMap<const BlockDecl*, unsigned> GlobalBlockIds;
|
llvm::DenseMap<const BlockDecl*, unsigned> GlobalBlockIds;
|
||||||
llvm::DenseMap<const BlockDecl*, unsigned> LocalBlockIds;
|
llvm::DenseMap<const BlockDecl*, unsigned> LocalBlockIds;
|
||||||
llvm::DenseMap<const NamedDecl*, uint64_t> AnonStructIds;
|
llvm::DenseMap<const NamedDecl*, uint64_t> AnonStructIds;
|
||||||
|
llvm::DenseMap<const FunctionDecl*, unsigned> FuncAnonStructSize;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
ManglerKind getKind() const { return Kind; }
|
ManglerKind getKind() const { return Kind; }
|
||||||
@@ -87,9 +89,17 @@ class MangleContext {
|
|||||||
return Result.first->second;
|
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>
|
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;
|
return Result.first->second;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -157,10 +167,10 @@ class MangleContext {
|
|||||||
virtual void mangleDynamicAtExitDestructor(const VarDecl *D,
|
virtual void mangleDynamicAtExitDestructor(const VarDecl *D,
|
||||||
raw_ostream &) = 0;
|
raw_ostream &) = 0;
|
||||||
|
|
||||||
virtual void mangleSEHFilterExpression(const NamedDecl *EnclosingDecl,
|
virtual void mangleSEHFilterExpression(GlobalDecl EnclosingDecl,
|
||||||
raw_ostream &Out) = 0;
|
raw_ostream &Out) = 0;
|
||||||
|
|
||||||
virtual void mangleSEHFinallyBlock(const NamedDecl *EnclosingDecl,
|
virtual void mangleSEHFinallyBlock(GlobalDecl EnclosingDecl,
|
||||||
raw_ostream &Out) = 0;
|
raw_ostream &Out) = 0;
|
||||||
|
|
||||||
/// Generates a unique string for an externally visible type for use with TBAA
|
/// Generates a unique string for an externally visible type for use with TBAA
|
||||||
@@ -175,7 +185,7 @@ class MangleContext {
|
|||||||
class ItaniumMangleContext : public MangleContext {
|
class ItaniumMangleContext : public MangleContext {
|
||||||
public:
|
public:
|
||||||
using DiscriminatorOverrideTy =
|
using DiscriminatorOverrideTy =
|
||||||
llvm::Optional<unsigned> (*)(ASTContext &, const NamedDecl *);
|
std::optional<unsigned> (*)(ASTContext &, const NamedDecl *);
|
||||||
explicit ItaniumMangleContext(ASTContext &C, DiagnosticsEngine &D,
|
explicit ItaniumMangleContext(ASTContext &C, DiagnosticsEngine &D,
|
||||||
bool IsAux = false)
|
bool IsAux = false)
|
||||||
: MangleContext(C, D, MK_Itanium, IsAux) {}
|
: MangleContext(C, D, MK_Itanium, IsAux) {}
|
||||||
|
|||||||
@@ -11,7 +11,7 @@
|
|||||||
|
|
||||||
#include "clang/Basic/IdentifierTable.h"
|
#include "clang/Basic/IdentifierTable.h"
|
||||||
#include "llvm/ADT/ArrayRef.h"
|
#include "llvm/ADT/ArrayRef.h"
|
||||||
#include "llvm/ADT/Optional.h"
|
#include <optional>
|
||||||
|
|
||||||
namespace clang {
|
namespace clang {
|
||||||
class ASTContext;
|
class ASTContext;
|
||||||
@@ -89,7 +89,7 @@ class NSAPI {
|
|||||||
Selector getNSArraySelector(NSArrayMethodKind MK) const;
|
Selector getNSArraySelector(NSArrayMethodKind MK) const;
|
||||||
|
|
||||||
/// Return NSArrayMethodKind if \p Sel is such a selector.
|
/// 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
|
/// Enumerates the NSDictionary/NSMutableDictionary methods used
|
||||||
/// to generate literals and to apply some checks.
|
/// to generate literals and to apply some checks.
|
||||||
@@ -114,7 +114,7 @@ class NSAPI {
|
|||||||
Selector getNSDictionarySelector(NSDictionaryMethodKind MK) const;
|
Selector getNSDictionarySelector(NSDictionaryMethodKind MK) const;
|
||||||
|
|
||||||
/// Return NSDictionaryMethodKind if \p Sel is such a selector.
|
/// 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
|
/// Enumerates the NSMutableSet/NSOrderedSet methods used
|
||||||
/// to apply some checks.
|
/// to apply some checks.
|
||||||
@@ -131,7 +131,7 @@ class NSAPI {
|
|||||||
Selector getNSSetSelector(NSSetMethodKind MK) const;
|
Selector getNSSetSelector(NSSetMethodKind MK) const;
|
||||||
|
|
||||||
/// Return NSSetMethodKind if \p Sel is such a selector.
|
/// Return NSSetMethodKind if \p Sel is such a selector.
|
||||||
Optional<NSSetMethodKind> getNSSetMethodKind(Selector Sel);
|
std::optional<NSSetMethodKind> getNSSetMethodKind(Selector Sel);
|
||||||
|
|
||||||
/// Returns selector for "objectForKeyedSubscript:".
|
/// Returns selector for "objectForKeyedSubscript:".
|
||||||
Selector getObjectForKeyedSubscriptSelector() const {
|
Selector getObjectForKeyedSubscriptSelector() const {
|
||||||
@@ -203,12 +203,12 @@ class NSAPI {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Return NSNumberLiteralMethodKind if \p Sel is such a selector.
|
/// Return NSNumberLiteralMethodKind if \p Sel is such a selector.
|
||||||
Optional<NSNumberLiteralMethodKind>
|
std::optional<NSNumberLiteralMethodKind>
|
||||||
getNSNumberLiteralMethodKind(Selector Sel) const;
|
getNSNumberLiteralMethodKind(Selector Sel) const;
|
||||||
|
|
||||||
/// Determine the appropriate NSNumber factory method kind for a
|
/// Determine the appropriate NSNumber factory method kind for a
|
||||||
/// literal of the given type.
|
/// literal of the given type.
|
||||||
Optional<NSNumberLiteralMethodKind>
|
std::optional<NSNumberLiteralMethodKind>
|
||||||
getNSNumberFactoryMethodKind(QualType T) const;
|
getNSNumberFactoryMethodKind(QualType T) const;
|
||||||
|
|
||||||
/// Returns true if \param T is a typedef of "BOOL" in objective-c.
|
/// 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.
|
// more information than the AddDecl class.
|
||||||
void AddCXXRecordDecl(const CXXRecordDecl *Record);
|
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
|
// Use this for ODR checking functions between modules. This method compares
|
||||||
// more information than the AddDecl class. SkipBody will process the
|
// more information than the AddDecl class. SkipBody will process the
|
||||||
// hash as if the function has no body.
|
// hash as if the function has no body.
|
||||||
@@ -64,6 +72,10 @@ class ODRHash {
|
|||||||
// more information than the AddDecl class.
|
// more information than the AddDecl class.
|
||||||
void AddEnumDecl(const EnumDecl *Enum);
|
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
|
// Process SubDecls of the main Decl. This method calls the DeclVisitor
|
||||||
// while AddDecl does not.
|
// while AddDecl does not.
|
||||||
void AddSubDecl(const Decl *D);
|
void AddSubDecl(const Decl *D);
|
||||||
@@ -89,7 +101,7 @@ class ODRHash {
|
|||||||
// Save booleans until the end to lower the size of data to process.
|
// Save booleans until the end to lower the size of data to process.
|
||||||
void AddBoolean(bool value);
|
void AddBoolean(bool value);
|
||||||
|
|
||||||
static bool isDeclToBeProcessed(const Decl* D, const DeclContext *Parent);
|
static bool isSubDeclToBeProcessed(const Decl *D, const DeclContext *Parent);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void AddDeclarationNameImpl(DeclarationName Name);
|
void AddDeclarationNameImpl(DeclarationName Name);
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@@ -77,7 +77,7 @@ class TraversalKindScope {
|
|||||||
TraversalKind TK = TK_AsIs;
|
TraversalKind TK = TK_AsIs;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
TraversalKindScope(ASTContext &ASTCtx, llvm::Optional<TraversalKind> ScopeTK)
|
TraversalKindScope(ASTContext &ASTCtx, std::optional<TraversalKind> ScopeTK)
|
||||||
: Ctx(ASTCtx.getParentMapContext()) {
|
: Ctx(ASTCtx.getParentMapContext()) {
|
||||||
TK = Ctx.getTraversalKind();
|
TK = Ctx.getTraversalKind();
|
||||||
if (ScopeTK)
|
if (ScopeTK)
|
||||||
|
|||||||
@@ -65,7 +65,8 @@ struct PrintingPolicy {
|
|||||||
SuppressStrongLifetime(false), SuppressLifetimeQualifiers(false),
|
SuppressStrongLifetime(false), SuppressLifetimeQualifiers(false),
|
||||||
SuppressTemplateArgsInCXXConstructors(false),
|
SuppressTemplateArgsInCXXConstructors(false),
|
||||||
SuppressDefaultTemplateArgs(true), Bool(LO.Bool),
|
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),
|
UnderscoreAlignof(LO.C11), UseVoidForZeroParams(!LO.CPlusPlus),
|
||||||
SplitTemplateClosers(!LO.CPlusPlus11), TerseOutput(false),
|
SplitTemplateClosers(!LO.CPlusPlus11), TerseOutput(false),
|
||||||
PolishForDeclaration(false), Half(LO.Half),
|
PolishForDeclaration(false), Half(LO.Half),
|
||||||
@@ -196,6 +197,9 @@ struct PrintingPolicy {
|
|||||||
/// constant.
|
/// constant.
|
||||||
unsigned Nullptr : 1;
|
unsigned Nullptr : 1;
|
||||||
|
|
||||||
|
/// Whether 'nullptr_t' is in namespace 'std' or not.
|
||||||
|
unsigned NullptrTypeInNamespace : 1;
|
||||||
|
|
||||||
/// Whether we can use 'restrict' rather than '__restrict'.
|
/// Whether we can use 'restrict' rather than '__restrict'.
|
||||||
unsigned Restrict : 1;
|
unsigned Restrict : 1;
|
||||||
|
|
||||||
|
|||||||
@@ -41,7 +41,7 @@ class RefPropertyType<string className> : PropertyType<className # "*"> {
|
|||||||
let PackOptional =
|
let PackOptional =
|
||||||
"value ? *value : nullptr";
|
"value ? *value : nullptr";
|
||||||
let UnpackOptional =
|
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.
|
/// Property types that correspond to a specific subclass of another type.
|
||||||
@@ -58,7 +58,7 @@ class DefaultValuePropertyType<string typeName = ""> : PropertyType<typeName> {
|
|||||||
let PackOptional =
|
let PackOptional =
|
||||||
"value ? *value : " # CXXName # "()";
|
"value ? *value : " # CXXName # "()";
|
||||||
let UnpackOptional =
|
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
|
/// Property types that correspond to integer types and support optional
|
||||||
@@ -67,7 +67,7 @@ class CountPropertyType<string typeName = ""> : PropertyType<typeName> {
|
|||||||
let PackOptional =
|
let PackOptional =
|
||||||
"value ? *value + 1 : 0";
|
"value ? *value + 1 : 0";
|
||||||
let UnpackOptional =
|
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; }
|
def APInt : PropertyType<"llvm::APInt"> { let PassByReference = 1; }
|
||||||
@@ -138,6 +138,7 @@ def TemplateArgument : PropertyType;
|
|||||||
def TemplateArgumentKind : EnumPropertyType<"TemplateArgument::ArgKind">;
|
def TemplateArgumentKind : EnumPropertyType<"TemplateArgument::ArgKind">;
|
||||||
def TemplateName : DefaultValuePropertyType;
|
def TemplateName : DefaultValuePropertyType;
|
||||||
def TemplateNameKind : EnumPropertyType<"TemplateName::NameKind">;
|
def TemplateNameKind : EnumPropertyType<"TemplateName::NameKind">;
|
||||||
|
def TypeOfKind : EnumPropertyType<"TypeOfKind">;
|
||||||
def UInt32 : CountPropertyType<"uint32_t">;
|
def UInt32 : CountPropertyType<"uint32_t">;
|
||||||
def UInt64 : CountPropertyType<"uint64_t">;
|
def UInt64 : CountPropertyType<"uint64_t">;
|
||||||
def UnaryTypeTransformKind : EnumPropertyType<"UnaryTransformType::UTTKind">;
|
def UnaryTypeTransformKind : EnumPropertyType<"UnaryTransformType::UTTKind">;
|
||||||
@@ -154,7 +155,7 @@ class Array<PropertyType element> : PropertyType {
|
|||||||
let BufferElementTypes = [ element ];
|
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.
|
/// corresponding C++ type of the element.
|
||||||
///
|
///
|
||||||
/// Optional<Unsigned> may restrict the range of the operand for some
|
/// Optional<Unsigned> may restrict the range of the operand for some
|
||||||
@@ -516,20 +517,16 @@ let Class = PropertyTypeCase<APValue, "LValue"> in {
|
|||||||
def : Creator<[{
|
def : Creator<[{
|
||||||
(void)ctx;
|
(void)ctx;
|
||||||
APValue::LValueBase base;
|
APValue::LValueBase base;
|
||||||
QualType elemTy;
|
|
||||||
if (hasBase) {
|
if (hasBase) {
|
||||||
if (isTypeInfo) {
|
if (isTypeInfo) {
|
||||||
base = APValue::LValueBase::getTypeInfo(
|
base = APValue::LValueBase::getTypeInfo(
|
||||||
TypeInfoLValue(typeInfo.value().getTypePtr()), type.value());
|
TypeInfoLValue(typeInfo->getTypePtr()), *type);
|
||||||
elemTy = base.getTypeInfoType();
|
|
||||||
} else if (isExpr) {
|
} else if (isExpr) {
|
||||||
base = APValue::LValueBase(cast<Expr>(stmt.value()),
|
base = APValue::LValueBase(cast<Expr>(*stmt),
|
||||||
callIndex.value(), version.value());
|
*callIndex, *version);
|
||||||
elemTy = base.get<const Expr *>()->getType();
|
|
||||||
} else {
|
} else {
|
||||||
base = APValue::LValueBase(cast<ValueDecl>(decl.value()),
|
base = APValue::LValueBase(cast<ValueDecl>(*decl),
|
||||||
callIndex.value(), version.value());
|
*callIndex, *version);
|
||||||
elemTy = base.get<const ValueDecl *>()->getType();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
CharUnits offset = CharUnits::fromQuantity(offsetQuantity);
|
CharUnits offset = CharUnits::fromQuantity(offsetQuantity);
|
||||||
@@ -542,7 +539,6 @@ let Class = PropertyTypeCase<APValue, "LValue"> in {
|
|||||||
auto pathLength = lvaluePath->Path.size();
|
auto pathLength = lvaluePath->Path.size();
|
||||||
APValue::LValuePathEntry *path = result.setLValueUninit(
|
APValue::LValuePathEntry *path = result.setLValueUninit(
|
||||||
base, offset, pathLength, isLValueOnePastTheEnd, isNullPtr).data();
|
base, offset, pathLength, isLValueOnePastTheEnd, isNullPtr).data();
|
||||||
assert(lvaluePath->getType() == elemTy && "Unexpected type reference!");
|
|
||||||
llvm::copy(lvaluePath->Path, path);
|
llvm::copy(lvaluePath->Path, path);
|
||||||
return result;
|
return result;
|
||||||
}]>;
|
}]>;
|
||||||
@@ -700,28 +696,40 @@ let Class = PropertyTypeCase<TemplateName, "SubstTemplateTemplateParm"> in {
|
|||||||
def : ReadHelper<[{
|
def : ReadHelper<[{
|
||||||
auto parm = node.getAsSubstTemplateTemplateParm();
|
auto parm = node.getAsSubstTemplateTemplateParm();
|
||||||
}]>;
|
}]>;
|
||||||
def : Property<"parameter", TemplateTemplateParmDeclRef> {
|
|
||||||
let Read = [{ parm->getParameter() }];
|
|
||||||
}
|
|
||||||
def : Property<"replacement", TemplateName> {
|
def : Property<"replacement", TemplateName> {
|
||||||
let Read = [{ parm->getReplacement() }];
|
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<[{
|
def : Creator<[{
|
||||||
return ctx.getSubstTemplateTemplateParm(parameter, replacement);
|
return ctx.getSubstTemplateTemplateParm(replacement, associatedDecl, index, packIndex);
|
||||||
}]>;
|
}]>;
|
||||||
}
|
}
|
||||||
let Class = PropertyTypeCase<TemplateName, "SubstTemplateTemplateParmPack"> in {
|
let Class = PropertyTypeCase<TemplateName, "SubstTemplateTemplateParmPack"> in {
|
||||||
def : ReadHelper<[{
|
def : ReadHelper<[{
|
||||||
auto parm = node.getAsSubstTemplateTemplateParmPack();
|
auto parm = node.getAsSubstTemplateTemplateParmPack();
|
||||||
}]>;
|
}]>;
|
||||||
def : Property<"parameterPack", TemplateTemplateParmDeclRef> {
|
|
||||||
let Read = [{ parm->getParameterPack() }];
|
|
||||||
}
|
|
||||||
def : Property<"argumentPack", TemplateArgument> {
|
def : Property<"argumentPack", TemplateArgument> {
|
||||||
let Read = [{ parm->getArgumentPack() }];
|
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<[{
|
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>> {
|
def : Property<"numExpansions", Optional<UInt32>> {
|
||||||
let Read = [{
|
let Read = [{
|
||||||
// Translate unsigned -> uint32_t just in case.
|
// Translate unsigned -> uint32_t just in case.
|
||||||
node.getNumTemplateExpansions().map(
|
llvm::transformOptional(node.getNumTemplateExpansions(),
|
||||||
[](unsigned i) { return uint32_t(i); })
|
[](unsigned i) { return uint32_t(i); })
|
||||||
}];
|
}];
|
||||||
}
|
}
|
||||||
def : Creator<[{
|
def : Creator<[{
|
||||||
auto numExpansionsUnsigned =
|
auto numExpansionsUnsigned = llvm::transformOptional(
|
||||||
numExpansions.map([](uint32_t i) { return unsigned(i); });
|
numExpansions, [](uint32_t i) { return unsigned(i); });
|
||||||
|
|
||||||
return TemplateArgument(name, numExpansionsUnsigned);
|
return TemplateArgument(name, numExpansionsUnsigned);
|
||||||
}]>;
|
}]>;
|
||||||
}
|
}
|
||||||
@@ -813,6 +822,6 @@ let Class = PropertyTypeCase<TemplateArgument, "Pack"> in {
|
|||||||
TemplateArgument *ctxElements = new (ctx) TemplateArgument[elements.size()];
|
TemplateArgument *ctxElements = new (ctx) TemplateArgument[elements.size()];
|
||||||
for (size_t i = 0, e = elements.size(); i != e; ++i)
|
for (size_t i = 0, e = elements.size(); i != e; ++i)
|
||||||
ctxElements[i] = elements[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...)>
|
struct has_same_member_pointer_type<R (T::*)(P...), R (U::*)(P...)>
|
||||||
: std::true_type {};
|
: 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
|
/// Returns true if and only if \p FirstMethodPtr and \p SecondMethodPtr
|
||||||
/// are pointers to the same non-static member function.
|
/// are pointers to the same non-static member function.
|
||||||
template <typename FirstMethodPtrTy, typename SecondMethodPtrTy>
|
template <typename FirstMethodPtrTy, typename SecondMethodPtrTy>
|
||||||
bool isSameMethod(FirstMethodPtrTy FirstMethodPtr,
|
LLVM_ATTRIBUTE_ALWAYS_INLINE LLVM_ATTRIBUTE_NODEBUG auto
|
||||||
SecondMethodPtrTy SecondMethodPtr) {
|
isSameMethod([[maybe_unused]] FirstMethodPtrTy FirstMethodPtr,
|
||||||
return is_same_method_impl<has_same_member_pointer_type<
|
[[maybe_unused]] SecondMethodPtrTy SecondMethodPtr)
|
||||||
FirstMethodPtrTy,
|
-> bool {
|
||||||
SecondMethodPtrTy>::value>::isSameMethod(FirstMethodPtr, SecondMethodPtr);
|
if constexpr (has_same_member_pointer_type<FirstMethodPtrTy,
|
||||||
|
SecondMethodPtrTy>::value)
|
||||||
|
return FirstMethodPtr == SecondMethodPtr;
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
} // end namespace detail
|
} // end namespace detail
|
||||||
@@ -289,8 +276,7 @@ template <typename Derived> class RecursiveASTVisitor {
|
|||||||
///
|
///
|
||||||
/// \returns false if the visitation was terminated early, true otherwise.
|
/// \returns false if the visitation was terminated early, true otherwise.
|
||||||
// FIXME: take a TemplateArgumentLoc* (or TemplateArgumentListInfo) instead.
|
// FIXME: take a TemplateArgumentLoc* (or TemplateArgumentListInfo) instead.
|
||||||
bool TraverseTemplateArguments(const TemplateArgument *Args,
|
bool TraverseTemplateArguments(ArrayRef<TemplateArgument> Args);
|
||||||
unsigned NumArgs);
|
|
||||||
|
|
||||||
/// Recursively visit a base specifier. This can be overridden by a
|
/// Recursively visit a base specifier. This can be overridden by a
|
||||||
/// subclass.
|
/// subclass.
|
||||||
@@ -614,7 +600,7 @@ bool RecursiveASTVisitor<Derived>::TraverseConceptExprRequirement(
|
|||||||
template <typename Derived>
|
template <typename Derived>
|
||||||
bool RecursiveASTVisitor<Derived>::TraverseConceptNestedRequirement(
|
bool RecursiveASTVisitor<Derived>::TraverseConceptNestedRequirement(
|
||||||
concepts::NestedRequirement *R) {
|
concepts::NestedRequirement *R) {
|
||||||
if (!R->isSubstitutionFailure())
|
if (!R->hasInvalidConstraint())
|
||||||
return getDerived().TraverseStmt(R->getConstraintExpr());
|
return getDerived().TraverseStmt(R->getConstraintExpr());
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@@ -886,8 +872,7 @@ bool RecursiveASTVisitor<Derived>::TraverseTemplateArgument(
|
|||||||
return getDerived().TraverseStmt(Arg.getAsExpr());
|
return getDerived().TraverseStmt(Arg.getAsExpr());
|
||||||
|
|
||||||
case TemplateArgument::Pack:
|
case TemplateArgument::Pack:
|
||||||
return getDerived().TraverseTemplateArguments(Arg.pack_begin(),
|
return getDerived().TraverseTemplateArguments(Arg.pack_elements());
|
||||||
Arg.pack_size());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
@@ -927,8 +912,7 @@ bool RecursiveASTVisitor<Derived>::TraverseTemplateArgumentLoc(
|
|||||||
return getDerived().TraverseStmt(ArgLoc.getSourceExpression());
|
return getDerived().TraverseStmt(ArgLoc.getSourceExpression());
|
||||||
|
|
||||||
case TemplateArgument::Pack:
|
case TemplateArgument::Pack:
|
||||||
return getDerived().TraverseTemplateArguments(Arg.pack_begin(),
|
return getDerived().TraverseTemplateArguments(Arg.pack_elements());
|
||||||
Arg.pack_size());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
@@ -936,10 +920,9 @@ bool RecursiveASTVisitor<Derived>::TraverseTemplateArgumentLoc(
|
|||||||
|
|
||||||
template <typename Derived>
|
template <typename Derived>
|
||||||
bool RecursiveASTVisitor<Derived>::TraverseTemplateArguments(
|
bool RecursiveASTVisitor<Derived>::TraverseTemplateArguments(
|
||||||
const TemplateArgument *Args, unsigned NumArgs) {
|
ArrayRef<TemplateArgument> Args) {
|
||||||
for (unsigned I = 0; I != NumArgs; ++I) {
|
for (const TemplateArgument &Arg : Args)
|
||||||
TRY_TO(TraverseTemplateArgument(Args[I]));
|
TRY_TO(TraverseTemplateArgument(Arg));
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@@ -1083,7 +1066,7 @@ DEF_TRAVERSE_TYPE(TypedefType, {})
|
|||||||
DEF_TRAVERSE_TYPE(TypeOfExprType,
|
DEF_TRAVERSE_TYPE(TypeOfExprType,
|
||||||
{ TRY_TO(TraverseStmt(T->getUnderlyingExpr())); })
|
{ 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,
|
DEF_TRAVERSE_TYPE(DecltypeType,
|
||||||
{ TRY_TO(TraverseStmt(T->getUnderlyingExpr())); })
|
{ TRY_TO(TraverseStmt(T->getUnderlyingExpr())); })
|
||||||
@@ -1096,7 +1079,7 @@ DEF_TRAVERSE_TYPE(UnaryTransformType, {
|
|||||||
DEF_TRAVERSE_TYPE(AutoType, {
|
DEF_TRAVERSE_TYPE(AutoType, {
|
||||||
TRY_TO(TraverseType(T->getDeducedType()));
|
TRY_TO(TraverseType(T->getDeducedType()));
|
||||||
if (T->isConstrained()) {
|
if (T->isConstrained()) {
|
||||||
TRY_TO(TraverseTemplateArguments(T->getArgs(), T->getNumArgs()));
|
TRY_TO(TraverseTemplateArguments(T->getTypeConstraintArguments()));
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
DEF_TRAVERSE_TYPE(DeducedTemplateSpecializationType, {
|
DEF_TRAVERSE_TYPE(DeducedTemplateSpecializationType, {
|
||||||
@@ -1116,7 +1099,7 @@ DEF_TRAVERSE_TYPE(SubstTemplateTypeParmPackType, {
|
|||||||
|
|
||||||
DEF_TRAVERSE_TYPE(TemplateSpecializationType, {
|
DEF_TRAVERSE_TYPE(TemplateSpecializationType, {
|
||||||
TRY_TO(TraverseTemplateName(T->getTemplateName()));
|
TRY_TO(TraverseTemplateName(T->getTemplateName()));
|
||||||
TRY_TO(TraverseTemplateArguments(T->getArgs(), T->getNumArgs()));
|
TRY_TO(TraverseTemplateArguments(T->template_arguments()));
|
||||||
})
|
})
|
||||||
|
|
||||||
DEF_TRAVERSE_TYPE(InjectedClassNameType, {})
|
DEF_TRAVERSE_TYPE(InjectedClassNameType, {})
|
||||||
@@ -1144,7 +1127,7 @@ DEF_TRAVERSE_TYPE(DependentNameType,
|
|||||||
|
|
||||||
DEF_TRAVERSE_TYPE(DependentTemplateSpecializationType, {
|
DEF_TRAVERSE_TYPE(DependentTemplateSpecializationType, {
|
||||||
TRY_TO(TraverseNestedNameSpecifier(T->getQualifier()));
|
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())); })
|
DEF_TRAVERSE_TYPE(PackExpansionType, { TRY_TO(TraverseType(T->getPattern())); })
|
||||||
@@ -1358,7 +1341,7 @@ DEF_TRAVERSE_TYPELOC(TypeOfExprType,
|
|||||||
{ TRY_TO(TraverseStmt(TL.getUnderlyingExpr())); })
|
{ TRY_TO(TraverseStmt(TL.getUnderlyingExpr())); })
|
||||||
|
|
||||||
DEF_TRAVERSE_TYPELOC(TypeOfType, {
|
DEF_TRAVERSE_TYPELOC(TypeOfType, {
|
||||||
TRY_TO(TraverseTypeLoc(TL.getUnderlyingTInfo()->getTypeLoc()));
|
TRY_TO(TraverseTypeLoc(TL.getUnmodifiedTInfo()->getTypeLoc()));
|
||||||
})
|
})
|
||||||
|
|
||||||
// FIXME: location of underlying expr
|
// FIXME: location of underlying expr
|
||||||
@@ -1551,6 +1534,8 @@ DEF_TRAVERSE_DECL(CapturedDecl, {
|
|||||||
|
|
||||||
DEF_TRAVERSE_DECL(EmptyDecl, {})
|
DEF_TRAVERSE_DECL(EmptyDecl, {})
|
||||||
|
|
||||||
|
DEF_TRAVERSE_DECL(HLSLBufferDecl, {})
|
||||||
|
|
||||||
DEF_TRAVERSE_DECL(LifetimeExtendedTemporaryDecl, {
|
DEF_TRAVERSE_DECL(LifetimeExtendedTemporaryDecl, {
|
||||||
TRY_TO(TraverseStmt(D->getTemporaryExpr()));
|
TRY_TO(TraverseStmt(D->getTemporaryExpr()));
|
||||||
})
|
})
|
||||||
@@ -1558,14 +1543,21 @@ DEF_TRAVERSE_DECL(LifetimeExtendedTemporaryDecl, {
|
|||||||
DEF_TRAVERSE_DECL(FileScopeAsmDecl,
|
DEF_TRAVERSE_DECL(FileScopeAsmDecl,
|
||||||
{ TRY_TO(TraverseStmt(D->getAsmString())); })
|
{ TRY_TO(TraverseStmt(D->getAsmString())); })
|
||||||
|
|
||||||
|
DEF_TRAVERSE_DECL(TopLevelStmtDecl, { TRY_TO(TraverseStmt(D->getStmt())); })
|
||||||
|
|
||||||
DEF_TRAVERSE_DECL(ImportDecl, {})
|
DEF_TRAVERSE_DECL(ImportDecl, {})
|
||||||
|
|
||||||
DEF_TRAVERSE_DECL(FriendDecl, {
|
DEF_TRAVERSE_DECL(FriendDecl, {
|
||||||
// Friend is either decl or a type.
|
// Friend is either decl or a type.
|
||||||
if (D->getFriendType())
|
if (D->getFriendType()) {
|
||||||
TRY_TO(TraverseTypeLoc(D->getFriendType()->getTypeLoc()));
|
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()));
|
TRY_TO(TraverseDecl(D->getFriendDecl()));
|
||||||
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
DEF_TRAVERSE_DECL(FriendTemplateDecl, {
|
DEF_TRAVERSE_DECL(FriendTemplateDecl, {
|
||||||
@@ -1730,7 +1722,8 @@ DEF_TRAVERSE_DECL(UsingDecl, {
|
|||||||
TRY_TO(TraverseDeclarationNameInfo(D->getNameInfo()));
|
TRY_TO(TraverseDeclarationNameInfo(D->getNameInfo()));
|
||||||
})
|
})
|
||||||
|
|
||||||
DEF_TRAVERSE_DECL(UsingEnumDecl, {})
|
DEF_TRAVERSE_DECL(UsingEnumDecl,
|
||||||
|
{ TRY_TO(TraverseTypeLoc(D->getEnumTypeLoc())); })
|
||||||
|
|
||||||
DEF_TRAVERSE_DECL(UsingPackDecl, {})
|
DEF_TRAVERSE_DECL(UsingPackDecl, {})
|
||||||
|
|
||||||
@@ -2309,6 +2302,10 @@ DEF_TRAVERSE_DECL(ParmVarDecl, {
|
|||||||
|
|
||||||
DEF_TRAVERSE_DECL(RequiresExprBodyDecl, {})
|
DEF_TRAVERSE_DECL(RequiresExprBodyDecl, {})
|
||||||
|
|
||||||
|
DEF_TRAVERSE_DECL(ImplicitConceptSpecializationDecl, {
|
||||||
|
TRY_TO(TraverseTemplateArguments(D->getTemplateArguments()));
|
||||||
|
})
|
||||||
|
|
||||||
#undef DEF_TRAVERSE_DECL
|
#undef DEF_TRAVERSE_DECL
|
||||||
|
|
||||||
// ----------------- Stmt traversal -----------------
|
// ----------------- Stmt traversal -----------------
|
||||||
@@ -2855,6 +2852,7 @@ DEF_TRAVERSE_STMT(SubstNonTypeTemplateParmExpr, {})
|
|||||||
DEF_TRAVERSE_STMT(FunctionParmPackExpr, {})
|
DEF_TRAVERSE_STMT(FunctionParmPackExpr, {})
|
||||||
DEF_TRAVERSE_STMT(CXXFoldExpr, {})
|
DEF_TRAVERSE_STMT(CXXFoldExpr, {})
|
||||||
DEF_TRAVERSE_STMT(AtomicExpr, {})
|
DEF_TRAVERSE_STMT(AtomicExpr, {})
|
||||||
|
DEF_TRAVERSE_STMT(CXXParenListInitExpr, {})
|
||||||
|
|
||||||
DEF_TRAVERSE_STMT(MaterializeTemporaryExpr, {
|
DEF_TRAVERSE_STMT(MaterializeTemporaryExpr, {
|
||||||
if (S->getLifetimeExtendedTemporaryDecl()) {
|
if (S->getLifetimeExtendedTemporaryDecl()) {
|
||||||
@@ -3158,6 +3156,10 @@ DEF_TRAVERSE_STMT(OMPParallelGenericLoopDirective,
|
|||||||
|
|
||||||
DEF_TRAVERSE_STMT(OMPTargetParallelGenericLoopDirective,
|
DEF_TRAVERSE_STMT(OMPTargetParallelGenericLoopDirective,
|
||||||
{ TRY_TO(TraverseOMPExecutableDirective(S)); })
|
{ TRY_TO(TraverseOMPExecutableDirective(S)); })
|
||||||
|
|
||||||
|
DEF_TRAVERSE_STMT(OMPErrorDirective,
|
||||||
|
{ TRY_TO(TraverseOMPExecutableDirective(S)); })
|
||||||
|
|
||||||
// OpenMP clauses.
|
// OpenMP clauses.
|
||||||
template <typename Derived>
|
template <typename Derived>
|
||||||
bool RecursiveASTVisitor<Derived>::TraverseOMPClause(OMPClause *C) {
|
bool RecursiveASTVisitor<Derived>::TraverseOMPClause(OMPClause *C) {
|
||||||
@@ -3311,6 +3313,22 @@ bool RecursiveASTVisitor<Derived>::VisitOMPAtomicDefaultMemOrderClause(
|
|||||||
return true;
|
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>
|
template <typename Derived>
|
||||||
bool
|
bool
|
||||||
RecursiveASTVisitor<Derived>::VisitOMPScheduleClause(OMPScheduleClause *C) {
|
RecursiveASTVisitor<Derived>::VisitOMPScheduleClause(OMPScheduleClause *C) {
|
||||||
@@ -3834,6 +3852,14 @@ bool RecursiveASTVisitor<Derived>::VisitOMPBindClause(OMPBindClause *C) {
|
|||||||
return true;
|
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
|
// FIXME: look at the following tricky-seeming exprs to see if we
|
||||||
// need to recurse on anything. These are ones that have methods
|
// need to recurse on anything. These are ones that have methods
|
||||||
// returning decls or qualtypes or nestednamespecifier -- though I'm
|
// returning decls or qualtypes or nestednamespecifier -- though I'm
|
||||||
|
|||||||
@@ -22,6 +22,7 @@
|
|||||||
#include "clang/Basic/LangOptions.h"
|
#include "clang/Basic/LangOptions.h"
|
||||||
#include "clang/Basic/SourceLocation.h"
|
#include "clang/Basic/SourceLocation.h"
|
||||||
#include "clang/Basic/Specifiers.h"
|
#include "clang/Basic/Specifiers.h"
|
||||||
|
#include "llvm/ADT/APFloat.h"
|
||||||
#include "llvm/ADT/ArrayRef.h"
|
#include "llvm/ADT/ArrayRef.h"
|
||||||
#include "llvm/ADT/BitmaskEnum.h"
|
#include "llvm/ADT/BitmaskEnum.h"
|
||||||
#include "llvm/ADT/PointerIntPair.h"
|
#include "llvm/ADT/PointerIntPair.h"
|
||||||
@@ -35,6 +36,7 @@
|
|||||||
#include <cassert>
|
#include <cassert>
|
||||||
#include <cstddef>
|
#include <cstddef>
|
||||||
#include <iterator>
|
#include <iterator>
|
||||||
|
#include <optional>
|
||||||
#include <string>
|
#include <string>
|
||||||
|
|
||||||
namespace llvm {
|
namespace llvm {
|
||||||
@@ -389,7 +391,10 @@ class alignas(void *) Stmt {
|
|||||||
|
|
||||||
unsigned : NumExprBits;
|
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;
|
unsigned IsExact : 1;
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -686,6 +691,9 @@ class alignas(void *) Stmt {
|
|||||||
|
|
||||||
unsigned : NumExprBits;
|
unsigned : NumExprBits;
|
||||||
|
|
||||||
|
/// Whether this CXXDefaultArgExpr rewrote its argument and stores a copy.
|
||||||
|
unsigned HasRewrittenInit : 1;
|
||||||
|
|
||||||
/// The location where the default argument expression was used.
|
/// The location where the default argument expression was used.
|
||||||
SourceLocation Loc;
|
SourceLocation Loc;
|
||||||
};
|
};
|
||||||
@@ -696,6 +704,10 @@ class alignas(void *) Stmt {
|
|||||||
|
|
||||||
unsigned : NumExprBits;
|
unsigned : NumExprBits;
|
||||||
|
|
||||||
|
/// Whether this CXXDefaultInitExprBitfields rewrote its argument and stores
|
||||||
|
/// a copy.
|
||||||
|
unsigned HasRewrittenInit : 1;
|
||||||
|
|
||||||
/// The location where the default initializer expression was used.
|
/// The location where the default initializer expression was used.
|
||||||
SourceLocation Loc;
|
SourceLocation Loc;
|
||||||
};
|
};
|
||||||
@@ -1912,7 +1924,7 @@ class AttributedStmt final
|
|||||||
|
|
||||||
SourceLocation getAttrLoc() const { return AttributedStmtBits.AttrLoc; }
|
SourceLocation getAttrLoc() const { return AttributedStmtBits.AttrLoc; }
|
||||||
ArrayRef<const Attr *> getAttrs() const {
|
ArrayRef<const Attr *> getAttrs() const {
|
||||||
return llvm::makeArrayRef(getAttrArrayPtr(), AttributedStmtBits.NumAttrs);
|
return llvm::ArrayRef(getAttrArrayPtr(), AttributedStmtBits.NumAttrs);
|
||||||
}
|
}
|
||||||
|
|
||||||
Stmt *getSubStmt() { return SubStmt; }
|
Stmt *getSubStmt() { return SubStmt; }
|
||||||
@@ -2136,9 +2148,9 @@ class IfStmt final
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// If this is an 'if constexpr', determine which substatement will be taken.
|
/// If this is an 'if constexpr', determine which substatement will be taken.
|
||||||
/// Otherwise, or if the condition is value-dependent, returns None.
|
/// Otherwise, or if the condition is value-dependent, returns std::nullopt.
|
||||||
Optional<const Stmt*> getNondiscardedCase(const ASTContext &Ctx) const;
|
std::optional<const Stmt *> getNondiscardedCase(const ASTContext &Ctx) const;
|
||||||
Optional<Stmt *> getNondiscardedCase(const ASTContext &Ctx);
|
std::optional<Stmt *> getNondiscardedCase(const ASTContext &Ctx);
|
||||||
|
|
||||||
bool isObjCAvailabilityCheck() const;
|
bool isObjCAvailabilityCheck() const;
|
||||||
|
|
||||||
@@ -3323,15 +3335,15 @@ class MSAsmStmt : public AsmStmt {
|
|||||||
//===--- Other ---===//
|
//===--- Other ---===//
|
||||||
|
|
||||||
ArrayRef<StringRef> getAllConstraints() const {
|
ArrayRef<StringRef> getAllConstraints() const {
|
||||||
return llvm::makeArrayRef(Constraints, NumInputs + NumOutputs);
|
return llvm::ArrayRef(Constraints, NumInputs + NumOutputs);
|
||||||
}
|
}
|
||||||
|
|
||||||
ArrayRef<StringRef> getClobbers() const {
|
ArrayRef<StringRef> getClobbers() const {
|
||||||
return llvm::makeArrayRef(Clobbers, NumClobbers);
|
return llvm::ArrayRef(Clobbers, NumClobbers);
|
||||||
}
|
}
|
||||||
|
|
||||||
ArrayRef<Expr*> getAllExprs() const {
|
ArrayRef<Expr*> getAllExprs() const {
|
||||||
return llvm::makeArrayRef(reinterpret_cast<Expr**>(Exprs),
|
return llvm::ArrayRef(reinterpret_cast<Expr **>(Exprs),
|
||||||
NumInputs + NumOutputs);
|
NumInputs + NumOutputs);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -277,7 +277,7 @@ class OMPExecutableDirective : public Stmt {
|
|||||||
/// Get the clauses storage.
|
/// Get the clauses storage.
|
||||||
MutableArrayRef<OMPClause *> getClauses() {
|
MutableArrayRef<OMPClause *> getClauses() {
|
||||||
if (!Data)
|
if (!Data)
|
||||||
return llvm::None;
|
return std::nullopt;
|
||||||
return Data->getClauses();
|
return Data->getClauses();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -399,8 +399,9 @@ class OMPExecutableDirective : public Stmt {
|
|||||||
|
|
||||||
static llvm::iterator_range<used_clauses_child_iterator>
|
static llvm::iterator_range<used_clauses_child_iterator>
|
||||||
used_clauses_children(ArrayRef<OMPClause *> Clauses) {
|
used_clauses_children(ArrayRef<OMPClause *> Clauses) {
|
||||||
return {used_clauses_child_iterator(Clauses),
|
return {
|
||||||
used_clauses_child_iterator(llvm::makeArrayRef(Clauses.end(), 0))};
|
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
|
/// Iterates over a filtered subrange of clauses applied to a
|
||||||
@@ -445,7 +446,7 @@ class OMPExecutableDirective : public Stmt {
|
|||||||
getClausesOfKind(ArrayRef<OMPClause *> Clauses) {
|
getClausesOfKind(ArrayRef<OMPClause *> Clauses) {
|
||||||
return {specific_clause_iterator<SpecificClause>(Clauses),
|
return {specific_clause_iterator<SpecificClause>(Clauses),
|
||||||
specific_clause_iterator<SpecificClause>(
|
specific_clause_iterator<SpecificClause>(
|
||||||
llvm::makeArrayRef(Clauses.end(), 0))};
|
llvm::ArrayRef(Clauses.end(), (size_t)0))};
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename SpecificClause>
|
template <typename SpecificClause>
|
||||||
@@ -571,7 +572,7 @@ class OMPExecutableDirective : public Stmt {
|
|||||||
|
|
||||||
ArrayRef<OMPClause *> clauses() const {
|
ArrayRef<OMPClause *> clauses() const {
|
||||||
if (!Data)
|
if (!Data)
|
||||||
return llvm::None;
|
return std::nullopt;
|
||||||
return Data->getClauses();
|
return Data->getClauses();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -980,7 +981,7 @@ class OMPLoopTransformationDirective : public OMPLoopBasedDirective {
|
|||||||
/// Return the number of loops generated by this loop transformation.
|
/// Return the number of loops generated by this loop transformation.
|
||||||
unsigned getNumGeneratedLoops() { return NumGeneratedLoops; }
|
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
|
/// Might be nullptr if either the directive generates no loops and is handled
|
||||||
/// directly in CodeGen, or resolving a template-dependence context is
|
/// directly in CodeGen, or resolving a template-dependence context is
|
||||||
@@ -1066,7 +1067,7 @@ class OMPLoopDirective : public OMPLoopBasedDirective {
|
|||||||
MutableArrayRef<Expr *> getCounters() {
|
MutableArrayRef<Expr *> getCounters() {
|
||||||
auto **Storage = reinterpret_cast<Expr **>(
|
auto **Storage = reinterpret_cast<Expr **>(
|
||||||
&Data->getChildren()[getArraysOffset(getDirectiveKind())]);
|
&Data->getChildren()[getArraysOffset(getDirectiveKind())]);
|
||||||
return llvm::makeMutableArrayRef(Storage, getLoopsNumber());
|
return llvm::MutableArrayRef(Storage, getLoopsNumber());
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Get the private counters storage.
|
/// Get the private counters storage.
|
||||||
@@ -1074,7 +1075,7 @@ class OMPLoopDirective : public OMPLoopBasedDirective {
|
|||||||
auto **Storage = reinterpret_cast<Expr **>(
|
auto **Storage = reinterpret_cast<Expr **>(
|
||||||
&Data->getChildren()[getArraysOffset(getDirectiveKind()) +
|
&Data->getChildren()[getArraysOffset(getDirectiveKind()) +
|
||||||
getLoopsNumber()]);
|
getLoopsNumber()]);
|
||||||
return llvm::makeMutableArrayRef(Storage, getLoopsNumber());
|
return llvm::MutableArrayRef(Storage, getLoopsNumber());
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Get the updates storage.
|
/// Get the updates storage.
|
||||||
@@ -1082,7 +1083,7 @@ class OMPLoopDirective : public OMPLoopBasedDirective {
|
|||||||
auto **Storage = reinterpret_cast<Expr **>(
|
auto **Storage = reinterpret_cast<Expr **>(
|
||||||
&Data->getChildren()[getArraysOffset(getDirectiveKind()) +
|
&Data->getChildren()[getArraysOffset(getDirectiveKind()) +
|
||||||
2 * getLoopsNumber()]);
|
2 * getLoopsNumber()]);
|
||||||
return llvm::makeMutableArrayRef(Storage, getLoopsNumber());
|
return llvm::MutableArrayRef(Storage, getLoopsNumber());
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Get the updates storage.
|
/// Get the updates storage.
|
||||||
@@ -1090,7 +1091,7 @@ class OMPLoopDirective : public OMPLoopBasedDirective {
|
|||||||
auto **Storage = reinterpret_cast<Expr **>(
|
auto **Storage = reinterpret_cast<Expr **>(
|
||||||
&Data->getChildren()[getArraysOffset(getDirectiveKind()) +
|
&Data->getChildren()[getArraysOffset(getDirectiveKind()) +
|
||||||
3 * getLoopsNumber()]);
|
3 * getLoopsNumber()]);
|
||||||
return llvm::makeMutableArrayRef(Storage, getLoopsNumber());
|
return llvm::MutableArrayRef(Storage, getLoopsNumber());
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Get the final counter updates storage.
|
/// Get the final counter updates storage.
|
||||||
@@ -1098,7 +1099,7 @@ class OMPLoopDirective : public OMPLoopBasedDirective {
|
|||||||
auto **Storage = reinterpret_cast<Expr **>(
|
auto **Storage = reinterpret_cast<Expr **>(
|
||||||
&Data->getChildren()[getArraysOffset(getDirectiveKind()) +
|
&Data->getChildren()[getArraysOffset(getDirectiveKind()) +
|
||||||
4 * getLoopsNumber()]);
|
4 * getLoopsNumber()]);
|
||||||
return llvm::makeMutableArrayRef(Storage, getLoopsNumber());
|
return llvm::MutableArrayRef(Storage, getLoopsNumber());
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Get the dependent counters storage.
|
/// Get the dependent counters storage.
|
||||||
@@ -1106,7 +1107,7 @@ class OMPLoopDirective : public OMPLoopBasedDirective {
|
|||||||
auto **Storage = reinterpret_cast<Expr **>(
|
auto **Storage = reinterpret_cast<Expr **>(
|
||||||
&Data->getChildren()[getArraysOffset(getDirectiveKind()) +
|
&Data->getChildren()[getArraysOffset(getDirectiveKind()) +
|
||||||
5 * getLoopsNumber()]);
|
5 * getLoopsNumber()]);
|
||||||
return llvm::makeMutableArrayRef(Storage, getLoopsNumber());
|
return llvm::MutableArrayRef(Storage, getLoopsNumber());
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Get the dependent inits storage.
|
/// Get the dependent inits storage.
|
||||||
@@ -1114,7 +1115,7 @@ class OMPLoopDirective : public OMPLoopBasedDirective {
|
|||||||
auto **Storage = reinterpret_cast<Expr **>(
|
auto **Storage = reinterpret_cast<Expr **>(
|
||||||
&Data->getChildren()[getArraysOffset(getDirectiveKind()) +
|
&Data->getChildren()[getArraysOffset(getDirectiveKind()) +
|
||||||
6 * getLoopsNumber()]);
|
6 * getLoopsNumber()]);
|
||||||
return llvm::makeMutableArrayRef(Storage, getLoopsNumber());
|
return llvm::MutableArrayRef(Storage, getLoopsNumber());
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Get the finals conditions storage.
|
/// Get the finals conditions storage.
|
||||||
@@ -1122,7 +1123,7 @@ class OMPLoopDirective : public OMPLoopBasedDirective {
|
|||||||
auto **Storage = reinterpret_cast<Expr **>(
|
auto **Storage = reinterpret_cast<Expr **>(
|
||||||
&Data->getChildren()[getArraysOffset(getDirectiveKind()) +
|
&Data->getChildren()[getArraysOffset(getDirectiveKind()) +
|
||||||
7 * getLoopsNumber()]);
|
7 * getLoopsNumber()]);
|
||||||
return llvm::makeMutableArrayRef(Storage, getLoopsNumber());
|
return llvm::MutableArrayRef(Storage, getLoopsNumber());
|
||||||
}
|
}
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
@@ -2873,7 +2874,7 @@ class OMPOrderedDirective : public OMPExecutableDirective {
|
|||||||
///
|
///
|
||||||
/// \param C AST context.
|
/// \param C AST context.
|
||||||
/// \param NumClauses Number of clauses.
|
/// \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,
|
static OMPOrderedDirective *CreateEmpty(const ASTContext &C,
|
||||||
unsigned NumClauses,
|
unsigned NumClauses,
|
||||||
@@ -6220,6 +6221,51 @@ class OMPTargetParallelGenericLoopDirective final : public OMPLoopDirective {
|
|||||||
return T->getStmtClass() == OMPTargetParallelGenericLoopDirectiveClass;
|
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
|
} // end namespace clang
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -23,14 +23,13 @@
|
|||||||
#include "llvm/ADT/APInt.h"
|
#include "llvm/ADT/APInt.h"
|
||||||
#include "llvm/ADT/APSInt.h"
|
#include "llvm/ADT/APSInt.h"
|
||||||
#include "llvm/ADT/ArrayRef.h"
|
#include "llvm/ADT/ArrayRef.h"
|
||||||
#include "llvm/ADT/None.h"
|
|
||||||
#include "llvm/ADT/Optional.h"
|
|
||||||
#include "llvm/ADT/SmallVector.h"
|
#include "llvm/ADT/SmallVector.h"
|
||||||
#include "llvm/Support/Compiler.h"
|
#include "llvm/Support/Compiler.h"
|
||||||
#include "llvm/Support/TrailingObjects.h"
|
#include "llvm/Support/TrailingObjects.h"
|
||||||
#include <cassert>
|
#include <cassert>
|
||||||
#include <cstddef>
|
#include <cstddef>
|
||||||
#include <cstdint>
|
#include <cstdint>
|
||||||
|
#include <optional>
|
||||||
|
|
||||||
namespace llvm {
|
namespace llvm {
|
||||||
|
|
||||||
@@ -202,7 +201,7 @@ class TemplateArgument {
|
|||||||
///
|
///
|
||||||
/// \param NumExpansions The number of expansions that will be generated by
|
/// \param NumExpansions The number of expansions that will be generated by
|
||||||
/// instantiating
|
/// instantiating
|
||||||
TemplateArgument(TemplateName Name, Optional<unsigned> NumExpansions) {
|
TemplateArgument(TemplateName Name, std::optional<unsigned> NumExpansions) {
|
||||||
TemplateArg.Kind = TemplateExpansion;
|
TemplateArg.Kind = TemplateExpansion;
|
||||||
TemplateArg.Name = Name.getAsVoidPointer();
|
TemplateArg.Name = Name.getAsVoidPointer();
|
||||||
if (NumExpansions)
|
if (NumExpansions)
|
||||||
@@ -233,7 +232,9 @@ class TemplateArgument {
|
|||||||
|
|
||||||
TemplateArgument(TemplateName, bool) = delete;
|
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
|
/// Create a new template argument pack by copying the given set of
|
||||||
/// template arguments.
|
/// template arguments.
|
||||||
@@ -305,7 +306,7 @@ class TemplateArgument {
|
|||||||
|
|
||||||
/// Retrieve the number of expansions that a template template argument
|
/// Retrieve the number of expansions that a template template argument
|
||||||
/// expansion will produce, if known.
|
/// expansion will produce, if known.
|
||||||
Optional<unsigned> getNumTemplateExpansions() const;
|
std::optional<unsigned> getNumTemplateExpansions() const;
|
||||||
|
|
||||||
/// Retrieve the template argument as an integral value.
|
/// Retrieve the template argument as an integral value.
|
||||||
// FIXME: Provide a way to read the integral data without copying the 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);
|
return APSInt(APInt(Integer.BitWidth, Integer.VAL), Integer.IsUnsigned);
|
||||||
|
|
||||||
unsigned NumWords = APInt::getNumWords(Integer.BitWidth);
|
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);
|
Integer.IsUnsigned);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -363,7 +364,7 @@ class TemplateArgument {
|
|||||||
/// Iterator range referencing all of the elements of a template
|
/// Iterator range referencing all of the elements of a template
|
||||||
/// argument pack.
|
/// argument pack.
|
||||||
ArrayRef<TemplateArgument> pack_elements() const {
|
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
|
/// 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.
|
/// Return the array of arguments in this template argument pack.
|
||||||
ArrayRef<TemplateArgument> getPackAsArray() const {
|
ArrayRef<TemplateArgument> getPackAsArray() const {
|
||||||
assert(getKind() == Pack);
|
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
|
/// Determines whether two template arguments are superficially the
|
||||||
@@ -641,7 +642,7 @@ struct ASTTemplateArgumentListInfo final
|
|||||||
unsigned getNumTemplateArgs() const { return NumTemplateArgs; }
|
unsigned getNumTemplateArgs() const { return NumTemplateArgs; }
|
||||||
|
|
||||||
llvm::ArrayRef<TemplateArgumentLoc> arguments() const {
|
llvm::ArrayRef<TemplateArgumentLoc> arguments() const {
|
||||||
return llvm::makeArrayRef(getTemplateArgs(), getNumTemplateArgs());
|
return llvm::ArrayRef(getTemplateArgs(), getNumTemplateArgs());
|
||||||
}
|
}
|
||||||
|
|
||||||
const TemplateArgumentLoc &operator[](unsigned I) const {
|
const TemplateArgumentLoc &operator[](unsigned I) const {
|
||||||
@@ -698,33 +699,6 @@ struct alignas(void *) ASTTemplateKWAndArgsInfo {
|
|||||||
const StreamingDiagnostic &operator<<(const StreamingDiagnostic &DB,
|
const StreamingDiagnostic &operator<<(const StreamingDiagnostic &DB,
|
||||||
const TemplateArgument &Arg);
|
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
|
} // namespace clang
|
||||||
|
|
||||||
#endif // LLVM_CLANG_AST_TEMPLATEBASE_H
|
#endif // LLVM_CLANG_AST_TEMPLATEBASE_H
|
||||||
|
|||||||
@@ -21,6 +21,7 @@
|
|||||||
#include "llvm/ADT/PointerUnion.h"
|
#include "llvm/ADT/PointerUnion.h"
|
||||||
#include "llvm/Support/PointerLikeTypeTraits.h"
|
#include "llvm/Support/PointerLikeTypeTraits.h"
|
||||||
#include <cassert>
|
#include <cassert>
|
||||||
|
#include <optional>
|
||||||
|
|
||||||
namespace clang {
|
namespace clang {
|
||||||
|
|
||||||
@@ -57,9 +58,12 @@ class UncommonTemplateNameStorage {
|
|||||||
/// A Kind.
|
/// A Kind.
|
||||||
unsigned Kind : 2;
|
unsigned Kind : 2;
|
||||||
|
|
||||||
/// The number of stored templates or template arguments,
|
// The template parameter index.
|
||||||
/// depending on which subclass we have.
|
unsigned Index : 15;
|
||||||
unsigned Size : 30;
|
|
||||||
|
/// The pack index, or the number of stored templates
|
||||||
|
/// or template arguments, depending on which subclass we have.
|
||||||
|
unsigned Data : 15;
|
||||||
};
|
};
|
||||||
|
|
||||||
union {
|
union {
|
||||||
@@ -67,14 +71,13 @@ class UncommonTemplateNameStorage {
|
|||||||
void *PointerAlignment;
|
void *PointerAlignment;
|
||||||
};
|
};
|
||||||
|
|
||||||
UncommonTemplateNameStorage(Kind kind, unsigned size) {
|
UncommonTemplateNameStorage(Kind Kind, unsigned Index, unsigned Data) {
|
||||||
Bits.Kind = kind;
|
Bits.Kind = Kind;
|
||||||
Bits.Size = size;
|
Bits.Index = Index;
|
||||||
|
Bits.Data = Data;
|
||||||
}
|
}
|
||||||
|
|
||||||
public:
|
public:
|
||||||
unsigned size() const { return Bits.Size; }
|
|
||||||
|
|
||||||
OverloadedTemplateStorage *getAsOverloadedStorage() {
|
OverloadedTemplateStorage *getAsOverloadedStorage() {
|
||||||
return Bits.Kind == Overloaded
|
return Bits.Kind == Overloaded
|
||||||
? reinterpret_cast<OverloadedTemplateStorage *>(this)
|
? reinterpret_cast<OverloadedTemplateStorage *>(this)
|
||||||
@@ -106,7 +109,7 @@ class OverloadedTemplateStorage : public UncommonTemplateNameStorage {
|
|||||||
friend class ASTContext;
|
friend class ASTContext;
|
||||||
|
|
||||||
OverloadedTemplateStorage(unsigned size)
|
OverloadedTemplateStorage(unsigned size)
|
||||||
: UncommonTemplateNameStorage(Overloaded, size) {}
|
: UncommonTemplateNameStorage(Overloaded, 0, size) {}
|
||||||
|
|
||||||
NamedDecl **getStorage() {
|
NamedDecl **getStorage() {
|
||||||
return reinterpret_cast<NamedDecl **>(this + 1);
|
return reinterpret_cast<NamedDecl **>(this + 1);
|
||||||
@@ -116,13 +119,15 @@ class OverloadedTemplateStorage : public UncommonTemplateNameStorage {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
unsigned size() const { return Bits.Data; }
|
||||||
|
|
||||||
using iterator = NamedDecl *const *;
|
using iterator = NamedDecl *const *;
|
||||||
|
|
||||||
iterator begin() const { return getStorage(); }
|
iterator begin() const { return getStorage(); }
|
||||||
iterator end() const { return getStorage() + size(); }
|
iterator end() const { return getStorage() + Bits.Data; }
|
||||||
|
|
||||||
llvm::ArrayRef<NamedDecl*> decls() const {
|
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
|
/// This kind of template names occurs when the parameter pack has been
|
||||||
/// provided with a template template argument pack in a context where its
|
/// provided with a template template argument pack in a context where its
|
||||||
/// enclosing pack expansion could not be fully expanded.
|
/// enclosing pack expansion could not be fully expanded.
|
||||||
class SubstTemplateTemplateParmPackStorage
|
class SubstTemplateTemplateParmPackStorage : public UncommonTemplateNameStorage,
|
||||||
: public UncommonTemplateNameStorage, public llvm::FoldingSetNode
|
public llvm::FoldingSetNode {
|
||||||
{
|
|
||||||
TemplateTemplateParmDecl *Parameter;
|
|
||||||
const TemplateArgument *Arguments;
|
const TemplateArgument *Arguments;
|
||||||
|
llvm::PointerIntPair<Decl *, 1, bool> AssociatedDeclAndFinal;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
SubstTemplateTemplateParmPackStorage(TemplateTemplateParmDecl *Parameter,
|
SubstTemplateTemplateParmPackStorage(ArrayRef<TemplateArgument> ArgPack,
|
||||||
unsigned Size,
|
Decl *AssociatedDecl, unsigned Index,
|
||||||
const TemplateArgument *Arguments)
|
bool Final);
|
||||||
: UncommonTemplateNameStorage(SubstTemplateTemplateParmPack, Size),
|
|
||||||
Parameter(Parameter), Arguments(Arguments) {}
|
/// 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.
|
/// Retrieve the template template parameter pack being substituted.
|
||||||
TemplateTemplateParmDecl *getParameterPack() const {
|
TemplateTemplateParmDecl *getParameterPack() const;
|
||||||
return Parameter;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Retrieve the template template argument pack with which this
|
/// Retrieve the template template argument pack with which this
|
||||||
/// parameter was substituted.
|
/// parameter was substituted.
|
||||||
@@ -156,10 +167,9 @@ class SubstTemplateTemplateParmPackStorage
|
|||||||
|
|
||||||
void Profile(llvm::FoldingSetNodeID &ID, ASTContext &Context);
|
void Profile(llvm::FoldingSetNodeID &ID, ASTContext &Context);
|
||||||
|
|
||||||
static void Profile(llvm::FoldingSetNodeID &ID,
|
static void Profile(llvm::FoldingSetNodeID &ID, ASTContext &Context,
|
||||||
ASTContext &Context,
|
const TemplateArgument &ArgPack, Decl *AssociatedDecl,
|
||||||
TemplateTemplateParmDecl *Parameter,
|
unsigned Index, bool Final);
|
||||||
const TemplateArgument &ArgPack);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/// Represents a C++ template name within the type system.
|
/// Represents a C++ template name within the type system.
|
||||||
@@ -365,23 +375,41 @@ class SubstTemplateTemplateParmStorage
|
|||||||
: public UncommonTemplateNameStorage, public llvm::FoldingSetNode {
|
: public UncommonTemplateNameStorage, public llvm::FoldingSetNode {
|
||||||
friend class ASTContext;
|
friend class ASTContext;
|
||||||
|
|
||||||
TemplateTemplateParmDecl *Parameter;
|
|
||||||
TemplateName Replacement;
|
TemplateName Replacement;
|
||||||
|
Decl *AssociatedDecl;
|
||||||
|
|
||||||
SubstTemplateTemplateParmStorage(TemplateTemplateParmDecl *parameter,
|
SubstTemplateTemplateParmStorage(TemplateName Replacement,
|
||||||
TemplateName replacement)
|
Decl *AssociatedDecl, unsigned Index,
|
||||||
: UncommonTemplateNameStorage(SubstTemplateTemplateParm, 0),
|
std::optional<unsigned> PackIndex)
|
||||||
Parameter(parameter), Replacement(replacement) {}
|
: UncommonTemplateNameStorage(SubstTemplateTemplateParm, Index,
|
||||||
|
PackIndex ? *PackIndex + 1 : 0),
|
||||||
|
Replacement(Replacement), AssociatedDecl(AssociatedDecl) {
|
||||||
|
assert(AssociatedDecl != nullptr);
|
||||||
|
}
|
||||||
|
|
||||||
public:
|
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; }
|
TemplateName getReplacement() const { return Replacement; }
|
||||||
|
|
||||||
void Profile(llvm::FoldingSetNodeID &ID);
|
void Profile(llvm::FoldingSetNodeID &ID);
|
||||||
|
|
||||||
static void Profile(llvm::FoldingSetNodeID &ID,
|
static void Profile(llvm::FoldingSetNodeID &ID, TemplateName Replacement,
|
||||||
TemplateTemplateParmDecl *parameter,
|
Decl *AssociatedDecl, unsigned Index,
|
||||||
TemplateName replacement);
|
std::optional<unsigned> PackIndex);
|
||||||
};
|
};
|
||||||
|
|
||||||
inline TemplateName TemplateName::getUnderlying() const {
|
inline TemplateName TemplateName::getUnderlying() const {
|
||||||
|
|||||||
@@ -317,6 +317,9 @@ class TextNodeDumper
|
|||||||
void VisitUnaryTransformType(const UnaryTransformType *T);
|
void VisitUnaryTransformType(const UnaryTransformType *T);
|
||||||
void VisitTagType(const TagType *T);
|
void VisitTagType(const TagType *T);
|
||||||
void VisitTemplateTypeParmType(const TemplateTypeParmType *T);
|
void VisitTemplateTypeParmType(const TemplateTypeParmType *T);
|
||||||
|
void VisitSubstTemplateTypeParmType(const SubstTemplateTypeParmType *T);
|
||||||
|
void
|
||||||
|
VisitSubstTemplateTypeParmPackType(const SubstTemplateTypeParmPackType *T);
|
||||||
void VisitAutoType(const AutoType *T);
|
void VisitAutoType(const AutoType *T);
|
||||||
void VisitDeducedTemplateSpecializationType(
|
void VisitDeducedTemplateSpecializationType(
|
||||||
const DeducedTemplateSpecializationType *T);
|
const DeducedTemplateSpecializationType *T);
|
||||||
@@ -380,6 +383,7 @@ class TextNodeDumper
|
|||||||
void VisitConceptDecl(const ConceptDecl *D);
|
void VisitConceptDecl(const ConceptDecl *D);
|
||||||
void
|
void
|
||||||
VisitLifetimeExtendedTemporaryDecl(const LifetimeExtendedTemporaryDecl *D);
|
VisitLifetimeExtendedTemporaryDecl(const LifetimeExtendedTemporaryDecl *D);
|
||||||
|
void VisitHLSLBufferDecl(const HLSLBufferDecl *D);
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace clang
|
} // namespace clang
|
||||||
|
|||||||
@@ -34,8 +34,6 @@
|
|||||||
#include "llvm/ADT/APSInt.h"
|
#include "llvm/ADT/APSInt.h"
|
||||||
#include "llvm/ADT/ArrayRef.h"
|
#include "llvm/ADT/ArrayRef.h"
|
||||||
#include "llvm/ADT/FoldingSet.h"
|
#include "llvm/ADT/FoldingSet.h"
|
||||||
#include "llvm/ADT/None.h"
|
|
||||||
#include "llvm/ADT/Optional.h"
|
|
||||||
#include "llvm/ADT/PointerIntPair.h"
|
#include "llvm/ADT/PointerIntPair.h"
|
||||||
#include "llvm/ADT/PointerUnion.h"
|
#include "llvm/ADT/PointerUnion.h"
|
||||||
#include "llvm/ADT/StringRef.h"
|
#include "llvm/ADT/StringRef.h"
|
||||||
@@ -51,6 +49,7 @@
|
|||||||
#include <cstddef>
|
#include <cstddef>
|
||||||
#include <cstdint>
|
#include <cstdint>
|
||||||
#include <cstring>
|
#include <cstring>
|
||||||
|
#include <optional>
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <type_traits>
|
#include <type_traits>
|
||||||
#include <utility>
|
#include <utility>
|
||||||
@@ -714,6 +713,12 @@ enum class ObjCSubstitutionContext {
|
|||||||
Superclass,
|
Superclass,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/// The kind of 'typeof' expression we're after.
|
||||||
|
enum class TypeOfKind : uint8_t {
|
||||||
|
Qualified,
|
||||||
|
Unqualified,
|
||||||
|
};
|
||||||
|
|
||||||
/// A (possibly-)qualified type.
|
/// A (possibly-)qualified type.
|
||||||
///
|
///
|
||||||
/// For efficiency, we don't store CV-qualified types as nodes on their
|
/// 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(); }
|
unsigned getLocalFastQualifiers() const { return Value.getInt(); }
|
||||||
void setLocalFastQualifiers(unsigned Quals) { Value.setInt(Quals); }
|
void setLocalFastQualifiers(unsigned Quals) { Value.setInt(Quals); }
|
||||||
|
|
||||||
|
bool UseExcessPrecision(const ASTContext &Ctx);
|
||||||
|
|
||||||
/// Retrieves a pointer to the underlying (unqualified) type.
|
/// Retrieves a pointer to the underlying (unqualified) type.
|
||||||
///
|
///
|
||||||
/// This function requires that the type not be NULL. If the type might be
|
/// This function requires that the type not be NULL. If the type might be
|
||||||
@@ -797,6 +804,9 @@ class QualType {
|
|||||||
return Value.getPointer().isNull();
|
return Value.getPointer().isNull();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Determines if a type can form `T&`.
|
||||||
|
bool isReferenceable() const;
|
||||||
|
|
||||||
/// Determine whether this particular QualType instance has the
|
/// Determine whether this particular QualType instance has the
|
||||||
/// "const" qualifier set, without looking through typedefs that may have
|
/// "const" qualifier set, without looking through typedefs that may have
|
||||||
/// added "const" at a different level.
|
/// added "const" at a different level.
|
||||||
@@ -1790,19 +1800,63 @@ class alignas(8) Type : public ExtQualsTypeCommonBase {
|
|||||||
unsigned NumArgs;
|
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 {
|
class SubstTemplateTypeParmPackTypeBitfields {
|
||||||
friend class SubstTemplateTypeParmPackType;
|
friend class SubstTemplateTypeParmPackType;
|
||||||
|
|
||||||
unsigned : NumTypeBits;
|
unsigned : NumTypeBits;
|
||||||
|
|
||||||
|
// The index of the template parameter this substitution represents.
|
||||||
|
unsigned Index : 16;
|
||||||
|
|
||||||
/// The number of template arguments in \c Arguments, which is
|
/// The number of template arguments in \c Arguments, which is
|
||||||
/// expected to be able to hold at least 1024 according to [implimits].
|
/// expected to be able to hold at least 1024 according to [implimits].
|
||||||
/// However as this limit is somewhat easy to hit with template
|
/// However as this limit is somewhat easy to hit with template
|
||||||
/// metaprogramming we'd prefer to keep it as large as possible.
|
/// 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
|
unsigned NumArgs : 16;
|
||||||
/// safely fits in 64 bits as an unsigned, so there is no reason to
|
|
||||||
/// introduce the performance impact of a bitfield.
|
|
||||||
unsigned NumArgs;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
class TemplateSpecializationTypeBitfields {
|
class TemplateSpecializationTypeBitfields {
|
||||||
@@ -1864,6 +1918,9 @@ class alignas(8) Type : public ExtQualsTypeCommonBase {
|
|||||||
ConstantArrayTypeBitfields ConstantArrayTypeBits;
|
ConstantArrayTypeBitfields ConstantArrayTypeBits;
|
||||||
AttributedTypeBitfields AttributedTypeBits;
|
AttributedTypeBitfields AttributedTypeBits;
|
||||||
AutoTypeBitfields AutoTypeBits;
|
AutoTypeBitfields AutoTypeBits;
|
||||||
|
TypeOfBitfields TypeOfBits;
|
||||||
|
TypedefBitfields TypedefBits;
|
||||||
|
UsingBitfields UsingBits;
|
||||||
BuiltinTypeBitfields BuiltinTypeBits;
|
BuiltinTypeBitfields BuiltinTypeBits;
|
||||||
FunctionTypeBitfields FunctionTypeBits;
|
FunctionTypeBitfields FunctionTypeBits;
|
||||||
ObjCObjectTypeBitfields ObjCObjectTypeBits;
|
ObjCObjectTypeBitfields ObjCObjectTypeBits;
|
||||||
@@ -1871,6 +1928,7 @@ class alignas(8) Type : public ExtQualsTypeCommonBase {
|
|||||||
TypeWithKeywordBitfields TypeWithKeywordBits;
|
TypeWithKeywordBitfields TypeWithKeywordBits;
|
||||||
ElaboratedTypeBitfields ElaboratedTypeBits;
|
ElaboratedTypeBitfields ElaboratedTypeBits;
|
||||||
VectorTypeBitfields VectorTypeBits;
|
VectorTypeBitfields VectorTypeBits;
|
||||||
|
SubstTemplateTypeParmTypeBitfields SubstTemplateTypeParmTypeBits;
|
||||||
SubstTemplateTypeParmPackTypeBitfields SubstTemplateTypeParmPackTypeBits;
|
SubstTemplateTypeParmPackTypeBitfields SubstTemplateTypeParmPackTypeBits;
|
||||||
TemplateSpecializationTypeBitfields TemplateSpecializationTypeBits;
|
TemplateSpecializationTypeBitfields TemplateSpecializationTypeBits;
|
||||||
DependentTemplateSpecializationTypeBitfields
|
DependentTemplateSpecializationTypeBitfields
|
||||||
@@ -1968,6 +2026,9 @@ class alignas(8) Type : public ExtQualsTypeCommonBase {
|
|||||||
bool isSizelessType() const;
|
bool isSizelessType() const;
|
||||||
bool isSizelessBuiltinType() const;
|
bool isSizelessBuiltinType() const;
|
||||||
|
|
||||||
|
/// Returns true for SVE scalable vector types.
|
||||||
|
bool isSVESizelessBuiltinType() const;
|
||||||
|
|
||||||
/// Determines if this is a sizeless type supported by the
|
/// Determines if this is a sizeless type supported by the
|
||||||
/// 'arm_sve_vector_bits' type attribute, which can be applied to a single
|
/// 'arm_sve_vector_bits' type attribute, which can be applied to a single
|
||||||
/// SVE vector or predicate, excluding tuple types such as svint32x4_t.
|
/// 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 isObjCARCBridgableType() const;
|
||||||
bool isCARCBridgableType() const;
|
bool isCARCBridgableType() const;
|
||||||
bool isTemplateTypeParmType() const; // C++ template type parameter
|
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 isNothrowT() const; // C++ std::nothrow_t
|
||||||
bool isAlignValT() const; // C++17 std::align_val_t
|
bool isAlignValT() const; // C++17 std::align_val_t
|
||||||
bool isStdByteType() const; // C++17 std::byte
|
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.
|
/// Check if the type is the CUDA device builtin texture type.
|
||||||
bool isCUDADeviceBuiltinTextureType() const;
|
bool isCUDADeviceBuiltinTextureType() const;
|
||||||
|
|
||||||
|
bool isRVVType() const;
|
||||||
|
|
||||||
/// Return the implicit lifetime for this type, which must not be dependent.
|
/// Return the implicit lifetime for this type, which must not be dependent.
|
||||||
Qualifiers::ObjCLifetime getObjCARCImplicitLifetime() const;
|
Qualifiers::ObjCLifetime getObjCARCImplicitLifetime() const;
|
||||||
|
|
||||||
@@ -2413,9 +2477,6 @@ class alignas(8) Type : public ExtQualsTypeCommonBase {
|
|||||||
/// removing any typedefs, typeofs, etc., as well as any qualifiers.
|
/// removing any typedefs, typeofs, etc., as well as any qualifiers.
|
||||||
const Type *getUnqualifiedDesugaredType() const;
|
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
|
/// Return true if this is an integer type that is
|
||||||
/// signed, according to C99 6.2.5p4 [char, signed char, short, int, long..],
|
/// signed, according to C99 6.2.5p4 [char, signed char, short, int, long..],
|
||||||
/// or an enum decl which has a signed representation.
|
/// 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
|
/// Note that nullability is only captured as sugar within the type
|
||||||
/// system, not as part of the canonical type, so nullability will
|
/// system, not as part of the canonical type, so nullability will
|
||||||
/// be lost by canonicalization and desugaring.
|
/// 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
|
/// Determine whether the given type can have a nullability
|
||||||
/// specifier applied to it, i.e., if it is any kind of pointer type.
|
/// 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
|
/// the type parameters of the given declaration context in any type described
|
||||||
/// within that context, or an empty optional to indicate that no
|
/// within that context, or an empty optional to indicate that no
|
||||||
/// substitution is required.
|
/// substitution is required.
|
||||||
Optional<ArrayRef<QualType>>
|
std::optional<ArrayRef<QualType>>
|
||||||
getObjCSubstitutions(const DeclContext *dc) const;
|
getObjCSubstitutions(const DeclContext *dc) const;
|
||||||
|
|
||||||
/// Determines if this is an ObjC interface type that may accept type
|
/// 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
|
/// This will check for a TypedefType by removing any existing sugar
|
||||||
/// until it reaches a TypedefType or a non-sugared type.
|
/// until it reaches a TypedefType or a non-sugared type.
|
||||||
template <> const TypedefType *Type::getAs() const;
|
template <> const TypedefType *Type::getAs() const;
|
||||||
|
template <> const UsingType *Type::getAs() const;
|
||||||
|
|
||||||
/// This will check for a TemplateSpecializationType by removing any
|
/// This will check for a TemplateSpecializationType by removing any
|
||||||
/// existing sugar until it reaches a TemplateSpecializationType or a
|
/// existing sugar until it reaches a TemplateSpecializationType or a
|
||||||
@@ -3873,7 +3935,10 @@ class FunctionType : public Type {
|
|||||||
}
|
}
|
||||||
|
|
||||||
Qualifiers getFastTypeQuals() const {
|
Qualifiers getFastTypeQuals() const {
|
||||||
|
if (isFunctionProtoType())
|
||||||
return Qualifiers::fromFastMask(FunctionTypeBits.FastTypeQuals);
|
return Qualifiers::fromFastMask(FunctionTypeBits.FastTypeQuals);
|
||||||
|
|
||||||
|
return Qualifiers();
|
||||||
}
|
}
|
||||||
|
|
||||||
public:
|
public:
|
||||||
@@ -4172,7 +4237,7 @@ class FunctionProtoType final
|
|||||||
}
|
}
|
||||||
|
|
||||||
ArrayRef<QualType> getParamTypes() const {
|
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 {
|
ExtProtoInfo getExtProtoInfo() const {
|
||||||
@@ -4317,10 +4382,9 @@ class FunctionProtoType final
|
|||||||
}
|
}
|
||||||
|
|
||||||
using param_type_iterator = const QualType *;
|
using param_type_iterator = const QualType *;
|
||||||
using param_type_range = llvm::iterator_range<param_type_iterator>;
|
|
||||||
|
|
||||||
param_type_range param_types() const {
|
ArrayRef<QualType> param_types() const {
|
||||||
return param_type_range(param_type_begin(), param_type_end());
|
return llvm::ArrayRef(param_type_begin(), param_type_end());
|
||||||
}
|
}
|
||||||
|
|
||||||
param_type_iterator param_type_begin() const {
|
param_type_iterator param_type_begin() const {
|
||||||
@@ -4334,7 +4398,7 @@ class FunctionProtoType final
|
|||||||
using exception_iterator = const QualType *;
|
using exception_iterator = const QualType *;
|
||||||
|
|
||||||
ArrayRef<QualType> exceptions() const {
|
ArrayRef<QualType> exceptions() const {
|
||||||
return llvm::makeArrayRef(exception_begin(), exception_end());
|
return llvm::ArrayRef(exception_begin(), exception_end());
|
||||||
}
|
}
|
||||||
|
|
||||||
exception_iterator exception_begin() const {
|
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;
|
UsingShadowDecl *Found;
|
||||||
friend class ASTContext; // ASTContext creates these.
|
friend class ASTContext; // ASTContext creates these.
|
||||||
|
friend TrailingObjects;
|
||||||
|
|
||||||
UsingType(const UsingShadowDecl *Found, QualType Underlying, QualType Canon);
|
UsingType(const UsingShadowDecl *Found, QualType Underlying, QualType Canon);
|
||||||
|
|
||||||
@@ -4451,21 +4518,31 @@ class UsingType : public Type, public llvm::FoldingSetNode {
|
|||||||
QualType getUnderlyingType() const;
|
QualType getUnderlyingType() const;
|
||||||
|
|
||||||
bool isSugared() const { return true; }
|
bool isSugared() const { return true; }
|
||||||
|
|
||||||
|
// This always has the 'same' type as declared, but not necessarily identical.
|
||||||
QualType desugar() const { return getUnderlyingType(); }
|
QualType desugar() const { return getUnderlyingType(); }
|
||||||
|
|
||||||
void Profile(llvm::FoldingSetNodeID &ID) { Profile(ID, Found); }
|
// Internal helper, for debugging purposes.
|
||||||
static void Profile(llvm::FoldingSetNodeID &ID,
|
bool typeMatchesDecl() const { return !UsingBits.hasTypeDifferentFromDecl; }
|
||||||
const UsingShadowDecl *Found) {
|
|
||||||
|
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);
|
ID.AddPointer(Found);
|
||||||
|
if (!Underlying.isNull())
|
||||||
|
Underlying.Profile(ID);
|
||||||
}
|
}
|
||||||
static bool classof(const Type *T) { return T->getTypeClass() == Using; }
|
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;
|
TypedefNameDecl *Decl;
|
||||||
|
|
||||||
private:
|
|
||||||
friend class ASTContext; // ASTContext creates these.
|
friend class ASTContext; // ASTContext creates these.
|
||||||
|
friend TrailingObjects;
|
||||||
|
|
||||||
TypedefType(TypeClass tc, const TypedefNameDecl *D, QualType underlying,
|
TypedefType(TypeClass tc, const TypedefNameDecl *D, QualType underlying,
|
||||||
QualType can);
|
QualType can);
|
||||||
@@ -4474,8 +4551,23 @@ class TypedefType : public Type {
|
|||||||
TypedefNameDecl *getDecl() const { return Decl; }
|
TypedefNameDecl *getDecl() const { return Decl; }
|
||||||
|
|
||||||
bool isSugared() const { return true; }
|
bool isSugared() const { return true; }
|
||||||
|
|
||||||
|
// This always has the 'same' type as declared, but not necessarily identical.
|
||||||
QualType desugar() const;
|
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; }
|
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 {
|
class TypeOfExprType : public Type {
|
||||||
Expr *TOExpr;
|
Expr *TOExpr;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
friend class ASTContext; // ASTContext creates these.
|
friend class ASTContext; // ASTContext creates these.
|
||||||
|
|
||||||
TypeOfExprType(Expr *E, QualType can = QualType());
|
TypeOfExprType(Expr *E, TypeOfKind Kind, QualType Can = QualType());
|
||||||
|
|
||||||
public:
|
public:
|
||||||
Expr *getUnderlyingExpr() const { return TOExpr; }
|
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.
|
/// Remove a single level of sugar.
|
||||||
QualType desugar() const;
|
QualType desugar() const;
|
||||||
|
|
||||||
@@ -4543,37 +4642,52 @@ class DependentTypeOfExprType
|
|||||||
const ASTContext &Context;
|
const ASTContext &Context;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
DependentTypeOfExprType(const ASTContext &Context, Expr *E)
|
DependentTypeOfExprType(const ASTContext &Context, Expr *E, TypeOfKind Kind)
|
||||||
: TypeOfExprType(E), Context(Context) {}
|
: TypeOfExprType(E, Kind), Context(Context) {}
|
||||||
|
|
||||||
void Profile(llvm::FoldingSetNodeID &ID) {
|
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,
|
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 {
|
class TypeOfType : public Type {
|
||||||
friend class ASTContext; // ASTContext creates these.
|
friend class ASTContext; // ASTContext creates these.
|
||||||
|
|
||||||
QualType TOType;
|
QualType TOType;
|
||||||
|
|
||||||
TypeOfType(QualType T, QualType can)
|
TypeOfType(QualType T, QualType Can, TypeOfKind Kind)
|
||||||
: Type(TypeOf, can, T->getDependence()), TOType(T) {
|
: Type(TypeOf,
|
||||||
assert(!isa<TypedefType>(can) && "Invalid canonical type");
|
Kind == TypeOfKind::Unqualified ? Can.getAtomicUnqualifiedType()
|
||||||
|
: Can,
|
||||||
|
T->getDependence()),
|
||||||
|
TOType(T) {
|
||||||
|
TypeOfBits.IsUnqual = Kind == TypeOfKind::Unqualified;
|
||||||
}
|
}
|
||||||
|
|
||||||
public:
|
public:
|
||||||
QualType getUnderlyingType() const { return TOType; }
|
QualType getUnmodifiedType() const { return TOType; }
|
||||||
|
|
||||||
/// Remove a single level of sugar.
|
/// 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.
|
/// Returns whether this type directly provides sugar.
|
||||||
bool isSugared() const { return true; }
|
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; }
|
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 {
|
class UnaryTransformType : public Type {
|
||||||
public:
|
public:
|
||||||
enum UTTKind {
|
enum UTTKind {
|
||||||
EnumUnderlyingType
|
#define TRANSFORM_TYPE_TRAIT_DEF(Enum, _) Enum,
|
||||||
|
#include "clang/Basic/TransformTypeTraits.def"
|
||||||
};
|
};
|
||||||
|
|
||||||
private:
|
private:
|
||||||
@@ -4807,7 +4922,7 @@ class AttributedType : public Type, public llvm::FoldingSetNode {
|
|||||||
|
|
||||||
bool isCallingConv() const;
|
bool isCallingConv() const;
|
||||||
|
|
||||||
llvm::Optional<NullabilityKind> getImmediateNullability() const;
|
std::optional<NullabilityKind> getImmediateNullability() const;
|
||||||
|
|
||||||
/// Retrieve the attribute kind corresponding to the given
|
/// Retrieve the attribute kind corresponding to the given
|
||||||
/// nullability kind.
|
/// nullability kind.
|
||||||
@@ -4837,7 +4952,7 @@ class AttributedType : public Type, public llvm::FoldingSetNode {
|
|||||||
/// to the underlying modified type.
|
/// to the underlying modified type.
|
||||||
///
|
///
|
||||||
/// \returns the top-level nullability, if present.
|
/// \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) {
|
void Profile(llvm::FoldingSetNodeID &ID) {
|
||||||
Profile(ID, getAttrKind(), ModifiedType, EquivalentType);
|
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
|
/// been replaced with these. They are used solely to record that a
|
||||||
/// type was originally written as a template type parameter;
|
/// type was originally written as a template type parameter;
|
||||||
/// therefore they are never canonical.
|
/// 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 ASTContext;
|
||||||
|
friend class llvm::TrailingObjects<SubstTemplateTypeParmType, QualType>;
|
||||||
|
|
||||||
// The original type parameter.
|
Decl *AssociatedDecl;
|
||||||
const TemplateTypeParmType *Replaced;
|
|
||||||
|
|
||||||
SubstTemplateTypeParmType(const TemplateTypeParmType *Param, QualType Canon)
|
SubstTemplateTypeParmType(QualType Replacement, Decl *AssociatedDecl,
|
||||||
: Type(SubstTemplateTypeParm, Canon, Canon->getDependence()),
|
unsigned Index, std::optional<unsigned> PackIndex);
|
||||||
Replaced(Param) {}
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
/// Gets the template parameter that was substituted for.
|
|
||||||
const TemplateTypeParmType *getReplacedParameter() const {
|
|
||||||
return Replaced;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Gets the type that was substituted for the template
|
/// Gets the type that was substituted for the template
|
||||||
/// parameter.
|
/// parameter.
|
||||||
QualType getReplacementType() const {
|
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; }
|
bool isSugared() const { return true; }
|
||||||
QualType desugar() const { return getReplacementType(); }
|
QualType desugar() const { return getReplacementType(); }
|
||||||
|
|
||||||
void Profile(llvm::FoldingSetNodeID &ID) {
|
void Profile(llvm::FoldingSetNodeID &ID) {
|
||||||
Profile(ID, getReplacedParameter(), getReplacementType());
|
Profile(ID, getReplacementType(), getAssociatedDecl(), getIndex(),
|
||||||
|
getPackIndex());
|
||||||
}
|
}
|
||||||
|
|
||||||
static void Profile(llvm::FoldingSetNodeID &ID,
|
static void Profile(llvm::FoldingSetNodeID &ID, QualType Replacement,
|
||||||
const TemplateTypeParmType *Replaced,
|
const Decl *AssociatedDecl, unsigned Index,
|
||||||
QualType Replacement) {
|
std::optional<unsigned> PackIndex) {
|
||||||
ID.AddPointer(Replaced);
|
Replacement.Profile(ID);
|
||||||
ID.AddPointer(Replacement.getAsOpaquePtr());
|
ID.AddPointer(AssociatedDecl);
|
||||||
|
ID.AddInteger(Index);
|
||||||
|
ID.AddInteger(PackIndex ? *PackIndex - 1 : 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool classof(const Type *T) {
|
static bool classof(const Type *T) {
|
||||||
@@ -5024,24 +5159,33 @@ class SubstTemplateTypeParmType : public Type, public llvm::FoldingSetNode {
|
|||||||
class SubstTemplateTypeParmPackType : public Type, public llvm::FoldingSetNode {
|
class SubstTemplateTypeParmPackType : public Type, public llvm::FoldingSetNode {
|
||||||
friend class ASTContext;
|
friend class ASTContext;
|
||||||
|
|
||||||
/// The original type parameter.
|
|
||||||
const TemplateTypeParmType *Replaced;
|
|
||||||
|
|
||||||
/// A pointer to the set of template arguments that this
|
/// A pointer to the set of template arguments that this
|
||||||
/// parameter pack is instantiated with.
|
/// parameter pack is instantiated with.
|
||||||
const TemplateArgument *Arguments;
|
const TemplateArgument *Arguments;
|
||||||
|
|
||||||
SubstTemplateTypeParmPackType(const TemplateTypeParmType *Param,
|
llvm::PointerIntPair<Decl *, 1, bool> AssociatedDeclAndFinal;
|
||||||
QualType Canon,
|
|
||||||
|
SubstTemplateTypeParmPackType(QualType Canon, Decl *AssociatedDecl,
|
||||||
|
unsigned Index, bool Final,
|
||||||
const TemplateArgument &ArgPack);
|
const TemplateArgument &ArgPack);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
IdentifierInfo *getIdentifier() const { return Replaced->getIdentifier(); }
|
IdentifierInfo *getIdentifier() const;
|
||||||
|
|
||||||
/// Gets the template parameter that was substituted for.
|
/// A template-like entity which owns the whole pattern being substituted.
|
||||||
const TemplateTypeParmType *getReplacedParameter() const {
|
/// This will usually own a set of template parameters, or in some
|
||||||
return Replaced;
|
/// 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 {
|
unsigned getNumArgs() const {
|
||||||
return SubstTemplateTypeParmPackTypeBits.NumArgs;
|
return SubstTemplateTypeParmPackTypeBits.NumArgs;
|
||||||
@@ -5053,8 +5197,8 @@ class SubstTemplateTypeParmPackType : public Type, public llvm::FoldingSetNode {
|
|||||||
TemplateArgument getArgumentPack() const;
|
TemplateArgument getArgumentPack() const;
|
||||||
|
|
||||||
void Profile(llvm::FoldingSetNodeID &ID);
|
void Profile(llvm::FoldingSetNodeID &ID);
|
||||||
static void Profile(llvm::FoldingSetNodeID &ID,
|
static void Profile(llvm::FoldingSetNodeID &ID, const Decl *AssociatedDecl,
|
||||||
const TemplateTypeParmType *Replaced,
|
unsigned Index, bool Final,
|
||||||
const TemplateArgument &ArgPack);
|
const TemplateArgument &ArgPack);
|
||||||
|
|
||||||
static bool classof(const Type *T) {
|
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,
|
TypeDependence ExtraDependence, QualType Canon, ConceptDecl *CD,
|
||||||
ArrayRef<TemplateArgument> TypeConstraintArgs);
|
ArrayRef<TemplateArgument> TypeConstraintArgs);
|
||||||
|
|
||||||
const TemplateArgument *getArgBuffer() const {
|
|
||||||
return reinterpret_cast<const TemplateArgument*>(this+1);
|
|
||||||
}
|
|
||||||
|
|
||||||
TemplateArgument *getArgBuffer() {
|
|
||||||
return reinterpret_cast<TemplateArgument*>(this+1);
|
|
||||||
}
|
|
||||||
|
|
||||||
public:
|
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 {
|
ArrayRef<TemplateArgument> getTypeConstraintArguments() const {
|
||||||
return {getArgs(), getNumArgs()};
|
return {reinterpret_cast<const TemplateArgument *>(this + 1),
|
||||||
|
AutoTypeBits.NumArgs};
|
||||||
}
|
}
|
||||||
|
|
||||||
ConceptDecl *getTypeConstraintConcept() const {
|
ConceptDecl *getTypeConstraintConcept() const {
|
||||||
@@ -5158,11 +5283,7 @@ class alignas(8) AutoType : public DeducedType, public llvm::FoldingSetNode {
|
|||||||
return (AutoTypeKeyword)AutoTypeBits.Keyword;
|
return (AutoTypeKeyword)AutoTypeBits.Keyword;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Profile(llvm::FoldingSetNodeID &ID, const ASTContext &Context) {
|
void Profile(llvm::FoldingSetNodeID &ID, const ASTContext &Context);
|
||||||
Profile(ID, Context, getDeducedType(), getKeyword(), isDependentType(),
|
|
||||||
getTypeConstraintConcept(), getTypeConstraintArguments());
|
|
||||||
}
|
|
||||||
|
|
||||||
static void Profile(llvm::FoldingSetNodeID &ID, const ASTContext &Context,
|
static void Profile(llvm::FoldingSetNodeID &ID, const ASTContext &Context,
|
||||||
QualType Deduced, AutoTypeKeyword Keyword,
|
QualType Deduced, AutoTypeKeyword Keyword,
|
||||||
bool IsDependent, ConceptDecl *CD,
|
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
|
/// Get the aliased type, if this is a specialization of a type alias
|
||||||
/// template.
|
/// template.
|
||||||
QualType getAliasedType() const {
|
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
|
|
||||||
|
|
||||||
/// Retrieve the name of the template that we are specializing.
|
/// Retrieve the name of the template that we are specializing.
|
||||||
TemplateName getTemplateName() const { return Template; }
|
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 {
|
ArrayRef<TemplateArgument> template_arguments() const {
|
||||||
return {getArgs(), getNumArgs()};
|
return {reinterpret_cast<const TemplateArgument *>(this + 1),
|
||||||
|
TemplateSpecializationTypeBits.NumArgs};
|
||||||
}
|
}
|
||||||
|
|
||||||
bool isSugared() const {
|
bool isSugared() const {
|
||||||
@@ -5339,12 +5439,7 @@ class alignas(8) TemplateSpecializationType
|
|||||||
return isTypeAlias() ? getAliasedType() : getCanonicalTypeInternal();
|
return isTypeAlias() ? getAliasedType() : getCanonicalTypeInternal();
|
||||||
}
|
}
|
||||||
|
|
||||||
void Profile(llvm::FoldingSetNodeID &ID, const ASTContext &Ctx) {
|
void Profile(llvm::FoldingSetNodeID &ID, const ASTContext &Ctx);
|
||||||
Profile(ID, Template, template_arguments(), Ctx);
|
|
||||||
if (isTypeAlias())
|
|
||||||
getAliasedType().Profile(ID);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void Profile(llvm::FoldingSetNodeID &ID, TemplateName T,
|
static void Profile(llvm::FoldingSetNodeID &ID, TemplateName T,
|
||||||
ArrayRef<TemplateArgument> Args,
|
ArrayRef<TemplateArgument> Args,
|
||||||
const ASTContext &Context);
|
const ASTContext &Context);
|
||||||
@@ -5371,6 +5466,13 @@ void printTemplateArgumentList(raw_ostream &OS,
|
|||||||
const PrintingPolicy &Policy,
|
const PrintingPolicy &Policy,
|
||||||
const TemplateParameterList *TPL = nullptr);
|
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
|
/// The injected class name of a C++ class template or class
|
||||||
/// template partial specialization. Used to record that a type was
|
/// template partial specialization. Used to record that a type was
|
||||||
/// spelled with a bare identifier rather than as a template-id; the
|
/// spelled with a bare identifier rather than as a template-id; the
|
||||||
@@ -5569,9 +5671,6 @@ class ElaboratedType final
|
|||||||
ElaboratedTypeBits.HasOwnedTagDecl = true;
|
ElaboratedTypeBits.HasOwnedTagDecl = true;
|
||||||
*getTrailingObjects<TagDecl *>() = OwnedTagDecl;
|
*getTrailingObjects<TagDecl *>() = OwnedTagDecl;
|
||||||
}
|
}
|
||||||
assert(!(Keyword == ETK_None && NNS == nullptr) &&
|
|
||||||
"ElaboratedType cannot have elaborated type keyword "
|
|
||||||
"and name qualifier both null.");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public:
|
public:
|
||||||
@@ -5690,44 +5789,20 @@ class alignas(8) DependentTemplateSpecializationType
|
|||||||
ArrayRef<TemplateArgument> Args,
|
ArrayRef<TemplateArgument> Args,
|
||||||
QualType Canon);
|
QualType Canon);
|
||||||
|
|
||||||
const TemplateArgument *getArgBuffer() const {
|
|
||||||
return reinterpret_cast<const TemplateArgument*>(this+1);
|
|
||||||
}
|
|
||||||
|
|
||||||
TemplateArgument *getArgBuffer() {
|
|
||||||
return reinterpret_cast<TemplateArgument*>(this+1);
|
|
||||||
}
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
NestedNameSpecifier *getQualifier() const { return NNS; }
|
NestedNameSpecifier *getQualifier() const { return NNS; }
|
||||||
const IdentifierInfo *getIdentifier() const { return Name; }
|
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 {
|
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; }
|
bool isSugared() const { return false; }
|
||||||
QualType desugar() const { return QualType(this, 0); }
|
QualType desugar() const { return QualType(this, 0); }
|
||||||
|
|
||||||
void Profile(llvm::FoldingSetNodeID &ID, const ASTContext &Context) {
|
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,
|
static void Profile(llvm::FoldingSetNodeID &ID,
|
||||||
@@ -5771,7 +5846,7 @@ class PackExpansionType : public Type, public llvm::FoldingSetNode {
|
|||||||
QualType Pattern;
|
QualType Pattern;
|
||||||
|
|
||||||
PackExpansionType(QualType Pattern, QualType Canon,
|
PackExpansionType(QualType Pattern, QualType Canon,
|
||||||
Optional<unsigned> NumExpansions)
|
std::optional<unsigned> NumExpansions)
|
||||||
: Type(PackExpansion, Canon,
|
: Type(PackExpansion, Canon,
|
||||||
(Pattern->getDependence() | TypeDependence::Dependent |
|
(Pattern->getDependence() | TypeDependence::Dependent |
|
||||||
TypeDependence::Instantiation) &
|
TypeDependence::Instantiation) &
|
||||||
@@ -5789,10 +5864,10 @@ class PackExpansionType : public Type, public llvm::FoldingSetNode {
|
|||||||
|
|
||||||
/// Retrieve the number of expansions that this pack expansion will
|
/// Retrieve the number of expansions that this pack expansion will
|
||||||
/// generate, if known.
|
/// generate, if known.
|
||||||
Optional<unsigned> getNumExpansions() const {
|
std::optional<unsigned> getNumExpansions() const {
|
||||||
if (PackExpansionTypeBits.NumExpansions)
|
if (PackExpansionTypeBits.NumExpansions)
|
||||||
return PackExpansionTypeBits.NumExpansions - 1;
|
return PackExpansionTypeBits.NumExpansions - 1;
|
||||||
return None;
|
return std::nullopt;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool isSugared() const { return false; }
|
bool isSugared() const { return false; }
|
||||||
@@ -5803,7 +5878,7 @@ class PackExpansionType : public Type, public llvm::FoldingSetNode {
|
|||||||
}
|
}
|
||||||
|
|
||||||
static void Profile(llvm::FoldingSetNodeID &ID, QualType Pattern,
|
static void Profile(llvm::FoldingSetNodeID &ID, QualType Pattern,
|
||||||
Optional<unsigned> NumExpansions) {
|
std::optional<unsigned> NumExpansions) {
|
||||||
ID.AddPointer(Pattern.getAsOpaquePtr());
|
ID.AddPointer(Pattern.getAsOpaquePtr());
|
||||||
ID.AddBoolean(NumExpansions.has_value());
|
ID.AddBoolean(NumExpansions.has_value());
|
||||||
if (NumExpansions)
|
if (NumExpansions)
|
||||||
@@ -6060,8 +6135,7 @@ class ObjCObjectType : public Type,
|
|||||||
/// Retrieve the type arguments of this object type as they were
|
/// Retrieve the type arguments of this object type as they were
|
||||||
/// written.
|
/// written.
|
||||||
ArrayRef<QualType> getTypeArgsAsWritten() const {
|
ArrayRef<QualType> getTypeArgsAsWritten() const {
|
||||||
return llvm::makeArrayRef(getTypeArgStorage(),
|
return llvm::ArrayRef(getTypeArgStorage(), ObjCObjectTypeBits.NumTypeArgs);
|
||||||
ObjCObjectTypeBits.NumTypeArgs);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Whether this is a "__kindof" type as written.
|
/// Whether this is a "__kindof" type as written.
|
||||||
@@ -6564,6 +6638,19 @@ inline const Type *QualType::getTypePtrOrNull() const {
|
|||||||
return (isNull() ? nullptr : getCommonPtr()->BaseType);
|
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 {
|
inline SplitQualType QualType::split() const {
|
||||||
if (!hasLocalNonFastQualifiers())
|
if (!hasLocalNonFastQualifiers())
|
||||||
return SplitQualType(getTypePtrUnsafe(),
|
return SplitQualType(getTypePtrUnsafe(),
|
||||||
@@ -7058,6 +7145,14 @@ inline bool Type::isOpenCLSpecificType() const {
|
|||||||
isQueueT() || isReserveIDT() || isPipeType() || isOCLExtOpaqueType();
|
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 {
|
inline bool Type::isTemplateTypeParmType() const {
|
||||||
return isa<TemplateTypeParmType>(CanonicalType);
|
return isa<TemplateTypeParmType>(CanonicalType);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -430,7 +430,7 @@ class ConcreteTypeLoc : public Base {
|
|||||||
unsigned size = sizeof(LocalData);
|
unsigned size = sizeof(LocalData);
|
||||||
unsigned extraAlign = asDerived()->getExtraLocalDataAlignment();
|
unsigned extraAlign = asDerived()->getExtraLocalDataAlignment();
|
||||||
size = llvm::alignTo(size, extraAlign);
|
size = llvm::alignTo(size, extraAlign);
|
||||||
return reinterpret_cast<char*>(Base::Data) + size;
|
return reinterpret_cast<char *>(Base::Data) + size;
|
||||||
}
|
}
|
||||||
|
|
||||||
void *getNonLocalData() const {
|
void *getNonLocalData() const {
|
||||||
@@ -814,7 +814,7 @@ class ObjCTypeParamTypeLoc : public ConcreteTypeLoc<UnqualTypeLoc,
|
|||||||
}
|
}
|
||||||
|
|
||||||
ArrayRef<SourceLocation> getProtocolLocs() const {
|
ArrayRef<SourceLocation> getProtocolLocs() const {
|
||||||
return llvm::makeArrayRef(getProtocolLocArray(), getNumProtocols());
|
return llvm::ArrayRef(getProtocolLocArray(), getNumProtocols());
|
||||||
}
|
}
|
||||||
|
|
||||||
void initializeLocal(ASTContext &Context, SourceLocation Loc);
|
void initializeLocal(ASTContext &Context, SourceLocation Loc);
|
||||||
@@ -1020,7 +1020,7 @@ class ObjCObjectTypeLoc : public ConcreteTypeLoc<UnqualTypeLoc,
|
|||||||
|
|
||||||
|
|
||||||
ArrayRef<SourceLocation> getProtocolLocs() const {
|
ArrayRef<SourceLocation> getProtocolLocs() const {
|
||||||
return llvm::makeArrayRef(getProtocolLocArray(), getNumProtocols());
|
return llvm::ArrayRef(getProtocolLocArray(), getNumProtocols());
|
||||||
}
|
}
|
||||||
|
|
||||||
bool hasBaseTypeAsWritten() const {
|
bool hasBaseTypeAsWritten() const {
|
||||||
@@ -1447,7 +1447,7 @@ class FunctionTypeLoc : public ConcreteTypeLoc<UnqualTypeLoc,
|
|||||||
}
|
}
|
||||||
|
|
||||||
ArrayRef<ParmVarDecl *> getParams() const {
|
ArrayRef<ParmVarDecl *> getParams() const {
|
||||||
return llvm::makeArrayRef(getParmArray(), getNumParams());
|
return llvm::ArrayRef(getParmArray(), getNumParams());
|
||||||
}
|
}
|
||||||
|
|
||||||
// ParmVarDecls* are stored after Info, one for each parameter.
|
// ParmVarDecls* are stored after Info, one for each parameter.
|
||||||
@@ -1634,7 +1634,7 @@ class TemplateSpecializationTypeLoc :
|
|||||||
}
|
}
|
||||||
|
|
||||||
unsigned getNumArgs() const {
|
unsigned getNumArgs() const {
|
||||||
return getTypePtr()->getNumArgs();
|
return getTypePtr()->template_arguments().size();
|
||||||
}
|
}
|
||||||
|
|
||||||
void setArgLocInfo(unsigned i, TemplateArgumentLocInfo AI) {
|
void setArgLocInfo(unsigned i, TemplateArgumentLocInfo AI) {
|
||||||
@@ -1646,7 +1646,8 @@ class TemplateSpecializationTypeLoc :
|
|||||||
}
|
}
|
||||||
|
|
||||||
TemplateArgumentLoc getArgLoc(unsigned i) const {
|
TemplateArgumentLoc getArgLoc(unsigned i) const {
|
||||||
return TemplateArgumentLoc(getTypePtr()->getArg(i), getArgLocInfo(i));
|
return TemplateArgumentLoc(getTypePtr()->template_arguments()[i],
|
||||||
|
getArgLocInfo(i));
|
||||||
}
|
}
|
||||||
|
|
||||||
SourceLocation getTemplateNameLoc() const {
|
SourceLocation getTemplateNameLoc() const {
|
||||||
@@ -1681,12 +1682,12 @@ class TemplateSpecializationTypeLoc :
|
|||||||
setTemplateNameLoc(Loc);
|
setTemplateNameLoc(Loc);
|
||||||
setLAngleLoc(Loc);
|
setLAngleLoc(Loc);
|
||||||
setRAngleLoc(Loc);
|
setRAngleLoc(Loc);
|
||||||
initializeArgLocs(Context, getNumArgs(), getTypePtr()->getArgs(),
|
initializeArgLocs(Context, getTypePtr()->template_arguments(),
|
||||||
getArgInfos(), Loc);
|
getArgInfos(), Loc);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void initializeArgLocs(ASTContext &Context, unsigned NumArgs,
|
static void initializeArgLocs(ASTContext &Context,
|
||||||
const TemplateArgument *Args,
|
ArrayRef<TemplateArgument> Args,
|
||||||
TemplateArgumentLocInfo *ArgInfos,
|
TemplateArgumentLocInfo *ArgInfos,
|
||||||
SourceLocation Loc);
|
SourceLocation Loc);
|
||||||
|
|
||||||
@@ -1934,7 +1935,7 @@ struct TypeOfExprTypeLocInfo : public TypeofLocInfo {
|
|||||||
};
|
};
|
||||||
|
|
||||||
struct TypeOfTypeLocInfo : public TypeofLocInfo {
|
struct TypeOfTypeLocInfo : public TypeofLocInfo {
|
||||||
TypeSourceInfo* UnderlyingTInfo;
|
TypeSourceInfo *UnmodifiedTInfo;
|
||||||
};
|
};
|
||||||
|
|
||||||
template <class Derived, class TypeClass, class LocalData = TypeofLocInfo>
|
template <class Derived, class TypeClass, class LocalData = TypeofLocInfo>
|
||||||
@@ -2002,16 +2003,16 @@ class TypeOfExprTypeLoc : public TypeofLikeTypeLoc<TypeOfExprTypeLoc,
|
|||||||
class TypeOfTypeLoc
|
class TypeOfTypeLoc
|
||||||
: public TypeofLikeTypeLoc<TypeOfTypeLoc, TypeOfType, TypeOfTypeLocInfo> {
|
: public TypeofLikeTypeLoc<TypeOfTypeLoc, TypeOfType, TypeOfTypeLocInfo> {
|
||||||
public:
|
public:
|
||||||
QualType getUnderlyingType() const {
|
QualType getUnmodifiedType() const {
|
||||||
return this->getTypePtr()->getUnderlyingType();
|
return this->getTypePtr()->getUnmodifiedType();
|
||||||
}
|
}
|
||||||
|
|
||||||
TypeSourceInfo* getUnderlyingTInfo() const {
|
TypeSourceInfo *getUnmodifiedTInfo() const {
|
||||||
return this->getLocalData()->UnderlyingTInfo;
|
return this->getLocalData()->UnmodifiedTInfo;
|
||||||
}
|
}
|
||||||
|
|
||||||
void setUnderlyingTInfo(TypeSourceInfo* TI) const {
|
void setUnmodifiedTInfo(TypeSourceInfo *TI) const {
|
||||||
this->getLocalData()->UnderlyingTInfo = TI;
|
this->getLocalData()->UnmodifiedTInfo = TI;
|
||||||
}
|
}
|
||||||
|
|
||||||
void initializeLocal(ASTContext &Context, SourceLocation Loc);
|
void initializeLocal(ASTContext &Context, SourceLocation Loc);
|
||||||
@@ -2188,7 +2189,7 @@ class AutoTypeLoc
|
|||||||
}
|
}
|
||||||
|
|
||||||
unsigned getNumArgs() const {
|
unsigned getNumArgs() const {
|
||||||
return getTypePtr()->getNumArgs();
|
return getTypePtr()->getTypeConstraintArguments().size();
|
||||||
}
|
}
|
||||||
|
|
||||||
void setArgLocInfo(unsigned i, TemplateArgumentLocInfo AI) {
|
void setArgLocInfo(unsigned i, TemplateArgumentLocInfo AI) {
|
||||||
@@ -2263,22 +2264,31 @@ class ElaboratedTypeLoc : public ConcreteTypeLoc<UnqualTypeLoc,
|
|||||||
ElaboratedLocInfo> {
|
ElaboratedLocInfo> {
|
||||||
public:
|
public:
|
||||||
SourceLocation getElaboratedKeywordLoc() const {
|
SourceLocation getElaboratedKeywordLoc() const {
|
||||||
return this->getLocalData()->ElaboratedKWLoc;
|
return !isEmpty() ? getLocalData()->ElaboratedKWLoc : SourceLocation();
|
||||||
}
|
}
|
||||||
|
|
||||||
void setElaboratedKeywordLoc(SourceLocation Loc) {
|
void setElaboratedKeywordLoc(SourceLocation Loc) {
|
||||||
this->getLocalData()->ElaboratedKWLoc = Loc;
|
if (isEmpty()) {
|
||||||
|
assert(Loc.isInvalid());
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
getLocalData()->ElaboratedKWLoc = Loc;
|
||||||
}
|
}
|
||||||
|
|
||||||
NestedNameSpecifierLoc getQualifierLoc() const {
|
NestedNameSpecifierLoc getQualifierLoc() const {
|
||||||
return NestedNameSpecifierLoc(getTypePtr()->getQualifier(),
|
return !isEmpty() ? NestedNameSpecifierLoc(getTypePtr()->getQualifier(),
|
||||||
getLocalData()->QualifierData);
|
getLocalData()->QualifierData)
|
||||||
|
: NestedNameSpecifierLoc();
|
||||||
}
|
}
|
||||||
|
|
||||||
void setQualifierLoc(NestedNameSpecifierLoc QualifierLoc) {
|
void setQualifierLoc(NestedNameSpecifierLoc QualifierLoc) {
|
||||||
assert(QualifierLoc.getNestedNameSpecifier()
|
assert(QualifierLoc.getNestedNameSpecifier() ==
|
||||||
== getTypePtr()->getQualifier() &&
|
getTypePtr()->getQualifier() &&
|
||||||
"Inconsistent nested-name-specifier pointer");
|
"Inconsistent nested-name-specifier pointer");
|
||||||
|
if (isEmpty()) {
|
||||||
|
assert(!QualifierLoc.hasQualifier());
|
||||||
|
return;
|
||||||
|
}
|
||||||
getLocalData()->QualifierData = QualifierLoc.getOpaqueData();
|
getLocalData()->QualifierData = QualifierLoc.getOpaqueData();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2295,12 +2305,24 @@ class ElaboratedTypeLoc : public ConcreteTypeLoc<UnqualTypeLoc,
|
|||||||
|
|
||||||
void initializeLocal(ASTContext &Context, SourceLocation Loc);
|
void initializeLocal(ASTContext &Context, SourceLocation Loc);
|
||||||
|
|
||||||
TypeLoc getNamedTypeLoc() const {
|
TypeLoc getNamedTypeLoc() const { return getInnerTypeLoc(); }
|
||||||
return getInnerTypeLoc();
|
|
||||||
|
QualType getInnerType() const { return getTypePtr()->getNamedType(); }
|
||||||
|
|
||||||
|
bool isEmpty() const {
|
||||||
|
return getTypePtr()->getKeyword() == ElaboratedTypeKeyword::ETK_None &&
|
||||||
|
!getTypePtr()->getQualifier();
|
||||||
}
|
}
|
||||||
|
|
||||||
QualType getInnerType() const {
|
unsigned getLocalDataAlignment() const {
|
||||||
return getTypePtr()->getNamedType();
|
// 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) {
|
void copy(ElaboratedTypeLoc Loc) {
|
||||||
@@ -2443,7 +2465,7 @@ class DependentTemplateSpecializationTypeLoc :
|
|||||||
}
|
}
|
||||||
|
|
||||||
unsigned getNumArgs() const {
|
unsigned getNumArgs() const {
|
||||||
return getTypePtr()->getNumArgs();
|
return getTypePtr()->template_arguments().size();
|
||||||
}
|
}
|
||||||
|
|
||||||
void setArgLocInfo(unsigned i, TemplateArgumentLocInfo AI) {
|
void setArgLocInfo(unsigned i, TemplateArgumentLocInfo AI) {
|
||||||
@@ -2455,7 +2477,8 @@ class DependentTemplateSpecializationTypeLoc :
|
|||||||
}
|
}
|
||||||
|
|
||||||
TemplateArgumentLoc getArgLoc(unsigned i) const {
|
TemplateArgumentLoc getArgLoc(unsigned i) const {
|
||||||
return TemplateArgumentLoc(getTypePtr()->getArg(i), getArgLocInfo(i));
|
return TemplateArgumentLoc(getTypePtr()->template_arguments()[i],
|
||||||
|
getArgLocInfo(i));
|
||||||
}
|
}
|
||||||
|
|
||||||
SourceRange getLocalSourceRange() const {
|
SourceRange getLocalSourceRange() const {
|
||||||
|
|||||||
@@ -379,16 +379,12 @@ let Class = TypedefType in {
|
|||||||
def : Property<"declaration", DeclRef> {
|
def : Property<"declaration", DeclRef> {
|
||||||
let Read = [{ node->getDecl() }];
|
let Read = [{ node->getDecl() }];
|
||||||
}
|
}
|
||||||
def : Property<"canonicalType", Optional<QualType>> {
|
def : Property<"underlyingType", QualType> {
|
||||||
let Read = [{ makeOptionalFromNullable(node->getCanonicalTypeInternal()) }];
|
let Read = [{ node->desugar() }];
|
||||||
}
|
}
|
||||||
|
|
||||||
def : Creator<[{
|
def : Creator<[{
|
||||||
QualType finalCanonicalType =
|
return ctx.getTypedefType(cast<TypedefNameDecl>(declaration), underlyingType);
|
||||||
canonicalType ? ctx.getCanonicalType(*canonicalType)
|
|
||||||
: QualType();
|
|
||||||
return ctx.getTypedefType(cast<TypedefNameDecl>(declaration),
|
|
||||||
finalCanonicalType);
|
|
||||||
}]>;
|
}]>;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -397,18 +393,26 @@ let Class = TypeOfExprType in {
|
|||||||
let Read = [{ node->getUnderlyingExpr() }];
|
let Read = [{ node->getUnderlyingExpr() }];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
def : Property<"kind", TypeOfKind> {
|
||||||
|
let Read = [{ node->getKind() }];
|
||||||
|
}
|
||||||
|
|
||||||
def : Creator<[{
|
def : Creator<[{
|
||||||
return ctx.getTypeOfExprType(expression);
|
return ctx.getTypeOfExprType(expression, kind);
|
||||||
}]>;
|
}]>;
|
||||||
}
|
}
|
||||||
|
|
||||||
let Class = TypeOfType in {
|
let Class = TypeOfType in {
|
||||||
def : Property<"underlyingType", QualType> {
|
def : Property<"unmodifiedType", QualType> {
|
||||||
let Read = [{ node->getUnderlyingType() }];
|
let Read = [{ node->getUnmodifiedType() }];
|
||||||
|
}
|
||||||
|
|
||||||
|
def : Property<"kind", TypeOfKind> {
|
||||||
|
let Read = [{ node->getKind() }];
|
||||||
}
|
}
|
||||||
|
|
||||||
def : Creator<[{
|
def : Creator<[{
|
||||||
return ctx.getTypeOfType(underlyingType);
|
return ctx.getTypeOfType(unmodifiedType, kind);
|
||||||
}]>;
|
}]>;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -662,10 +666,10 @@ let Class = TemplateSpecializationType in {
|
|||||||
def : Property<"underlyingType", Optional<QualType>> {
|
def : Property<"underlyingType", Optional<QualType>> {
|
||||||
let Read = [{
|
let Read = [{
|
||||||
node->isTypeAlias()
|
node->isTypeAlias()
|
||||||
? llvm::Optional<QualType>(node->getAliasedType())
|
? std::optional<QualType>(node->getAliasedType())
|
||||||
: node->isCanonicalUnqualified()
|
: node->isCanonicalUnqualified()
|
||||||
? llvm::None
|
? std::nullopt
|
||||||
: llvm::Optional<QualType>(node->getCanonicalTypeInternal())
|
: std::optional<QualType>(node->getCanonicalTypeInternal())
|
||||||
}];
|
}];
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -728,18 +732,23 @@ let Class = TemplateTypeParmType in {
|
|||||||
}
|
}
|
||||||
|
|
||||||
let Class = SubstTemplateTypeParmType in {
|
let Class = SubstTemplateTypeParmType in {
|
||||||
def : Property<"replacedParameter", QualType> {
|
|
||||||
let Read = [{ QualType(node->getReplacedParameter(), 0) }];
|
|
||||||
}
|
|
||||||
def : Property<"replacementType", QualType> {
|
def : Property<"replacementType", QualType> {
|
||||||
let Read = [{ node->getReplacementType() }];
|
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.
|
// The call to getCanonicalType here existed in ASTReader.cpp, too.
|
||||||
|
def : Creator<[{
|
||||||
return ctx.getSubstTemplateTypeParmType(
|
return ctx.getSubstTemplateTypeParmType(
|
||||||
cast<TemplateTypeParmType>(replacedParameter),
|
replacementType, associatedDecl, Index, PackIndex);
|
||||||
ctx.getCanonicalType(replacementType));
|
|
||||||
}]>;
|
}]>;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -758,8 +767,14 @@ let Class = PackExpansionType in {
|
|||||||
}
|
}
|
||||||
|
|
||||||
let Class = SubstTemplateTypeParmPackType in {
|
let Class = SubstTemplateTypeParmPackType in {
|
||||||
def : Property<"replacedParameter", QualType> {
|
def : Property<"associatedDecl", DeclRef> {
|
||||||
let Read = [{ QualType(node->getReplacedParameter(), 0) }];
|
let Read = [{ node->getAssociatedDecl() }];
|
||||||
|
}
|
||||||
|
def : Property<"Index", UInt32> {
|
||||||
|
let Read = [{ node->getIndex() }];
|
||||||
|
}
|
||||||
|
def : Property<"Final", Bool> {
|
||||||
|
let Read = [{ node->getFinal() }];
|
||||||
}
|
}
|
||||||
def : Property<"replacementPack", TemplateArgument> {
|
def : Property<"replacementPack", TemplateArgument> {
|
||||||
let Read = [{ node->getArgumentPack() }];
|
let Read = [{ node->getArgumentPack() }];
|
||||||
@@ -767,8 +782,7 @@ let Class = SubstTemplateTypeParmPackType in {
|
|||||||
|
|
||||||
def : Creator<[{
|
def : Creator<[{
|
||||||
return ctx.getSubstTemplateTypeParmPackType(
|
return ctx.getSubstTemplateTypeParmPackType(
|
||||||
cast<TemplateTypeParmType>(replacedParameter),
|
associatedDecl, Index, Final, replacementPack);
|
||||||
replacementPack);
|
|
||||||
}]>;
|
}]>;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -820,8 +834,8 @@ let Class = DependentNameType in {
|
|||||||
def : Property<"underlyingType", Optional<QualType>> {
|
def : Property<"underlyingType", Optional<QualType>> {
|
||||||
let Read = [{
|
let Read = [{
|
||||||
node->isCanonicalUnqualified()
|
node->isCanonicalUnqualified()
|
||||||
? llvm::None
|
? std::nullopt
|
||||||
: llvm::Optional<QualType>(node->getCanonicalTypeInternal())
|
: std::optional<QualType>(node->getCanonicalTypeInternal())
|
||||||
}];
|
}];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -44,6 +44,7 @@
|
|||||||
#include "llvm/ADT/SmallPtrSet.h"
|
#include "llvm/ADT/SmallPtrSet.h"
|
||||||
#include "llvm/ADT/StringMap.h"
|
#include "llvm/ADT/StringMap.h"
|
||||||
#include "llvm/Support/Timer.h"
|
#include "llvm/Support/Timer.h"
|
||||||
|
#include <optional>
|
||||||
|
|
||||||
namespace clang {
|
namespace clang {
|
||||||
|
|
||||||
@@ -115,7 +116,7 @@ class MatchFinder {
|
|||||||
/// the result nodes. This API is temporary to facilitate
|
/// the result nodes. This API is temporary to facilitate
|
||||||
/// third parties porting existing code to the default
|
/// third parties porting existing code to the default
|
||||||
/// behavior of clang-tidy.
|
/// 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.
|
/// Called when parsing is finished. Intended for testing only.
|
||||||
@@ -137,7 +138,7 @@ class MatchFinder {
|
|||||||
/// Enables per-check timers.
|
/// Enables per-check timers.
|
||||||
///
|
///
|
||||||
/// It prints a report after match.
|
/// It prints a report after match.
|
||||||
llvm::Optional<Profiling> CheckProfiling;
|
std::optional<Profiling> CheckProfiling;
|
||||||
};
|
};
|
||||||
|
|
||||||
MatchFinder(MatchFinderOptions Options = MatchFinderOptions());
|
MatchFinder(MatchFinderOptions Options = MatchFinderOptions());
|
||||||
@@ -289,8 +290,8 @@ class CollectMatchesCallback : public MatchFinder::MatchCallback {
|
|||||||
Nodes.push_back(Result.Nodes);
|
Nodes.push_back(Result.Nodes);
|
||||||
}
|
}
|
||||||
|
|
||||||
llvm::Optional<TraversalKind> getCheckTraversalKind() const override {
|
std::optional<TraversalKind> getCheckTraversalKind() const override {
|
||||||
return llvm::None;
|
return std::nullopt;
|
||||||
}
|
}
|
||||||
|
|
||||||
SmallVector<BoundNodes, 1> Nodes;
|
SmallVector<BoundNodes, 1> Nodes;
|
||||||
|
|||||||
@@ -90,6 +90,7 @@
|
|||||||
#include <cstddef>
|
#include <cstddef>
|
||||||
#include <iterator>
|
#include <iterator>
|
||||||
#include <limits>
|
#include <limits>
|
||||||
|
#include <optional>
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <utility>
|
#include <utility>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
@@ -317,10 +318,10 @@ AST_POLYMORPHIC_MATCHER_P(isExpandedFromMacro,
|
|||||||
// Verifies that the statement' beginning and ending are both expanded from
|
// Verifies that the statement' beginning and ending are both expanded from
|
||||||
// the same instance of the given macro.
|
// the same instance of the given macro.
|
||||||
auto& Context = Finder->getASTContext();
|
auto& Context = Finder->getASTContext();
|
||||||
llvm::Optional<SourceLocation> B =
|
std::optional<SourceLocation> B =
|
||||||
internal::getExpansionLocOfMacro(MacroName, Node.getBeginLoc(), Context);
|
internal::getExpansionLocOfMacro(MacroName, Node.getBeginLoc(), Context);
|
||||||
if (!B) return false;
|
if (!B) return false;
|
||||||
llvm::Optional<SourceLocation> E =
|
std::optional<SourceLocation> E =
|
||||||
internal::getExpansionLocOfMacro(MacroName, Node.getEndLoc(), Context);
|
internal::getExpansionLocOfMacro(MacroName, Node.getEndLoc(), Context);
|
||||||
if (!E) return false;
|
if (!E) return false;
|
||||||
return *B == *E;
|
return *B == *E;
|
||||||
@@ -1101,9 +1102,9 @@ AST_POLYMORPHIC_MATCHER_P(
|
|||||||
/// template<typename T> struct A {};
|
/// template<typename T> struct A {};
|
||||||
/// A<X> a;
|
/// A<X> a;
|
||||||
/// \endcode
|
/// \endcode
|
||||||
/// classTemplateSpecializationDecl(hasAnyTemplateArgument(
|
/// classTemplateSpecializationDecl(hasAnyTemplateArgument(refersToType(
|
||||||
/// refersToType(class(hasName("X")))))
|
/// recordType(hasDeclaration(recordDecl(hasName("X")))))))
|
||||||
/// matches the specialization \c A<X>
|
/// matches the specialization of \c struct A generated by \c A<X>.
|
||||||
AST_MATCHER_P(TemplateArgument, refersToType,
|
AST_MATCHER_P(TemplateArgument, refersToType,
|
||||||
internal::Matcher<QualType>, InnerMatcher) {
|
internal::Matcher<QualType>, InnerMatcher) {
|
||||||
if (Node.getKind() != TemplateArgument::Type)
|
if (Node.getKind() != TemplateArgument::Type)
|
||||||
@@ -3954,14 +3955,14 @@ AST_POLYMORPHIC_MATCHER_P_OVERLOAD(
|
|||||||
///
|
///
|
||||||
/// \code
|
/// \code
|
||||||
/// auto x = int(3);
|
/// auto x = int(3);
|
||||||
/// \code
|
/// \endcode
|
||||||
/// cxxTemporaryObjectExpr(hasTypeLoc(loc(asString("int"))))
|
/// cxxTemporaryObjectExpr(hasTypeLoc(loc(asString("int"))))
|
||||||
/// matches int(3)
|
/// matches int(3)
|
||||||
///
|
///
|
||||||
/// \code
|
/// \code
|
||||||
/// struct Foo { Foo(int, int); };
|
/// struct Foo { Foo(int, int); };
|
||||||
/// auto x = Foo(1, 2);
|
/// auto x = Foo(1, 2);
|
||||||
/// \code
|
/// \endcode
|
||||||
/// cxxFunctionalCastExpr(hasTypeLoc(loc(asString("struct Foo"))))
|
/// cxxFunctionalCastExpr(hasTypeLoc(loc(asString("struct Foo"))))
|
||||||
/// matches Foo(1, 2)
|
/// matches Foo(1, 2)
|
||||||
///
|
///
|
||||||
@@ -4175,7 +4176,7 @@ AST_MATCHER_P(DeclRefExpr, to, internal::Matcher<Decl>,
|
|||||||
/// namespace a { class X{}; }
|
/// namespace a { class X{}; }
|
||||||
/// using a::X;
|
/// using a::X;
|
||||||
/// X x;
|
/// X x;
|
||||||
/// \code
|
/// \endcode
|
||||||
/// typeLoc(loc(usingType(throughUsingDecl(anything()))))
|
/// typeLoc(loc(usingType(throughUsingDecl(anything()))))
|
||||||
/// matches \c X
|
/// matches \c X
|
||||||
///
|
///
|
||||||
@@ -4722,7 +4723,7 @@ AST_MATCHER_P(LambdaExpr, hasAnyCapture, internal::Matcher<LambdaCapture>,
|
|||||||
/// In the matcher
|
/// In the matcher
|
||||||
/// lambdaExpr(hasAnyCapture(lambdaCapture(capturesVar(hasName("x")))),
|
/// lambdaExpr(hasAnyCapture(lambdaCapture(capturesVar(hasName("x")))),
|
||||||
/// capturesVar(hasName("x")) matches `x` and `x = 1`.
|
/// 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) {
|
InnerMatcher) {
|
||||||
auto *capturedVar = Node.getCapturedVar();
|
auto *capturedVar = Node.getCapturedVar();
|
||||||
return capturedVar && InnerMatcher.matches(*capturedVar, Finder, Builder);
|
return capturedVar && InnerMatcher.matches(*capturedVar, Finder, Builder);
|
||||||
@@ -5459,16 +5460,15 @@ AST_MATCHER_P(ArraySubscriptExpr, hasBase,
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Matches a 'for', 'while', 'do while' statement or a function
|
/// Matches a 'for', 'while', 'do' statement or a function definition that has
|
||||||
/// definition that has a given body. Note that in case of functions
|
/// a given body. Note that in case of functions this matcher only matches the
|
||||||
/// this matcher only matches the definition itself and not the other
|
/// definition itself and not the other declarations of the same function.
|
||||||
/// declarations of the same function.
|
|
||||||
///
|
///
|
||||||
/// Given
|
/// Given
|
||||||
/// \code
|
/// \code
|
||||||
/// for (;;) {}
|
/// for (;;) {}
|
||||||
/// \endcode
|
/// \endcode
|
||||||
/// hasBody(compoundStmt())
|
/// forStmt(hasBody(compoundStmt()))
|
||||||
/// matches 'for (;;) {}'
|
/// matches 'for (;;) {}'
|
||||||
/// with compoundStmt()
|
/// with compoundStmt()
|
||||||
/// matching '{}'
|
/// matching '{}'
|
||||||
@@ -5478,12 +5478,11 @@ AST_MATCHER_P(ArraySubscriptExpr, hasBase,
|
|||||||
/// void f();
|
/// void f();
|
||||||
/// void f() {}
|
/// void f() {}
|
||||||
/// \endcode
|
/// \endcode
|
||||||
/// hasBody(functionDecl())
|
/// functionDecl(hasBody(compoundStmt()))
|
||||||
/// matches 'void f() {}'
|
/// matches 'void f() {}'
|
||||||
/// with compoundStmt()
|
/// with compoundStmt()
|
||||||
/// matching '{}'
|
/// matching '{}'
|
||||||
/// but does not match 'void f();'
|
/// but does not match 'void f();'
|
||||||
|
|
||||||
AST_POLYMORPHIC_MATCHER_P(hasBody,
|
AST_POLYMORPHIC_MATCHER_P(hasBody,
|
||||||
AST_POLYMORPHIC_SUPPORTED_TYPES(DoStmt, ForStmt,
|
AST_POLYMORPHIC_SUPPORTED_TYPES(DoStmt, ForStmt,
|
||||||
WhileStmt,
|
WhileStmt,
|
||||||
@@ -5630,7 +5629,7 @@ AST_POLYMORPHIC_MATCHER_P(
|
|||||||
AST_POLYMORPHIC_SUPPORTED_TYPES(BinaryOperator, CXXOperatorCallExpr,
|
AST_POLYMORPHIC_SUPPORTED_TYPES(BinaryOperator, CXXOperatorCallExpr,
|
||||||
CXXRewrittenBinaryOperator, UnaryOperator),
|
CXXRewrittenBinaryOperator, UnaryOperator),
|
||||||
std::string, Name) {
|
std::string, Name) {
|
||||||
if (Optional<StringRef> OpName = internal::getOpName(Node))
|
if (std::optional<StringRef> OpName = internal::getOpName(Node))
|
||||||
return *OpName == Name;
|
return *OpName == Name;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@@ -5824,8 +5823,6 @@ AST_MATCHER_P(ExplicitCastExpr, hasDestinationType,
|
|||||||
|
|
||||||
/// Matches implicit casts whose destination type matches a given
|
/// Matches implicit casts whose destination type matches a given
|
||||||
/// matcher.
|
/// matcher.
|
||||||
///
|
|
||||||
/// FIXME: Unit test this matcher
|
|
||||||
AST_MATCHER_P(ImplicitCastExpr, hasImplicitDestinationType,
|
AST_MATCHER_P(ImplicitCastExpr, hasImplicitDestinationType,
|
||||||
internal::Matcher<QualType>, InnerMatcher) {
|
internal::Matcher<QualType>, InnerMatcher) {
|
||||||
return InnerMatcher.matches(Node.getType(), Finder, Builder);
|
return InnerMatcher.matches(Node.getType(), Finder, Builder);
|
||||||
@@ -7813,6 +7810,30 @@ AST_MATCHER(NamespaceDecl, isAnonymous) {
|
|||||||
/// cxxRecordDecl(hasName("vector"), isInStdNamespace()) will match only #1.
|
/// cxxRecordDecl(hasName("vector"), isInStdNamespace()) will match only #1.
|
||||||
AST_MATCHER(Decl, isInStdNamespace) { return Node.isInStdNamespace(); }
|
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
|
/// If the given case statement does not use the GNU case range
|
||||||
/// extension, matches the constant given in the statement.
|
/// extension, matches the constant given in the statement.
|
||||||
///
|
///
|
||||||
|
|||||||
@@ -52,8 +52,6 @@
|
|||||||
#include "llvm/ADT/APFloat.h"
|
#include "llvm/ADT/APFloat.h"
|
||||||
#include "llvm/ADT/ArrayRef.h"
|
#include "llvm/ADT/ArrayRef.h"
|
||||||
#include "llvm/ADT/IntrusiveRefCntPtr.h"
|
#include "llvm/ADT/IntrusiveRefCntPtr.h"
|
||||||
#include "llvm/ADT/None.h"
|
|
||||||
#include "llvm/ADT/Optional.h"
|
|
||||||
#include "llvm/ADT/STLExtras.h"
|
#include "llvm/ADT/STLExtras.h"
|
||||||
#include "llvm/ADT/SmallVector.h"
|
#include "llvm/ADT/SmallVector.h"
|
||||||
#include "llvm/ADT/StringRef.h"
|
#include "llvm/ADT/StringRef.h"
|
||||||
@@ -67,6 +65,7 @@
|
|||||||
#include <cstdint>
|
#include <cstdint>
|
||||||
#include <map>
|
#include <map>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
|
#include <optional>
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <tuple>
|
#include <tuple>
|
||||||
#include <type_traits>
|
#include <type_traits>
|
||||||
@@ -122,7 +121,7 @@ template <typename T> struct TypeListContainsSuperOf<EmptyTypeList, T> {
|
|||||||
template <typename ResultT, typename ArgT,
|
template <typename ResultT, typename ArgT,
|
||||||
ResultT (*Func)(ArrayRef<const ArgT *>)>
|
ResultT (*Func)(ArrayRef<const ArgT *>)>
|
||||||
struct VariadicFunction {
|
struct VariadicFunction {
|
||||||
ResultT operator()() const { return Func(None); }
|
ResultT operator()() const { return Func(std::nullopt); }
|
||||||
|
|
||||||
template <typename... ArgsT>
|
template <typename... ArgsT>
|
||||||
ResultT operator()(const ArgT &Arg1, const ArgsT &... Args) const {
|
ResultT operator()(const ArgT &Arg1, const ArgsT &... Args) const {
|
||||||
@@ -351,8 +350,8 @@ class DynMatcherInterface
|
|||||||
virtual bool dynMatches(const DynTypedNode &DynNode, ASTMatchFinder *Finder,
|
virtual bool dynMatches(const DynTypedNode &DynNode, ASTMatchFinder *Finder,
|
||||||
BoundNodesTreeBuilder *Builder) const = 0;
|
BoundNodesTreeBuilder *Builder) const = 0;
|
||||||
|
|
||||||
virtual llvm::Optional<clang::TraversalKind> TraversalKind() const {
|
virtual std::optional<clang::TraversalKind> TraversalKind() const {
|
||||||
return llvm::None;
|
return std::nullopt;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -464,7 +463,7 @@ class DynTypedMatcher {
|
|||||||
/// restricts the node types for \p Kind.
|
/// restricts the node types for \p Kind.
|
||||||
DynTypedMatcher dynCastTo(const ASTNodeKind Kind) const;
|
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.
|
/// traversal kind.
|
||||||
///
|
///
|
||||||
/// If the traversal kind is already set, then \c TK overrides it.
|
/// 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.
|
/// Bind the specified \p ID to the matcher.
|
||||||
/// \return A new matcher with the \p ID bound to it if this matcher supports
|
/// \return A new matcher with the \p ID bound to it if this matcher supports
|
||||||
/// binding. Otherwise, returns an empty \c Optional<>.
|
/// binding. Otherwise, returns an empty \c std::optional<>.
|
||||||
llvm::Optional<DynTypedMatcher> tryBind(StringRef ID) const;
|
std::optional<DynTypedMatcher> tryBind(StringRef ID) const;
|
||||||
|
|
||||||
/// Returns a unique \p ID for the matcher.
|
/// 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.
|
/// Returns the \c TraversalKind respected by calls to `match()`, if any.
|
||||||
///
|
///
|
||||||
/// Most matchers will not have a traversal kind set, instead relying on the
|
/// Most matchers will not have a traversal kind set, instead relying on the
|
||||||
/// surrounding context. For those, \c llvm::None is returned.
|
/// surrounding context. For those, \c std::nullopt is returned.
|
||||||
llvm::Optional<clang::TraversalKind> getTraversalKind() const {
|
std::optional<clang::TraversalKind> getTraversalKind() const {
|
||||||
return Implementation->TraversalKind();
|
return Implementation->TraversalKind();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -649,7 +648,7 @@ class Matcher {
|
|||||||
Builder);
|
Builder);
|
||||||
}
|
}
|
||||||
|
|
||||||
llvm::Optional<clang::TraversalKind> TraversalKind() const override {
|
std::optional<clang::TraversalKind> TraversalKind() const override {
|
||||||
return this->InnerMatcher.getTraversalKind();
|
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>
|
template <typename T, bool IsBaseOf, typename Head, typename Tail>
|
||||||
struct GetCladeImpl {
|
struct GetCladeImpl {
|
||||||
using Type = Head;
|
using Type = Head;
|
||||||
@@ -1428,12 +1413,11 @@ struct MapAnyOfMatcherImpl {
|
|||||||
template <typename... InnerMatchers>
|
template <typename... InnerMatchers>
|
||||||
BindableMatcher<CladeType>
|
BindableMatcher<CladeType>
|
||||||
operator()(InnerMatchers &&... InnerMatcher) const {
|
operator()(InnerMatchers &&... InnerMatcher) const {
|
||||||
// TODO: Use std::apply from c++17
|
return VariadicAllOfMatcher<CladeType>()(std::apply(
|
||||||
return VariadicAllOfMatcher<CladeType>()(applyMatcher(
|
|
||||||
internal::VariadicOperatorMatcherFunc<
|
internal::VariadicOperatorMatcherFunc<
|
||||||
0, std::numeric_limits<unsigned>::max()>{
|
0, std::numeric_limits<unsigned>::max()>{
|
||||||
internal::DynTypedMatcher::VO_AnyOf},
|
internal::DynTypedMatcher::VO_AnyOf},
|
||||||
applyMatcher(
|
std::apply(
|
||||||
[&](auto... Matcher) {
|
[&](auto... Matcher) {
|
||||||
return std::make_tuple(Matcher(InnerMatcher...)...);
|
return std::make_tuple(Matcher(InnerMatcher...)...);
|
||||||
},
|
},
|
||||||
@@ -1531,7 +1515,7 @@ template <typename T> class TraversalMatcher : public MatcherInterface<T> {
|
|||||||
Builder);
|
Builder);
|
||||||
}
|
}
|
||||||
|
|
||||||
llvm::Optional<clang::TraversalKind> TraversalKind() const override {
|
std::optional<clang::TraversalKind> TraversalKind() const override {
|
||||||
if (auto NestedKind = this->InnerMatcher.getTraversalKind())
|
if (auto NestedKind = this->InnerMatcher.getTraversalKind())
|
||||||
return NestedKind;
|
return NestedKind;
|
||||||
return Traversal;
|
return Traversal;
|
||||||
@@ -1957,7 +1941,7 @@ getTemplateSpecializationArgs(const ClassTemplateSpecializationDecl &D) {
|
|||||||
|
|
||||||
inline ArrayRef<TemplateArgument>
|
inline ArrayRef<TemplateArgument>
|
||||||
getTemplateSpecializationArgs(const TemplateSpecializationType &T) {
|
getTemplateSpecializationArgs(const TemplateSpecializationType &T) {
|
||||||
return llvm::makeArrayRef(T.getArgs(), T.getNumArgs());
|
return T.template_arguments();
|
||||||
}
|
}
|
||||||
|
|
||||||
inline ArrayRef<TemplateArgument>
|
inline ArrayRef<TemplateArgument>
|
||||||
@@ -1981,27 +1965,27 @@ template <typename Ty, typename Enable = void> struct GetBodyMatcher {
|
|||||||
};
|
};
|
||||||
|
|
||||||
template <typename Ty>
|
template <typename Ty>
|
||||||
struct GetBodyMatcher<Ty, typename std::enable_if<
|
struct GetBodyMatcher<
|
||||||
std::is_base_of<FunctionDecl, Ty>::value>::type> {
|
Ty, std::enable_if_t<std::is_base_of<FunctionDecl, Ty>::value>> {
|
||||||
static const Stmt *get(const Ty &Node) {
|
static const Stmt *get(const Ty &Node) {
|
||||||
return Node.doesThisDeclarationHaveABody() ? Node.getBody() : nullptr;
|
return Node.doesThisDeclarationHaveABody() ? Node.getBody() : nullptr;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
template <typename NodeType>
|
template <typename NodeType>
|
||||||
inline Optional<BinaryOperatorKind>
|
inline std::optional<BinaryOperatorKind>
|
||||||
equivalentBinaryOperator(const NodeType &Node) {
|
equivalentBinaryOperator(const NodeType &Node) {
|
||||||
return Node.getOpcode();
|
return Node.getOpcode();
|
||||||
}
|
}
|
||||||
|
|
||||||
template <>
|
template <>
|
||||||
inline Optional<BinaryOperatorKind>
|
inline std::optional<BinaryOperatorKind>
|
||||||
equivalentBinaryOperator<CXXOperatorCallExpr>(const CXXOperatorCallExpr &Node) {
|
equivalentBinaryOperator<CXXOperatorCallExpr>(const CXXOperatorCallExpr &Node) {
|
||||||
if (Node.getNumArgs() != 2)
|
if (Node.getNumArgs() != 2)
|
||||||
return None;
|
return std::nullopt;
|
||||||
switch (Node.getOperator()) {
|
switch (Node.getOperator()) {
|
||||||
default:
|
default:
|
||||||
return None;
|
return std::nullopt;
|
||||||
case OO_ArrowStar:
|
case OO_ArrowStar:
|
||||||
return BO_PtrMemI;
|
return BO_PtrMemI;
|
||||||
case OO_Star:
|
case OO_Star:
|
||||||
@@ -2070,20 +2054,20 @@ equivalentBinaryOperator<CXXOperatorCallExpr>(const CXXOperatorCallExpr &Node) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
template <typename NodeType>
|
template <typename NodeType>
|
||||||
inline Optional<UnaryOperatorKind>
|
inline std::optional<UnaryOperatorKind>
|
||||||
equivalentUnaryOperator(const NodeType &Node) {
|
equivalentUnaryOperator(const NodeType &Node) {
|
||||||
return Node.getOpcode();
|
return Node.getOpcode();
|
||||||
}
|
}
|
||||||
|
|
||||||
template <>
|
template <>
|
||||||
inline Optional<UnaryOperatorKind>
|
inline std::optional<UnaryOperatorKind>
|
||||||
equivalentUnaryOperator<CXXOperatorCallExpr>(const CXXOperatorCallExpr &Node) {
|
equivalentUnaryOperator<CXXOperatorCallExpr>(const CXXOperatorCallExpr &Node) {
|
||||||
if (Node.getNumArgs() != 1 && Node.getOperator() != OO_PlusPlus &&
|
if (Node.getNumArgs() != 1 && Node.getOperator() != OO_PlusPlus &&
|
||||||
Node.getOperator() != OO_MinusMinus)
|
Node.getOperator() != OO_MinusMinus)
|
||||||
return None;
|
return std::nullopt;
|
||||||
switch (Node.getOperator()) {
|
switch (Node.getOperator()) {
|
||||||
default:
|
default:
|
||||||
return None;
|
return std::nullopt;
|
||||||
case OO_Plus:
|
case OO_Plus:
|
||||||
return UO_Plus;
|
return UO_Plus;
|
||||||
case OO_Minus:
|
case OO_Minus:
|
||||||
@@ -2099,13 +2083,13 @@ equivalentUnaryOperator<CXXOperatorCallExpr>(const CXXOperatorCallExpr &Node) {
|
|||||||
case OO_PlusPlus: {
|
case OO_PlusPlus: {
|
||||||
const auto *FD = Node.getDirectCallee();
|
const auto *FD = Node.getDirectCallee();
|
||||||
if (!FD)
|
if (!FD)
|
||||||
return None;
|
return std::nullopt;
|
||||||
return FD->getNumParams() > 0 ? UO_PostInc : UO_PreInc;
|
return FD->getNumParams() > 0 ? UO_PostInc : UO_PreInc;
|
||||||
}
|
}
|
||||||
case OO_MinusMinus: {
|
case OO_MinusMinus: {
|
||||||
const auto *FD = Node.getDirectCallee();
|
const auto *FD = Node.getDirectCallee();
|
||||||
if (!FD)
|
if (!FD)
|
||||||
return None;
|
return std::nullopt;
|
||||||
return FD->getNumParams() > 0 ? UO_PostDec : UO_PreDec;
|
return FD->getNumParams() > 0 ? UO_PostDec : UO_PreDec;
|
||||||
}
|
}
|
||||||
case OO_Coawait:
|
case OO_Coawait:
|
||||||
@@ -2188,25 +2172,25 @@ CompoundStmtMatcher<StmtExpr>::get(const StmtExpr &Node) {
|
|||||||
/// location (in the chain of expansions) at which \p MacroName was
|
/// location (in the chain of expansions) at which \p MacroName was
|
||||||
/// expanded. Since the macro may have been expanded inside a series of
|
/// expanded. Since the macro may have been expanded inside a series of
|
||||||
/// expansions, that location may itself be a MacroID.
|
/// expansions, that location may itself be a MacroID.
|
||||||
llvm::Optional<SourceLocation>
|
std::optional<SourceLocation> getExpansionLocOfMacro(StringRef MacroName,
|
||||||
getExpansionLocOfMacro(StringRef MacroName, SourceLocation Loc,
|
SourceLocation Loc,
|
||||||
const ASTContext &Context);
|
const ASTContext &Context);
|
||||||
|
|
||||||
inline Optional<StringRef> getOpName(const UnaryOperator &Node) {
|
inline std::optional<StringRef> getOpName(const UnaryOperator &Node) {
|
||||||
return Node.getOpcodeStr(Node.getOpcode());
|
return Node.getOpcodeStr(Node.getOpcode());
|
||||||
}
|
}
|
||||||
inline Optional<StringRef> getOpName(const BinaryOperator &Node) {
|
inline std::optional<StringRef> getOpName(const BinaryOperator &Node) {
|
||||||
return Node.getOpcodeStr();
|
return Node.getOpcodeStr();
|
||||||
}
|
}
|
||||||
inline StringRef getOpName(const CXXRewrittenBinaryOperator &Node) {
|
inline StringRef getOpName(const CXXRewrittenBinaryOperator &Node) {
|
||||||
return Node.getOpcodeStr();
|
return Node.getOpcodeStr();
|
||||||
}
|
}
|
||||||
inline Optional<StringRef> getOpName(const CXXOperatorCallExpr &Node) {
|
inline std::optional<StringRef> getOpName(const CXXOperatorCallExpr &Node) {
|
||||||
auto optBinaryOpcode = equivalentBinaryOperator(Node);
|
auto optBinaryOpcode = equivalentBinaryOperator(Node);
|
||||||
if (!optBinaryOpcode) {
|
if (!optBinaryOpcode) {
|
||||||
auto optUnaryOpcode = equivalentUnaryOperator(Node);
|
auto optUnaryOpcode = equivalentUnaryOperator(Node);
|
||||||
if (!optUnaryOpcode)
|
if (!optUnaryOpcode)
|
||||||
return None;
|
return std::nullopt;
|
||||||
return UnaryOperator::getOpcodeStr(*optUnaryOpcode);
|
return UnaryOperator::getOpcodeStr(*optUnaryOpcode);
|
||||||
}
|
}
|
||||||
return BinaryOperator::getOpcodeStr(*optBinaryOpcode);
|
return BinaryOperator::getOpcodeStr(*optBinaryOpcode);
|
||||||
@@ -2232,26 +2216,26 @@ class HasAnyOperatorNameMatcher : public SingleNodeMatcherInterface<T> {
|
|||||||
: SingleNodeMatcherInterface<T>(), Names(std::move(Names)) {}
|
: SingleNodeMatcherInterface<T>(), Names(std::move(Names)) {}
|
||||||
|
|
||||||
bool matchesNode(const T &Node) const override {
|
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);
|
return OptOpName && llvm::is_contained(Names, *OptOpName);
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
static Optional<StringRef> getOpName(const UnaryOperator &Node) {
|
static std::optional<StringRef> getOpName(const UnaryOperator &Node) {
|
||||||
return Node.getOpcodeStr(Node.getOpcode());
|
return Node.getOpcodeStr(Node.getOpcode());
|
||||||
}
|
}
|
||||||
static Optional<StringRef> getOpName(const BinaryOperator &Node) {
|
static std::optional<StringRef> getOpName(const BinaryOperator &Node) {
|
||||||
return Node.getOpcodeStr();
|
return Node.getOpcodeStr();
|
||||||
}
|
}
|
||||||
static StringRef getOpName(const CXXRewrittenBinaryOperator &Node) {
|
static StringRef getOpName(const CXXRewrittenBinaryOperator &Node) {
|
||||||
return Node.getOpcodeStr();
|
return Node.getOpcodeStr();
|
||||||
}
|
}
|
||||||
static Optional<StringRef> getOpName(const CXXOperatorCallExpr &Node) {
|
static std::optional<StringRef> getOpName(const CXXOperatorCallExpr &Node) {
|
||||||
auto optBinaryOpcode = equivalentBinaryOperator(Node);
|
auto optBinaryOpcode = equivalentBinaryOperator(Node);
|
||||||
if (!optBinaryOpcode) {
|
if (!optBinaryOpcode) {
|
||||||
auto optUnaryOpcode = equivalentUnaryOperator(Node);
|
auto optUnaryOpcode = equivalentUnaryOperator(Node);
|
||||||
if (!optUnaryOpcode)
|
if (!optUnaryOpcode)
|
||||||
return None;
|
return std::nullopt;
|
||||||
return UnaryOperator::getOpcodeStr(*optUnaryOpcode);
|
return UnaryOperator::getOpcodeStr(*optUnaryOpcode);
|
||||||
}
|
}
|
||||||
return BinaryOperator::getOpcodeStr(*optBinaryOpcode);
|
return BinaryOperator::getOpcodeStr(*optBinaryOpcode);
|
||||||
|
|||||||
@@ -39,9 +39,9 @@
|
|||||||
#include "clang/ASTMatchers/Dynamic/Registry.h"
|
#include "clang/ASTMatchers/Dynamic/Registry.h"
|
||||||
#include "clang/ASTMatchers/Dynamic/VariantValue.h"
|
#include "clang/ASTMatchers/Dynamic/VariantValue.h"
|
||||||
#include "llvm/ADT/ArrayRef.h"
|
#include "llvm/ADT/ArrayRef.h"
|
||||||
#include "llvm/ADT/Optional.h"
|
|
||||||
#include "llvm/ADT/StringMap.h"
|
#include "llvm/ADT/StringMap.h"
|
||||||
#include "llvm/ADT/StringRef.h"
|
#include "llvm/ADT/StringRef.h"
|
||||||
|
#include <optional>
|
||||||
#include <utility>
|
#include <utility>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
@@ -95,9 +95,9 @@ class Parser {
|
|||||||
///
|
///
|
||||||
/// \param MatcherName The matcher name found by the 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.
|
/// found.
|
||||||
virtual llvm::Optional<MatcherCtor>
|
virtual std::optional<MatcherCtor>
|
||||||
lookupMatcherCtor(StringRef MatcherName) = 0;
|
lookupMatcherCtor(StringRef MatcherName) = 0;
|
||||||
|
|
||||||
virtual bool isBuilderMatcher(MatcherCtor) const = 0;
|
virtual bool isBuilderMatcher(MatcherCtor) const = 0;
|
||||||
@@ -138,7 +138,7 @@ class Parser {
|
|||||||
public:
|
public:
|
||||||
~RegistrySema() override;
|
~RegistrySema() override;
|
||||||
|
|
||||||
llvm::Optional<MatcherCtor>
|
std::optional<MatcherCtor>
|
||||||
lookupMatcherCtor(StringRef MatcherName) override;
|
lookupMatcherCtor(StringRef MatcherName) override;
|
||||||
|
|
||||||
VariantMatcher actOnMatcherExpression(MatcherCtor Ctor,
|
VariantMatcher actOnMatcherExpression(MatcherCtor Ctor,
|
||||||
@@ -180,14 +180,14 @@ class Parser {
|
|||||||
/// Optional if an error occurred. In that case, \c Error will contain a
|
/// Optional if an error occurred. In that case, \c Error will contain a
|
||||||
/// description of the error.
|
/// description of the error.
|
||||||
/// The caller takes ownership of the DynTypedMatcher object returned.
|
/// The caller takes ownership of the DynTypedMatcher object returned.
|
||||||
static llvm::Optional<DynTypedMatcher>
|
static std::optional<DynTypedMatcher>
|
||||||
parseMatcherExpression(StringRef &MatcherCode, Sema *S,
|
parseMatcherExpression(StringRef &MatcherCode, Sema *S,
|
||||||
const NamedValueMap *NamedValues, Diagnostics *Error);
|
const NamedValueMap *NamedValues, Diagnostics *Error);
|
||||||
static llvm::Optional<DynTypedMatcher>
|
static std::optional<DynTypedMatcher>
|
||||||
parseMatcherExpression(StringRef &MatcherCode, Sema *S, Diagnostics *Error) {
|
parseMatcherExpression(StringRef &MatcherCode, Sema *S, Diagnostics *Error) {
|
||||||
return parseMatcherExpression(MatcherCode, S, nullptr, Error);
|
return parseMatcherExpression(MatcherCode, S, nullptr, Error);
|
||||||
}
|
}
|
||||||
static llvm::Optional<DynTypedMatcher>
|
static std::optional<DynTypedMatcher>
|
||||||
parseMatcherExpression(StringRef &MatcherCode, Diagnostics *Error) {
|
parseMatcherExpression(StringRef &MatcherCode, Diagnostics *Error) {
|
||||||
return parseMatcherExpression(MatcherCode, nullptr, Error);
|
return parseMatcherExpression(MatcherCode, nullptr, Error);
|
||||||
}
|
}
|
||||||
@@ -254,7 +254,7 @@ class Parser {
|
|||||||
const TokenInfo &OpenToken, VariantValue *Value);
|
const TokenInfo &OpenToken, VariantValue *Value);
|
||||||
bool parseMatcherExpressionImpl(const TokenInfo &NameToken,
|
bool parseMatcherExpressionImpl(const TokenInfo &NameToken,
|
||||||
const TokenInfo &OpenToken,
|
const TokenInfo &OpenToken,
|
||||||
llvm::Optional<MatcherCtor> Ctor,
|
std::optional<MatcherCtor> Ctor,
|
||||||
VariantValue *Value);
|
VariantValue *Value);
|
||||||
bool parseIdentifierPrefixImpl(VariantValue *Value);
|
bool parseIdentifierPrefixImpl(VariantValue *Value);
|
||||||
|
|
||||||
|
|||||||
@@ -19,8 +19,8 @@
|
|||||||
#include "clang/ASTMatchers/Dynamic/Diagnostics.h"
|
#include "clang/ASTMatchers/Dynamic/Diagnostics.h"
|
||||||
#include "clang/ASTMatchers/Dynamic/VariantValue.h"
|
#include "clang/ASTMatchers/Dynamic/VariantValue.h"
|
||||||
#include "llvm/ADT/ArrayRef.h"
|
#include "llvm/ADT/ArrayRef.h"
|
||||||
#include "llvm/ADT/Optional.h"
|
|
||||||
#include "llvm/ADT/StringRef.h"
|
#include "llvm/ADT/StringRef.h"
|
||||||
|
#include <optional>
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <utility>
|
#include <utility>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
@@ -94,8 +94,8 @@ class Registry {
|
|||||||
/// Look up a matcher in the registry by name,
|
/// Look up a matcher in the registry by name,
|
||||||
///
|
///
|
||||||
/// \return An opaque value which may be used to refer to the matcher
|
/// \return An opaque value which may be used to refer to the matcher
|
||||||
/// constructor, or Optional<MatcherCtor>() if not found.
|
/// constructor, or std::optional<MatcherCtor>() if not found.
|
||||||
static llvm::Optional<MatcherCtor> lookupMatcherCtor(StringRef MatcherName);
|
static std::optional<MatcherCtor> lookupMatcherCtor(StringRef MatcherName);
|
||||||
|
|
||||||
/// Compute the list of completion types for \p Context.
|
/// Compute the list of completion types for \p Context.
|
||||||
///
|
///
|
||||||
|
|||||||
@@ -20,8 +20,8 @@
|
|||||||
#include "clang/ASTMatchers/ASTMatchers.h"
|
#include "clang/ASTMatchers/ASTMatchers.h"
|
||||||
#include "clang/ASTMatchers/ASTMatchersInternal.h"
|
#include "clang/ASTMatchers/ASTMatchersInternal.h"
|
||||||
#include "llvm/ADT/IntrusiveRefCntPtr.h"
|
#include "llvm/ADT/IntrusiveRefCntPtr.h"
|
||||||
#include "llvm/ADT/Optional.h"
|
|
||||||
#include <memory>
|
#include <memory>
|
||||||
|
#include <optional>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
namespace clang {
|
namespace clang {
|
||||||
@@ -117,8 +117,8 @@ class VariantMatcher {
|
|||||||
|
|
||||||
/// Constructs a variadic typed matcher from \p InnerMatchers.
|
/// Constructs a variadic typed matcher from \p InnerMatchers.
|
||||||
/// Will try to convert each inner matcher to the destination type and
|
/// Will try to convert each inner matcher to the destination type and
|
||||||
/// return llvm::None if it fails to do so.
|
/// return std::nullopt if it fails to do so.
|
||||||
llvm::Optional<DynTypedMatcher>
|
std::optional<DynTypedMatcher>
|
||||||
constructVariadicOperator(DynTypedMatcher::VariadicOperator Op,
|
constructVariadicOperator(DynTypedMatcher::VariadicOperator Op,
|
||||||
ArrayRef<VariantMatcher> InnerMatchers) const;
|
ArrayRef<VariantMatcher> InnerMatchers) const;
|
||||||
|
|
||||||
@@ -132,9 +132,9 @@ class VariantMatcher {
|
|||||||
class Payload {
|
class Payload {
|
||||||
public:
|
public:
|
||||||
virtual ~Payload();
|
virtual ~Payload();
|
||||||
virtual llvm::Optional<DynTypedMatcher> getSingleMatcher() const = 0;
|
virtual std::optional<DynTypedMatcher> getSingleMatcher() const = 0;
|
||||||
virtual std::string getTypeAsString() const = 0;
|
virtual std::string getTypeAsString() const = 0;
|
||||||
virtual llvm::Optional<DynTypedMatcher>
|
virtual std::optional<DynTypedMatcher>
|
||||||
getTypedMatcher(const MatcherOps &Ops) const = 0;
|
getTypedMatcher(const MatcherOps &Ops) const = 0;
|
||||||
virtual bool isConvertibleTo(ASTNodeKind Kind,
|
virtual bool isConvertibleTo(ASTNodeKind Kind,
|
||||||
unsigned *Specificity) const = 0;
|
unsigned *Specificity) const = 0;
|
||||||
@@ -171,7 +171,7 @@ class VariantMatcher {
|
|||||||
/// \returns the matcher, if there is only one matcher. An empty Optional, if
|
/// \returns the matcher, if there is only one matcher. An empty Optional, if
|
||||||
/// the underlying matcher is a polymorphic matcher with more than one
|
/// the underlying matcher is a polymorphic matcher with more than one
|
||||||
/// representation.
|
/// representation.
|
||||||
llvm::Optional<DynTypedMatcher> getSingleMatcher() const;
|
std::optional<DynTypedMatcher> getSingleMatcher() const;
|
||||||
|
|
||||||
/// Determines if the contained matcher can be converted to
|
/// Determines if the contained matcher can be converted to
|
||||||
/// \c Matcher<T>.
|
/// \c Matcher<T>.
|
||||||
|
|||||||
@@ -18,7 +18,6 @@
|
|||||||
#include "clang/Basic/LLVM.h"
|
#include "clang/Basic/LLVM.h"
|
||||||
#include "llvm/ADT/BitVector.h"
|
#include "llvm/ADT/BitVector.h"
|
||||||
#include "llvm/ADT/DenseMap.h"
|
#include "llvm/ADT/DenseMap.h"
|
||||||
#include "llvm/ADT/None.h"
|
|
||||||
#include "llvm/ADT/PostOrderIterator.h"
|
#include "llvm/ADT/PostOrderIterator.h"
|
||||||
#include <utility>
|
#include <utility>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
@@ -48,17 +47,18 @@ class PostOrderCFGView : public ManagedAnalysis {
|
|||||||
|
|
||||||
/// Set the bit associated with a particular CFGBlock.
|
/// Set the bit associated with a particular CFGBlock.
|
||||||
/// This is the important method for the SetType template parameter.
|
/// 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
|
// 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
|
// make sure that Block is non-null. Moreover, the CFGBlock iterator will
|
||||||
// occasionally hand out null pointers for pruned edges, so we catch those
|
// occasionally hand out null pointers for pruned edges, so we catch those
|
||||||
// here.
|
// here.
|
||||||
if (!Block)
|
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()))
|
if (VisitedBlockIDs.test(Block->getBlockID()))
|
||||||
return std::make_pair(None, false);
|
return std::make_pair(std::nullopt, false);
|
||||||
VisitedBlockIDs.set(Block->getBlockID());
|
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.
|
/// Check if the bit for a CFGBlock has been already set.
|
||||||
|
|||||||
@@ -31,6 +31,7 @@
|
|||||||
#include "clang/Basic/LLVM.h"
|
#include "clang/Basic/LLVM.h"
|
||||||
#include "llvm/ADT/DenseMap.h"
|
#include "llvm/ADT/DenseMap.h"
|
||||||
#include "llvm/ADT/PointerIntPair.h"
|
#include "llvm/ADT/PointerIntPair.h"
|
||||||
|
#include "llvm/ADT/PointerUnion.h"
|
||||||
#include "llvm/ADT/SmallVector.h"
|
#include "llvm/ADT/SmallVector.h"
|
||||||
#include "llvm/Support/Casting.h"
|
#include "llvm/Support/Casting.h"
|
||||||
#include <sstream>
|
#include <sstream>
|
||||||
@@ -354,7 +355,7 @@ class SExprBuilder {
|
|||||||
const NamedDecl *AttrDecl;
|
const NamedDecl *AttrDecl;
|
||||||
|
|
||||||
// Implicit object argument -- e.g. 'this'
|
// Implicit object argument -- e.g. 'this'
|
||||||
const Expr *SelfArg = nullptr;
|
llvm::PointerUnion<const Expr *, til::SExpr *> SelfArg = nullptr;
|
||||||
|
|
||||||
// Number of funArgs
|
// Number of funArgs
|
||||||
unsigned NumArgs = 0;
|
unsigned NumArgs = 0;
|
||||||
@@ -378,10 +379,18 @@ class SExprBuilder {
|
|||||||
// Translate a clang expression in an attribute to a til::SExpr.
|
// Translate a clang expression in an attribute to a til::SExpr.
|
||||||
// Constructs the context from D, DeclExp, and SelfDecl.
|
// Constructs the context from D, DeclExp, and SelfDecl.
|
||||||
CapabilityExpr translateAttrExpr(const Expr *AttrExp, const NamedDecl *D,
|
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);
|
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.
|
// Translate a clang statement or expression to a TIL expression.
|
||||||
// Also performs substitution of variables; Ctx provides the context.
|
// Also performs substitution of variables; Ctx provides the context.
|
||||||
// Dispatches on the type of S.
|
// Dispatches on the type of S.
|
||||||
|
|||||||
@@ -50,8 +50,6 @@
|
|||||||
#include "clang/Analysis/Analyses/ThreadSafetyUtil.h"
|
#include "clang/Analysis/Analyses/ThreadSafetyUtil.h"
|
||||||
#include "clang/Basic/LLVM.h"
|
#include "clang/Basic/LLVM.h"
|
||||||
#include "llvm/ADT/ArrayRef.h"
|
#include "llvm/ADT/ArrayRef.h"
|
||||||
#include "llvm/ADT/None.h"
|
|
||||||
#include "llvm/ADT/Optional.h"
|
|
||||||
#include "llvm/ADT/StringRef.h"
|
#include "llvm/ADT/StringRef.h"
|
||||||
#include "llvm/Support/Casting.h"
|
#include "llvm/Support/Casting.h"
|
||||||
#include "llvm/Support/raw_ostream.h"
|
#include "llvm/Support/raw_ostream.h"
|
||||||
@@ -60,6 +58,7 @@
|
|||||||
#include <cstddef>
|
#include <cstddef>
|
||||||
#include <cstdint>
|
#include <cstdint>
|
||||||
#include <iterator>
|
#include <iterator>
|
||||||
|
#include <optional>
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <utility>
|
#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.
|
/// At compile time, pointer literals are represented by symbolic names.
|
||||||
class LiteralPtr : public SExpr {
|
class LiteralPtr : public SExpr {
|
||||||
public:
|
public:
|
||||||
LiteralPtr(const ValueDecl *D) : SExpr(COP_LiteralPtr), Cvdecl(D) {
|
LiteralPtr(const ValueDecl *D) : SExpr(COP_LiteralPtr), Cvdecl(D) {}
|
||||||
assert(D && "ValueDecl must not be null");
|
|
||||||
}
|
|
||||||
LiteralPtr(const LiteralPtr &) = default;
|
LiteralPtr(const LiteralPtr &) = default;
|
||||||
|
|
||||||
static bool classof(const SExpr *E) { return E->opcode() == COP_LiteralPtr; }
|
static bool classof(const SExpr *E) { return E->opcode() == COP_LiteralPtr; }
|
||||||
|
|
||||||
// The clang declaration for the value that this pointer points to.
|
// The clang declaration for the value that this pointer points to.
|
||||||
const ValueDecl *clangDecl() const { return Cvdecl; }
|
const ValueDecl *clangDecl() const { return Cvdecl; }
|
||||||
|
void setClangDecl(const ValueDecl *VD) { Cvdecl = VD; }
|
||||||
|
|
||||||
template <class V>
|
template <class V>
|
||||||
typename V::R_SExpr traverse(V &Vs, typename V::R_Ctx Ctx) {
|
typename V::R_SExpr traverse(V &Vs, typename V::R_Ctx Ctx) {
|
||||||
@@ -651,6 +649,8 @@ class LiteralPtr : public SExpr {
|
|||||||
|
|
||||||
template <class C>
|
template <class C>
|
||||||
typename C::CType compare(const LiteralPtr* E, C& Cmp) const {
|
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);
|
return Cmp.comparePointers(Cvdecl, E->Cvdecl);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -957,7 +957,7 @@ class Project : public SExpr {
|
|||||||
|
|
||||||
private:
|
private:
|
||||||
SExpr* Rec;
|
SExpr* Rec;
|
||||||
mutable llvm::Optional<std::string> SlotName;
|
mutable std::optional<std::string> SlotName;
|
||||||
const ValueDecl *Cvdecl;
|
const ValueDecl *Cvdecl;
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -1430,9 +1430,7 @@ class Branch : public Terminator {
|
|||||||
BasicBlock *elseBlock() { return Branches[1]; }
|
BasicBlock *elseBlock() { return Branches[1]; }
|
||||||
|
|
||||||
/// Return the list of basic blocks that this terminator can branch to.
|
/// Return the list of basic blocks that this terminator can branch to.
|
||||||
ArrayRef<BasicBlock*> successors() {
|
ArrayRef<BasicBlock *> successors() { return llvm::ArrayRef(Branches); }
|
||||||
return llvm::makeArrayRef(Branches);
|
|
||||||
}
|
|
||||||
|
|
||||||
template <class V>
|
template <class V>
|
||||||
typename V::R_SExpr traverse(V &Vs, typename V::R_Ctx Ctx) {
|
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; }
|
static bool classof(const SExpr *E) { return E->opcode() == COP_Return; }
|
||||||
|
|
||||||
/// Return an empty list.
|
/// Return an empty list.
|
||||||
ArrayRef<BasicBlock *> successors() { return None; }
|
ArrayRef<BasicBlock *> successors() { return std::nullopt; }
|
||||||
|
|
||||||
SExpr *returnValue() { return Retval; }
|
SExpr *returnValue() { return Retval; }
|
||||||
const SExpr *returnValue() const { 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_Branch: return cast<Branch>(this)->successors();
|
||||||
case COP_Return: return cast<Return>(this)->successors();
|
case COP_Return: return cast<Return>(this)->successors();
|
||||||
default:
|
default:
|
||||||
return None;
|
return std::nullopt;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -623,7 +623,10 @@ class PrettyPrinter {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void printLiteralPtr(const LiteralPtr *E, StreamType &SS) {
|
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) {
|
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() {
|
llvm::iterator_range<reverse_iterator> reverse() {
|
||||||
return llvm::make_range(rbegin(), rend());
|
return llvm::reverse(*this);
|
||||||
}
|
}
|
||||||
|
|
||||||
llvm::iterator_range<const_reverse_iterator> reverse() const {
|
llvm::iterator_range<const_reverse_iterator> reverse() const {
|
||||||
return llvm::make_range(rbegin(), rend());
|
return llvm::reverse(*this);
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
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/Decl.h"
|
||||||
#include "clang/AST/ExprCXX.h"
|
#include "clang/AST/ExprCXX.h"
|
||||||
#include "clang/AST/ExprObjC.h"
|
#include "clang/AST/ExprObjC.h"
|
||||||
|
#include <optional>
|
||||||
|
|
||||||
namespace clang {
|
namespace clang {
|
||||||
|
|
||||||
@@ -108,8 +109,8 @@ class AnyCall {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// If @c E is a generic call (to ObjC method /function/block/etc),
|
/// If @c E is a generic call (to ObjC method /function/block/etc),
|
||||||
/// return a constructed @c AnyCall object. Return None otherwise.
|
/// return a constructed @c AnyCall object. Return std::nullopt otherwise.
|
||||||
static Optional<AnyCall> forExpr(const Expr *E) {
|
static std::optional<AnyCall> forExpr(const Expr *E) {
|
||||||
if (const auto *ME = dyn_cast<ObjCMessageExpr>(E)) {
|
if (const auto *ME = dyn_cast<ObjCMessageExpr>(E)) {
|
||||||
return AnyCall(ME);
|
return AnyCall(ME);
|
||||||
} else if (const auto *CE = dyn_cast<CallExpr>(E)) {
|
} else if (const auto *CE = dyn_cast<CallExpr>(E)) {
|
||||||
@@ -123,26 +124,26 @@ class AnyCall {
|
|||||||
} else if (const auto *CXCIE = dyn_cast<CXXInheritedCtorInitExpr>(E)) {
|
} else if (const auto *CXCIE = dyn_cast<CXXInheritedCtorInitExpr>(E)) {
|
||||||
return AnyCall(CXCIE);
|
return AnyCall(CXCIE);
|
||||||
} else {
|
} else {
|
||||||
return None;
|
return std::nullopt;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// If @c D is a callable (Objective-C method or a function), return
|
/// 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.
|
// 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)) {
|
if (const auto *FD = dyn_cast<FunctionDecl>(D)) {
|
||||||
return AnyCall(FD);
|
return AnyCall(FD);
|
||||||
} else if (const auto *MD = dyn_cast<ObjCMethodDecl>(D)) {
|
} else if (const auto *MD = dyn_cast<ObjCMethodDecl>(D)) {
|
||||||
return AnyCall(MD);
|
return AnyCall(MD);
|
||||||
}
|
}
|
||||||
return None;
|
return std::nullopt;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// \returns formal parameters for direct calls (including virtual calls)
|
/// \returns formal parameters for direct calls (including virtual calls)
|
||||||
ArrayRef<ParmVarDecl *> parameters() const {
|
ArrayRef<ParmVarDecl *> parameters() const {
|
||||||
if (!D)
|
if (!D)
|
||||||
return None;
|
return std::nullopt;
|
||||||
|
|
||||||
if (const auto *FD = dyn_cast<FunctionDecl>(D)) {
|
if (const auto *FD = dyn_cast<FunctionDecl>(D)) {
|
||||||
return FD->parameters();
|
return FD->parameters();
|
||||||
@@ -151,7 +152,7 @@ class AnyCall {
|
|||||||
} else if (const auto *BD = dyn_cast<BlockDecl>(D)) {
|
} else if (const auto *BD = dyn_cast<BlockDecl>(D)) {
|
||||||
return BD->parameters();
|
return BD->parameters();
|
||||||
} else {
|
} else {
|
||||||
return None;
|
return std::nullopt;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -17,7 +17,7 @@
|
|||||||
#include "clang/AST/DeclBase.h"
|
#include "clang/AST/DeclBase.h"
|
||||||
#include "clang/Basic/LLVM.h"
|
#include "clang/Basic/LLVM.h"
|
||||||
#include "llvm/ADT/DenseMap.h"
|
#include "llvm/ADT/DenseMap.h"
|
||||||
#include "llvm/ADT/Optional.h"
|
#include <optional>
|
||||||
|
|
||||||
namespace clang {
|
namespace clang {
|
||||||
|
|
||||||
@@ -41,7 +41,7 @@ class BodyFarm {
|
|||||||
BodyFarm(const BodyFarm &other) = delete;
|
BodyFarm(const BodyFarm &other) = delete;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
typedef llvm::DenseMap<const Decl *, Optional<Stmt *>> BodyMap;
|
typedef llvm::DenseMap<const Decl *, std::optional<Stmt *>> BodyMap;
|
||||||
|
|
||||||
ASTContext &C;
|
ASTContext &C;
|
||||||
BodyMap Bodies;
|
BodyMap Bodies;
|
||||||
|
|||||||
@@ -21,8 +21,6 @@
|
|||||||
#include "clang/Basic/LLVM.h"
|
#include "clang/Basic/LLVM.h"
|
||||||
#include "llvm/ADT/DenseMap.h"
|
#include "llvm/ADT/DenseMap.h"
|
||||||
#include "llvm/ADT/GraphTraits.h"
|
#include "llvm/ADT/GraphTraits.h"
|
||||||
#include "llvm/ADT/None.h"
|
|
||||||
#include "llvm/ADT/Optional.h"
|
|
||||||
#include "llvm/ADT/PointerIntPair.h"
|
#include "llvm/ADT/PointerIntPair.h"
|
||||||
#include "llvm/ADT/iterator_range.h"
|
#include "llvm/ADT/iterator_range.h"
|
||||||
#include "llvm/Support/Allocator.h"
|
#include "llvm/Support/Allocator.h"
|
||||||
@@ -32,6 +30,7 @@
|
|||||||
#include <cstddef>
|
#include <cstddef>
|
||||||
#include <iterator>
|
#include <iterator>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
|
#include <optional>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
namespace clang {
|
namespace clang {
|
||||||
@@ -103,12 +102,11 @@ class CFGElement {
|
|||||||
return t;
|
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.
|
/// CFGElement is not of the desired type.
|
||||||
template<typename T>
|
template <typename T> std::optional<T> getAs() const {
|
||||||
Optional<T> getAs() const {
|
|
||||||
if (!T::isKind(*this))
|
if (!T::isKind(*this))
|
||||||
return None;
|
return std::nullopt;
|
||||||
T t;
|
T t;
|
||||||
CFGElement& e = t;
|
CFGElement& e = t;
|
||||||
e = *this;
|
e = *this;
|
||||||
@@ -131,7 +129,7 @@ class CFGElement {
|
|||||||
|
|
||||||
class CFGStmt : public CFGElement {
|
class CFGStmt : public CFGElement {
|
||||||
public:
|
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));
|
assert(isKind(*this));
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -155,7 +153,8 @@ class CFGStmt : public CFGElement {
|
|||||||
/// this is only used by the analyzer's CFG.
|
/// this is only used by the analyzer's CFG.
|
||||||
class CFGConstructor : public CFGStmt {
|
class CFGConstructor : public CFGStmt {
|
||||||
public:
|
public:
|
||||||
explicit CFGConstructor(CXXConstructExpr *CE, const ConstructionContext *C)
|
explicit CFGConstructor(const CXXConstructExpr *CE,
|
||||||
|
const ConstructionContext *C)
|
||||||
: CFGStmt(CE, Constructor) {
|
: CFGStmt(CE, Constructor) {
|
||||||
assert(C);
|
assert(C);
|
||||||
Data2.setPointer(const_cast<ConstructionContext *>(C));
|
Data2.setPointer(const_cast<ConstructionContext *>(C));
|
||||||
@@ -185,7 +184,7 @@ class CFGCXXRecordTypedCall : public CFGStmt {
|
|||||||
public:
|
public:
|
||||||
/// Returns true when call expression \p CE needs to be represented
|
/// Returns true when call expression \p CE needs to be represented
|
||||||
/// by CFGCXXRecordTypedCall, as opposed to a regular CFGStmt.
|
/// 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));
|
assert(isa<CallExpr>(E) || isa<ObjCMessageExpr>(E));
|
||||||
// There is no such thing as reference-type expression. If the function
|
// There is no such thing as reference-type expression. If the function
|
||||||
// returns a reference, it'll return the respective lvalue or xvalue
|
// returns a reference, it'll return the respective lvalue or xvalue
|
||||||
@@ -194,7 +193,7 @@ class CFGCXXRecordTypedCall : public CFGStmt {
|
|||||||
E->getType().getCanonicalType()->getAsCXXRecordDecl();
|
E->getType().getCanonicalType()->getAsCXXRecordDecl();
|
||||||
}
|
}
|
||||||
|
|
||||||
explicit CFGCXXRecordTypedCall(Expr *E, const ConstructionContext *C)
|
explicit CFGCXXRecordTypedCall(const Expr *E, const ConstructionContext *C)
|
||||||
: CFGStmt(E, CXXRecordTypedCall) {
|
: CFGStmt(E, CXXRecordTypedCall) {
|
||||||
assert(isCXXRecordTypedCall(E));
|
assert(isCXXRecordTypedCall(E));
|
||||||
assert(C && (isa<TemporaryObjectConstructionContext>(C) ||
|
assert(C && (isa<TemporaryObjectConstructionContext>(C) ||
|
||||||
@@ -225,7 +224,7 @@ class CFGCXXRecordTypedCall : public CFGStmt {
|
|||||||
/// list.
|
/// list.
|
||||||
class CFGInitializer : public CFGElement {
|
class CFGInitializer : public CFGElement {
|
||||||
public:
|
public:
|
||||||
explicit CFGInitializer(CXXCtorInitializer *initializer)
|
explicit CFGInitializer(const CXXCtorInitializer *initializer)
|
||||||
: CFGElement(Initializer, initializer) {}
|
: CFGElement(Initializer, initializer) {}
|
||||||
|
|
||||||
CXXCtorInitializer* getInitializer() const {
|
CXXCtorInitializer* getInitializer() const {
|
||||||
@@ -264,7 +263,7 @@ class CFGNewAllocator : public CFGElement {
|
|||||||
};
|
};
|
||||||
|
|
||||||
/// Represents the point where a loop ends.
|
/// 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.
|
/// 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
|
/// 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.
|
/// expression for temporary object.
|
||||||
class CFGTemporaryDtor : public CFGImplicitDtor {
|
class CFGTemporaryDtor : public CFGImplicitDtor {
|
||||||
public:
|
public:
|
||||||
CFGTemporaryDtor(CXXBindTemporaryExpr *expr)
|
CFGTemporaryDtor(const CXXBindTemporaryExpr *expr)
|
||||||
: CFGImplicitDtor(TemporaryDtor, expr, nullptr) {}
|
: CFGImplicitDtor(TemporaryDtor, expr, nullptr) {}
|
||||||
|
|
||||||
const CXXBindTemporaryExpr *getBindTemporaryExpr() const {
|
const CXXBindTemporaryExpr *getBindTemporaryExpr() const {
|
||||||
@@ -1399,7 +1398,7 @@ class CFG {
|
|||||||
for (const_iterator I = begin(), E = end(); I != E; ++I)
|
for (const_iterator I = begin(), E = end(); I != E; ++I)
|
||||||
for (CFGBlock::const_iterator BI = (*I)->begin(), BE = (*I)->end();
|
for (CFGBlock::const_iterator BI = (*I)->begin(), BE = (*I)->end();
|
||||||
BI != BE; ++BI) {
|
BI != BE; ++BI) {
|
||||||
if (Optional<CFGStmt> stmt = BI->getAs<CFGStmt>())
|
if (std::optional<CFGStmt> stmt = BI->getAs<CFGStmt>())
|
||||||
O(const_cast<Stmt *>(stmt->getStmt()));
|
O(const_cast<Stmt *>(stmt->getStmt()));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1466,6 +1465,8 @@ class CFG {
|
|||||||
llvm::DenseMap<const DeclStmt *, const DeclStmt *> SyntheticDeclStmts;
|
llvm::DenseMap<const DeclStmt *, const DeclStmt *> SyntheticDeclStmts;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
Expr *extractElementInitializerFromNestedAILE(const ArrayInitLoopExpr *AILE);
|
||||||
|
|
||||||
} // namespace clang
|
} // namespace clang
|
||||||
|
|
||||||
//===----------------------------------------------------------------------===//
|
//===----------------------------------------------------------------------===//
|
||||||
|
|||||||
@@ -260,7 +260,7 @@ class RecursiveCloneTypeIIHashConstraint {
|
|||||||
///
|
///
|
||||||
/// Clones that aren't type II clones are moved into separate clone groups.
|
/// Clones that aren't type II clones are moved into separate clone groups.
|
||||||
/// In contrast to the RecursiveCloneTypeIIHashConstraint, all clones in a clone
|
/// 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.
|
/// slow to efficiently handle large amounts of clones.
|
||||||
class RecursiveCloneTypeIIVerifyConstraint {
|
class RecursiveCloneTypeIIVerifyConstraint {
|
||||||
public:
|
public:
|
||||||
|
|||||||
@@ -542,7 +542,7 @@ class SimpleTemporaryObjectConstructionContext
|
|||||||
/// of being immediately copied by an elidable copy/move constructor.
|
/// of being immediately copied by an elidable copy/move constructor.
|
||||||
/// For example, T t = T(123); includes a temporary T(123) that is immediately
|
/// 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
|
/// 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.
|
/// language; the constructor would then construct variable t directly.
|
||||||
/// This construction context contains information of the elidable constructor
|
/// This construction context contains information of the elidable constructor
|
||||||
/// and its respective construction context.
|
/// 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.
|
/// analysis.
|
||||||
class ControlFlowContext {
|
class ControlFlowContext {
|
||||||
public:
|
public:
|
||||||
/// Builds a ControlFlowContext from an AST node.
|
/// Builds a ControlFlowContext from an AST node. `D` is the function in which
|
||||||
static llvm::Expected<ControlFlowContext> build(const Decl *D, Stmt *S,
|
/// `S` resides and must not be null.
|
||||||
ASTContext *C);
|
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.
|
/// Returns the CFG that is stored in this context.
|
||||||
const CFG &getCFG() const { return *Cfg; }
|
const CFG &getCFG() const { return *Cfg; }
|
||||||
@@ -43,10 +48,15 @@ class ControlFlowContext {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private:
|
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)
|
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;
|
std::unique_ptr<CFG> Cfg;
|
||||||
llvm::DenseMap<const Stmt *, const CFGBlock *> StmtToBlock;
|
llvm::DenseMap<const Stmt *, const CFGBlock *> StmtToBlock;
|
||||||
};
|
};
|
||||||
|
|||||||
+95
-25
@@ -15,17 +15,18 @@
|
|||||||
#define LLVM_CLANG_ANALYSIS_FLOWSENSITIVE_DATAFLOWANALYSIS_H
|
#define LLVM_CLANG_ANALYSIS_FLOWSENSITIVE_DATAFLOWANALYSIS_H
|
||||||
|
|
||||||
#include <iterator>
|
#include <iterator>
|
||||||
|
#include <optional>
|
||||||
|
#include <type_traits>
|
||||||
#include <utility>
|
#include <utility>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
#include "clang/AST/ASTContext.h"
|
#include "clang/AST/ASTContext.h"
|
||||||
#include "clang/AST/Stmt.h"
|
|
||||||
#include "clang/Analysis/CFG.h"
|
#include "clang/Analysis/CFG.h"
|
||||||
#include "clang/Analysis/FlowSensitive/ControlFlowContext.h"
|
#include "clang/Analysis/FlowSensitive/ControlFlowContext.h"
|
||||||
#include "clang/Analysis/FlowSensitive/DataflowEnvironment.h"
|
#include "clang/Analysis/FlowSensitive/DataflowEnvironment.h"
|
||||||
|
#include "clang/Analysis/FlowSensitive/DataflowLattice.h"
|
||||||
#include "clang/Analysis/FlowSensitive/TypeErasedDataflowAnalysis.h"
|
#include "clang/Analysis/FlowSensitive/TypeErasedDataflowAnalysis.h"
|
||||||
#include "llvm/ADT/Any.h"
|
#include "llvm/ADT/Any.h"
|
||||||
#include "llvm/ADT/Optional.h"
|
|
||||||
#include "llvm/ADT/STLExtras.h"
|
#include "llvm/ADT/STLExtras.h"
|
||||||
#include "llvm/Support/Error.h"
|
#include "llvm/Support/Error.h"
|
||||||
|
|
||||||
@@ -40,8 +41,14 @@ namespace dataflow {
|
|||||||
/// must provide the following public members:
|
/// must provide the following public members:
|
||||||
/// * `LatticeT initialElement()` - returns a lattice element that models the
|
/// * `LatticeT initialElement()` - returns a lattice element that models the
|
||||||
/// initial state of a basic block;
|
/// initial state of a basic block;
|
||||||
/// * `void transfer(const Stmt *, LatticeT &, Environment &)` - applies the
|
/// * `void transfer(const CFGElement *, LatticeT &, Environment &)` - applies
|
||||||
/// analysis transfer function for a given statement and lattice element.
|
/// 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:
|
/// `Derived` can optionally override the following members:
|
||||||
/// * `bool merge(QualType, const Value &, const Value &, Value &,
|
/// * `bool merge(QualType, const Value &, const Value &, Value &,
|
||||||
@@ -56,6 +63,15 @@ namespace dataflow {
|
|||||||
/// made to it;
|
/// made to it;
|
||||||
/// * `bool operator==(const LatticeT &) const` - returns true if and only if
|
/// * `bool operator==(const LatticeT &) const` - returns true if and only if
|
||||||
/// the object is equal to the argument.
|
/// 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>
|
template <typename Derived, typename LatticeT>
|
||||||
class DataflowAnalysis : public TypeErasedDataflowAnalysis {
|
class DataflowAnalysis : public TypeErasedDataflowAnalysis {
|
||||||
public:
|
public:
|
||||||
@@ -66,7 +82,11 @@ class DataflowAnalysis : public TypeErasedDataflowAnalysis {
|
|||||||
|
|
||||||
/// Deprecated. Use the `DataflowAnalysisOptions` constructor instead.
|
/// Deprecated. Use the `DataflowAnalysisOptions` constructor instead.
|
||||||
explicit DataflowAnalysis(ASTContext &Context, bool ApplyBuiltinTransfer)
|
explicit DataflowAnalysis(ASTContext &Context, bool ApplyBuiltinTransfer)
|
||||||
: TypeErasedDataflowAnalysis(ApplyBuiltinTransfer), Context(Context) {}
|
: DataflowAnalysis(
|
||||||
|
Context,
|
||||||
|
{ApplyBuiltinTransfer
|
||||||
|
? DataflowAnalysisContext::Options{}
|
||||||
|
: std::optional<DataflowAnalysisContext::Options>()}) {}
|
||||||
|
|
||||||
explicit DataflowAnalysis(ASTContext &Context,
|
explicit DataflowAnalysis(ASTContext &Context,
|
||||||
DataflowAnalysisOptions Options)
|
DataflowAnalysisOptions Options)
|
||||||
@@ -85,6 +105,13 @@ class DataflowAnalysis : public TypeErasedDataflowAnalysis {
|
|||||||
return L1.join(L2);
|
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,
|
bool isEqualTypeErased(const TypeErasedLattice &E1,
|
||||||
const TypeErasedLattice &E2) final {
|
const TypeErasedLattice &E2) final {
|
||||||
const Lattice &L1 = llvm::any_cast<const Lattice &>(E1.Value);
|
const Lattice &L1 = llvm::any_cast<const Lattice &>(E1.Value);
|
||||||
@@ -92,13 +119,55 @@ class DataflowAnalysis : public TypeErasedDataflowAnalysis {
|
|||||||
return L1 == L2;
|
return L1 == L2;
|
||||||
}
|
}
|
||||||
|
|
||||||
void transferTypeErased(const Stmt *Stmt, TypeErasedLattice &E,
|
void transferTypeErased(const CFGElement *Element, TypeErasedLattice &E,
|
||||||
Environment &Env) final {
|
Environment &Env) final {
|
||||||
Lattice &L = llvm::any_cast<Lattice &>(E.Value);
|
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:
|
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;
|
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
|
/// 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
|
/// blocks, with indices corresponding to basic block IDs. Returns an error if
|
||||||
/// the dataflow analysis cannot be performed successfully. Otherwise, calls
|
/// 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.
|
/// program point.
|
||||||
template <typename AnalysisT>
|
template <typename AnalysisT>
|
||||||
llvm::Expected<std::vector<
|
llvm::Expected<std::vector<
|
||||||
llvm::Optional<DataflowAnalysisState<typename AnalysisT::Lattice>>>>
|
std::optional<DataflowAnalysisState<typename AnalysisT::Lattice>>>>
|
||||||
runDataflowAnalysis(
|
runDataflowAnalysis(
|
||||||
const ControlFlowContext &CFCtx, AnalysisT &Analysis,
|
const ControlFlowContext &CFCtx, AnalysisT &Analysis,
|
||||||
const Environment &InitEnv,
|
const Environment &InitEnv,
|
||||||
std::function<void(const Stmt *, const DataflowAnalysisState<
|
std::function<void(const CFGElement &, const DataflowAnalysisState<
|
||||||
typename AnalysisT::Lattice> &)>
|
typename AnalysisT::Lattice> &)>
|
||||||
PostVisitStmt = nullptr) {
|
PostVisitCFG = nullptr) {
|
||||||
std::function<void(const Stmt *, const TypeErasedDataflowAnalysisState &)>
|
std::function<void(const CFGElement &,
|
||||||
PostVisitStmtClosure = nullptr;
|
const TypeErasedDataflowAnalysisState &)>
|
||||||
if (PostVisitStmt != nullptr) {
|
PostVisitCFGClosure = nullptr;
|
||||||
PostVisitStmtClosure = [&PostVisitStmt](
|
if (PostVisitCFG) {
|
||||||
const Stmt *Stmt,
|
PostVisitCFGClosure = [&PostVisitCFG](
|
||||||
|
const CFGElement &Element,
|
||||||
const TypeErasedDataflowAnalysisState &State) {
|
const TypeErasedDataflowAnalysisState &State) {
|
||||||
auto *Lattice =
|
auto *Lattice =
|
||||||
llvm::any_cast<typename AnalysisT::Lattice>(&State.Lattice.Value);
|
llvm::any_cast<typename AnalysisT::Lattice>(&State.Lattice.Value);
|
||||||
PostVisitStmt(Stmt, DataflowAnalysisState<typename AnalysisT::Lattice>{
|
PostVisitCFG(Element, DataflowAnalysisState<typename AnalysisT::Lattice>{
|
||||||
*Lattice, State.Env});
|
*Lattice, State.Env});
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
auto TypeErasedBlockStates = runTypeErasedDataflowAnalysis(
|
auto TypeErasedBlockStates = runTypeErasedDataflowAnalysis(
|
||||||
CFCtx, Analysis, InitEnv, PostVisitStmtClosure);
|
CFCtx, Analysis, InitEnv, PostVisitCFGClosure);
|
||||||
if (!TypeErasedBlockStates)
|
if (!TypeErasedBlockStates)
|
||||||
return TypeErasedBlockStates.takeError();
|
return TypeErasedBlockStates.takeError();
|
||||||
|
|
||||||
std::vector<
|
std::vector<std::optional<DataflowAnalysisState<typename AnalysisT::Lattice>>>
|
||||||
llvm::Optional<DataflowAnalysisState<typename AnalysisT::Lattice>>>
|
|
||||||
BlockStates;
|
BlockStates;
|
||||||
BlockStates.reserve(TypeErasedBlockStates->size());
|
BlockStates.reserve(TypeErasedBlockStates->size());
|
||||||
|
|
||||||
llvm::transform(std::move(*TypeErasedBlockStates),
|
llvm::transform(
|
||||||
std::back_inserter(BlockStates), [](auto &OptState) {
|
std::move(*TypeErasedBlockStates), std::back_inserter(BlockStates),
|
||||||
return std::move(OptState).map([](auto &&State) {
|
[](auto &OptState) {
|
||||||
|
return llvm::transformOptional(std::move(OptState), [](auto &&State) {
|
||||||
return DataflowAnalysisState<typename AnalysisT::Lattice>{
|
return DataflowAnalysisState<typename AnalysisT::Lattice>{
|
||||||
llvm::any_cast<typename AnalysisT::Lattice>(
|
llvm::any_cast<typename AnalysisT::Lattice>(
|
||||||
std::move(State.Lattice.Value)),
|
std::move(State.Lattice.Value)),
|
||||||
@@ -167,8 +237,8 @@ runDataflowAnalysis(
|
|||||||
/// example, a model may capture a type and its related functions.
|
/// example, a model may capture a type and its related functions.
|
||||||
class DataflowModel : public Environment::ValueModel {
|
class DataflowModel : public Environment::ValueModel {
|
||||||
public:
|
public:
|
||||||
/// Return value indicates whether the model processed the `Stmt`.
|
/// Return value indicates whether the model processed the `Element`.
|
||||||
virtual bool transfer(const Stmt *Stmt, Environment &Env) = 0;
|
virtual bool transfer(const CFGElement *Element, Environment &Env) = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace dataflow
|
} // namespace dataflow
|
||||||
|
|||||||
+59
-27
@@ -18,6 +18,7 @@
|
|||||||
#include "clang/AST/Decl.h"
|
#include "clang/AST/Decl.h"
|
||||||
#include "clang/AST/Expr.h"
|
#include "clang/AST/Expr.h"
|
||||||
#include "clang/AST/TypeOrdering.h"
|
#include "clang/AST/TypeOrdering.h"
|
||||||
|
#include "clang/Analysis/FlowSensitive/ControlFlowContext.h"
|
||||||
#include "clang/Analysis/FlowSensitive/Solver.h"
|
#include "clang/Analysis/FlowSensitive/Solver.h"
|
||||||
#include "clang/Analysis/FlowSensitive/StorageLocation.h"
|
#include "clang/Analysis/FlowSensitive/StorageLocation.h"
|
||||||
#include "clang/Analysis/FlowSensitive/Value.h"
|
#include "clang/Analysis/FlowSensitive/Value.h"
|
||||||
@@ -26,6 +27,7 @@
|
|||||||
#include "llvm/Support/Compiler.h"
|
#include "llvm/Support/Compiler.h"
|
||||||
#include <cassert>
|
#include <cassert>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
|
#include <optional>
|
||||||
#include <type_traits>
|
#include <type_traits>
|
||||||
#include <utility>
|
#include <utility>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
@@ -49,18 +51,34 @@ const Stmt &ignoreCFGOmittedNodes(const Stmt &S);
|
|||||||
/// Returns the set of all fields in the type.
|
/// Returns the set of all fields in the type.
|
||||||
llvm::DenseSet<const FieldDecl *> getObjectFields(QualType 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
|
/// Owns objects that encompass the state of a program and stores context that
|
||||||
/// is used during dataflow analysis.
|
/// is used during dataflow analysis.
|
||||||
class DataflowAnalysisContext {
|
class DataflowAnalysisContext {
|
||||||
public:
|
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.
|
/// Constructs a dataflow analysis context.
|
||||||
///
|
///
|
||||||
/// Requirements:
|
/// Requirements:
|
||||||
///
|
///
|
||||||
/// `S` must not be null.
|
/// `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()),
|
: S(std::move(S)), TrueVal(createAtomicBoolValue()),
|
||||||
FalseVal(createAtomicBoolValue()) {
|
FalseVal(createAtomicBoolValue()), Opts(Opts) {
|
||||||
assert(this->S != nullptr);
|
assert(this->S != nullptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -70,7 +88,7 @@ class DataflowAnalysisContext {
|
|||||||
///
|
///
|
||||||
/// `Loc` must not be null.
|
/// `Loc` must not be null.
|
||||||
template <typename T>
|
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) {
|
takeOwnership(std::unique_ptr<T> Loc) {
|
||||||
assert(Loc != nullptr);
|
assert(Loc != nullptr);
|
||||||
Locs.push_back(std::move(Loc));
|
Locs.push_back(std::move(Loc));
|
||||||
@@ -83,19 +101,17 @@ class DataflowAnalysisContext {
|
|||||||
///
|
///
|
||||||
/// `Val` must not be null.
|
/// `Val` must not be null.
|
||||||
template <typename T>
|
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) {
|
takeOwnership(std::unique_ptr<T> Val) {
|
||||||
assert(Val != nullptr);
|
assert(Val != nullptr);
|
||||||
Vals.push_back(std::move(Val));
|
Vals.push_back(std::move(Val));
|
||||||
return *cast<T>(Vals.back().get());
|
return *cast<T>(Vals.back().get());
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns a stable storage location appropriate for `Type`.
|
/// Returns a new storage location appropriate for `Type`.
|
||||||
///
|
///
|
||||||
/// Requirements:
|
/// A null `Type` is interpreted as the pointee type of `std::nullptr_t`.
|
||||||
///
|
StorageLocation &createStorageLocation(QualType Type);
|
||||||
/// `Type` must not be null.
|
|
||||||
StorageLocation &getStableStorageLocation(QualType Type);
|
|
||||||
|
|
||||||
/// Returns a stable storage location for `D`.
|
/// Returns a stable storage location for `D`.
|
||||||
StorageLocation &getStableStorageLocation(const VarDecl &D);
|
StorageLocation &getStableStorageLocation(const VarDecl &D);
|
||||||
@@ -138,22 +154,6 @@ class DataflowAnalysisContext {
|
|||||||
return It == ExprToLoc.end() ? nullptr : It->second;
|
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
|
/// Returns a pointer value that represents a null pointer. Calls with
|
||||||
/// `PointeeType` that are canonically equivalent will return the same result.
|
/// `PointeeType` that are canonically equivalent will return the same result.
|
||||||
/// A null `PointeeType` can be used for the pointee of `std::nullptr_t`.
|
/// 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>());
|
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
|
/// Returns a boolean value that represents the conjunction of `LHS` and
|
||||||
/// `RHS`. Subsequent calls with the same arguments, regardless of their
|
/// `RHS`. Subsequent calls with the same arguments, regardless of their
|
||||||
/// order, will return the same result. If the given boolean values represent
|
/// 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);
|
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:
|
private:
|
||||||
|
friend class Environment;
|
||||||
|
|
||||||
struct NullableQualTypeDenseMapInfo : private llvm::DenseMapInfo<QualType> {
|
struct NullableQualTypeDenseMapInfo : private llvm::DenseMapInfo<QualType> {
|
||||||
static QualType getEmptyKey() {
|
static QualType getEmptyKey() {
|
||||||
// Allow a NULL `QualType` by using a different value as the empty key.
|
// Allow a NULL `QualType` by using a different value as the empty key.
|
||||||
@@ -266,6 +286,13 @@ class DataflowAnalysisContext {
|
|||||||
using DenseMapInfo::isEqual;
|
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
|
/// Adds all constraints of the flow condition identified by `Token` and all
|
||||||
/// of its transitive dependencies to `Constraints`. `VisitedTokens` is used
|
/// of its transitive dependencies to `Constraints`. `VisitedTokens` is used
|
||||||
/// to track tokens of flow conditions that were already visited by recursive
|
/// 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 ValueDecl *, StorageLocation *> DeclToLoc;
|
||||||
llvm::DenseMap<const Expr *, StorageLocation *> ExprToLoc;
|
llvm::DenseMap<const Expr *, StorageLocation *> ExprToLoc;
|
||||||
|
|
||||||
StorageLocation *ThisPointeeLoc = nullptr;
|
|
||||||
|
|
||||||
// Null pointer values, keyed by the canonical pointee type.
|
// Null pointer values, keyed by the canonical pointee type.
|
||||||
//
|
//
|
||||||
// FIXME: The pointer values are indexed by the pointee types which are
|
// FIXME: The pointer values are indexed by the pointee types which are
|
||||||
@@ -333,6 +358,8 @@ class DataflowAnalysisContext {
|
|||||||
AtomicBoolValue &TrueVal;
|
AtomicBoolValue &TrueVal;
|
||||||
AtomicBoolValue &FalseVal;
|
AtomicBoolValue &FalseVal;
|
||||||
|
|
||||||
|
Options Opts;
|
||||||
|
|
||||||
// Indices that are used to avoid recreating the same composite boolean
|
// Indices that are used to avoid recreating the same composite boolean
|
||||||
// values.
|
// values.
|
||||||
llvm::DenseMap<std::pair<BoolValue *, BoolValue *>, ConjunctionValue *>
|
llvm::DenseMap<std::pair<BoolValue *, BoolValue *>, ConjunctionValue *>
|
||||||
@@ -360,6 +387,11 @@ class DataflowAnalysisContext {
|
|||||||
llvm::DenseMap<AtomicBoolValue *, llvm::DenseSet<AtomicBoolValue *>>
|
llvm::DenseMap<AtomicBoolValue *, llvm::DenseSet<AtomicBoolValue *>>
|
||||||
FlowConditionDeps;
|
FlowConditionDeps;
|
||||||
llvm::DenseMap<AtomicBoolValue *, BoolValue *> FlowConditionConstraints;
|
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
|
} // namespace dataflow
|
||||||
|
|||||||
+127
-12
@@ -19,12 +19,14 @@
|
|||||||
#include "clang/AST/DeclBase.h"
|
#include "clang/AST/DeclBase.h"
|
||||||
#include "clang/AST/Expr.h"
|
#include "clang/AST/Expr.h"
|
||||||
#include "clang/AST/Type.h"
|
#include "clang/AST/Type.h"
|
||||||
|
#include "clang/Analysis/FlowSensitive/ControlFlowContext.h"
|
||||||
#include "clang/Analysis/FlowSensitive/DataflowAnalysisContext.h"
|
#include "clang/Analysis/FlowSensitive/DataflowAnalysisContext.h"
|
||||||
#include "clang/Analysis/FlowSensitive/DataflowLattice.h"
|
#include "clang/Analysis/FlowSensitive/DataflowLattice.h"
|
||||||
#include "clang/Analysis/FlowSensitive/StorageLocation.h"
|
#include "clang/Analysis/FlowSensitive/StorageLocation.h"
|
||||||
#include "clang/Analysis/FlowSensitive/Value.h"
|
#include "clang/Analysis/FlowSensitive/Value.h"
|
||||||
#include "llvm/ADT/DenseMap.h"
|
#include "llvm/ADT/DenseMap.h"
|
||||||
#include "llvm/ADT/DenseSet.h"
|
#include "llvm/ADT/DenseSet.h"
|
||||||
|
#include "llvm/Support/ErrorHandling.h"
|
||||||
#include <memory>
|
#include <memory>
|
||||||
#include <type_traits>
|
#include <type_traits>
|
||||||
#include <utility>
|
#include <utility>
|
||||||
@@ -47,6 +49,13 @@ enum class SkipPast {
|
|||||||
ReferenceThenPointer,
|
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.
|
/// 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
|
/// WARNING: Symbolic values that are created by the environment for static
|
||||||
@@ -61,7 +70,11 @@ class Environment {
|
|||||||
public:
|
public:
|
||||||
virtual ~ValueModel() = default;
|
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:
|
/// Requirements:
|
||||||
///
|
///
|
||||||
@@ -71,16 +84,12 @@ class Environment {
|
|||||||
///
|
///
|
||||||
/// `Val1` and `Val2` must be assigned to the same storage location in
|
/// `Val1` and `Val2` must be assigned to the same storage location in
|
||||||
/// `Env1` and `Env2` respectively.
|
/// `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 &Env1, const Value &Val2,
|
||||||
const Environment &Env2) {
|
const Environment &Env2) {
|
||||||
// FIXME: Consider adding QualType to StructValue and removing the Type
|
// FIXME: Consider adding QualType to StructValue and removing the Type
|
||||||
// argument here.
|
// argument here.
|
||||||
//
|
return ComparisonResult::Unknown;
|
||||||
// FIXME: default to a sound comparison and/or expand the comparison logic
|
|
||||||
// built into the framework to support broader forms of equivalence than
|
|
||||||
// strict pointer equality.
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Modifies `MergedVal` to approximate both `Val1` and `Val2`. This could
|
/// Modifies `MergedVal` to approximate both `Val1` and `Val2`. This could
|
||||||
@@ -106,6 +115,46 @@ class Environment {
|
|||||||
Environment &MergedEnv) {
|
Environment &MergedEnv) {
|
||||||
return true;
|
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
|
/// 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.
|
/// with a symbolic representation of the `this` pointee.
|
||||||
Environment(DataflowAnalysisContext &DACtx, const DeclContext &DeclCtx);
|
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
|
/// 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
|
/// callee. Uses the storage location from each argument in the `Call` as the
|
||||||
/// storage location for the corresponding parameter in the callee.
|
/// storage location for the corresponding parameter in the callee.
|
||||||
///
|
///
|
||||||
/// Requirements:
|
/// 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 body of the callee must not reference globals.
|
||||||
///
|
///
|
||||||
/// The arguments of `Call` must map 1:1 to the callee's parameters.
|
/// 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 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
|
/// Returns true if and only if the environment is equivalent to `Other`, i.e
|
||||||
/// the two environments:
|
/// the two environments:
|
||||||
@@ -167,6 +223,17 @@ class Environment {
|
|||||||
LatticeJoinEffect join(const Environment &Other,
|
LatticeJoinEffect join(const Environment &Other,
|
||||||
Environment::ValueModel &Model);
|
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`,
|
// FIXME: Rename `createOrGetStorageLocation` to `getOrCreateStorageLocation`,
|
||||||
// `getStableStorageLocation`, or something more appropriate.
|
// `getStableStorageLocation`, or something more appropriate.
|
||||||
|
|
||||||
@@ -217,6 +284,9 @@ class Environment {
|
|||||||
/// in the environment.
|
/// in the environment.
|
||||||
StorageLocation *getThisPointeeStorageLocation() const;
|
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
|
/// Returns a pointer value that represents a null pointer. Calls with
|
||||||
/// `PointeeType` that are canonically equivalent will return the same result.
|
/// `PointeeType` that are canonically equivalent will return the same result.
|
||||||
PointerValue &getOrCreateNullPointerValue(QualType PointeeType);
|
PointerValue &getOrCreateNullPointerValue(QualType PointeeType);
|
||||||
@@ -253,7 +323,7 @@ class Environment {
|
|||||||
///
|
///
|
||||||
/// `Loc` must not be null.
|
/// `Loc` must not be null.
|
||||||
template <typename T>
|
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) {
|
takeOwnership(std::unique_ptr<T> Loc) {
|
||||||
return DACtx->takeOwnership(std::move(Loc));
|
return DACtx->takeOwnership(std::move(Loc));
|
||||||
}
|
}
|
||||||
@@ -265,7 +335,7 @@ class Environment {
|
|||||||
///
|
///
|
||||||
/// `Val` must not be null.
|
/// `Val` must not be null.
|
||||||
template <typename T>
|
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) {
|
takeOwnership(std::unique_ptr<T> Val) {
|
||||||
return DACtx->takeOwnership(std::move(Val));
|
return DACtx->takeOwnership(std::move(Val));
|
||||||
}
|
}
|
||||||
@@ -281,6 +351,11 @@ class Environment {
|
|||||||
return DACtx->createAtomicBoolValue();
|
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
|
/// Returns a boolean value that represents the conjunction of `LHS` and
|
||||||
/// `RHS`. Subsequent calls with the same arguments, regardless of their
|
/// `RHS`. Subsequent calls with the same arguments, regardless of their
|
||||||
/// order, will return the same result. If the given boolean values represent
|
/// order, will return the same result. If the given boolean values represent
|
||||||
@@ -339,7 +414,23 @@ class Environment {
|
|||||||
/// imply that `Val` is true.
|
/// imply that `Val` is true.
|
||||||
bool flowConditionImplies(BoolValue &Val) const;
|
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() const;
|
||||||
|
LLVM_DUMP_METHOD void dump(raw_ostream &OS) const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
/// Creates a value appropriate for `Type`, if `Type` is supported, otherwise
|
/// Creates a value appropriate for `Type`, if `Type` is supported, otherwise
|
||||||
@@ -360,9 +451,33 @@ class Environment {
|
|||||||
StorageLocation &skip(StorageLocation &Loc, SkipPast SP) const;
|
StorageLocation &skip(StorageLocation &Loc, SkipPast SP) const;
|
||||||
const StorageLocation &skip(const 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.
|
// `DACtx` is not null and not owned by this object.
|
||||||
DataflowAnalysisContext *DACtx;
|
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
|
// Maps from program declarations and statements to storage locations that are
|
||||||
// assigned to them. Unlike the maps in `DataflowAnalysisContext`, these
|
// assigned to them. Unlike the maps in `DataflowAnalysisContext`, these
|
||||||
// include only storage locations that are in scope for a particular basic
|
// include only storage locations that are in scope for a particular basic
|
||||||
|
|||||||
@@ -18,6 +18,8 @@ namespace clang {
|
|||||||
namespace dataflow {
|
namespace dataflow {
|
||||||
|
|
||||||
/// Effect indicating whether a lattice join operation resulted in a new value.
|
/// 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 {
|
enum class LatticeJoinEffect {
|
||||||
Unchanged,
|
Unchanged,
|
||||||
Changed,
|
Changed,
|
||||||
|
|||||||
@@ -134,7 +134,7 @@ class DataflowValues {
|
|||||||
/// getBlockDataMap - Retrieves the internal map between CFGBlocks and
|
/// getBlockDataMap - Retrieves the internal map between CFGBlocks and
|
||||||
/// dataflow values. If the dataflow analysis operates in the forward
|
/// dataflow values. If the dataflow analysis operates in the forward
|
||||||
/// direction, the values correspond to the dataflow values at the start
|
/// 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.
|
/// to the dataflow values at the end of the block.
|
||||||
BlockDataMapTy& getBlockDataMap() { return BlockDataMap; }
|
BlockDataMapTy& getBlockDataMap() { return BlockDataMap; }
|
||||||
const BlockDataMapTy& getBlockDataMap() const { return BlockDataMap; }
|
const BlockDataMapTy& getBlockDataMap() const { return BlockDataMap; }
|
||||||
|
|||||||
@@ -20,15 +20,19 @@
|
|||||||
#include "clang/Analysis/FlowSensitive/Solver.h"
|
#include "clang/Analysis/FlowSensitive/Solver.h"
|
||||||
#include "clang/Analysis/FlowSensitive/Value.h"
|
#include "clang/Analysis/FlowSensitive/Value.h"
|
||||||
#include "llvm/ADT/DenseMap.h"
|
#include "llvm/ADT/DenseMap.h"
|
||||||
|
#include "llvm/ADT/StringRef.h"
|
||||||
|
|
||||||
namespace clang {
|
namespace clang {
|
||||||
namespace dataflow {
|
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.
|
/// 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.
|
/// 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`.
|
/// Returns a string representation for the boolean value `B`.
|
||||||
///
|
///
|
||||||
|
|||||||
@@ -16,6 +16,9 @@
|
|||||||
// library may be generalized and moved to ASTMatchers.
|
// 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_
|
#ifndef LLVM_CLANG_ANALYSIS_FLOWSENSITIVE_MATCHSWITCH_H_
|
||||||
#define LLVM_CLANG_ANALYSIS_FLOWSENSITIVE_MATCHSWITCH_H_
|
#define LLVM_CLANG_ANALYSIS_FLOWSENSITIVE_MATCHSWITCH_H_
|
||||||
@@ -28,6 +31,7 @@
|
|||||||
#include "llvm/ADT/StringRef.h"
|
#include "llvm/ADT/StringRef.h"
|
||||||
#include <functional>
|
#include <functional>
|
||||||
#include <string>
|
#include <string>
|
||||||
|
#include <type_traits>
|
||||||
#include <utility>
|
#include <utility>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
@@ -44,23 +48,45 @@ template <typename LatticeT> struct TransferState {
|
|||||||
Environment &Env;
|
Environment &Env;
|
||||||
};
|
};
|
||||||
|
|
||||||
/// Matches against `Stmt` and, based on its structure, dispatches to an
|
/// A read-only version of TransferState.
|
||||||
/// appropriate handler.
|
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>
|
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
|
/// Collects cases of a "match switch": a collection of matchers paired with
|
||||||
/// callbacks, which together define a switch that can be applied to a
|
/// callbacks, which together define a switch that can be applied to a node
|
||||||
/// `Stmt`. This structure can simplify the definition of `transfer` functions
|
/// whose type derives from `BaseT`. This structure can simplify the definition
|
||||||
/// that rely on pattern-matching.
|
/// of `transfer` functions that rely on pattern-matching.
|
||||||
///
|
///
|
||||||
/// For example, consider an analysis that handles particular function calls. It
|
/// For example, consider an analysis that handles particular function calls. It
|
||||||
/// can define the `MatchSwitch` once, in the constructor of the analysis, and
|
/// can define the `ASTMatchSwitch` once, in the constructor of the analysis,
|
||||||
/// then reuse it each time that `transfer` is called, with a fresh state value.
|
/// and then reuse it each time that `transfer` is called, with a fresh state
|
||||||
|
/// value.
|
||||||
///
|
///
|
||||||
/// \code
|
/// \code
|
||||||
/// MatchSwitch<TransferState<MyLattice> BuildSwitch() {
|
/// ASTMatchSwitch<Stmt, TransferState<MyLattice> BuildSwitch() {
|
||||||
/// return MatchSwitchBuilder<TransferState<MyLattice>>()
|
/// return ASTMatchSwitchBuilder<TransferState<MyLattice>>()
|
||||||
/// .CaseOf(callExpr(callee(functionDecl(hasName("foo")))), TransferFooCall)
|
/// .CaseOf(callExpr(callee(functionDecl(hasName("foo")))), TransferFooCall)
|
||||||
/// .CaseOf(callExpr(argumentCountIs(2),
|
/// .CaseOf(callExpr(argumentCountIs(2),
|
||||||
/// callee(functionDecl(hasName("bar")))),
|
/// callee(functionDecl(hasName("bar")))),
|
||||||
@@ -68,35 +94,35 @@ using MatchSwitch = std::function<Result(const Stmt &, ASTContext &, State &)>;
|
|||||||
/// .Build();
|
/// .Build();
|
||||||
/// }
|
/// }
|
||||||
/// \endcode
|
/// \endcode
|
||||||
template <typename State, typename Result = void> class MatchSwitchBuilder {
|
template <typename BaseT, typename State, typename Result = void>
|
||||||
|
class ASTMatchSwitchBuilder {
|
||||||
public:
|
public:
|
||||||
/// Registers an action that will be triggered by the match of a pattern
|
/// Registers an action that will be triggered by the match of a pattern
|
||||||
/// against the input statement.
|
/// against the input statement.
|
||||||
///
|
///
|
||||||
/// Requirements:
|
/// Requirements:
|
||||||
///
|
///
|
||||||
/// `Node` should be a subclass of `Stmt`.
|
/// `NodeT` should be derived from `BaseT`.
|
||||||
template <typename Node>
|
template <typename NodeT>
|
||||||
MatchSwitchBuilder &&
|
ASTMatchSwitchBuilder &&CaseOf(MatchSwitchMatcher<BaseT> M,
|
||||||
CaseOf(ast_matchers::internal::Matcher<Stmt> M,
|
MatchSwitchAction<NodeT, State, Result> A) && {
|
||||||
std::function<Result(const Node *,
|
static_assert(std::is_base_of<BaseT, NodeT>::value,
|
||||||
const ast_matchers::MatchFinder::MatchResult &,
|
"NodeT must be derived from BaseT.");
|
||||||
State &)>
|
|
||||||
A) && {
|
|
||||||
Matchers.push_back(std::move(M));
|
Matchers.push_back(std::move(M));
|
||||||
Actions.push_back(
|
Actions.push_back(
|
||||||
[A = std::move(A)](const Stmt *Stmt,
|
[A = std::move(A)](const BaseT *Node,
|
||||||
const ast_matchers::MatchFinder::MatchResult &R,
|
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);
|
return std::move(*this);
|
||||||
}
|
}
|
||||||
|
|
||||||
MatchSwitch<State, Result> Build() && {
|
ASTMatchSwitch<BaseT, State, Result> Build() && {
|
||||||
return [Matcher = BuildMatcher(), Actions = std::move(Actions)](
|
return [Matcher = BuildMatcher(), Actions = std::move(Actions)](
|
||||||
const Stmt &Stmt, ASTContext &Context, State &S) -> Result {
|
const BaseT &Node, ASTContext &Context, State &S) -> Result {
|
||||||
auto Results = ast_matchers::matchDynamic(Matcher, Stmt, Context);
|
auto Results = ast_matchers::matchDynamic(Matcher, Node, Context);
|
||||||
if (Results.empty())
|
if (Results.empty()) {
|
||||||
return Result();
|
return Result();
|
||||||
|
}
|
||||||
// Look through the map for the first binding of the form "TagN..." use
|
// Look through the map for the first binding of the form "TagN..." use
|
||||||
// that to select the action.
|
// that to select the action.
|
||||||
for (const auto &Element : Results[0].getMap()) {
|
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) &&
|
if (ID.consume_front("Tag") && !ID.getAsInteger(10, Index) &&
|
||||||
Index < Actions.size()) {
|
Index < Actions.size()) {
|
||||||
return Actions[Index](
|
return Actions[Index](
|
||||||
&Stmt,
|
&Node,
|
||||||
ast_matchers::MatchFinder::MatchResult(Results[0], &Context), S);
|
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
|
// The matcher type on the cases ensures that `Expr` kind is compatible with
|
||||||
// all of the matchers.
|
// all of the matchers.
|
||||||
return DynTypedMatcher::constructVariadic(
|
return DynTypedMatcher::constructVariadic(
|
||||||
DynTypedMatcher::VO_AnyOf, ASTNodeKind::getFromNodeKind<Stmt>(),
|
DynTypedMatcher::VO_AnyOf, ASTNodeKind::getFromNodeKind<BaseT>(),
|
||||||
std::move(Matchers));
|
std::move(Matchers));
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<ast_matchers::internal::DynTypedMatcher> Matchers;
|
std::vector<ast_matchers::internal::DynTypedMatcher> Matchers;
|
||||||
std::vector<std::function<Result(
|
std::vector<MatchSwitchAction<BaseT, State, Result>> Actions;
|
||||||
const Stmt *, const ast_matchers::MatchFinder::MatchResult &, State &)>>
|
|
||||||
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 dataflow
|
||||||
} // namespace clang
|
} // namespace clang
|
||||||
#endif // LLVM_CLANG_ANALYSIS_FLOWSENSITIVE_MATCHSWITCH_H_
|
#endif // LLVM_CLANG_ANALYSIS_FLOWSENSITIVE_MATCHSWITCH_H_
|
||||||
|
|||||||
+1
-1
@@ -26,7 +26,7 @@ namespace dataflow {
|
|||||||
class ChromiumCheckModel : public DataflowModel {
|
class ChromiumCheckModel : public DataflowModel {
|
||||||
public:
|
public:
|
||||||
ChromiumCheckModel() = default;
|
ChromiumCheckModel() = default;
|
||||||
bool transfer(const Stmt *Stmt, Environment &Env) override;
|
bool transfer(const CFGElement *Element, Environment &Env) override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
/// Declarations for `::logging::CheckError::.*Check`, lazily initialized.
|
/// Declarations for `::logging::CheckError::.*Check`, lazily initialized.
|
||||||
|
|||||||
+17
-14
@@ -15,10 +15,10 @@
|
|||||||
#define CLANG_ANALYSIS_FLOWSENSITIVE_MODELS_UNCHECKEDOPTIONALACCESSMODEL_H
|
#define CLANG_ANALYSIS_FLOWSENSITIVE_MODELS_UNCHECKEDOPTIONALACCESSMODEL_H
|
||||||
|
|
||||||
#include "clang/AST/ASTContext.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/DataflowAnalysis.h"
|
||||||
#include "clang/Analysis/FlowSensitive/DataflowEnvironment.h"
|
#include "clang/Analysis/FlowSensitive/DataflowEnvironment.h"
|
||||||
#include "clang/Analysis/FlowSensitive/MatchSwitch.h"
|
|
||||||
#include "clang/Analysis/FlowSensitive/NoopLattice.h"
|
#include "clang/Analysis/FlowSensitive/NoopLattice.h"
|
||||||
#include "clang/Basic/SourceLocation.h"
|
#include "clang/Basic/SourceLocation.h"
|
||||||
#include <vector>
|
#include <vector>
|
||||||
@@ -30,11 +30,12 @@ namespace dataflow {
|
|||||||
// analysis are always enabled and additional constructs are enabled through the
|
// analysis are always enabled and additional constructs are enabled through the
|
||||||
// `Options`.
|
// `Options`.
|
||||||
struct UncheckedOptionalAccessModelOptions {
|
struct UncheckedOptionalAccessModelOptions {
|
||||||
/// Ignore optionals reachable through overloaded `operator*` or `operator->`
|
/// In generating diagnostics, ignore optionals reachable through overloaded
|
||||||
/// (other than those of the optional type itself). The analysis does not
|
/// `operator*` or `operator->` (other than those of the optional type
|
||||||
/// equate the results of such calls, so it can't identify when their results
|
/// itself). The analysis does not equate the results of such calls, so it
|
||||||
/// are used safely (across calls), resulting in false positives in all such
|
/// can't identify when their results are used safely (across calls),
|
||||||
/// cases. Note: this option does not cover access through `operator[]`.
|
/// resulting in false positives in all such cases. Note: this option does not
|
||||||
|
/// cover access through `operator[]`.
|
||||||
bool IgnoreSmartPointerDereference = false;
|
bool IgnoreSmartPointerDereference = false;
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -44,17 +45,16 @@ struct UncheckedOptionalAccessModelOptions {
|
|||||||
class UncheckedOptionalAccessModel
|
class UncheckedOptionalAccessModel
|
||||||
: public DataflowAnalysis<UncheckedOptionalAccessModel, NoopLattice> {
|
: public DataflowAnalysis<UncheckedOptionalAccessModel, NoopLattice> {
|
||||||
public:
|
public:
|
||||||
UncheckedOptionalAccessModel(
|
UncheckedOptionalAccessModel(ASTContext &Ctx);
|
||||||
ASTContext &AstContext, UncheckedOptionalAccessModelOptions Options = {});
|
|
||||||
|
|
||||||
/// Returns a matcher for the optional classes covered by this model.
|
/// Returns a matcher for the optional classes covered by this model.
|
||||||
static ast_matchers::DeclarationMatcher optionalClassDecl();
|
static ast_matchers::DeclarationMatcher optionalClassDecl();
|
||||||
|
|
||||||
static NoopLattice initialElement() { return {}; }
|
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 &Env1, const Value &Val2,
|
||||||
const Environment &Env2) override;
|
const Environment &Env2) override;
|
||||||
|
|
||||||
@@ -62,8 +62,11 @@ class UncheckedOptionalAccessModel
|
|||||||
const Value &Val2, const Environment &Env2, Value &MergedVal,
|
const Value &Val2, const Environment &Env2, Value &MergedVal,
|
||||||
Environment &MergedEnv) override;
|
Environment &MergedEnv) override;
|
||||||
|
|
||||||
|
Value *widen(QualType Type, Value &Prev, const Environment &PrevEnv,
|
||||||
|
Value &Current, Environment &CurrentEnv) override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
MatchSwitch<TransferState<NoopLattice>> TransferMatchSwitch;
|
CFGMatchSwitch<TransferState<NoopLattice>> TransferMatchSwitch;
|
||||||
};
|
};
|
||||||
|
|
||||||
class UncheckedOptionalAccessDiagnoser {
|
class UncheckedOptionalAccessDiagnoser {
|
||||||
@@ -71,11 +74,11 @@ class UncheckedOptionalAccessDiagnoser {
|
|||||||
UncheckedOptionalAccessDiagnoser(
|
UncheckedOptionalAccessDiagnoser(
|
||||||
UncheckedOptionalAccessModelOptions Options = {});
|
UncheckedOptionalAccessModelOptions Options = {});
|
||||||
|
|
||||||
std::vector<SourceLocation> diagnose(ASTContext &Context, const Stmt *Stmt,
|
std::vector<SourceLocation> diagnose(ASTContext &Ctx, const CFGElement *Elt,
|
||||||
const Environment &Env);
|
const Environment &Env);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
MatchSwitch<const Environment, std::vector<SourceLocation>>
|
CFGMatchSwitch<const Environment, std::vector<SourceLocation>>
|
||||||
DiagnoseMatchSwitch;
|
DiagnoseMatchSwitch;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -14,7 +14,7 @@
|
|||||||
#define LLVM_CLANG_ANALYSIS_FLOWSENSITIVE_NOOPANALYSIS_H
|
#define LLVM_CLANG_ANALYSIS_FLOWSENSITIVE_NOOPANALYSIS_H
|
||||||
|
|
||||||
#include "clang/AST/ASTContext.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/DataflowAnalysis.h"
|
||||||
#include "clang/Analysis/FlowSensitive/DataflowEnvironment.h"
|
#include "clang/Analysis/FlowSensitive/DataflowEnvironment.h"
|
||||||
#include "clang/Analysis/FlowSensitive/NoopLattice.h"
|
#include "clang/Analysis/FlowSensitive/NoopLattice.h"
|
||||||
@@ -38,7 +38,7 @@ class NoopAnalysis : public DataflowAnalysis<NoopAnalysis, NoopLattice> {
|
|||||||
|
|
||||||
static NoopLattice initialElement() { return {}; }
|
static NoopLattice initialElement() { return {}; }
|
||||||
|
|
||||||
void transfer(const Stmt *S, NoopLattice &E, Environment &Env) {}
|
void transfer(const CFGElement *E, NoopLattice &L, Environment &Env) {}
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace dataflow
|
} // namespace dataflow
|
||||||
|
|||||||
@@ -17,7 +17,7 @@
|
|||||||
#include "clang/Analysis/FlowSensitive/Value.h"
|
#include "clang/Analysis/FlowSensitive/Value.h"
|
||||||
#include "llvm/ADT/DenseMap.h"
|
#include "llvm/ADT/DenseMap.h"
|
||||||
#include "llvm/ADT/DenseSet.h"
|
#include "llvm/ADT/DenseSet.h"
|
||||||
#include "llvm/ADT/Optional.h"
|
#include <optional>
|
||||||
|
|
||||||
namespace clang {
|
namespace clang {
|
||||||
namespace dataflow {
|
namespace dataflow {
|
||||||
@@ -64,7 +64,7 @@ class Solver {
|
|||||||
|
|
||||||
/// Returns a truth assignment to boolean values that satisfies the queried
|
/// Returns a truth assignment to boolean values that satisfies the queried
|
||||||
/// boolean formula if available. Otherwise, an empty optional is returned.
|
/// boolean formula if available. Otherwise, an empty optional is returned.
|
||||||
llvm::Optional<llvm::DenseMap<AtomicBoolValue *, Assignment>>
|
std::optional<llvm::DenseMap<AtomicBoolValue *, Assignment>>
|
||||||
getSolution() const {
|
getSolution() const {
|
||||||
return Solution;
|
return Solution;
|
||||||
}
|
}
|
||||||
@@ -72,11 +72,11 @@ class Solver {
|
|||||||
private:
|
private:
|
||||||
Result(
|
Result(
|
||||||
enum Status SATCheckStatus,
|
enum Status SATCheckStatus,
|
||||||
llvm::Optional<llvm::DenseMap<AtomicBoolValue *, Assignment>> Solution)
|
std::optional<llvm::DenseMap<AtomicBoolValue *, Assignment>> Solution)
|
||||||
: SATCheckStatus(SATCheckStatus), Solution(std::move(Solution)) {}
|
: SATCheckStatus(SATCheckStatus), Solution(std::move(Solution)) {}
|
||||||
|
|
||||||
Status SATCheckStatus;
|
Status SATCheckStatus;
|
||||||
llvm::Optional<llvm::DenseMap<AtomicBoolValue *, Assignment>> Solution;
|
std::optional<llvm::DenseMap<AtomicBoolValue *, Assignment>> Solution;
|
||||||
};
|
};
|
||||||
|
|
||||||
virtual ~Solver() = default;
|
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
|
/// 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
|
/// or class type, all accessible members of base struct and class types are
|
||||||
/// directly accesible as children of this location.
|
/// 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 {
|
class AggregateStorageLocation final : public StorageLocation {
|
||||||
public:
|
public:
|
||||||
explicit AggregateStorageLocation(QualType Type)
|
explicit AggregateStorageLocation(QualType Type)
|
||||||
|
|||||||
@@ -15,17 +15,12 @@
|
|||||||
#define LLVM_CLANG_ANALYSIS_FLOWSENSITIVE_TRANSFER_H
|
#define LLVM_CLANG_ANALYSIS_FLOWSENSITIVE_TRANSFER_H
|
||||||
|
|
||||||
#include "clang/AST/Stmt.h"
|
#include "clang/AST/Stmt.h"
|
||||||
|
#include "clang/Analysis/FlowSensitive/DataflowAnalysisContext.h"
|
||||||
#include "clang/Analysis/FlowSensitive/DataflowEnvironment.h"
|
#include "clang/Analysis/FlowSensitive/DataflowEnvironment.h"
|
||||||
|
|
||||||
namespace clang {
|
namespace clang {
|
||||||
namespace dataflow {
|
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.
|
/// Maps statements to the environments of basic blocks that contain them.
|
||||||
class StmtToEnvMap {
|
class StmtToEnvMap {
|
||||||
public:
|
public:
|
||||||
@@ -42,8 +37,7 @@ class StmtToEnvMap {
|
|||||||
/// Requirements:
|
/// Requirements:
|
||||||
///
|
///
|
||||||
/// `S` must not be `ParenExpr` or `ExprWithCleanups`.
|
/// `S` must not be `ParenExpr` or `ExprWithCleanups`.
|
||||||
void transfer(const StmtToEnvMap &StmtToEnv, const Stmt &S, Environment &Env,
|
void transfer(const StmtToEnvMap &StmtToEnv, const Stmt &S, Environment &Env);
|
||||||
TransferOptions Options);
|
|
||||||
|
|
||||||
} // namespace dataflow
|
} // namespace dataflow
|
||||||
} // namespace clang
|
} // namespace clang
|
||||||
|
|||||||
+46
-31
@@ -14,6 +14,7 @@
|
|||||||
#ifndef LLVM_CLANG_ANALYSIS_FLOWSENSITIVE_TYPEERASEDDATAFLOWANALYSIS_H
|
#ifndef LLVM_CLANG_ANALYSIS_FLOWSENSITIVE_TYPEERASEDDATAFLOWANALYSIS_H
|
||||||
#define LLVM_CLANG_ANALYSIS_FLOWSENSITIVE_TYPEERASEDDATAFLOWANALYSIS_H
|
#define LLVM_CLANG_ANALYSIS_FLOWSENSITIVE_TYPEERASEDDATAFLOWANALYSIS_H
|
||||||
|
|
||||||
|
#include <optional>
|
||||||
#include <utility>
|
#include <utility>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
@@ -21,25 +22,22 @@
|
|||||||
#include "clang/AST/Stmt.h"
|
#include "clang/AST/Stmt.h"
|
||||||
#include "clang/Analysis/CFG.h"
|
#include "clang/Analysis/CFG.h"
|
||||||
#include "clang/Analysis/FlowSensitive/ControlFlowContext.h"
|
#include "clang/Analysis/FlowSensitive/ControlFlowContext.h"
|
||||||
|
#include "clang/Analysis/FlowSensitive/DataflowAnalysisContext.h"
|
||||||
#include "clang/Analysis/FlowSensitive/DataflowEnvironment.h"
|
#include "clang/Analysis/FlowSensitive/DataflowEnvironment.h"
|
||||||
#include "clang/Analysis/FlowSensitive/DataflowLattice.h"
|
#include "clang/Analysis/FlowSensitive/DataflowLattice.h"
|
||||||
#include "clang/Analysis/FlowSensitive/Transfer.h"
|
|
||||||
#include "llvm/ADT/Any.h"
|
#include "llvm/ADT/Any.h"
|
||||||
#include "llvm/ADT/Optional.h"
|
|
||||||
#include "llvm/Support/Error.h"
|
#include "llvm/Support/Error.h"
|
||||||
|
|
||||||
namespace clang {
|
namespace clang {
|
||||||
namespace dataflow {
|
namespace dataflow {
|
||||||
|
|
||||||
struct DataflowAnalysisOptions {
|
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
|
// FIXME: Remove this option once the framework supports composing analyses
|
||||||
// (at which point the built-in transfer functions can be simply a standalone
|
// (at which point the built-in transfer functions can be simply a standalone
|
||||||
// analysis).
|
// analysis).
|
||||||
bool ApplyBuiltinTransfer = true;
|
std::optional<DataflowAnalysisContext::Options> BuiltinOpts =
|
||||||
|
DataflowAnalysisContext::Options{};
|
||||||
/// Only has an effect if `ApplyBuiltinTransfer` is true.
|
|
||||||
TransferOptions BuiltinTransferOptions;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/// Type-erased lattice element container.
|
/// Type-erased lattice element container.
|
||||||
@@ -59,10 +57,6 @@ class TypeErasedDataflowAnalysis : public Environment::ValueModel {
|
|||||||
public:
|
public:
|
||||||
TypeErasedDataflowAnalysis() : Options({}) {}
|
TypeErasedDataflowAnalysis() : Options({}) {}
|
||||||
|
|
||||||
/// Deprecated. Use the `DataflowAnalysisOptions` constructor instead.
|
|
||||||
TypeErasedDataflowAnalysis(bool ApplyBuiltinTransfer)
|
|
||||||
: Options({ApplyBuiltinTransfer, TransferOptions{}}) {}
|
|
||||||
|
|
||||||
TypeErasedDataflowAnalysis(DataflowAnalysisOptions Options)
|
TypeErasedDataflowAnalysis(DataflowAnalysisOptions Options)
|
||||||
: Options(Options) {}
|
: Options(Options) {}
|
||||||
|
|
||||||
@@ -81,23 +75,43 @@ class TypeErasedDataflowAnalysis : public Environment::ValueModel {
|
|||||||
virtual LatticeJoinEffect joinTypeErased(TypeErasedLattice &,
|
virtual LatticeJoinEffect joinTypeErased(TypeErasedLattice &,
|
||||||
const TypeErasedLattice &) = 0;
|
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
|
/// Returns true if and only if the two given type-erased lattice elements are
|
||||||
/// equal.
|
/// equal.
|
||||||
virtual bool isEqualTypeErased(const TypeErasedLattice &,
|
virtual bool isEqualTypeErased(const TypeErasedLattice &,
|
||||||
const TypeErasedLattice &) = 0;
|
const TypeErasedLattice &) = 0;
|
||||||
|
|
||||||
/// Applies the analysis transfer function for a given statement and
|
/// Applies the analysis transfer function for a given control flow graph
|
||||||
/// type-erased lattice element.
|
/// element and type-erased lattice element.
|
||||||
virtual void transferTypeErased(const Stmt *, TypeErasedLattice &,
|
virtual void transferTypeErased(const CFGElement *, TypeErasedLattice &,
|
||||||
Environment &) = 0;
|
Environment &) = 0;
|
||||||
|
|
||||||
/// Determines whether to apply the built-in transfer functions, which model
|
/// Applies the analysis transfer function for a given edge from a CFG block
|
||||||
/// the heap and stack in the `Environment`.
|
/// of a conditional statement.
|
||||||
bool applyBuiltinTransfer() const { return Options.ApplyBuiltinTransfer; }
|
/// @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.
|
/// If the built-in model is enabled, returns the options to be passed to
|
||||||
TransferOptions builtinTransferOptions() const {
|
/// them. Otherwise returns empty.
|
||||||
return Options.BuiltinTransferOptions;
|
const std::optional<DataflowAnalysisContext::Options> &
|
||||||
|
builtinOptions() const {
|
||||||
|
return Options.BuiltinOpts;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -113,37 +127,38 @@ struct TypeErasedDataflowAnalysisState {
|
|||||||
: Lattice(std::move(Lattice)), Env(std::move(Env)) {}
|
: 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
|
/// the context of `Analysis` and the states of its predecessors that are
|
||||||
/// available in `BlockStates`. `HandleTransferredStmt` (if provided) will be
|
/// available in `BlockStates`. `PostVisitCFG` (if provided) will be applied to
|
||||||
/// applied to each statement in the block, after it is evaluated.
|
/// each element in the block, after it is evaluated.
|
||||||
///
|
///
|
||||||
/// Requirements:
|
/// Requirements:
|
||||||
///
|
///
|
||||||
/// All predecessors of `Block` except those with loop back edges must have
|
/// All predecessors of `Block` except those with loop back edges must have
|
||||||
/// already been transferred. States in `BlockStates` that are set to
|
/// 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(
|
TypeErasedDataflowAnalysisState transferBlock(
|
||||||
const ControlFlowContext &CFCtx,
|
const ControlFlowContext &CFCtx,
|
||||||
std::vector<llvm::Optional<TypeErasedDataflowAnalysisState>> &BlockStates,
|
llvm::ArrayRef<std::optional<TypeErasedDataflowAnalysisState>> BlockStates,
|
||||||
const CFGBlock &Block, const Environment &InitEnv,
|
const CFGBlock &Block, const Environment &InitEnv,
|
||||||
TypeErasedDataflowAnalysis &Analysis,
|
TypeErasedDataflowAnalysis &Analysis,
|
||||||
std::function<void(const CFGStmt &,
|
std::function<void(const CFGElement &,
|
||||||
const TypeErasedDataflowAnalysisState &)>
|
const TypeErasedDataflowAnalysisState &)>
|
||||||
HandleTransferredStmt = nullptr);
|
PostVisitCFG = nullptr);
|
||||||
|
|
||||||
/// Performs dataflow analysis and returns a mapping from basic block IDs to
|
/// Performs dataflow analysis and returns a mapping from basic block IDs to
|
||||||
/// dataflow analysis states that model the respective basic blocks. Indices of
|
/// dataflow analysis states that model the respective basic blocks. Indices of
|
||||||
/// the returned vector correspond to basic block IDs. Returns an error if the
|
/// the returned vector correspond to basic block IDs. Returns an error if the
|
||||||
/// dataflow analysis cannot be performed successfully. Otherwise, calls
|
/// 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.
|
/// program point.
|
||||||
llvm::Expected<std::vector<llvm::Optional<TypeErasedDataflowAnalysisState>>>
|
llvm::Expected<std::vector<std::optional<TypeErasedDataflowAnalysisState>>>
|
||||||
runTypeErasedDataflowAnalysis(
|
runTypeErasedDataflowAnalysis(
|
||||||
const ControlFlowContext &CFCtx, TypeErasedDataflowAnalysis &Analysis,
|
const ControlFlowContext &CFCtx, TypeErasedDataflowAnalysis &Analysis,
|
||||||
const Environment &InitEnv,
|
const Environment &InitEnv,
|
||||||
std::function<void(const Stmt *, const TypeErasedDataflowAnalysisState &)>
|
std::function<void(const CFGElement &,
|
||||||
PostVisitStmt = nullptr);
|
const TypeErasedDataflowAnalysisState &)>
|
||||||
|
PostVisitCFG = nullptr);
|
||||||
|
|
||||||
} // namespace dataflow
|
} // namespace dataflow
|
||||||
} // namespace clang
|
} // namespace clang
|
||||||
|
|||||||
@@ -19,6 +19,7 @@
|
|||||||
#include "llvm/ADT/DenseMap.h"
|
#include "llvm/ADT/DenseMap.h"
|
||||||
#include "llvm/ADT/StringMap.h"
|
#include "llvm/ADT/StringMap.h"
|
||||||
#include "llvm/ADT/StringRef.h"
|
#include "llvm/ADT/StringRef.h"
|
||||||
|
#include "llvm/Support/raw_ostream.h"
|
||||||
#include <cassert>
|
#include <cassert>
|
||||||
#include <utility>
|
#include <utility>
|
||||||
|
|
||||||
@@ -38,6 +39,7 @@ class Value {
|
|||||||
Struct,
|
Struct,
|
||||||
|
|
||||||
// Synthetic boolean values are either atomic values or logical connectives.
|
// Synthetic boolean values are either atomic values or logical connectives.
|
||||||
|
TopBool,
|
||||||
AtomicBool,
|
AtomicBool,
|
||||||
Conjunction,
|
Conjunction,
|
||||||
Disjunction,
|
Disjunction,
|
||||||
@@ -76,13 +78,25 @@ class Value {
|
|||||||
llvm::StringMap<Value *> Properties;
|
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.
|
/// Models a boolean.
|
||||||
class BoolValue : public Value {
|
class BoolValue : public Value {
|
||||||
public:
|
public:
|
||||||
explicit BoolValue(Kind ValueKind) : Value(ValueKind) {}
|
explicit BoolValue(Kind ValueKind) : Value(ValueKind) {}
|
||||||
|
|
||||||
static bool classof(const Value *Val) {
|
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::Conjunction ||
|
||||||
Val->getKind() == Kind::Disjunction ||
|
Val->getKind() == Kind::Disjunction ||
|
||||||
Val->getKind() == Kind::Negation ||
|
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.
|
/// Models an atomic boolean.
|
||||||
class AtomicBoolValue : public BoolValue {
|
class AtomicBoolValue : public BoolValue {
|
||||||
public:
|
public:
|
||||||
@@ -286,6 +311,8 @@ class StructValue final : public Value {
|
|||||||
llvm::DenseMap<const ValueDecl *, Value *> Children;
|
llvm::DenseMap<const ValueDecl *, Value *> Children;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
raw_ostream &operator<<(raw_ostream &OS, const Value &Val);
|
||||||
|
|
||||||
} // namespace dataflow
|
} // namespace dataflow
|
||||||
} // namespace clang
|
} // namespace clang
|
||||||
|
|
||||||
|
|||||||
@@ -13,9 +13,9 @@
|
|||||||
#include "clang/Basic/SourceLocation.h"
|
#include "clang/Basic/SourceLocation.h"
|
||||||
#include "clang/Lex/Preprocessor.h"
|
#include "clang/Lex/Preprocessor.h"
|
||||||
#include "llvm/ADT/DenseMap.h"
|
#include "llvm/ADT/DenseMap.h"
|
||||||
#include "llvm/ADT/Optional.h"
|
|
||||||
#include "llvm/ADT/SmallString.h"
|
#include "llvm/ADT/SmallString.h"
|
||||||
#include "llvm/ADT/SmallVector.h"
|
#include "llvm/ADT/SmallVector.h"
|
||||||
|
#include <optional>
|
||||||
|
|
||||||
namespace clang {
|
namespace clang {
|
||||||
|
|
||||||
@@ -85,14 +85,16 @@ class MacroExpansionContext {
|
|||||||
/// \param MacroExpansionLoc Must be the expansion location of a macro.
|
/// \param MacroExpansionLoc Must be the expansion location of a macro.
|
||||||
/// \return The textual representation of the token sequence which was
|
/// \return The textual representation of the token sequence which was
|
||||||
/// substituted in place of the macro after the preprocessing.
|
/// substituted in place of the macro after the preprocessing.
|
||||||
/// If no macro was expanded at that location, returns llvm::None.
|
/// If no macro was expanded at that location, returns std::nullopt.
|
||||||
Optional<StringRef> getExpandedText(SourceLocation MacroExpansionLoc) const;
|
std::optional<StringRef>
|
||||||
|
getExpandedText(SourceLocation MacroExpansionLoc) const;
|
||||||
|
|
||||||
/// \param MacroExpansionLoc Must be the expansion location of a macro.
|
/// \param MacroExpansionLoc Must be the expansion location of a macro.
|
||||||
/// \return The text from the original source code which were substituted by
|
/// \return The text from the original source code which were substituted by
|
||||||
/// the macro expansion chain from the given location.
|
/// the macro expansion chain from the given location.
|
||||||
/// If no macro was expanded at that location, returns llvm::None.
|
/// If no macro was expanded at that location, returns std::nullopt.
|
||||||
Optional<StringRef> getOriginalText(SourceLocation MacroExpansionLoc) const;
|
std::optional<StringRef>
|
||||||
|
getOriginalText(SourceLocation MacroExpansionLoc) const;
|
||||||
|
|
||||||
LLVM_DUMP_METHOD void dumpExpansionRangesToStream(raw_ostream &OS) const;
|
LLVM_DUMP_METHOD void dumpExpansionRangesToStream(raw_ostream &OS) const;
|
||||||
LLVM_DUMP_METHOD void dumpExpandedTextsToStream(raw_ostream &OS) const;
|
LLVM_DUMP_METHOD void dumpExpandedTextsToStream(raw_ostream &OS) const;
|
||||||
|
|||||||
@@ -19,7 +19,6 @@
|
|||||||
#include "clang/Basic/SourceLocation.h"
|
#include "clang/Basic/SourceLocation.h"
|
||||||
#include "llvm/ADT/ArrayRef.h"
|
#include "llvm/ADT/ArrayRef.h"
|
||||||
#include "llvm/ADT/FoldingSet.h"
|
#include "llvm/ADT/FoldingSet.h"
|
||||||
#include "llvm/ADT/Optional.h"
|
|
||||||
#include "llvm/ADT/PointerUnion.h"
|
#include "llvm/ADT/PointerUnion.h"
|
||||||
#include "llvm/ADT/SmallVector.h"
|
#include "llvm/ADT/SmallVector.h"
|
||||||
#include "llvm/ADT/StringRef.h"
|
#include "llvm/ADT/StringRef.h"
|
||||||
@@ -30,6 +29,7 @@
|
|||||||
#include <list>
|
#include <list>
|
||||||
#include <map>
|
#include <map>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
|
#include <optional>
|
||||||
#include <set>
|
#include <set>
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <utility>
|
#include <utility>
|
||||||
@@ -73,7 +73,7 @@ struct PathDiagnosticConsumerOptions {
|
|||||||
bool ShouldSerializeStats = false;
|
bool ShouldSerializeStats = false;
|
||||||
|
|
||||||
/// If the consumer intends to produce multiple output files, should it
|
/// 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;
|
bool ShouldWriteVerboseReportFilename = false;
|
||||||
|
|
||||||
/// Whether the consumer should treat consumed diagnostics as hard errors.
|
/// Whether the consumer should treat consumed diagnostics as hard errors.
|
||||||
@@ -532,7 +532,7 @@ class PathDiagnosticSpotPiece : public PathDiagnosticPiece {
|
|||||||
};
|
};
|
||||||
|
|
||||||
class PathDiagnosticEventPiece : public PathDiagnosticSpotPiece {
|
class PathDiagnosticEventPiece : public PathDiagnosticSpotPiece {
|
||||||
Optional<bool> IsPrunable;
|
std::optional<bool> IsPrunable;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
PathDiagnosticEventPiece(const PathDiagnosticLocation &pos,
|
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