mirror of
https://github.com/opnsense/src.git
synced 2026-06-04 06:15:33 -04:00
Merge llvm-project main llvmorg-19-init-18630-gf2ccf80136a0
This updates llvm, clang, compiler-rt, libc++, libunwind, lld, lldb and openmp to llvm-project main llvmorg-19-init-18630-gf2ccf80136a0, the last commit before the upstream release/19.x branch was created. PR: 280562 MFC after: 1 month
This commit is contained in:
commit
0fca6ea1d4
5782 changed files with 428434 additions and 220812 deletions
|
|
@ -51,6 +51,483 @@
|
|||
# xargs -n1 | sort | uniq -d;
|
||||
# done
|
||||
|
||||
# 20241023: new clang import which bumps version from 18 to 19
|
||||
OLD_FILES+=usr/lib/clang/18/include/__clang_cuda_builtin_vars.h
|
||||
OLD_FILES+=usr/lib/clang/18/include/__clang_cuda_cmath.h
|
||||
OLD_FILES+=usr/lib/clang/18/include/__clang_cuda_complex_builtins.h
|
||||
OLD_FILES+=usr/lib/clang/18/include/__clang_cuda_device_functions.h
|
||||
OLD_FILES+=usr/lib/clang/18/include/__clang_cuda_intrinsics.h
|
||||
OLD_FILES+=usr/lib/clang/18/include/__clang_cuda_libdevice_declares.h
|
||||
OLD_FILES+=usr/lib/clang/18/include/__clang_cuda_math.h
|
||||
OLD_FILES+=usr/lib/clang/18/include/__clang_cuda_math_forward_declares.h
|
||||
OLD_FILES+=usr/lib/clang/18/include/__clang_cuda_runtime_wrapper.h
|
||||
OLD_FILES+=usr/lib/clang/18/include/__clang_cuda_texture_intrinsics.h
|
||||
OLD_FILES+=usr/lib/clang/18/include/__clang_hip_cmath.h
|
||||
OLD_FILES+=usr/lib/clang/18/include/__clang_hip_libdevice_declares.h
|
||||
OLD_FILES+=usr/lib/clang/18/include/__clang_hip_math.h
|
||||
OLD_FILES+=usr/lib/clang/18/include/__clang_hip_runtime_wrapper.h
|
||||
OLD_FILES+=usr/lib/clang/18/include/__clang_hip_stdlib.h
|
||||
OLD_FILES+=usr/lib/clang/18/include/__stdarg___gnuc_va_list.h
|
||||
OLD_FILES+=usr/lib/clang/18/include/__stdarg___va_copy.h
|
||||
OLD_FILES+=usr/lib/clang/18/include/__stdarg_va_arg.h
|
||||
OLD_FILES+=usr/lib/clang/18/include/__stdarg_va_copy.h
|
||||
OLD_FILES+=usr/lib/clang/18/include/__stdarg_va_list.h
|
||||
OLD_FILES+=usr/lib/clang/18/include/__stddef_max_align_t.h
|
||||
OLD_FILES+=usr/lib/clang/18/include/__stddef_null.h
|
||||
OLD_FILES+=usr/lib/clang/18/include/__stddef_nullptr_t.h
|
||||
OLD_FILES+=usr/lib/clang/18/include/__stddef_offsetof.h
|
||||
OLD_FILES+=usr/lib/clang/18/include/__stddef_ptrdiff_t.h
|
||||
OLD_FILES+=usr/lib/clang/18/include/__stddef_rsize_t.h
|
||||
OLD_FILES+=usr/lib/clang/18/include/__stddef_size_t.h
|
||||
OLD_FILES+=usr/lib/clang/18/include/__stddef_unreachable.h
|
||||
OLD_FILES+=usr/lib/clang/18/include/__stddef_wchar_t.h
|
||||
OLD_FILES+=usr/lib/clang/18/include/__stddef_wint_t.h
|
||||
OLD_FILES+=usr/lib/clang/18/include/__wmmintrin_aes.h
|
||||
OLD_FILES+=usr/lib/clang/18/include/__wmmintrin_pclmul.h
|
||||
OLD_FILES+=usr/lib/clang/18/include/adcintrin.h
|
||||
OLD_FILES+=usr/lib/clang/18/include/adxintrin.h
|
||||
OLD_FILES+=usr/lib/clang/18/include/altivec.h
|
||||
OLD_FILES+=usr/lib/clang/18/include/ammintrin.h
|
||||
OLD_FILES+=usr/lib/clang/18/include/amxcomplexintrin.h
|
||||
OLD_FILES+=usr/lib/clang/18/include/amxfp16intrin.h
|
||||
OLD_FILES+=usr/lib/clang/18/include/amxintrin.h
|
||||
OLD_FILES+=usr/lib/clang/18/include/arm64intr.h
|
||||
OLD_FILES+=usr/lib/clang/18/include/arm_acle.h
|
||||
OLD_FILES+=usr/lib/clang/18/include/arm_bf16.h
|
||||
OLD_FILES+=usr/lib/clang/18/include/arm_cde.h
|
||||
OLD_FILES+=usr/lib/clang/18/include/arm_cmse.h
|
||||
OLD_FILES+=usr/lib/clang/18/include/arm_fp16.h
|
||||
OLD_FILES+=usr/lib/clang/18/include/arm_mve.h
|
||||
OLD_FILES+=usr/lib/clang/18/include/arm_neon.h
|
||||
OLD_FILES+=usr/lib/clang/18/include/arm_neon_sve_bridge.h
|
||||
OLD_FILES+=usr/lib/clang/18/include/arm_sme_draft_spec_subject_to_change.h
|
||||
OLD_FILES+=usr/lib/clang/18/include/arm_sve.h
|
||||
OLD_FILES+=usr/lib/clang/18/include/arm_vector_types.h
|
||||
OLD_FILES+=usr/lib/clang/18/include/armintr.h
|
||||
OLD_FILES+=usr/lib/clang/18/include/avx2intrin.h
|
||||
OLD_FILES+=usr/lib/clang/18/include/avx512bf16intrin.h
|
||||
OLD_FILES+=usr/lib/clang/18/include/avx512bitalgintrin.h
|
||||
OLD_FILES+=usr/lib/clang/18/include/avx512bwintrin.h
|
||||
OLD_FILES+=usr/lib/clang/18/include/avx512cdintrin.h
|
||||
OLD_FILES+=usr/lib/clang/18/include/avx512dqintrin.h
|
||||
OLD_FILES+=usr/lib/clang/18/include/avx512erintrin.h
|
||||
OLD_FILES+=usr/lib/clang/18/include/avx512fintrin.h
|
||||
OLD_FILES+=usr/lib/clang/18/include/avx512fp16intrin.h
|
||||
OLD_FILES+=usr/lib/clang/18/include/avx512ifmaintrin.h
|
||||
OLD_FILES+=usr/lib/clang/18/include/avx512ifmavlintrin.h
|
||||
OLD_FILES+=usr/lib/clang/18/include/avx512pfintrin.h
|
||||
OLD_FILES+=usr/lib/clang/18/include/avx512vbmi2intrin.h
|
||||
OLD_FILES+=usr/lib/clang/18/include/avx512vbmiintrin.h
|
||||
OLD_FILES+=usr/lib/clang/18/include/avx512vbmivlintrin.h
|
||||
OLD_FILES+=usr/lib/clang/18/include/avx512vlbf16intrin.h
|
||||
OLD_FILES+=usr/lib/clang/18/include/avx512vlbitalgintrin.h
|
||||
OLD_FILES+=usr/lib/clang/18/include/avx512vlbwintrin.h
|
||||
OLD_FILES+=usr/lib/clang/18/include/avx512vlcdintrin.h
|
||||
OLD_FILES+=usr/lib/clang/18/include/avx512vldqintrin.h
|
||||
OLD_FILES+=usr/lib/clang/18/include/avx512vlfp16intrin.h
|
||||
OLD_FILES+=usr/lib/clang/18/include/avx512vlintrin.h
|
||||
OLD_FILES+=usr/lib/clang/18/include/avx512vlvbmi2intrin.h
|
||||
OLD_FILES+=usr/lib/clang/18/include/avx512vlvnniintrin.h
|
||||
OLD_FILES+=usr/lib/clang/18/include/avx512vlvp2intersectintrin.h
|
||||
OLD_FILES+=usr/lib/clang/18/include/avx512vnniintrin.h
|
||||
OLD_FILES+=usr/lib/clang/18/include/avx512vp2intersectintrin.h
|
||||
OLD_FILES+=usr/lib/clang/18/include/avx512vpopcntdqintrin.h
|
||||
OLD_FILES+=usr/lib/clang/18/include/avx512vpopcntdqvlintrin.h
|
||||
OLD_FILES+=usr/lib/clang/18/include/avxifmaintrin.h
|
||||
OLD_FILES+=usr/lib/clang/18/include/avxintrin.h
|
||||
OLD_FILES+=usr/lib/clang/18/include/avxneconvertintrin.h
|
||||
OLD_FILES+=usr/lib/clang/18/include/avxvnniint16intrin.h
|
||||
OLD_FILES+=usr/lib/clang/18/include/avxvnniint8intrin.h
|
||||
OLD_FILES+=usr/lib/clang/18/include/avxvnniintrin.h
|
||||
OLD_FILES+=usr/lib/clang/18/include/bmi2intrin.h
|
||||
OLD_FILES+=usr/lib/clang/18/include/bmiintrin.h
|
||||
OLD_FILES+=usr/lib/clang/18/include/builtins.h
|
||||
OLD_FILES+=usr/lib/clang/18/include/cet.h
|
||||
OLD_FILES+=usr/lib/clang/18/include/cetintrin.h
|
||||
OLD_FILES+=usr/lib/clang/18/include/cldemoteintrin.h
|
||||
OLD_FILES+=usr/lib/clang/18/include/clflushoptintrin.h
|
||||
OLD_FILES+=usr/lib/clang/18/include/clwbintrin.h
|
||||
OLD_FILES+=usr/lib/clang/18/include/clzerointrin.h
|
||||
OLD_FILES+=usr/lib/clang/18/include/cmpccxaddintrin.h
|
||||
OLD_FILES+=usr/lib/clang/18/include/cpuid.h
|
||||
OLD_FILES+=usr/lib/clang/18/include/crc32intrin.h
|
||||
OLD_FILES+=usr/lib/clang/18/include/cuda_wrappers/algorithm
|
||||
OLD_FILES+=usr/lib/clang/18/include/cuda_wrappers/bits/basic_string.h
|
||||
OLD_FILES+=usr/lib/clang/18/include/cuda_wrappers/bits/basic_string.tcc
|
||||
OLD_FILES+=usr/lib/clang/18/include/cuda_wrappers/bits/shared_ptr_base.h
|
||||
OLD_DIRS+=usr/lib/clang/18/include/cuda_wrappers/bits
|
||||
OLD_FILES+=usr/lib/clang/18/include/cuda_wrappers/cmath
|
||||
OLD_FILES+=usr/lib/clang/18/include/cuda_wrappers/complex
|
||||
OLD_FILES+=usr/lib/clang/18/include/cuda_wrappers/new
|
||||
OLD_DIRS+=usr/lib/clang/18/include/cuda_wrappers
|
||||
OLD_FILES+=usr/lib/clang/18/include/emmintrin.h
|
||||
OLD_FILES+=usr/lib/clang/18/include/enqcmdintrin.h
|
||||
OLD_FILES+=usr/lib/clang/18/include/f16cintrin.h
|
||||
OLD_FILES+=usr/lib/clang/18/include/float.h
|
||||
OLD_FILES+=usr/lib/clang/18/include/fma4intrin.h
|
||||
OLD_FILES+=usr/lib/clang/18/include/fmaintrin.h
|
||||
OLD_FILES+=usr/lib/clang/18/include/fuzzer/FuzzedDataProvider.h
|
||||
OLD_DIRS+=usr/lib/clang/18/include/fuzzer
|
||||
OLD_FILES+=usr/lib/clang/18/include/fxsrintrin.h
|
||||
OLD_FILES+=usr/lib/clang/18/include/gfniintrin.h
|
||||
OLD_FILES+=usr/lib/clang/18/include/hexagon_circ_brev_intrinsics.h
|
||||
OLD_FILES+=usr/lib/clang/18/include/hexagon_protos.h
|
||||
OLD_FILES+=usr/lib/clang/18/include/hexagon_types.h
|
||||
OLD_FILES+=usr/lib/clang/18/include/hlsl/hlsl_basic_types.h
|
||||
OLD_FILES+=usr/lib/clang/18/include/hlsl/hlsl_intrinsics.h
|
||||
OLD_DIRS+=usr/lib/clang/18/include/hlsl
|
||||
OLD_FILES+=usr/lib/clang/18/include/hlsl.h
|
||||
OLD_FILES+=usr/lib/clang/18/include/hresetintrin.h
|
||||
OLD_FILES+=usr/lib/clang/18/include/htmintrin.h
|
||||
OLD_FILES+=usr/lib/clang/18/include/htmxlintrin.h
|
||||
OLD_FILES+=usr/lib/clang/18/include/hvx_hexagon_protos.h
|
||||
OLD_FILES+=usr/lib/clang/18/include/ia32intrin.h
|
||||
OLD_FILES+=usr/lib/clang/18/include/immintrin.h
|
||||
OLD_FILES+=usr/lib/clang/18/include/intrin.h
|
||||
OLD_FILES+=usr/lib/clang/18/include/inttypes.h
|
||||
OLD_FILES+=usr/lib/clang/18/include/invpcidintrin.h
|
||||
OLD_FILES+=usr/lib/clang/18/include/iso646.h
|
||||
OLD_FILES+=usr/lib/clang/18/include/keylockerintrin.h
|
||||
OLD_FILES+=usr/lib/clang/18/include/larchintrin.h
|
||||
OLD_FILES+=usr/lib/clang/18/include/lasxintrin.h
|
||||
OLD_FILES+=usr/lib/clang/18/include/limits.h
|
||||
OLD_FILES+=usr/lib/clang/18/include/lsxintrin.h
|
||||
OLD_FILES+=usr/lib/clang/18/include/lwpintrin.h
|
||||
OLD_FILES+=usr/lib/clang/18/include/lzcntintrin.h
|
||||
OLD_FILES+=usr/lib/clang/18/include/mm3dnow.h
|
||||
OLD_FILES+=usr/lib/clang/18/include/mm_malloc.h
|
||||
OLD_FILES+=usr/lib/clang/18/include/mmintrin.h
|
||||
OLD_FILES+=usr/lib/clang/18/include/module.modulemap
|
||||
OLD_FILES+=usr/lib/clang/18/include/movdirintrin.h
|
||||
OLD_FILES+=usr/lib/clang/18/include/msa.h
|
||||
OLD_FILES+=usr/lib/clang/18/include/mwaitxintrin.h
|
||||
OLD_FILES+=usr/lib/clang/18/include/nmmintrin.h
|
||||
OLD_FILES+=usr/lib/clang/18/include/omp-tools.h
|
||||
OLD_FILES+=usr/lib/clang/18/include/omp.h
|
||||
OLD_FILES+=usr/lib/clang/18/include/ompt.h
|
||||
OLD_FILES+=usr/lib/clang/18/include/opencl-c-base.h
|
||||
OLD_FILES+=usr/lib/clang/18/include/opencl-c.h
|
||||
OLD_FILES+=usr/lib/clang/18/include/openmp_wrappers/__clang_openmp_device_functions.h
|
||||
OLD_FILES+=usr/lib/clang/18/include/openmp_wrappers/cmath
|
||||
OLD_FILES+=usr/lib/clang/18/include/openmp_wrappers/complex
|
||||
OLD_FILES+=usr/lib/clang/18/include/openmp_wrappers/complex.h
|
||||
OLD_FILES+=usr/lib/clang/18/include/openmp_wrappers/complex_cmath.h
|
||||
OLD_FILES+=usr/lib/clang/18/include/openmp_wrappers/math.h
|
||||
OLD_FILES+=usr/lib/clang/18/include/openmp_wrappers/new
|
||||
OLD_DIRS+=usr/lib/clang/18/include/openmp_wrappers
|
||||
OLD_FILES+=usr/lib/clang/18/include/orc_rt/c_api.h
|
||||
OLD_DIRS+=usr/lib/clang/18/include/orc_rt
|
||||
OLD_FILES+=usr/lib/clang/18/include/pconfigintrin.h
|
||||
OLD_FILES+=usr/lib/clang/18/include/pkuintrin.h
|
||||
OLD_FILES+=usr/lib/clang/18/include/pmmintrin.h
|
||||
OLD_FILES+=usr/lib/clang/18/include/popcntintrin.h
|
||||
OLD_FILES+=usr/lib/clang/18/include/ppc_wrappers/bmi2intrin.h
|
||||
OLD_FILES+=usr/lib/clang/18/include/ppc_wrappers/bmiintrin.h
|
||||
OLD_FILES+=usr/lib/clang/18/include/ppc_wrappers/emmintrin.h
|
||||
OLD_FILES+=usr/lib/clang/18/include/ppc_wrappers/immintrin.h
|
||||
OLD_FILES+=usr/lib/clang/18/include/ppc_wrappers/mm_malloc.h
|
||||
OLD_FILES+=usr/lib/clang/18/include/ppc_wrappers/mmintrin.h
|
||||
OLD_FILES+=usr/lib/clang/18/include/ppc_wrappers/nmmintrin.h
|
||||
OLD_FILES+=usr/lib/clang/18/include/ppc_wrappers/pmmintrin.h
|
||||
OLD_FILES+=usr/lib/clang/18/include/ppc_wrappers/smmintrin.h
|
||||
OLD_FILES+=usr/lib/clang/18/include/ppc_wrappers/tmmintrin.h
|
||||
OLD_FILES+=usr/lib/clang/18/include/ppc_wrappers/x86gprintrin.h
|
||||
OLD_FILES+=usr/lib/clang/18/include/ppc_wrappers/x86intrin.h
|
||||
OLD_FILES+=usr/lib/clang/18/include/ppc_wrappers/xmmintrin.h
|
||||
OLD_DIRS+=usr/lib/clang/18/include/ppc_wrappers
|
||||
OLD_FILES+=usr/lib/clang/18/include/prfchiintrin.h
|
||||
OLD_FILES+=usr/lib/clang/18/include/prfchwintrin.h
|
||||
OLD_FILES+=usr/lib/clang/18/include/profile/InstrProfData.inc
|
||||
OLD_FILES+=usr/lib/clang/18/include/profile/MemProfData.inc
|
||||
OLD_DIRS+=usr/lib/clang/18/include/profile
|
||||
OLD_FILES+=usr/lib/clang/18/include/ptwriteintrin.h
|
||||
OLD_FILES+=usr/lib/clang/18/include/raointintrin.h
|
||||
OLD_FILES+=usr/lib/clang/18/include/rdpruintrin.h
|
||||
OLD_FILES+=usr/lib/clang/18/include/rdseedintrin.h
|
||||
OLD_FILES+=usr/lib/clang/18/include/riscv_bitmanip.h
|
||||
OLD_FILES+=usr/lib/clang/18/include/riscv_crypto.h
|
||||
OLD_FILES+=usr/lib/clang/18/include/riscv_ntlh.h
|
||||
OLD_FILES+=usr/lib/clang/18/include/riscv_vector.h
|
||||
OLD_FILES+=usr/lib/clang/18/include/rtmintrin.h
|
||||
OLD_FILES+=usr/lib/clang/18/include/s390intrin.h
|
||||
OLD_FILES+=usr/lib/clang/18/include/sanitizer/allocator_interface.h
|
||||
OLD_FILES+=usr/lib/clang/18/include/sanitizer/asan_interface.h
|
||||
OLD_FILES+=usr/lib/clang/18/include/sanitizer/common_interface_defs.h
|
||||
OLD_FILES+=usr/lib/clang/18/include/sanitizer/coverage_interface.h
|
||||
OLD_FILES+=usr/lib/clang/18/include/sanitizer/dfsan_interface.h
|
||||
OLD_FILES+=usr/lib/clang/18/include/sanitizer/hwasan_interface.h
|
||||
OLD_FILES+=usr/lib/clang/18/include/sanitizer/linux_syscall_hooks.h
|
||||
OLD_FILES+=usr/lib/clang/18/include/sanitizer/lsan_interface.h
|
||||
OLD_FILES+=usr/lib/clang/18/include/sanitizer/memprof_interface.h
|
||||
OLD_FILES+=usr/lib/clang/18/include/sanitizer/msan_interface.h
|
||||
OLD_FILES+=usr/lib/clang/18/include/sanitizer/netbsd_syscall_hooks.h
|
||||
OLD_FILES+=usr/lib/clang/18/include/sanitizer/scudo_interface.h
|
||||
OLD_FILES+=usr/lib/clang/18/include/sanitizer/tsan_interface.h
|
||||
OLD_FILES+=usr/lib/clang/18/include/sanitizer/tsan_interface_atomic.h
|
||||
OLD_FILES+=usr/lib/clang/18/include/sanitizer/ubsan_interface.h
|
||||
OLD_DIRS+=usr/lib/clang/18/include/sanitizer
|
||||
OLD_FILES+=usr/lib/clang/18/include/serializeintrin.h
|
||||
OLD_FILES+=usr/lib/clang/18/include/sgxintrin.h
|
||||
OLD_FILES+=usr/lib/clang/18/include/sha512intrin.h
|
||||
OLD_FILES+=usr/lib/clang/18/include/shaintrin.h
|
||||
OLD_FILES+=usr/lib/clang/18/include/sifive_vector.h
|
||||
OLD_FILES+=usr/lib/clang/18/include/sm3intrin.h
|
||||
OLD_FILES+=usr/lib/clang/18/include/sm4intrin.h
|
||||
OLD_FILES+=usr/lib/clang/18/include/smmintrin.h
|
||||
OLD_FILES+=usr/lib/clang/18/include/stdalign.h
|
||||
OLD_FILES+=usr/lib/clang/18/include/stdarg.h
|
||||
OLD_FILES+=usr/lib/clang/18/include/stdatomic.h
|
||||
OLD_FILES+=usr/lib/clang/18/include/stdbool.h
|
||||
OLD_FILES+=usr/lib/clang/18/include/stdckdint.h
|
||||
OLD_FILES+=usr/lib/clang/18/include/stddef.h
|
||||
OLD_FILES+=usr/lib/clang/18/include/stdint.h
|
||||
OLD_FILES+=usr/lib/clang/18/include/stdnoreturn.h
|
||||
OLD_FILES+=usr/lib/clang/18/include/tbmintrin.h
|
||||
OLD_FILES+=usr/lib/clang/18/include/tgmath.h
|
||||
OLD_FILES+=usr/lib/clang/18/include/tmmintrin.h
|
||||
OLD_FILES+=usr/lib/clang/18/include/tsxldtrkintrin.h
|
||||
OLD_FILES+=usr/lib/clang/18/include/uintrintrin.h
|
||||
OLD_FILES+=usr/lib/clang/18/include/unwind.h
|
||||
OLD_FILES+=usr/lib/clang/18/include/usermsrintrin.h
|
||||
OLD_FILES+=usr/lib/clang/18/include/vadefs.h
|
||||
OLD_FILES+=usr/lib/clang/18/include/vaesintrin.h
|
||||
OLD_FILES+=usr/lib/clang/18/include/varargs.h
|
||||
OLD_FILES+=usr/lib/clang/18/include/vecintrin.h
|
||||
OLD_FILES+=usr/lib/clang/18/include/velintrin.h
|
||||
OLD_FILES+=usr/lib/clang/18/include/velintrin_approx.h
|
||||
OLD_FILES+=usr/lib/clang/18/include/velintrin_gen.h
|
||||
OLD_FILES+=usr/lib/clang/18/include/vpclmulqdqintrin.h
|
||||
OLD_FILES+=usr/lib/clang/18/include/waitpkgintrin.h
|
||||
OLD_FILES+=usr/lib/clang/18/include/wasm_simd128.h
|
||||
OLD_FILES+=usr/lib/clang/18/include/wbnoinvdintrin.h
|
||||
OLD_FILES+=usr/lib/clang/18/include/wmmintrin.h
|
||||
OLD_FILES+=usr/lib/clang/18/include/x86gprintrin.h
|
||||
OLD_FILES+=usr/lib/clang/18/include/x86intrin.h
|
||||
OLD_FILES+=usr/lib/clang/18/include/xmmintrin.h
|
||||
OLD_FILES+=usr/lib/clang/18/include/xopintrin.h
|
||||
OLD_FILES+=usr/lib/clang/18/include/xray/xray_interface.h
|
||||
OLD_FILES+=usr/lib/clang/18/include/xray/xray_log_interface.h
|
||||
OLD_FILES+=usr/lib/clang/18/include/xray/xray_records.h
|
||||
OLD_DIRS+=usr/lib/clang/18/include/xray
|
||||
OLD_FILES+=usr/lib/clang/18/include/xsavecintrin.h
|
||||
OLD_FILES+=usr/lib/clang/18/include/xsaveintrin.h
|
||||
OLD_FILES+=usr/lib/clang/18/include/xsaveoptintrin.h
|
||||
OLD_FILES+=usr/lib/clang/18/include/xsavesintrin.h
|
||||
OLD_FILES+=usr/lib/clang/18/include/xtestintrin.h
|
||||
OLD_DIRS+=usr/lib/clang/18/include
|
||||
OLD_FILES+=usr/lib/clang/18/lib/freebsd/libclang_rt.asan-aarch64.a
|
||||
OLD_FILES+=usr/lib/clang/18/lib/freebsd/libclang_rt.asan-aarch64.so
|
||||
OLD_FILES+=usr/lib/clang/18/lib/freebsd/libclang_rt.asan-arm.a
|
||||
OLD_FILES+=usr/lib/clang/18/lib/freebsd/libclang_rt.asan-arm.so
|
||||
OLD_FILES+=usr/lib/clang/18/lib/freebsd/libclang_rt.asan-armhf.a
|
||||
OLD_FILES+=usr/lib/clang/18/lib/freebsd/libclang_rt.asan-armhf.so
|
||||
OLD_FILES+=usr/lib/clang/18/lib/freebsd/libclang_rt.asan-i386.a
|
||||
OLD_FILES+=usr/lib/clang/18/lib/freebsd/libclang_rt.asan-i386.so
|
||||
OLD_FILES+=usr/lib/clang/18/lib/freebsd/libclang_rt.asan-powerpc64.a
|
||||
OLD_FILES+=usr/lib/clang/18/lib/freebsd/libclang_rt.asan-powerpc64.so
|
||||
OLD_FILES+=usr/lib/clang/18/lib/freebsd/libclang_rt.asan-powerpc64le.a
|
||||
OLD_FILES+=usr/lib/clang/18/lib/freebsd/libclang_rt.asan-powerpc64le.so
|
||||
OLD_FILES+=usr/lib/clang/18/lib/freebsd/libclang_rt.asan-preinit-aarch64.a
|
||||
OLD_FILES+=usr/lib/clang/18/lib/freebsd/libclang_rt.asan-preinit-arm.a
|
||||
OLD_FILES+=usr/lib/clang/18/lib/freebsd/libclang_rt.asan-preinit-armhf.a
|
||||
OLD_FILES+=usr/lib/clang/18/lib/freebsd/libclang_rt.asan-preinit-i386.a
|
||||
OLD_FILES+=usr/lib/clang/18/lib/freebsd/libclang_rt.asan-preinit-powerpc64.a
|
||||
OLD_FILES+=usr/lib/clang/18/lib/freebsd/libclang_rt.asan-preinit-powerpc64le.a
|
||||
OLD_FILES+=usr/lib/clang/18/lib/freebsd/libclang_rt.asan-preinit-riscv64.a
|
||||
OLD_FILES+=usr/lib/clang/18/lib/freebsd/libclang_rt.asan-preinit-x86_64.a
|
||||
OLD_FILES+=usr/lib/clang/18/lib/freebsd/libclang_rt.asan-riscv64.a
|
||||
OLD_FILES+=usr/lib/clang/18/lib/freebsd/libclang_rt.asan-riscv64.so
|
||||
OLD_FILES+=usr/lib/clang/18/lib/freebsd/libclang_rt.asan-x86_64.a
|
||||
OLD_FILES+=usr/lib/clang/18/lib/freebsd/libclang_rt.asan-x86_64.so
|
||||
OLD_FILES+=usr/lib/clang/18/lib/freebsd/libclang_rt.asan_cxx-aarch64.a
|
||||
OLD_FILES+=usr/lib/clang/18/lib/freebsd/libclang_rt.asan_cxx-arm.a
|
||||
OLD_FILES+=usr/lib/clang/18/lib/freebsd/libclang_rt.asan_cxx-armhf.a
|
||||
OLD_FILES+=usr/lib/clang/18/lib/freebsd/libclang_rt.asan_cxx-i386.a
|
||||
OLD_FILES+=usr/lib/clang/18/lib/freebsd/libclang_rt.asan_cxx-powerpc64.a
|
||||
OLD_FILES+=usr/lib/clang/18/lib/freebsd/libclang_rt.asan_cxx-powerpc64le.a
|
||||
OLD_FILES+=usr/lib/clang/18/lib/freebsd/libclang_rt.asan_cxx-riscv64.a
|
||||
OLD_FILES+=usr/lib/clang/18/lib/freebsd/libclang_rt.asan_cxx-x86_64.a
|
||||
OLD_FILES+=usr/lib/clang/18/lib/freebsd/libclang_rt.asan_static-i386.a
|
||||
OLD_FILES+=usr/lib/clang/18/lib/freebsd/libclang_rt.asan_static-powerpc64.a
|
||||
OLD_FILES+=usr/lib/clang/18/lib/freebsd/libclang_rt.asan_static-powerpc64le.a
|
||||
OLD_FILES+=usr/lib/clang/18/lib/freebsd/libclang_rt.asan_static-x86_64.a
|
||||
OLD_FILES+=usr/lib/clang/18/lib/freebsd/libclang_rt.cfi-aarch64.a
|
||||
OLD_FILES+=usr/lib/clang/18/lib/freebsd/libclang_rt.cfi-arm.a
|
||||
OLD_FILES+=usr/lib/clang/18/lib/freebsd/libclang_rt.cfi-armhf.a
|
||||
OLD_FILES+=usr/lib/clang/18/lib/freebsd/libclang_rt.cfi-i386.a
|
||||
OLD_FILES+=usr/lib/clang/18/lib/freebsd/libclang_rt.cfi-x86_64.a
|
||||
OLD_FILES+=usr/lib/clang/18/lib/freebsd/libclang_rt.cfi_diag-aarch64.a
|
||||
OLD_FILES+=usr/lib/clang/18/lib/freebsd/libclang_rt.cfi_diag-arm.a
|
||||
OLD_FILES+=usr/lib/clang/18/lib/freebsd/libclang_rt.cfi_diag-armhf.a
|
||||
OLD_FILES+=usr/lib/clang/18/lib/freebsd/libclang_rt.cfi_diag-i386.a
|
||||
OLD_FILES+=usr/lib/clang/18/lib/freebsd/libclang_rt.cfi_diag-x86_64.a
|
||||
OLD_FILES+=usr/lib/clang/18/lib/freebsd/libclang_rt.dd-aarch64.a
|
||||
OLD_FILES+=usr/lib/clang/18/lib/freebsd/libclang_rt.dd-x86_64.a
|
||||
OLD_FILES+=usr/lib/clang/18/lib/freebsd/libclang_rt.fuzzer-aarch64.a
|
||||
OLD_FILES+=usr/lib/clang/18/lib/freebsd/libclang_rt.fuzzer-x86_64.a
|
||||
OLD_FILES+=usr/lib/clang/18/lib/freebsd/libclang_rt.fuzzer_interceptors-x86_64.a
|
||||
OLD_FILES+=usr/lib/clang/18/lib/freebsd/libclang_rt.fuzzer_no_main-aarch64.a
|
||||
OLD_FILES+=usr/lib/clang/18/lib/freebsd/libclang_rt.fuzzer_no_main-x86_64.a
|
||||
OLD_FILES+=usr/lib/clang/18/lib/freebsd/libclang_rt.msan-aarch64.a
|
||||
OLD_FILES+=usr/lib/clang/18/lib/freebsd/libclang_rt.msan-powerpc64.a
|
||||
OLD_FILES+=usr/lib/clang/18/lib/freebsd/libclang_rt.msan-powerpc64le.a
|
||||
OLD_FILES+=usr/lib/clang/18/lib/freebsd/libclang_rt.msan-x86_64.a
|
||||
OLD_FILES+=usr/lib/clang/18/lib/freebsd/libclang_rt.msan_cxx-aarch64.a
|
||||
OLD_FILES+=usr/lib/clang/18/lib/freebsd/libclang_rt.msan_cxx-powerpc64.a
|
||||
OLD_FILES+=usr/lib/clang/18/lib/freebsd/libclang_rt.msan_cxx-powerpc64le.a
|
||||
OLD_FILES+=usr/lib/clang/18/lib/freebsd/libclang_rt.msan_cxx-x86_64.a
|
||||
OLD_FILES+=usr/lib/clang/18/lib/freebsd/libclang_rt.profile-aarch64.a
|
||||
OLD_FILES+=usr/lib/clang/18/lib/freebsd/libclang_rt.profile-arm.a
|
||||
OLD_FILES+=usr/lib/clang/18/lib/freebsd/libclang_rt.profile-armhf.a
|
||||
OLD_FILES+=usr/lib/clang/18/lib/freebsd/libclang_rt.profile-i386.a
|
||||
OLD_FILES+=usr/lib/clang/18/lib/freebsd/libclang_rt.profile-powerpc.a
|
||||
OLD_FILES+=usr/lib/clang/18/lib/freebsd/libclang_rt.profile-powerpc64.a
|
||||
OLD_FILES+=usr/lib/clang/18/lib/freebsd/libclang_rt.profile-powerpc64le.a
|
||||
OLD_FILES+=usr/lib/clang/18/lib/freebsd/libclang_rt.profile-riscv64.a
|
||||
OLD_FILES+=usr/lib/clang/18/lib/freebsd/libclang_rt.profile-x86_64.a
|
||||
OLD_FILES+=usr/lib/clang/18/lib/freebsd/libclang_rt.safestack-aarch64.a
|
||||
OLD_FILES+=usr/lib/clang/18/lib/freebsd/libclang_rt.safestack-i386.a
|
||||
OLD_FILES+=usr/lib/clang/18/lib/freebsd/libclang_rt.safestack-x86_64.a
|
||||
OLD_FILES+=usr/lib/clang/18/lib/freebsd/libclang_rt.stats-aarch64.a
|
||||
OLD_FILES+=usr/lib/clang/18/lib/freebsd/libclang_rt.stats-arm.a
|
||||
OLD_FILES+=usr/lib/clang/18/lib/freebsd/libclang_rt.stats-armhf.a
|
||||
OLD_FILES+=usr/lib/clang/18/lib/freebsd/libclang_rt.stats-i386.a
|
||||
OLD_FILES+=usr/lib/clang/18/lib/freebsd/libclang_rt.stats-powerpc64.a
|
||||
OLD_FILES+=usr/lib/clang/18/lib/freebsd/libclang_rt.stats-powerpc64le.a
|
||||
OLD_FILES+=usr/lib/clang/18/lib/freebsd/libclang_rt.stats-riscv64.a
|
||||
OLD_FILES+=usr/lib/clang/18/lib/freebsd/libclang_rt.stats-x86_64.a
|
||||
OLD_FILES+=usr/lib/clang/18/lib/freebsd/libclang_rt.stats_client-aarch64.a
|
||||
OLD_FILES+=usr/lib/clang/18/lib/freebsd/libclang_rt.stats_client-arm.a
|
||||
OLD_FILES+=usr/lib/clang/18/lib/freebsd/libclang_rt.stats_client-armhf.a
|
||||
OLD_FILES+=usr/lib/clang/18/lib/freebsd/libclang_rt.stats_client-i386.a
|
||||
OLD_FILES+=usr/lib/clang/18/lib/freebsd/libclang_rt.stats_client-powerpc64.a
|
||||
OLD_FILES+=usr/lib/clang/18/lib/freebsd/libclang_rt.stats_client-powerpc64le.a
|
||||
OLD_FILES+=usr/lib/clang/18/lib/freebsd/libclang_rt.stats_client-riscv64.a
|
||||
OLD_FILES+=usr/lib/clang/18/lib/freebsd/libclang_rt.stats_client-x86_64.a
|
||||
OLD_FILES+=usr/lib/clang/18/lib/freebsd/libclang_rt.tsan-aarch64.a
|
||||
OLD_FILES+=usr/lib/clang/18/lib/freebsd/libclang_rt.tsan-powerpc64.a
|
||||
OLD_FILES+=usr/lib/clang/18/lib/freebsd/libclang_rt.tsan-powerpc64le.a
|
||||
OLD_FILES+=usr/lib/clang/18/lib/freebsd/libclang_rt.tsan-x86_64.a
|
||||
OLD_FILES+=usr/lib/clang/18/lib/freebsd/libclang_rt.tsan_cxx-aarch64.a
|
||||
OLD_FILES+=usr/lib/clang/18/lib/freebsd/libclang_rt.tsan_cxx-powerpc64.a
|
||||
OLD_FILES+=usr/lib/clang/18/lib/freebsd/libclang_rt.tsan_cxx-powerpc64le.a
|
||||
OLD_FILES+=usr/lib/clang/18/lib/freebsd/libclang_rt.tsan_cxx-x86_64.a
|
||||
OLD_FILES+=usr/lib/clang/18/lib/freebsd/libclang_rt.ubsan_minimal-aarch64.a
|
||||
OLD_FILES+=usr/lib/clang/18/lib/freebsd/libclang_rt.ubsan_minimal-arm.a
|
||||
OLD_FILES+=usr/lib/clang/18/lib/freebsd/libclang_rt.ubsan_minimal-armhf.a
|
||||
OLD_FILES+=usr/lib/clang/18/lib/freebsd/libclang_rt.ubsan_minimal-i386.a
|
||||
OLD_FILES+=usr/lib/clang/18/lib/freebsd/libclang_rt.ubsan_minimal-powerpc64.a
|
||||
OLD_FILES+=usr/lib/clang/18/lib/freebsd/libclang_rt.ubsan_minimal-powerpc64le.a
|
||||
OLD_FILES+=usr/lib/clang/18/lib/freebsd/libclang_rt.ubsan_minimal-riscv64.a
|
||||
OLD_FILES+=usr/lib/clang/18/lib/freebsd/libclang_rt.ubsan_minimal-x86_64.a
|
||||
OLD_FILES+=usr/lib/clang/18/lib/freebsd/libclang_rt.ubsan_standalone-aarch64.a
|
||||
OLD_FILES+=usr/lib/clang/18/lib/freebsd/libclang_rt.ubsan_standalone-arm.a
|
||||
OLD_FILES+=usr/lib/clang/18/lib/freebsd/libclang_rt.ubsan_standalone-armhf.a
|
||||
OLD_FILES+=usr/lib/clang/18/lib/freebsd/libclang_rt.ubsan_standalone-i386.a
|
||||
OLD_FILES+=usr/lib/clang/18/lib/freebsd/libclang_rt.ubsan_standalone-powerpc64.a
|
||||
OLD_FILES+=usr/lib/clang/18/lib/freebsd/libclang_rt.ubsan_standalone-powerpc64le.a
|
||||
OLD_FILES+=usr/lib/clang/18/lib/freebsd/libclang_rt.ubsan_standalone-riscv64.a
|
||||
OLD_FILES+=usr/lib/clang/18/lib/freebsd/libclang_rt.ubsan_standalone-x86_64.a
|
||||
OLD_FILES+=usr/lib/clang/18/lib/freebsd/libclang_rt.ubsan_standalone_cxx-aarch64.a
|
||||
OLD_FILES+=usr/lib/clang/18/lib/freebsd/libclang_rt.ubsan_standalone_cxx-arm.a
|
||||
OLD_FILES+=usr/lib/clang/18/lib/freebsd/libclang_rt.ubsan_standalone_cxx-armhf.a
|
||||
OLD_FILES+=usr/lib/clang/18/lib/freebsd/libclang_rt.ubsan_standalone_cxx-i386.a
|
||||
OLD_FILES+=usr/lib/clang/18/lib/freebsd/libclang_rt.ubsan_standalone_cxx-powerpc64.a
|
||||
OLD_FILES+=usr/lib/clang/18/lib/freebsd/libclang_rt.ubsan_standalone_cxx-powerpc64le.a
|
||||
OLD_FILES+=usr/lib/clang/18/lib/freebsd/libclang_rt.ubsan_standalone_cxx-riscv64.a
|
||||
OLD_FILES+=usr/lib/clang/18/lib/freebsd/libclang_rt.ubsan_standalone_cxx-x86_64.a
|
||||
OLD_FILES+=usr/lib/clang/18/lib/freebsd/libclang_rt.xray-aarch64.a
|
||||
OLD_FILES+=usr/lib/clang/18/lib/freebsd/libclang_rt.xray-arm.a
|
||||
OLD_FILES+=usr/lib/clang/18/lib/freebsd/libclang_rt.xray-armhf.a
|
||||
OLD_FILES+=usr/lib/clang/18/lib/freebsd/libclang_rt.xray-basic-aarch64.a
|
||||
OLD_FILES+=usr/lib/clang/18/lib/freebsd/libclang_rt.xray-basic-arm.a
|
||||
OLD_FILES+=usr/lib/clang/18/lib/freebsd/libclang_rt.xray-basic-armhf.a
|
||||
OLD_FILES+=usr/lib/clang/18/lib/freebsd/libclang_rt.xray-basic-powerpc64le.a
|
||||
OLD_FILES+=usr/lib/clang/18/lib/freebsd/libclang_rt.xray-basic-x86_64.a
|
||||
OLD_FILES+=usr/lib/clang/18/lib/freebsd/libclang_rt.xray-fdr-aarch64.a
|
||||
OLD_FILES+=usr/lib/clang/18/lib/freebsd/libclang_rt.xray-fdr-arm.a
|
||||
OLD_FILES+=usr/lib/clang/18/lib/freebsd/libclang_rt.xray-fdr-armhf.a
|
||||
OLD_FILES+=usr/lib/clang/18/lib/freebsd/libclang_rt.xray-fdr-powerpc64le.a
|
||||
OLD_FILES+=usr/lib/clang/18/lib/freebsd/libclang_rt.xray-fdr-x86_64.a
|
||||
OLD_FILES+=usr/lib/clang/18/lib/freebsd/libclang_rt.xray-powerpc64le.a
|
||||
OLD_FILES+=usr/lib/clang/18/lib/freebsd/libclang_rt.xray-profiling-aarch64.a
|
||||
OLD_FILES+=usr/lib/clang/18/lib/freebsd/libclang_rt.xray-profiling-arm.a
|
||||
OLD_FILES+=usr/lib/clang/18/lib/freebsd/libclang_rt.xray-profiling-armhf.a
|
||||
OLD_FILES+=usr/lib/clang/18/lib/freebsd/libclang_rt.xray-profiling-powerpc64le.a
|
||||
OLD_FILES+=usr/lib/clang/18/lib/freebsd/libclang_rt.xray-profiling-x86_64.a
|
||||
OLD_FILES+=usr/lib/clang/18/lib/freebsd/libclang_rt.xray-x86_64.a
|
||||
OLD_DIRS+=usr/lib/clang/18/lib/freebsd
|
||||
OLD_DIRS+=usr/lib/clang/18/lib
|
||||
OLD_FILES+=usr/lib/clang/18/share/asan_ignorelist.txt
|
||||
OLD_FILES+=usr/lib/clang/18/share/cfi_ignorelist.txt
|
||||
OLD_FILES+=usr/lib/clang/18/share/msan_ignorelist.txt
|
||||
OLD_DIRS+=usr/lib/clang/18/share
|
||||
OLD_DIRS+=usr/lib/clang/18
|
||||
|
||||
# 20241023: new libc++ import which bumps version from 18 to 19
|
||||
OLD_FILES+=usr/include/c++/v1/__algorithm/pstl_any_all_none_of.h
|
||||
OLD_FILES+=usr/include/c++/v1/__algorithm/pstl_backend.h
|
||||
OLD_FILES+=usr/include/c++/v1/__algorithm/pstl_backends/cpu_backend.h
|
||||
OLD_FILES+=usr/include/c++/v1/__algorithm/pstl_backends/cpu_backends/any_of.h
|
||||
OLD_FILES+=usr/include/c++/v1/__algorithm/pstl_backends/cpu_backends/backend.h
|
||||
OLD_FILES+=usr/include/c++/v1/__algorithm/pstl_backends/cpu_backends/fill.h
|
||||
OLD_FILES+=usr/include/c++/v1/__algorithm/pstl_backends/cpu_backends/find_if.h
|
||||
OLD_FILES+=usr/include/c++/v1/__algorithm/pstl_backends/cpu_backends/for_each.h
|
||||
OLD_FILES+=usr/include/c++/v1/__algorithm/pstl_backends/cpu_backends/libdispatch.h
|
||||
OLD_FILES+=usr/include/c++/v1/__algorithm/pstl_backends/cpu_backends/merge.h
|
||||
OLD_FILES+=usr/include/c++/v1/__algorithm/pstl_backends/cpu_backends/serial.h
|
||||
OLD_FILES+=usr/include/c++/v1/__algorithm/pstl_backends/cpu_backends/stable_sort.h
|
||||
OLD_FILES+=usr/include/c++/v1/__algorithm/pstl_backends/cpu_backends/thread.h
|
||||
OLD_FILES+=usr/include/c++/v1/__algorithm/pstl_backends/cpu_backends/transform.h
|
||||
OLD_FILES+=usr/include/c++/v1/__algorithm/pstl_backends/cpu_backends/transform_reduce.h
|
||||
OLD_DIRS+=usr/include/c++/v1/__algorithm/pstl_backends/cpu_backends
|
||||
OLD_DIRS+=usr/include/c++/v1/__algorithm/pstl_backends
|
||||
OLD_FILES+=usr/include/c++/v1/__algorithm/pstl_copy.h
|
||||
OLD_FILES+=usr/include/c++/v1/__algorithm/pstl_count.h
|
||||
OLD_FILES+=usr/include/c++/v1/__algorithm/pstl_equal.h
|
||||
OLD_FILES+=usr/include/c++/v1/__algorithm/pstl_fill.h
|
||||
OLD_FILES+=usr/include/c++/v1/__algorithm/pstl_find.h
|
||||
OLD_FILES+=usr/include/c++/v1/__algorithm/pstl_for_each.h
|
||||
OLD_FILES+=usr/include/c++/v1/__algorithm/pstl_frontend_dispatch.h
|
||||
OLD_FILES+=usr/include/c++/v1/__algorithm/pstl_generate.h
|
||||
OLD_FILES+=usr/include/c++/v1/__algorithm/pstl_is_partitioned.h
|
||||
OLD_FILES+=usr/include/c++/v1/__algorithm/pstl_merge.h
|
||||
OLD_FILES+=usr/include/c++/v1/__algorithm/pstl_move.h
|
||||
OLD_FILES+=usr/include/c++/v1/__algorithm/pstl_replace.h
|
||||
OLD_FILES+=usr/include/c++/v1/__algorithm/pstl_rotate_copy.h
|
||||
OLD_FILES+=usr/include/c++/v1/__algorithm/pstl_sort.h
|
||||
OLD_FILES+=usr/include/c++/v1/__algorithm/pstl_stable_sort.h
|
||||
OLD_FILES+=usr/include/c++/v1/__algorithm/pstl_transform.h
|
||||
OLD_FILES+=usr/include/c++/v1/__availability
|
||||
OLD_FILES+=usr/include/c++/v1/__format/format_fwd.h
|
||||
OLD_FILES+=usr/include/c++/v1/__fwd/get.h
|
||||
OLD_FILES+=usr/include/c++/v1/__fwd/hash.h
|
||||
OLD_FILES+=usr/include/c++/v1/__numeric/pstl_reduce.h
|
||||
OLD_FILES+=usr/include/c++/v1/__numeric/pstl_transform_reduce.h
|
||||
OLD_FILES+=usr/include/c++/v1/__threading_support
|
||||
OLD_FILES+=usr/include/c++/v1/__tuple/pair_like.h
|
||||
OLD_FILES+=usr/include/c++/v1/__type_traits/apply_cv.h
|
||||
OLD_FILES+=usr/include/c++/v1/__type_traits/is_copy_assignable.h
|
||||
OLD_FILES+=usr/include/c++/v1/__type_traits/is_copy_constructible.h
|
||||
OLD_FILES+=usr/include/c++/v1/__type_traits/is_default_constructible.h
|
||||
OLD_FILES+=usr/include/c++/v1/__type_traits/is_member_function_pointer.h
|
||||
OLD_FILES+=usr/include/c++/v1/__type_traits/is_member_object_pointer.h
|
||||
OLD_FILES+=usr/include/c++/v1/__type_traits/is_move_assignable.h
|
||||
OLD_FILES+=usr/include/c++/v1/__type_traits/is_move_constructible.h
|
||||
OLD_FILES+=usr/include/c++/v1/__type_traits/is_nothrow_copy_assignable.h
|
||||
OLD_FILES+=usr/include/c++/v1/__type_traits/is_nothrow_copy_constructible.h
|
||||
OLD_FILES+=usr/include/c++/v1/__type_traits/is_nothrow_default_constructible.h
|
||||
OLD_FILES+=usr/include/c++/v1/__type_traits/is_nothrow_move_assignable.h
|
||||
OLD_FILES+=usr/include/c++/v1/__type_traits/is_nothrow_move_constructible.h
|
||||
OLD_FILES+=usr/include/c++/v1/__type_traits/is_scoped_enum.h
|
||||
OLD_FILES+=usr/include/c++/v1/__type_traits/is_trivially_copy_assignable.h
|
||||
OLD_FILES+=usr/include/c++/v1/__type_traits/is_trivially_copy_constructible.h
|
||||
OLD_FILES+=usr/include/c++/v1/__type_traits/is_trivially_default_constructible.h
|
||||
OLD_FILES+=usr/include/c++/v1/__type_traits/is_trivially_move_assignable.h
|
||||
OLD_FILES+=usr/include/c++/v1/__type_traits/is_trivially_move_constructible.h
|
||||
OLD_FILES+=usr/include/c++/v1/__type_traits/operation_traits.h
|
||||
OLD_FILES+=usr/include/c++/v1/experimental/__memory
|
||||
|
||||
# 20241014: move divapp to netpfil/common/
|
||||
OLD_FILES+=usr/tests/sys/netpfil/pf/divapp
|
||||
|
||||
|
|
|
|||
|
|
@ -1,5 +1,3 @@
|
|||
.arcconfig
|
||||
.arclint
|
||||
.ci/
|
||||
.clang-format
|
||||
.clang-tidy
|
||||
|
|
@ -29,7 +27,11 @@ clang/examples/
|
|||
clang/include/CMakeLists.txt
|
||||
clang/include/clang/AST/CMakeLists.txt
|
||||
clang/include/clang/Basic/CMakeLists.txt
|
||||
clang/include/clang/Basic/Target/
|
||||
clang/include/clang/Basic/Version.inc.in
|
||||
clang/include/clang/CIR/CMakeLists.txt
|
||||
clang/include/clang/CIR/Dialect/CMakeLists.txt
|
||||
clang/include/clang/CIR/Dialect/IR/CMakeLists.txt
|
||||
clang/include/clang/CMakeLists.txt
|
||||
clang/include/clang/Config/
|
||||
clang/include/clang/Driver/CMakeLists.txt
|
||||
|
|
@ -52,6 +54,9 @@ clang/lib/Analysis/plugins/CheckerDependencyHandling/CMakeLists.txt
|
|||
clang/lib/Analysis/plugins/CheckerOptionHandling/CMakeLists.txt
|
||||
clang/lib/Analysis/plugins/SampleAnalyzer/CMakeLists.txt
|
||||
clang/lib/Basic/CMakeLists.txt
|
||||
clang/lib/CIR/CMakeLists.txt
|
||||
clang/lib/CIR/Dialect/CMakeLists.txt
|
||||
clang/lib/CIR/Dialect/IR/CMakeLists.txt
|
||||
clang/lib/CMakeLists.txt
|
||||
clang/lib/CodeGen/CMakeLists.txt
|
||||
clang/lib/CodeGen/README.txt
|
||||
|
|
@ -68,6 +73,7 @@ clang/lib/FrontendTool/CMakeLists.txt
|
|||
clang/lib/Headers/CMakeLists.txt
|
||||
clang/lib/Index/CMakeLists.txt
|
||||
clang/lib/IndexSerialization/CMakeLists.txt
|
||||
clang/lib/InstallAPI/CMakeLists.txt
|
||||
clang/lib/Interpreter/CMakeLists.txt
|
||||
clang/lib/Lex/CMakeLists.txt
|
||||
clang/lib/Parse/CMakeLists.txt
|
||||
|
|
@ -85,8 +91,6 @@ clang/lib/Tooling/ASTDiff/CMakeLists.txt
|
|||
clang/lib/Tooling/CMakeLists.txt
|
||||
clang/lib/Tooling/Core/CMakeLists.txt
|
||||
clang/lib/Tooling/DependencyScanning/CMakeLists.txt
|
||||
clang/lib/Tooling/DumpTool/CMakeLists.txt
|
||||
clang/lib/Tooling/DumpTool/generate_cxx_src_locs.py
|
||||
clang/lib/Tooling/Inclusions/CMakeLists.txt
|
||||
clang/lib/Tooling/Inclusions/Stdlib/CMakeLists.txt
|
||||
clang/lib/Tooling/Refactoring/CMakeLists.txt
|
||||
|
|
@ -95,7 +99,7 @@ clang/lib/Tooling/Transformer/CMakeLists.txt
|
|||
clang/runtime/
|
||||
clang/test/
|
||||
clang/tools/CMakeLists.txt
|
||||
clang/tools/amdgpu-arch/CMakeLists.txt
|
||||
clang/tools/amdgpu-arch/
|
||||
clang/tools/apinotes-test/
|
||||
clang/tools/arcmt-test/
|
||||
clang/tools/c-arcmt-test/
|
||||
|
|
@ -117,12 +121,14 @@ clang/tools/clang-format/git-clang-format.bat
|
|||
clang/tools/clang-format-vs/
|
||||
clang/tools/clang-fuzzer/
|
||||
clang/tools/clang-import-test/
|
||||
clang/tools/clang-installapi/
|
||||
clang/tools/clang-linker-wrapper/
|
||||
clang/tools/clang-nvlink-wrapper/
|
||||
clang/tools/clang-offload-bundler/
|
||||
clang/tools/clang-offload-packager/
|
||||
clang/tools/clang-refactor/
|
||||
clang/tools/clang-rename/
|
||||
clang/tools/clang-repl/CMakeLists.txt
|
||||
clang/tools/clang-repl/
|
||||
clang/tools/clang-scan-deps/
|
||||
clang/tools/clang-shlib/
|
||||
clang/tools/diag-build/
|
||||
|
|
@ -131,7 +137,7 @@ clang/tools/driver/CMakeLists.txt
|
|||
clang/tools/driver/Info.plist.in
|
||||
clang/tools/include-mapping/
|
||||
clang/tools/libclang/
|
||||
clang/tools/nvptx-arch/CMakeLists.txt
|
||||
clang/tools/nvptx-arch/
|
||||
clang/tools/scan-build/
|
||||
clang/tools/scan-build-py/
|
||||
clang/tools/scan-view/
|
||||
|
|
@ -139,7 +145,6 @@ clang/unittests/
|
|||
clang/utils/ABITest/
|
||||
clang/utils/CIndex/
|
||||
clang/utils/CaptureCmd
|
||||
clang/utils/ClangDataFormat.py
|
||||
clang/utils/ClangVisualizers/
|
||||
clang/utils/CmpDriver
|
||||
clang/utils/FindSpecRefs
|
||||
|
|
@ -153,7 +158,6 @@ clang/utils/bash-autocomplete.sh
|
|||
clang/utils/builtin-defines.c
|
||||
clang/utils/bundle_resources.py
|
||||
clang/utils/check_cfc/
|
||||
clang/utils/ci/
|
||||
clang/utils/clangdiag.py
|
||||
clang/utils/convert_arm_neon.py
|
||||
clang/utils/creduce-clang-crash.py
|
||||
|
|
@ -164,7 +168,6 @@ clang/utils/modfuzz.py
|
|||
clang/utils/module-deps-to-rsp.py
|
||||
clang/utils/perf-training/
|
||||
clang/utils/token-delta.py
|
||||
clang/utils/update_options_td_flags.py
|
||||
clang/utils/valgrind/
|
||||
clang/www/
|
||||
clang-tools-extra/
|
||||
|
|
@ -185,6 +188,8 @@ compiler-rt/lib/builtins/CMakeLists.txt
|
|||
compiler-rt/lib/builtins/Darwin-excludes/
|
||||
compiler-rt/lib/builtins/macho_embedded/
|
||||
compiler-rt/lib/cfi/CMakeLists.txt
|
||||
compiler-rt/lib/ctx_profile/CMakeLists.txt
|
||||
compiler-rt/lib/ctx_profile/tests/CMakeLists.txt
|
||||
compiler-rt/lib/dfsan/.clang-format
|
||||
compiler-rt/lib/dfsan/CMakeLists.txt
|
||||
compiler-rt/lib/dfsan/scripts/
|
||||
|
|
@ -211,11 +216,15 @@ compiler-rt/lib/memprof/tests/CMakeLists.txt
|
|||
compiler-rt/lib/msan/.clang-format
|
||||
compiler-rt/lib/msan/CMakeLists.txt
|
||||
compiler-rt/lib/msan/tests/
|
||||
compiler-rt/lib/nsan/CMakeLists.txt
|
||||
compiler-rt/lib/nsan/tests/CMakeLists.txt
|
||||
compiler-rt/lib/orc/CMakeLists.txt
|
||||
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/rtsan/CMakeLists.txt
|
||||
compiler-rt/lib/rtsan/tests/CMakeLists.txt
|
||||
compiler-rt/lib/safestack/.clang-format
|
||||
compiler-rt/lib/safestack/CMakeLists.txt
|
||||
compiler-rt/lib/sanitizer_common/.clang-format
|
||||
|
|
@ -267,6 +276,7 @@ libcxx/include/__config_site.in
|
|||
libcxx/include/__support/
|
||||
libcxx/lib/
|
||||
libcxx/modules/CMakeLists.txt
|
||||
libcxx/modules/CMakeLists.txt.in
|
||||
libcxx/modules/README.md
|
||||
libcxx/src/CMakeLists.txt
|
||||
libcxx/src/support/win32/
|
||||
|
|
@ -309,9 +319,6 @@ lldb/docs/conf.py
|
|||
lldb/docs/doxygen-mainpage.dox
|
||||
lldb/docs/doxygen.cfg.in
|
||||
lldb/docs/index.rst
|
||||
lldb/docs/lldb-for-gdb-users.txt
|
||||
lldb/docs/lldb-gdb-remote.txt
|
||||
lldb/docs/lldb-platform-packets.txt
|
||||
lldb/docs/resources/
|
||||
lldb/docs/testsuite/
|
||||
lldb/docs/use/
|
||||
|
|
@ -483,7 +490,6 @@ lldb/source/Target/CMakeLists.txt
|
|||
lldb/source/Utility/CMakeLists.txt
|
||||
lldb/source/Version/CMakeLists.txt
|
||||
lldb/test/
|
||||
lldb/third_party/
|
||||
lldb/tools/CMakeLists.txt
|
||||
lldb/tools/argdumper/CMakeLists.txt
|
||||
lldb/tools/darwin-debug/
|
||||
|
|
@ -548,6 +554,8 @@ llvm/lib/CodeGen/GlobalISel/CMakeLists.txt
|
|||
llvm/lib/CodeGen/MIRParser/CMakeLists.txt
|
||||
llvm/lib/CodeGen/README.txt
|
||||
llvm/lib/CodeGen/SelectionDAG/CMakeLists.txt
|
||||
llvm/lib/CodeGenData/CMakeLists.txt
|
||||
llvm/lib/CodeGenTypes/CMakeLists.txt
|
||||
llvm/lib/DWARFLinker/CMakeLists.txt
|
||||
llvm/lib/DWARFLinker/Classic/CMakeLists.txt
|
||||
llvm/lib/DWARFLinker/Parallel/CMakeLists.txt
|
||||
|
|
@ -565,6 +573,7 @@ llvm/lib/Debuginfod/CMakeLists.txt
|
|||
llvm/lib/Demangle/CMakeLists.txt
|
||||
llvm/lib/ExecutionEngine/CMakeLists.txt
|
||||
llvm/lib/ExecutionEngine/IntelJITEvents/CMakeLists.txt
|
||||
llvm/lib/ExecutionEngine/IntelJITProfiling/CMakeLists.txt
|
||||
llvm/lib/ExecutionEngine/Interpreter/CMakeLists.txt
|
||||
llvm/lib/ExecutionEngine/JITLink/CMakeLists.txt
|
||||
llvm/lib/ExecutionEngine/MCJIT/CMakeLists.txt
|
||||
|
|
@ -604,9 +613,11 @@ llvm/lib/Passes/CMakeLists.txt
|
|||
llvm/lib/ProfileData/CMakeLists.txt
|
||||
llvm/lib/ProfileData/Coverage/CMakeLists.txt
|
||||
llvm/lib/Remarks/CMakeLists.txt
|
||||
llvm/lib/SandboxIR/CMakeLists.txt
|
||||
llvm/lib/Support/BLAKE3/.clang-format
|
||||
llvm/lib/Support/BLAKE3/CMakeLists.txt
|
||||
llvm/lib/Support/CMakeLists.txt
|
||||
llvm/lib/Support/rpmalloc/
|
||||
llvm/lib/TableGen/CMakeLists.txt
|
||||
llvm/lib/Target/AArch64/AsmParser/CMakeLists.txt
|
||||
llvm/lib/Target/AArch64/CMakeLists.txt
|
||||
|
|
@ -614,6 +625,7 @@ llvm/lib/Target/AArch64/Disassembler/CMakeLists.txt
|
|||
llvm/lib/Target/AArch64/MCTargetDesc/CMakeLists.txt
|
||||
llvm/lib/Target/AArch64/TargetInfo/CMakeLists.txt
|
||||
llvm/lib/Target/AArch64/Utils/CMakeLists.txt
|
||||
llvm/lib/Target/AArch64/peephole-sxtw.mir
|
||||
llvm/lib/Target/AMDGPU/AsmParser/CMakeLists.txt
|
||||
llvm/lib/Target/AMDGPU/CMakeLists.txt
|
||||
llvm/lib/Target/AMDGPU/Disassembler/CMakeLists.txt
|
||||
|
|
@ -703,6 +715,7 @@ llvm/lib/Target/RISCV/Disassembler/CMakeLists.txt
|
|||
llvm/lib/Target/RISCV/MCA/CMakeLists.txt
|
||||
llvm/lib/Target/RISCV/MCTargetDesc/CMakeLists.txt
|
||||
llvm/lib/Target/RISCV/TargetInfo/CMakeLists.txt
|
||||
llvm/lib/Target/SPIRV/Analysis/CMakeLists.txt
|
||||
llvm/lib/Target/SPIRV/CMakeLists.txt
|
||||
llvm/lib/Target/SPIRV/MCTargetDesc/CMakeLists.txt
|
||||
llvm/lib/Target/SPIRV/TargetInfo/CMakeLists.txt
|
||||
|
|
@ -761,7 +774,6 @@ llvm/lib/Transforms/AggressiveInstCombine/CMakeLists.txt
|
|||
llvm/lib/Transforms/CFGuard/CMakeLists.txt
|
||||
llvm/lib/Transforms/CMakeLists.txt
|
||||
llvm/lib/Transforms/Coroutines/CMakeLists.txt
|
||||
llvm/lib/Transforms/Hello/
|
||||
llvm/lib/Transforms/HipStdPar/CMakeLists.txt
|
||||
llvm/lib/Transforms/IPO/CMakeLists.txt
|
||||
llvm/lib/Transforms/InstCombine/CMakeLists.txt
|
||||
|
|
@ -773,7 +785,6 @@ llvm/lib/Transforms/Vectorize/CMakeLists.txt
|
|||
llvm/lib/WindowsDriver/CMakeLists.txt
|
||||
llvm/lib/WindowsManifest/CMakeLists.txt
|
||||
llvm/lib/XRay/CMakeLists.txt
|
||||
llvm/llvm.spec.in
|
||||
llvm/projects/
|
||||
llvm/resources/
|
||||
llvm/runtimes/
|
||||
|
|
@ -794,6 +805,7 @@ llvm/tools/llvm-bcanalyzer/CMakeLists.txt
|
|||
llvm/tools/llvm-c-test/
|
||||
llvm/tools/llvm-cat/
|
||||
llvm/tools/llvm-cfi-verify/
|
||||
llvm/tools/llvm-cgdata/
|
||||
llvm/tools/llvm-config/
|
||||
llvm/tools/llvm-cov/CMakeLists.txt
|
||||
llvm/tools/llvm-cvtres/
|
||||
|
|
@ -866,6 +878,7 @@ llvm/tools/lto/
|
|||
llvm/tools/obj2yaml/
|
||||
llvm/tools/opt/CMakeLists.txt
|
||||
llvm/tools/opt-viewer/
|
||||
llvm/tools/reduce-chunk-list/
|
||||
llvm/tools/remarks-shlib/
|
||||
llvm/tools/sancov/
|
||||
llvm/tools/sanstats/
|
||||
|
|
@ -885,8 +898,9 @@ llvm/utils/LLVMVisualizers/
|
|||
llvm/utils/Misc/
|
||||
llvm/utils/PerfectShuffle/
|
||||
llvm/utils/Reviewing/
|
||||
llvm/utils/TableGen/Basic/CMakeLists.txt
|
||||
llvm/utils/TableGen/CMakeLists.txt
|
||||
llvm/utils/TableGen/GlobalISel/CMakeLists.txt
|
||||
llvm/utils/TableGen/Common/CMakeLists.txt
|
||||
llvm/utils/TableGen/README.md
|
||||
llvm/utils/TableGen/jupyter/
|
||||
llvm/utils/TableGen/tdtags
|
||||
|
|
@ -908,6 +922,7 @@ llvm/utils/codegen-diff
|
|||
llvm/utils/collect_and_build_with_pgo.py
|
||||
llvm/utils/convert-constraint-log-to-z3.py
|
||||
llvm/utils/count/
|
||||
llvm/utils/count_running_jobs.py
|
||||
llvm/utils/create_ladder_graph.py
|
||||
llvm/utils/crosstool/
|
||||
llvm/utils/demangle_tree.py
|
||||
|
|
@ -956,8 +971,7 @@ llvm/utils/schedcover.py
|
|||
llvm/utils/shuffle_fuzz.py
|
||||
llvm/utils/shuffle_select_fuzz_tester.py
|
||||
llvm/utils/sort_includes.py
|
||||
llvm/utils/split-file/.clang-tidy
|
||||
llvm/utils/split-file/CMakeLists.txt
|
||||
llvm/utils/split-file/
|
||||
llvm/utils/sysroot.py
|
||||
llvm/utils/testgen/
|
||||
llvm/utils/textmate/
|
||||
|
|
@ -968,6 +982,7 @@ llvm/utils/update_cc_test_checks.py
|
|||
llvm/utils/update_llc_test_checks.py
|
||||
llvm/utils/update_mca_test_checks.py
|
||||
llvm/utils/update_mir_test_checks.py
|
||||
llvm/utils/update_test_body.py
|
||||
llvm/utils/update_test_checks.py
|
||||
llvm/utils/update_test_prefix.py
|
||||
llvm/utils/valgrind/
|
||||
|
|
@ -977,13 +992,13 @@ llvm/utils/wciia.py
|
|||
llvm/utils/yaml-bench/
|
||||
llvm-libgcc/
|
||||
mlir/
|
||||
offload/
|
||||
openmp/.gitignore
|
||||
openmp/CMakeLists.txt
|
||||
openmp/README.rst
|
||||
openmp/cmake/
|
||||
openmp/docs/
|
||||
openmp/libompd/
|
||||
openmp/libomptarget/
|
||||
openmp/runtime/.clang-format
|
||||
openmp/runtime/.clang-tidy
|
||||
openmp/runtime/CMakeLists.txt
|
||||
|
|
@ -997,6 +1012,7 @@ openmp/runtime/tools/
|
|||
openmp/tools/
|
||||
polly/
|
||||
pstl/
|
||||
pyproject.toml
|
||||
runtimes/
|
||||
third-party/
|
||||
utils/
|
||||
|
|
|
|||
|
|
@ -1644,8 +1644,9 @@ enum CXCursorKind {
|
|||
CXCursor_ObjCSelfExpr = 146,
|
||||
|
||||
/** OpenMP 5.0 [2.1.5, Array Section].
|
||||
* OpenACC 3.3 [2.7.1, Data Specification for Data Clauses (Sub Arrays)]
|
||||
*/
|
||||
CXCursor_OMPArraySectionExpr = 147,
|
||||
CXCursor_ArraySectionExpr = 147,
|
||||
|
||||
/** Represents an @available(...) check.
|
||||
*/
|
||||
|
|
@ -1675,7 +1676,7 @@ enum CXCursorKind {
|
|||
CXCursor_ConceptSpecializationExpr = 153,
|
||||
|
||||
/**
|
||||
* Expression that references a C++20 concept.
|
||||
* Expression that references a C++20 requires expression.
|
||||
*/
|
||||
CXCursor_RequiresExpr = 154,
|
||||
|
||||
|
|
@ -1685,7 +1686,12 @@ enum CXCursorKind {
|
|||
*/
|
||||
CXCursor_CXXParenListInitExpr = 155,
|
||||
|
||||
CXCursor_LastExpr = CXCursor_CXXParenListInitExpr,
|
||||
/**
|
||||
* Represents a C++26 pack indexing expression.
|
||||
*/
|
||||
CXCursor_PackIndexingExpr = 156,
|
||||
|
||||
CXCursor_LastExpr = CXCursor_PackIndexingExpr,
|
||||
|
||||
/* Statements */
|
||||
CXCursor_FirstStmt = 200,
|
||||
|
|
@ -2140,7 +2146,23 @@ enum CXCursorKind {
|
|||
*/
|
||||
CXCursor_OMPScopeDirective = 306,
|
||||
|
||||
CXCursor_LastStmt = CXCursor_OMPScopeDirective,
|
||||
/** OpenMP reverse directive.
|
||||
*/
|
||||
CXCursor_OMPReverseDirective = 307,
|
||||
|
||||
/** OpenMP interchange directive.
|
||||
*/
|
||||
CXCursor_OMPInterchangeDirective = 308,
|
||||
|
||||
/** OpenACC Compute Construct.
|
||||
*/
|
||||
CXCursor_OpenACCComputeConstruct = 320,
|
||||
|
||||
/** OpenACC Loop Construct.
|
||||
*/
|
||||
CXCursor_OpenACCLoopConstruct = 321,
|
||||
|
||||
CXCursor_LastStmt = CXCursor_OpenACCLoopConstruct,
|
||||
|
||||
/**
|
||||
* Cursor that represents the translation unit itself.
|
||||
|
|
@ -2981,6 +3003,8 @@ enum CXCallingConv {
|
|||
CXCallingConv_SwiftAsync = 17,
|
||||
CXCallingConv_AArch64SVEPCS = 18,
|
||||
CXCallingConv_M68kRTD = 19,
|
||||
CXCallingConv_PreserveNone = 20,
|
||||
CXCallingConv_RISCVVectorCall = 21,
|
||||
|
||||
CXCallingConv_Invalid = 100,
|
||||
CXCallingConv_Unexposed = 200
|
||||
|
|
@ -3734,6 +3758,59 @@ enum CX_StorageClass {
|
|||
CX_SC_Register
|
||||
};
|
||||
|
||||
/**
|
||||
* Represents a specific kind of binary operator which can appear at a cursor.
|
||||
*/
|
||||
enum CX_BinaryOperatorKind {
|
||||
CX_BO_Invalid = 0,
|
||||
CX_BO_PtrMemD = 1,
|
||||
CX_BO_PtrMemI = 2,
|
||||
CX_BO_Mul = 3,
|
||||
CX_BO_Div = 4,
|
||||
CX_BO_Rem = 5,
|
||||
CX_BO_Add = 6,
|
||||
CX_BO_Sub = 7,
|
||||
CX_BO_Shl = 8,
|
||||
CX_BO_Shr = 9,
|
||||
CX_BO_Cmp = 10,
|
||||
CX_BO_LT = 11,
|
||||
CX_BO_GT = 12,
|
||||
CX_BO_LE = 13,
|
||||
CX_BO_GE = 14,
|
||||
CX_BO_EQ = 15,
|
||||
CX_BO_NE = 16,
|
||||
CX_BO_And = 17,
|
||||
CX_BO_Xor = 18,
|
||||
CX_BO_Or = 19,
|
||||
CX_BO_LAnd = 20,
|
||||
CX_BO_LOr = 21,
|
||||
CX_BO_Assign = 22,
|
||||
CX_BO_MulAssign = 23,
|
||||
CX_BO_DivAssign = 24,
|
||||
CX_BO_RemAssign = 25,
|
||||
CX_BO_AddAssign = 26,
|
||||
CX_BO_SubAssign = 27,
|
||||
CX_BO_ShlAssign = 28,
|
||||
CX_BO_ShrAssign = 29,
|
||||
CX_BO_AndAssign = 30,
|
||||
CX_BO_XorAssign = 31,
|
||||
CX_BO_OrAssign = 32,
|
||||
CX_BO_Comma = 33,
|
||||
CX_BO_LAST = CX_BO_Comma
|
||||
};
|
||||
|
||||
/**
|
||||
* \brief Returns the operator code for the binary operator.
|
||||
*/
|
||||
CINDEX_LINKAGE enum CX_BinaryOperatorKind
|
||||
clang_Cursor_getBinaryOpcode(CXCursor C);
|
||||
|
||||
/**
|
||||
* \brief Returns a string containing the spelling of the binary operator.
|
||||
*/
|
||||
CINDEX_LINKAGE CXString
|
||||
clang_Cursor_getBinaryOpcodeStr(enum CX_BinaryOperatorKind Op);
|
||||
|
||||
/**
|
||||
* Returns the storage class for a function or variable declaration.
|
||||
*
|
||||
|
|
|
|||
|
|
@ -9,7 +9,6 @@
|
|||
#ifndef LLVM_CLANG_APINOTES_APINOTESMANAGER_H
|
||||
#define LLVM_CLANG_APINOTES_APINOTESMANAGER_H
|
||||
|
||||
#include "clang/Basic/Module.h"
|
||||
#include "clang/Basic/SourceLocation.h"
|
||||
#include "llvm/ADT/ArrayRef.h"
|
||||
#include "llvm/ADT/DenseMap.h"
|
||||
|
|
@ -24,6 +23,7 @@ namespace clang {
|
|||
class DirectoryEntry;
|
||||
class FileEntry;
|
||||
class LangOptions;
|
||||
class Module;
|
||||
class SourceManager;
|
||||
|
||||
namespace api_notes {
|
||||
|
|
|
|||
|
|
@ -101,7 +101,7 @@ public:
|
|||
/// \param Name The name of the class we're looking for.
|
||||
///
|
||||
/// \returns The information about the class, if known.
|
||||
VersionedInfo<ObjCContextInfo> lookupObjCClassInfo(llvm::StringRef Name);
|
||||
VersionedInfo<ContextInfo> lookupObjCClassInfo(llvm::StringRef Name);
|
||||
|
||||
/// Look for the context ID of the given Objective-C protocol.
|
||||
///
|
||||
|
|
@ -115,7 +115,7 @@ public:
|
|||
/// \param Name The name of the protocol we're looking for.
|
||||
///
|
||||
/// \returns The information about the protocol, if known.
|
||||
VersionedInfo<ObjCContextInfo> lookupObjCProtocolInfo(llvm::StringRef Name);
|
||||
VersionedInfo<ContextInfo> lookupObjCProtocolInfo(llvm::StringRef Name);
|
||||
|
||||
/// Look for information regarding the given Objective-C property in
|
||||
/// the given context.
|
||||
|
|
@ -141,6 +141,16 @@ public:
|
|||
ObjCSelectorRef Selector,
|
||||
bool IsInstanceMethod);
|
||||
|
||||
/// Look for information regarding the given C++ method in the given C++ tag
|
||||
/// context.
|
||||
///
|
||||
/// \param CtxID The ID that references the parent context, i.e. a C++ tag.
|
||||
/// \param Name The name of the C++ method we're looking for.
|
||||
///
|
||||
/// \returns Information about the method, if known.
|
||||
VersionedInfo<CXXMethodInfo> lookupCXXMethod(ContextID CtxID,
|
||||
llvm::StringRef Name);
|
||||
|
||||
/// Look for information regarding the given global variable.
|
||||
///
|
||||
/// \param Name The name of the global variable.
|
||||
|
|
@ -166,6 +176,17 @@ public:
|
|||
/// \returns information about the enumerator, if known.
|
||||
VersionedInfo<EnumConstantInfo> lookupEnumConstant(llvm::StringRef Name);
|
||||
|
||||
/// Look for the context ID of the given C++ tag.
|
||||
///
|
||||
/// \param Name The name of the tag we're looking for.
|
||||
/// \param ParentCtx The context in which this tag is declared, e.g. a C++
|
||||
/// namespace.
|
||||
///
|
||||
/// \returns The ID, if known.
|
||||
std::optional<ContextID>
|
||||
lookupTagID(llvm::StringRef Name,
|
||||
std::optional<Context> ParentCtx = std::nullopt);
|
||||
|
||||
/// Look for information regarding the given tag
|
||||
/// (struct/union/enum/C++ class).
|
||||
///
|
||||
|
|
|
|||
|
|
@ -5,7 +5,13 @@
|
|||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
//
|
||||
// This file defines the \c APINotesWriter class that writes out source
|
||||
// API notes data providing additional information about source code as
|
||||
// a separate input, such as the non-nil/nilable annotations for
|
||||
// method parameters.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
#ifndef LLVM_CLANG_APINOTES_WRITER_H
|
||||
#define LLVM_CLANG_APINOTES_WRITER_H
|
||||
|
||||
|
|
@ -20,11 +26,16 @@ namespace clang {
|
|||
class FileEntry;
|
||||
|
||||
namespace api_notes {
|
||||
|
||||
/// A class that writes API notes data to a binary representation that can be
|
||||
/// read by the \c APINotesReader.
|
||||
class APINotesWriter {
|
||||
class Implementation;
|
||||
std::unique_ptr<Implementation> Implementation;
|
||||
|
||||
public:
|
||||
/// Create a new API notes writer with the given module name and
|
||||
/// (optional) source file.
|
||||
APINotesWriter(llvm::StringRef ModuleName, const FileEntry *SF);
|
||||
~APINotesWriter();
|
||||
|
||||
|
|
@ -42,10 +53,10 @@ public:
|
|||
///
|
||||
/// \returns the ID of the class, protocol, or namespace, which can be used to
|
||||
/// add properties and methods to the class/protocol/namespace.
|
||||
ContextID addObjCContext(std::optional<ContextID> ParentCtxID,
|
||||
llvm::StringRef Name, ContextKind Kind,
|
||||
const ObjCContextInfo &Info,
|
||||
llvm::VersionTuple SwiftVersion);
|
||||
ContextID addContext(std::optional<ContextID> ParentCtxID,
|
||||
llvm::StringRef Name, ContextKind Kind,
|
||||
const ContextInfo &Info,
|
||||
llvm::VersionTuple SwiftVersion);
|
||||
|
||||
/// Add information about a specific Objective-C property.
|
||||
///
|
||||
|
|
@ -67,6 +78,14 @@ public:
|
|||
bool IsInstanceMethod, const ObjCMethodInfo &Info,
|
||||
llvm::VersionTuple SwiftVersion);
|
||||
|
||||
/// Add information about a specific C++ method.
|
||||
///
|
||||
/// \param CtxID The context in which this method resides, i.e. a C++ tag.
|
||||
/// \param Name The name of the method.
|
||||
/// \param Info Information about this method.
|
||||
void addCXXMethod(ContextID CtxID, llvm::StringRef Name,
|
||||
const CXXMethodInfo &Info, llvm::VersionTuple SwiftVersion);
|
||||
|
||||
/// Add information about a global variable.
|
||||
///
|
||||
/// \param Name The name of this global variable.
|
||||
|
|
|
|||
|
|
@ -55,16 +55,20 @@ public:
|
|||
std::string UnavailableMsg;
|
||||
|
||||
/// Whether this entity is marked unavailable.
|
||||
LLVM_PREFERRED_TYPE(bool)
|
||||
unsigned Unavailable : 1;
|
||||
|
||||
/// Whether this entity is marked unavailable in Swift.
|
||||
LLVM_PREFERRED_TYPE(bool)
|
||||
unsigned UnavailableInSwift : 1;
|
||||
|
||||
private:
|
||||
/// Whether SwiftPrivate was specified.
|
||||
LLVM_PREFERRED_TYPE(bool)
|
||||
unsigned SwiftPrivateSpecified : 1;
|
||||
|
||||
/// Whether this entity is considered "private" to a Swift overlay.
|
||||
LLVM_PREFERRED_TYPE(bool)
|
||||
unsigned SwiftPrivate : 1;
|
||||
|
||||
public:
|
||||
|
|
@ -188,25 +192,33 @@ inline bool operator!=(const CommonTypeInfo &LHS, const CommonTypeInfo &RHS) {
|
|||
return !(LHS == RHS);
|
||||
}
|
||||
|
||||
/// Describes API notes data for an Objective-C class or protocol.
|
||||
class ObjCContextInfo : public CommonTypeInfo {
|
||||
/// Describes API notes data for an Objective-C class or protocol or a C++
|
||||
/// namespace.
|
||||
class ContextInfo : public CommonTypeInfo {
|
||||
/// Whether this class has a default nullability.
|
||||
LLVM_PREFERRED_TYPE(bool)
|
||||
unsigned HasDefaultNullability : 1;
|
||||
|
||||
/// The default nullability.
|
||||
LLVM_PREFERRED_TYPE(NullabilityKind)
|
||||
unsigned DefaultNullability : 2;
|
||||
|
||||
/// Whether this class has designated initializers recorded.
|
||||
LLVM_PREFERRED_TYPE(bool)
|
||||
unsigned HasDesignatedInits : 1;
|
||||
|
||||
LLVM_PREFERRED_TYPE(bool)
|
||||
unsigned SwiftImportAsNonGenericSpecified : 1;
|
||||
LLVM_PREFERRED_TYPE(bool)
|
||||
unsigned SwiftImportAsNonGeneric : 1;
|
||||
|
||||
LLVM_PREFERRED_TYPE(bool)
|
||||
unsigned SwiftObjCMembersSpecified : 1;
|
||||
LLVM_PREFERRED_TYPE(bool)
|
||||
unsigned SwiftObjCMembers : 1;
|
||||
|
||||
public:
|
||||
ObjCContextInfo()
|
||||
ContextInfo()
|
||||
: HasDefaultNullability(0), DefaultNullability(0), HasDesignatedInits(0),
|
||||
SwiftImportAsNonGenericSpecified(false), SwiftImportAsNonGeneric(false),
|
||||
SwiftObjCMembersSpecified(false), SwiftObjCMembers(false) {}
|
||||
|
|
@ -251,16 +263,9 @@ public:
|
|||
SwiftObjCMembers = Value.value_or(false);
|
||||
}
|
||||
|
||||
/// Strip off any information within the class information structure that is
|
||||
/// module-local, such as 'audited' flags.
|
||||
void stripModuleLocalInfo() {
|
||||
HasDefaultNullability = false;
|
||||
DefaultNullability = 0;
|
||||
}
|
||||
friend bool operator==(const ContextInfo &, const ContextInfo &);
|
||||
|
||||
friend bool operator==(const ObjCContextInfo &, const ObjCContextInfo &);
|
||||
|
||||
ObjCContextInfo &operator|=(const ObjCContextInfo &RHS) {
|
||||
ContextInfo &operator|=(const ContextInfo &RHS) {
|
||||
// Merge inherited info.
|
||||
static_cast<CommonTypeInfo &>(*this) |= RHS;
|
||||
|
||||
|
|
@ -283,7 +288,7 @@ public:
|
|||
LLVM_DUMP_METHOD void dump(llvm::raw_ostream &OS);
|
||||
};
|
||||
|
||||
inline bool operator==(const ObjCContextInfo &LHS, const ObjCContextInfo &RHS) {
|
||||
inline bool operator==(const ContextInfo &LHS, const ContextInfo &RHS) {
|
||||
return static_cast<const CommonTypeInfo &>(LHS) == RHS &&
|
||||
LHS.getDefaultNullability() == RHS.getDefaultNullability() &&
|
||||
LHS.HasDesignatedInits == RHS.HasDesignatedInits &&
|
||||
|
|
@ -291,17 +296,19 @@ inline bool operator==(const ObjCContextInfo &LHS, const ObjCContextInfo &RHS) {
|
|||
LHS.getSwiftObjCMembers() == RHS.getSwiftObjCMembers();
|
||||
}
|
||||
|
||||
inline bool operator!=(const ObjCContextInfo &LHS, const ObjCContextInfo &RHS) {
|
||||
inline bool operator!=(const ContextInfo &LHS, const ContextInfo &RHS) {
|
||||
return !(LHS == RHS);
|
||||
}
|
||||
|
||||
/// API notes for a variable/property.
|
||||
class VariableInfo : public CommonEntityInfo {
|
||||
/// Whether this property has been audited for nullability.
|
||||
LLVM_PREFERRED_TYPE(bool)
|
||||
unsigned NullabilityAudited : 1;
|
||||
|
||||
/// The kind of nullability for this property. Only valid if the nullability
|
||||
/// has been audited.
|
||||
LLVM_PREFERRED_TYPE(NullabilityKind)
|
||||
unsigned Nullable : 2;
|
||||
|
||||
/// The C type of the variable, as a string.
|
||||
|
|
@ -352,7 +359,9 @@ inline bool operator!=(const VariableInfo &LHS, const VariableInfo &RHS) {
|
|||
|
||||
/// Describes API notes data for an Objective-C property.
|
||||
class ObjCPropertyInfo : public VariableInfo {
|
||||
LLVM_PREFERRED_TYPE(bool)
|
||||
unsigned SwiftImportAsAccessorsSpecified : 1;
|
||||
LLVM_PREFERRED_TYPE(bool)
|
||||
unsigned SwiftImportAsAccessors : 1;
|
||||
|
||||
public:
|
||||
|
|
@ -372,7 +381,7 @@ public:
|
|||
friend bool operator==(const ObjCPropertyInfo &, const ObjCPropertyInfo &);
|
||||
|
||||
/// Merge class-wide information into the given property.
|
||||
ObjCPropertyInfo &operator|=(const ObjCContextInfo &RHS) {
|
||||
ObjCPropertyInfo &operator|=(const ContextInfo &RHS) {
|
||||
static_cast<CommonEntityInfo &>(*this) |= RHS;
|
||||
|
||||
// Merge nullability.
|
||||
|
|
@ -409,9 +418,11 @@ inline bool operator!=(const ObjCPropertyInfo &LHS,
|
|||
/// Describes a function or method parameter.
|
||||
class ParamInfo : public VariableInfo {
|
||||
/// Whether noescape was specified.
|
||||
LLVM_PREFERRED_TYPE(bool)
|
||||
unsigned NoEscapeSpecified : 1;
|
||||
|
||||
/// Whether the this parameter has the 'noescape' attribute.
|
||||
LLVM_PREFERRED_TYPE(bool)
|
||||
unsigned NoEscape : 1;
|
||||
|
||||
/// A biased RetainCountConventionKind, where 0 means "unspecified".
|
||||
|
|
@ -488,6 +499,7 @@ public:
|
|||
// unknown nullability.
|
||||
|
||||
/// Whether the signature has been audited with respect to nullability.
|
||||
LLVM_PREFERRED_TYPE(bool)
|
||||
unsigned NullabilityAudited : 1;
|
||||
|
||||
/// Number of types whose nullability is encoded with the NullabilityPayload.
|
||||
|
|
@ -597,16 +609,18 @@ inline bool operator!=(const FunctionInfo &LHS, const FunctionInfo &RHS) {
|
|||
class ObjCMethodInfo : public FunctionInfo {
|
||||
public:
|
||||
/// Whether this is a designated initializer of its class.
|
||||
LLVM_PREFERRED_TYPE(bool)
|
||||
unsigned DesignatedInit : 1;
|
||||
|
||||
/// Whether this is a required initializer.
|
||||
LLVM_PREFERRED_TYPE(bool)
|
||||
unsigned RequiredInit : 1;
|
||||
|
||||
ObjCMethodInfo() : DesignatedInit(false), RequiredInit(false) {}
|
||||
|
||||
friend bool operator==(const ObjCMethodInfo &, const ObjCMethodInfo &);
|
||||
|
||||
ObjCMethodInfo &operator|=(const ObjCContextInfo &RHS) {
|
||||
ObjCMethodInfo &operator|=(const ContextInfo &RHS) {
|
||||
// Merge Nullability.
|
||||
if (!NullabilityAudited) {
|
||||
if (auto Nullable = RHS.getDefaultNullability()) {
|
||||
|
|
@ -642,6 +656,12 @@ public:
|
|||
GlobalFunctionInfo() {}
|
||||
};
|
||||
|
||||
/// Describes API notes data for a C++ method.
|
||||
class CXXMethodInfo : public FunctionInfo {
|
||||
public:
|
||||
CXXMethodInfo() {}
|
||||
};
|
||||
|
||||
/// Describes API notes data for an enumerator.
|
||||
class EnumConstantInfo : public CommonEntityInfo {
|
||||
public:
|
||||
|
|
@ -650,9 +670,16 @@ public:
|
|||
|
||||
/// Describes API notes data for a tag.
|
||||
class TagInfo : public CommonTypeInfo {
|
||||
LLVM_PREFERRED_TYPE(bool)
|
||||
unsigned HasFlagEnum : 1;
|
||||
LLVM_PREFERRED_TYPE(bool)
|
||||
unsigned IsFlagEnum : 1;
|
||||
|
||||
LLVM_PREFERRED_TYPE(bool)
|
||||
unsigned SwiftCopyableSpecified : 1;
|
||||
LLVM_PREFERRED_TYPE(bool)
|
||||
unsigned SwiftCopyable : 1;
|
||||
|
||||
public:
|
||||
std::optional<std::string> SwiftImportAs;
|
||||
std::optional<std::string> SwiftRetainOp;
|
||||
|
|
@ -660,7 +687,9 @@ public:
|
|||
|
||||
std::optional<EnumExtensibilityKind> EnumExtensibility;
|
||||
|
||||
TagInfo() : HasFlagEnum(0), IsFlagEnum(0) {}
|
||||
TagInfo()
|
||||
: HasFlagEnum(0), IsFlagEnum(0), SwiftCopyableSpecified(false),
|
||||
SwiftCopyable(false) {}
|
||||
|
||||
std::optional<bool> isFlagEnum() const {
|
||||
if (HasFlagEnum)
|
||||
|
|
@ -672,6 +701,15 @@ public:
|
|||
IsFlagEnum = Value.value_or(false);
|
||||
}
|
||||
|
||||
std::optional<bool> isSwiftCopyable() const {
|
||||
return SwiftCopyableSpecified ? std::optional<bool>(SwiftCopyable)
|
||||
: std::nullopt;
|
||||
}
|
||||
void setSwiftCopyable(std::optional<bool> Value) {
|
||||
SwiftCopyableSpecified = Value.has_value();
|
||||
SwiftCopyable = Value.value_or(false);
|
||||
}
|
||||
|
||||
TagInfo &operator|=(const TagInfo &RHS) {
|
||||
static_cast<CommonTypeInfo &>(*this) |= RHS;
|
||||
|
||||
|
|
@ -688,6 +726,9 @@ public:
|
|||
if (!EnumExtensibility)
|
||||
EnumExtensibility = RHS.EnumExtensibility;
|
||||
|
||||
if (!SwiftCopyableSpecified)
|
||||
setSwiftCopyable(RHS.isSwiftCopyable());
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
|
@ -702,6 +743,7 @@ inline bool operator==(const TagInfo &LHS, const TagInfo &RHS) {
|
|||
LHS.SwiftRetainOp == RHS.SwiftRetainOp &&
|
||||
LHS.SwiftReleaseOp == RHS.SwiftReleaseOp &&
|
||||
LHS.isFlagEnum() == RHS.isFlagEnum() &&
|
||||
LHS.isSwiftCopyable() == RHS.isSwiftCopyable() &&
|
||||
LHS.EnumExtensibility == RHS.EnumExtensibility;
|
||||
}
|
||||
|
||||
|
|
@ -753,6 +795,7 @@ enum class ContextKind : uint8_t {
|
|||
ObjCClass = 0,
|
||||
ObjCProtocol = 1,
|
||||
Namespace = 2,
|
||||
Tag = 3,
|
||||
};
|
||||
|
||||
struct Context {
|
||||
|
|
|
|||
|
|
@ -53,11 +53,10 @@ public:
|
|||
bool IsSatisfied = false;
|
||||
bool ContainsErrors = false;
|
||||
|
||||
/// \brief Pairs of unsatisfied atomic constraint expressions along with the
|
||||
/// substituted constraint expr, if the template arguments could be
|
||||
/// \brief The substituted constraint expr, if the template arguments could be
|
||||
/// substituted into them, or a diagnostic if substitution resulted in an
|
||||
/// invalid expression.
|
||||
llvm::SmallVector<std::pair<const Expr *, Detail>, 4> Details;
|
||||
llvm::SmallVector<Detail, 4> Details;
|
||||
|
||||
void Profile(llvm::FoldingSetNodeID &ID, const ASTContext &C) {
|
||||
Profile(ID, C, ConstraintOwner, TemplateArgs);
|
||||
|
|
@ -69,7 +68,7 @@ public:
|
|||
|
||||
bool HasSubstitutionFailure() {
|
||||
for (const auto &Detail : Details)
|
||||
if (Detail.second.dyn_cast<SubstitutionDiagnostic *>())
|
||||
if (Detail.dyn_cast<SubstitutionDiagnostic *>())
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
|
@ -80,9 +79,7 @@ public:
|
|||
/// substituted into them, or a diagnostic if substitution resulted in
|
||||
/// an invalid expression.
|
||||
using UnsatisfiedConstraintRecord =
|
||||
std::pair<const Expr *,
|
||||
llvm::PointerUnion<Expr *,
|
||||
std::pair<SourceLocation, StringRef> *>>;
|
||||
llvm::PointerUnion<Expr *, std::pair<SourceLocation, StringRef> *>;
|
||||
|
||||
/// \brief The result of a constraint satisfaction check, containing the
|
||||
/// necessary information to diagnose an unsatisfied constraint.
|
||||
|
|
|
|||
|
|
@ -23,6 +23,7 @@ namespace clang {
|
|||
class ASTDeserializationListener; // layering violation because void* is ugly
|
||||
class SemaConsumer; // layering violation required for safe SemaConsumer
|
||||
class TagDecl;
|
||||
class DeclaratorDecl;
|
||||
class VarDecl;
|
||||
class FunctionDecl;
|
||||
class ImportDecl;
|
||||
|
|
@ -105,7 +106,7 @@ public:
|
|||
/// CompleteExternalDeclaration - Callback invoked at the end of a translation
|
||||
/// unit to notify the consumer that the given external declaration should be
|
||||
/// completed.
|
||||
virtual void CompleteExternalDeclaration(VarDecl *D) {}
|
||||
virtual void CompleteExternalDeclaration(DeclaratorDecl *D) {}
|
||||
|
||||
/// Callback invoked when an MSInheritanceAttr has been attached to a
|
||||
/// CXXRecordDecl.
|
||||
|
|
|
|||
|
|
@ -37,6 +37,7 @@
|
|||
#include "llvm/ADT/SmallVector.h"
|
||||
#include "llvm/ADT/StringMap.h"
|
||||
#include "llvm/ADT/StringRef.h"
|
||||
#include "llvm/ADT/StringSet.h"
|
||||
#include "llvm/ADT/TinyPtrVector.h"
|
||||
#include "llvm/Support/TypeSize.h"
|
||||
#include <optional>
|
||||
|
|
@ -110,6 +111,9 @@ class VarTemplateDecl;
|
|||
class VTableContextBase;
|
||||
class XRayFunctionFilter;
|
||||
|
||||
/// A simple array of base specifiers.
|
||||
typedef SmallVector<CXXBaseSpecifier *, 4> CXXCastPath;
|
||||
|
||||
namespace Builtin {
|
||||
|
||||
class Context;
|
||||
|
|
@ -214,6 +218,9 @@ class ASTContext : public RefCountedBase<ASTContext> {
|
|||
DependentTypeOfExprTypes;
|
||||
mutable llvm::ContextualFoldingSet<DependentDecltypeType, ASTContext &>
|
||||
DependentDecltypeTypes;
|
||||
|
||||
mutable llvm::FoldingSet<PackIndexingType> DependentPackIndexingTypes;
|
||||
|
||||
mutable llvm::FoldingSet<TemplateTypeParmType> TemplateTypeParmTypes;
|
||||
mutable llvm::FoldingSet<ObjCTypeParamType> ObjCTypeParamTypes;
|
||||
mutable llvm::FoldingSet<SubstTemplateTypeParmType>
|
||||
|
|
@ -247,6 +254,8 @@ class ASTContext : public RefCountedBase<ASTContext> {
|
|||
DependentBitIntTypes;
|
||||
llvm::FoldingSet<BTFTagAttributedType> BTFTagAttributedTypes;
|
||||
|
||||
mutable llvm::FoldingSet<CountAttributedType> CountAttributedTypes;
|
||||
|
||||
mutable llvm::FoldingSet<QualifiedTemplateName> QualifiedTemplateNames;
|
||||
mutable llvm::FoldingSet<DependentTemplateName> DependentTemplateNames;
|
||||
mutable llvm::FoldingSet<SubstTemplateTemplateParmStorage>
|
||||
|
|
@ -255,6 +264,9 @@ class ASTContext : public RefCountedBase<ASTContext> {
|
|||
ASTContext&>
|
||||
SubstTemplateTemplateParmPacks;
|
||||
|
||||
mutable llvm::ContextualFoldingSet<ArrayParameterType, ASTContext &>
|
||||
ArrayParameterTypes;
|
||||
|
||||
/// The set of nested name specifiers.
|
||||
///
|
||||
/// This set is managed by the NestedNameSpecifier class.
|
||||
|
|
@ -447,7 +459,7 @@ class ASTContext : public RefCountedBase<ASTContext> {
|
|||
/// initialization of another module).
|
||||
struct PerModuleInitializers {
|
||||
llvm::SmallVector<Decl*, 4> Initializers;
|
||||
llvm::SmallVector<uint32_t, 4> LazyInitializers;
|
||||
llvm::SmallVector<GlobalDeclID, 4> LazyInitializers;
|
||||
|
||||
void resolve(ASTContext &Ctx);
|
||||
};
|
||||
|
|
@ -456,6 +468,14 @@ class ASTContext : public RefCountedBase<ASTContext> {
|
|||
/// This is the top-level (C++20) Named module we are building.
|
||||
Module *CurrentCXXNamedModule = nullptr;
|
||||
|
||||
/// Help structures to decide whether two `const Module *` belongs
|
||||
/// to the same conceptual module to avoid the expensive to string comparison
|
||||
/// if possible.
|
||||
///
|
||||
/// Not serialized intentionally.
|
||||
llvm::StringMap<const Module *> PrimaryModuleNameMap;
|
||||
llvm::DenseMap<const Module *, const Module *> SameModuleLookupSet;
|
||||
|
||||
static constexpr unsigned ConstantArrayTypesLog2InitSize = 8;
|
||||
static constexpr unsigned GeneralTypesLog2InitSize = 9;
|
||||
static constexpr unsigned FunctionProtoTypesLog2InitSize = 12;
|
||||
|
|
@ -623,6 +643,9 @@ private:
|
|||
/// address spaces (e.g. OpenCL/CUDA)
|
||||
bool AddrSpaceMapMangling;
|
||||
|
||||
/// For performance, track whether any function effects are in use.
|
||||
mutable bool AnyFunctionEffects = false;
|
||||
|
||||
const TargetInfo *Target = nullptr;
|
||||
const TargetInfo *AuxTarget = nullptr;
|
||||
clang::PrintingPolicy PrintingPolicy;
|
||||
|
|
@ -715,6 +738,12 @@ public:
|
|||
}
|
||||
void Deallocate(void *Ptr) const {}
|
||||
|
||||
llvm::StringRef backupStr(llvm::StringRef S) const {
|
||||
char *Buf = new (*this) char[S.size()];
|
||||
std::copy(S.begin(), S.end(), Buf);
|
||||
return llvm::StringRef(Buf, S.size());
|
||||
}
|
||||
|
||||
/// Allocates a \c DeclListNode or returns one from the \c ListNodeFreeList
|
||||
/// pool.
|
||||
DeclListNode *AllocateDeclListNode(clang::NamedDecl *ND) {
|
||||
|
|
@ -1051,7 +1080,7 @@ public:
|
|||
/// or an ImportDecl nominating another module that has initializers.
|
||||
void addModuleInitializer(Module *M, Decl *Init);
|
||||
|
||||
void addLazyModuleInitializers(Module *M, ArrayRef<uint32_t> IDs);
|
||||
void addLazyModuleInitializers(Module *M, ArrayRef<GlobalDeclID> IDs);
|
||||
|
||||
/// Get the initializations to perform when importing a module, if any.
|
||||
ArrayRef<Decl*> getModuleInitializers(Module *M);
|
||||
|
|
@ -1062,6 +1091,12 @@ public:
|
|||
/// Get module under construction, nullptr if this is not a C++20 module.
|
||||
Module *getCurrentNamedModule() const { return CurrentCXXNamedModule; }
|
||||
|
||||
/// If the two module \p M1 and \p M2 are in the same module.
|
||||
///
|
||||
/// FIXME: The signature may be confusing since `clang::Module` means to
|
||||
/// a module fragment or a module unit but not a C++20 module.
|
||||
bool isInSameModule(const Module *M1, const Module *M2);
|
||||
|
||||
TranslationUnitDecl *getTranslationUnitDecl() const {
|
||||
return TUDecl->getMostRecentDecl();
|
||||
}
|
||||
|
|
@ -1108,7 +1143,8 @@ public:
|
|||
CanQualType BFloat16Ty;
|
||||
CanQualType Float16Ty; // C11 extension ISO/IEC TS 18661-3
|
||||
CanQualType VoidPtrTy, NullPtrTy;
|
||||
CanQualType DependentTy, OverloadTy, BoundMemberTy, UnknownAnyTy;
|
||||
CanQualType DependentTy, OverloadTy, BoundMemberTy, UnresolvedTemplateTy,
|
||||
UnknownAnyTy;
|
||||
CanQualType BuiltinFnTy;
|
||||
CanQualType PseudoObjectTy, ARCUnbridgedCastTy;
|
||||
CanQualType ObjCBuiltinIdTy, ObjCBuiltinClassTy, ObjCBuiltinSelTy;
|
||||
|
|
@ -1119,7 +1155,8 @@ public:
|
|||
CanQualType OCLSamplerTy, OCLEventTy, OCLClkEventTy;
|
||||
CanQualType OCLQueueTy, OCLReserveIDTy;
|
||||
CanQualType IncompleteMatrixIdxTy;
|
||||
CanQualType OMPArraySectionTy, OMPArrayShapingTy, OMPIteratorTy;
|
||||
CanQualType ArraySectionTy;
|
||||
CanQualType OMPArrayShapingTy, OMPIteratorTy;
|
||||
#define EXT_OPAQUE_TYPE(ExtType, Id, Ext) \
|
||||
CanQualType Id##Ty;
|
||||
#include "clang/Basic/OpenCLExtensionTypes.def"
|
||||
|
|
@ -1134,6 +1171,8 @@ public:
|
|||
#include "clang/Basic/RISCVVTypes.def"
|
||||
#define WASM_TYPE(Name, Id, SingletonId) CanQualType SingletonId;
|
||||
#include "clang/Basic/WebAssemblyReferenceTypes.def"
|
||||
#define AMDGPU_TYPE(Name, Id, SingletonId) CanQualType SingletonId;
|
||||
#include "clang/Basic/AMDGPUTypes.def"
|
||||
|
||||
// Types for deductions in C++0x [stmt.ranged]'s desugaring. Built on demand.
|
||||
mutable QualType AutoDeductTy; // Deduction against 'auto'.
|
||||
|
|
@ -1160,6 +1199,12 @@ public:
|
|||
/// in device compilation.
|
||||
llvm::DenseSet<const FunctionDecl *> CUDAImplicitHostDeviceFunUsedByDevice;
|
||||
|
||||
/// For capturing lambdas with an explicit object parameter whose type is
|
||||
/// derived from the lambda type, we need to perform derived-to-base
|
||||
/// conversion so we can access the captures; the cast paths for that
|
||||
/// are stored here.
|
||||
llvm::DenseMap<const CXXMethodDecl *, CXXCastPath> LambdaCastPaths;
|
||||
|
||||
ASTContext(LangOptions &LOpts, SourceManager &SM, IdentifierTable &idents,
|
||||
SelectorTable &sels, Builtin::Context &builtins,
|
||||
TranslationUnitKind TUKind);
|
||||
|
|
@ -1242,6 +1287,14 @@ public:
|
|||
/// space.
|
||||
QualType removeAddrSpaceQualType(QualType T) const;
|
||||
|
||||
/// Return the "other" discriminator used for the pointer auth schema used for
|
||||
/// vtable pointers in instances of the requested type.
|
||||
uint16_t
|
||||
getPointerAuthVTablePointerDiscriminator(const CXXRecordDecl *RD);
|
||||
|
||||
/// Return the "other" type-specific discriminator for the given type.
|
||||
uint16_t getPointerAuthTypeDiscriminator(QualType T);
|
||||
|
||||
/// Apply Objective-C protocol qualifiers to the given type.
|
||||
/// \param allowOnPointerType specifies if we can apply protocol
|
||||
/// qualifiers on ObjCObjectPointerType. It can be set to true when
|
||||
|
|
@ -1338,6 +1391,11 @@ public:
|
|||
return CanQualType::CreateUnsafe(getPointerType((QualType) T));
|
||||
}
|
||||
|
||||
QualType
|
||||
getCountAttributedType(QualType T, Expr *CountExpr, bool CountInBytes,
|
||||
bool OrNull,
|
||||
ArrayRef<TypeCoupledDeclRefInfo> DependentDecls) const;
|
||||
|
||||
/// Return the uniqued reference to a type adjusted from the original
|
||||
/// type to a new type.
|
||||
QualType getAdjustedType(QualType Orig, QualType New) const;
|
||||
|
|
@ -1357,6 +1415,10 @@ public:
|
|||
/// type to the decayed type.
|
||||
QualType getDecayedType(QualType Orig, QualType Decayed) const;
|
||||
|
||||
/// Return the uniqued reference to a specified array parameter type from the
|
||||
/// original array type.
|
||||
QualType getArrayParameterType(QualType Ty) const;
|
||||
|
||||
/// Return the uniqued reference to the atomic type for the specified
|
||||
/// type.
|
||||
QualType getAtomicType(QualType T) const;
|
||||
|
|
@ -1713,6 +1775,11 @@ public:
|
|||
/// C++11 decltype.
|
||||
QualType getDecltypeType(Expr *e, QualType UnderlyingType) const;
|
||||
|
||||
QualType getPackIndexingType(QualType Pattern, Expr *IndexExpr,
|
||||
bool FullySubstituted = false,
|
||||
ArrayRef<QualType> Expansions = {},
|
||||
int Index = -1) const;
|
||||
|
||||
/// Unary type transforms
|
||||
QualType getUnaryTransformType(QualType BaseType, QualType UnderlyingType,
|
||||
UnaryTransformType::UTTKind UKind) const;
|
||||
|
|
@ -1738,6 +1805,13 @@ public:
|
|||
QualType DeducedType,
|
||||
bool IsDependent) const;
|
||||
|
||||
private:
|
||||
QualType getDeducedTemplateSpecializationTypeInternal(TemplateName Template,
|
||||
QualType DeducedType,
|
||||
bool IsDependent,
|
||||
QualType Canon) const;
|
||||
|
||||
public:
|
||||
/// Return the unique reference to the type for the specified TagDecl
|
||||
/// (struct/union/class/enum) decl.
|
||||
QualType getTagDeclType(const TagDecl *Decl) const;
|
||||
|
|
@ -2174,6 +2248,16 @@ public:
|
|||
return getQualifiedType(type.getUnqualifiedType(), Qs);
|
||||
}
|
||||
|
||||
/// \brief Return a type with the given __ptrauth qualifier.
|
||||
QualType getPointerAuthType(QualType Ty, PointerAuthQualifier PointerAuth) {
|
||||
assert(!Ty.getPointerAuth());
|
||||
assert(PointerAuth);
|
||||
|
||||
Qualifiers Qs;
|
||||
Qs.setPointerAuth(PointerAuth);
|
||||
return getQualifiedType(Ty, Qs);
|
||||
}
|
||||
|
||||
unsigned char getFixedPointScale(QualType Ty) const;
|
||||
unsigned char getFixedPointIBits(QualType Ty) const;
|
||||
llvm::FixedPointSemantics getFixedPointSemantics(QualType Ty) const;
|
||||
|
|
@ -2405,12 +2489,18 @@ public:
|
|||
unsigned getTargetDefaultAlignForAttributeAligned() const;
|
||||
|
||||
/// Return the alignment in bits that should be given to a
|
||||
/// global variable with type \p T.
|
||||
unsigned getAlignOfGlobalVar(QualType T) const;
|
||||
/// global variable with type \p T. If \p VD is non-null it will be
|
||||
/// considered specifically for the query.
|
||||
unsigned getAlignOfGlobalVar(QualType T, const VarDecl *VD) const;
|
||||
|
||||
/// Return the alignment in characters that should be given to a
|
||||
/// global variable with type \p T.
|
||||
CharUnits getAlignOfGlobalVarInChars(QualType T) const;
|
||||
/// global variable with type \p T. If \p VD is non-null it will be
|
||||
/// considered specifically for the query.
|
||||
CharUnits getAlignOfGlobalVarInChars(QualType T, const VarDecl *VD) const;
|
||||
|
||||
/// Return the minimum alignement as specified by the target. If \p VD is
|
||||
/// non-null it may be used to identify external or weak variables.
|
||||
unsigned getMinGlobalAlignOfVar(uint64_t Size, const VarDecl *VD) const;
|
||||
|
||||
/// Return a conservative estimate of the alignment of the specified
|
||||
/// decl \p D.
|
||||
|
|
@ -2571,7 +2661,11 @@ public:
|
|||
///
|
||||
/// \returns if this is an array type, the completely unqualified array type
|
||||
/// that corresponds to it. Otherwise, returns T.getUnqualifiedType().
|
||||
QualType getUnqualifiedArrayType(QualType T, Qualifiers &Quals);
|
||||
QualType getUnqualifiedArrayType(QualType T, Qualifiers &Quals) const;
|
||||
QualType getUnqualifiedArrayType(QualType T) const {
|
||||
Qualifiers Quals;
|
||||
return getUnqualifiedArrayType(T, Quals);
|
||||
}
|
||||
|
||||
/// Determine whether the given types are equivalent after
|
||||
/// cvr-qualifiers have been removed.
|
||||
|
|
@ -2824,6 +2918,8 @@ public:
|
|||
return AddrSpaceMapMangling || isTargetAddressSpace(AS);
|
||||
}
|
||||
|
||||
bool hasAnyFunctionEffects() const { return AnyFunctionEffects; }
|
||||
|
||||
// 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.
|
||||
|
|
@ -2967,6 +3063,10 @@ public:
|
|||
// corresponding saturated type for a given fixed point type.
|
||||
QualType getCorrespondingSaturatedType(QualType Ty) const;
|
||||
|
||||
// Per ISO N1169, this method accepts fixed point types and returns the
|
||||
// corresponding non-saturated type for a given fixed point type.
|
||||
QualType getCorrespondingUnsaturatedType(QualType Ty) const;
|
||||
|
||||
// This method accepts fixed point types and returns the corresponding signed
|
||||
// type. Unlike getCorrespondingUnsignedType(), this only accepts unsigned
|
||||
// fixed point types because there are unsigned integer types like bool and
|
||||
|
|
@ -3150,9 +3250,6 @@ public:
|
|||
/// valid feature names.
|
||||
ParsedTargetAttr filterFunctionTargetAttrs(const TargetAttr *TD) const;
|
||||
|
||||
std::vector<std::string>
|
||||
filterFunctionTargetVersionAttrs(const TargetVersionAttr *TV) const;
|
||||
|
||||
void getFunctionFeatureMap(llvm::StringMap<bool> &FeatureMap,
|
||||
const FunctionDecl *) const;
|
||||
void getFunctionFeatureMap(llvm::StringMap<bool> &FeatureMap,
|
||||
|
|
@ -3365,12 +3462,21 @@ public:
|
|||
/// Whether a C++ static variable or CUDA/HIP kernel should be externalized.
|
||||
bool shouldExternalize(const Decl *D) const;
|
||||
|
||||
/// Resolve the root record to be used to derive the vtable pointer
|
||||
/// authentication policy for the specified record.
|
||||
const CXXRecordDecl *
|
||||
baseForVTableAuthentication(const CXXRecordDecl *ThisClass);
|
||||
bool useAbbreviatedThunkName(GlobalDecl VirtualMethodDecl,
|
||||
StringRef MangledName);
|
||||
|
||||
StringRef getCUIDHash() const;
|
||||
|
||||
private:
|
||||
/// All OMPTraitInfo objects live in this collection, one per
|
||||
/// `pragma omp [begin] declare variant` directive.
|
||||
SmallVector<std::unique_ptr<OMPTraitInfo>, 4> OMPTraitInfoVector;
|
||||
|
||||
llvm::DenseMap<GlobalDecl, llvm::StringSet<>> ThunksToBeAbbreviated;
|
||||
};
|
||||
|
||||
/// Insertion operator for diagnostics.
|
||||
|
|
@ -3379,13 +3485,13 @@ const StreamingDiagnostic &operator<<(const StreamingDiagnostic &DB,
|
|||
|
||||
/// Utility function for constructing a nullary selector.
|
||||
inline Selector GetNullarySelector(StringRef name, ASTContext &Ctx) {
|
||||
IdentifierInfo* II = &Ctx.Idents.get(name);
|
||||
const IdentifierInfo *II = &Ctx.Idents.get(name);
|
||||
return Ctx.Selectors.getSelector(0, &II);
|
||||
}
|
||||
|
||||
/// Utility function for constructing an unary selector.
|
||||
inline Selector GetUnarySelector(StringRef name, ASTContext &Ctx) {
|
||||
IdentifierInfo* II = &Ctx.Idents.get(name);
|
||||
const IdentifierInfo *II = &Ctx.Idents.get(name);
|
||||
return Ctx.Selectors.getSelector(1, &II);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -27,6 +27,7 @@ namespace clang {
|
|||
class FunctionTemplateDecl;
|
||||
class Module;
|
||||
class NamedDecl;
|
||||
class NamespaceDecl;
|
||||
class ObjCCategoryDecl;
|
||||
class ObjCContainerDecl;
|
||||
class ObjCInterfaceDecl;
|
||||
|
|
@ -35,6 +36,7 @@ namespace clang {
|
|||
class QualType;
|
||||
class RecordDecl;
|
||||
class TagDecl;
|
||||
class TranslationUnitDecl;
|
||||
class ValueDecl;
|
||||
class VarDecl;
|
||||
class VarTemplateDecl;
|
||||
|
|
@ -147,6 +149,31 @@ public:
|
|||
virtual void AddedAttributeToRecord(const Attr *Attr,
|
||||
const RecordDecl *Record) {}
|
||||
|
||||
/// The parser find the named module declaration.
|
||||
virtual void EnteringModulePurview() {}
|
||||
|
||||
/// An mangling number was added to a Decl
|
||||
///
|
||||
/// \param D The decl that got a mangling number
|
||||
///
|
||||
/// \param Number The mangling number that was added to the Decl
|
||||
virtual void AddedManglingNumber(const Decl *D, unsigned Number) {}
|
||||
|
||||
/// An static local number was added to a Decl
|
||||
///
|
||||
/// \param D The decl that got a static local number
|
||||
///
|
||||
/// \param Number The static local number that was added to the Decl
|
||||
virtual void AddedStaticLocalNumbers(const Decl *D, unsigned Number) {}
|
||||
|
||||
/// An anonymous namespace was added the translation unit decl
|
||||
///
|
||||
/// \param TU The translation unit decl that got a new anonymous namespace
|
||||
///
|
||||
/// \param AnonNamespace The anonymous namespace that was added
|
||||
virtual void AddedAnonymousNamespace(const TranslationUnitDecl *TU,
|
||||
NamespaceDecl *AnonNamespace) {}
|
||||
|
||||
// NOTE: If new methods are added they should also be added to
|
||||
// MultiplexASTMutationListener.
|
||||
};
|
||||
|
|
|
|||
|
|
@ -23,7 +23,9 @@
|
|||
#include "clang/AST/StmtVisitor.h"
|
||||
#include "clang/AST/TemplateArgumentVisitor.h"
|
||||
#include "clang/AST/Type.h"
|
||||
#include "clang/AST/TypeLocVisitor.h"
|
||||
#include "clang/AST/TypeVisitor.h"
|
||||
#include "llvm/Support/SaveAndRestore.h"
|
||||
|
||||
namespace clang {
|
||||
|
||||
|
|
@ -48,8 +50,10 @@ struct {
|
|||
void Visit(const Stmt *Node);
|
||||
void Visit(const Type *T);
|
||||
void Visit(QualType T);
|
||||
void Visit(TypeLoc);
|
||||
void Visit(const Decl *D);
|
||||
void Visit(const CXXCtorInitializer *Init);
|
||||
void Visit(const OpenACCClause *C);
|
||||
void Visit(const OMPClause *C);
|
||||
void Visit(const BlockDecl::Capture &C);
|
||||
void Visit(const GenericSelectionExpr::ConstAssociation &A);
|
||||
|
|
@ -64,6 +68,7 @@ class ASTNodeTraverser
|
|||
public comments::ConstCommentVisitor<Derived, void,
|
||||
const comments::FullComment *>,
|
||||
public TypeVisitor<Derived>,
|
||||
public TypeLocVisitor<Derived>,
|
||||
public ConstAttrVisitor<Derived>,
|
||||
public ConstTemplateArgumentVisitor<Derived> {
|
||||
|
||||
|
|
@ -71,6 +76,14 @@ class ASTNodeTraverser
|
|||
/// not already been loaded.
|
||||
bool Deserialize = false;
|
||||
|
||||
/// Tracks whether we should dump TypeLocs etc.
|
||||
///
|
||||
/// Detailed location information such as TypeLoc nodes is not usually
|
||||
/// included in the dump (too verbose).
|
||||
/// But when explicitly asked to dump a Loc node, we do so recursively,
|
||||
/// including e.g. FunctionTypeLoc => ParmVarDecl => TypeLoc.
|
||||
bool VisitLocs = false;
|
||||
|
||||
TraversalKind Traversal = TraversalKind::TK_AsIs;
|
||||
|
||||
NodeDelegateType &getNodeDelegate() {
|
||||
|
|
@ -85,7 +98,7 @@ public:
|
|||
void SetTraversalKind(TraversalKind TK) { Traversal = TK; }
|
||||
TraversalKind GetTraversalKind() const { return Traversal; }
|
||||
|
||||
void Visit(const Decl *D) {
|
||||
void Visit(const Decl *D, bool VisitLocs = false) {
|
||||
if (Traversal == TK_IgnoreUnlessSpelledInSource && D->isImplicit())
|
||||
return;
|
||||
|
||||
|
|
@ -94,7 +107,10 @@ public:
|
|||
if (!D)
|
||||
return;
|
||||
|
||||
ConstDeclVisitor<Derived>::Visit(D);
|
||||
{
|
||||
llvm::SaveAndRestore RestoreVisitLocs(this->VisitLocs, VisitLocs);
|
||||
ConstDeclVisitor<Derived>::Visit(D);
|
||||
}
|
||||
|
||||
for (const auto &A : D->attrs())
|
||||
Visit(A);
|
||||
|
|
@ -181,6 +197,17 @@ public:
|
|||
});
|
||||
}
|
||||
|
||||
void Visit(TypeLoc T) {
|
||||
getNodeDelegate().AddChild([=] {
|
||||
getNodeDelegate().Visit(T);
|
||||
if (T.isNull())
|
||||
return;
|
||||
TypeLocVisitor<Derived>::Visit(T);
|
||||
if (auto Inner = T.getNextTypeLoc())
|
||||
Visit(Inner);
|
||||
});
|
||||
}
|
||||
|
||||
void Visit(const Attr *A) {
|
||||
getNodeDelegate().AddChild([=] {
|
||||
getNodeDelegate().Visit(A);
|
||||
|
|
@ -213,6 +240,14 @@ public:
|
|||
});
|
||||
}
|
||||
|
||||
void Visit(const OpenACCClause *C) {
|
||||
getNodeDelegate().AddChild([=] {
|
||||
getNodeDelegate().Visit(C);
|
||||
for (const auto *S : C->children())
|
||||
Visit(S);
|
||||
});
|
||||
}
|
||||
|
||||
void Visit(const OMPClause *C) {
|
||||
getNodeDelegate().AddChild([=] {
|
||||
getNodeDelegate().Visit(C);
|
||||
|
|
@ -286,6 +321,8 @@ public:
|
|||
Visit(*QT);
|
||||
else if (const auto *T = N.get<Type>())
|
||||
Visit(T);
|
||||
else if (const auto *TL = N.get<TypeLoc>())
|
||||
Visit(*TL);
|
||||
else if (const auto *C = N.get<CXXCtorInitializer>())
|
||||
Visit(C);
|
||||
else if (const auto *C = N.get<OMPClause>())
|
||||
|
|
@ -346,7 +383,7 @@ public:
|
|||
|
||||
void VisitComplexType(const ComplexType *T) { Visit(T->getElementType()); }
|
||||
void VisitLocInfoType(const LocInfoType *T) {
|
||||
Visit(T->getTypeSourceInfo()->getType());
|
||||
Visit(T->getTypeSourceInfo()->getTypeLoc());
|
||||
}
|
||||
void VisitPointerType(const PointerType *T) { Visit(T->getPointeeType()); }
|
||||
void VisitBlockPointerType(const BlockPointerType *T) {
|
||||
|
|
@ -385,6 +422,12 @@ public:
|
|||
void VisitDecltypeType(const DecltypeType *T) {
|
||||
Visit(T->getUnderlyingExpr());
|
||||
}
|
||||
|
||||
void VisitPackIndexingType(const PackIndexingType *T) {
|
||||
Visit(T->getPattern());
|
||||
Visit(T->getIndexExpr());
|
||||
}
|
||||
|
||||
void VisitUnaryTransformType(const UnaryTransformType *T) {
|
||||
Visit(T->getBaseType());
|
||||
}
|
||||
|
|
@ -415,9 +458,55 @@ public:
|
|||
if (!T->isSugared())
|
||||
Visit(T->getPattern());
|
||||
}
|
||||
void VisitAutoType(const AutoType *T) {
|
||||
for (const auto &Arg : T->getTypeConstraintArguments())
|
||||
Visit(Arg);
|
||||
}
|
||||
// FIXME: ElaboratedType, DependentNameType,
|
||||
// DependentTemplateSpecializationType, ObjCObjectType
|
||||
|
||||
// For TypeLocs, we automatically visit the inner type loc (pointee type etc).
|
||||
// We must explicitly visit other lexically-nested nodes.
|
||||
void VisitFunctionProtoTypeLoc(FunctionProtoTypeLoc TL) {
|
||||
TypeLocVisitor<Derived>::VisitFunctionTypeLoc(TL);
|
||||
for (const auto *Param : TL.getParams())
|
||||
Visit(Param, /*VisitTypeLocs=*/true);
|
||||
}
|
||||
void VisitAutoTypeLoc(AutoTypeLoc TL) {
|
||||
if (const auto *CR = TL.getConceptReference()) {
|
||||
if (auto *Args = CR->getTemplateArgsAsWritten())
|
||||
for (const auto &Arg : Args->arguments())
|
||||
dumpTemplateArgumentLoc(Arg);
|
||||
}
|
||||
}
|
||||
void VisitMemberPointerTypeLoc(MemberPointerTypeLoc TL) {
|
||||
Visit(TL.getClassTInfo()->getTypeLoc());
|
||||
}
|
||||
void VisitVariableArrayTypeLoc(VariableArrayTypeLoc TL) {
|
||||
Visit(TL.getSizeExpr());
|
||||
}
|
||||
void VisitDependentSizedArrayTypeLoc(DependentSizedArrayTypeLoc TL) {
|
||||
Visit(TL.getSizeExpr());
|
||||
}
|
||||
void VisitDependentSizedExtVectorTypeLoc(DependentSizedExtVectorTypeLoc TL) {
|
||||
Visit(cast<DependentSizedExtVectorType>(TL.getType())->getSizeExpr());
|
||||
}
|
||||
void VisitTypeOfExprTypeLoc(TypeOfExprTypeLoc TL) {
|
||||
Visit(TL.getUnderlyingExpr());
|
||||
}
|
||||
void VisitDecltypeType(DecltypeType TL) {
|
||||
Visit(TL.getUnderlyingExpr());
|
||||
}
|
||||
void VisitTemplateSpecializationTypeLoc(TemplateSpecializationTypeLoc TL) {
|
||||
for (unsigned I=0, N=TL.getNumArgs(); I < N; ++I)
|
||||
dumpTemplateArgumentLoc(TL.getArgLoc(I));
|
||||
}
|
||||
void VisitDependentTemplateSpecializationTypeLoc(
|
||||
DependentTemplateSpecializationTypeLoc TL) {
|
||||
for (unsigned I=0, N=TL.getNumArgs(); I < N; ++I)
|
||||
dumpTemplateArgumentLoc(TL.getArgLoc(I));
|
||||
}
|
||||
|
||||
void VisitTypedefDecl(const TypedefDecl *D) { Visit(D->getUnderlyingType()); }
|
||||
|
||||
void VisitEnumConstantDecl(const EnumConstantDecl *D) {
|
||||
|
|
@ -462,6 +551,8 @@ public:
|
|||
if (Traversal == TK_IgnoreUnlessSpelledInSource && D->isCXXForRangeDecl())
|
||||
return;
|
||||
|
||||
if (const auto *TSI = D->getTypeSourceInfo(); VisitLocs && TSI)
|
||||
Visit(TSI->getTypeLoc());
|
||||
if (D->hasInit())
|
||||
Visit(D->getInit());
|
||||
}
|
||||
|
|
@ -604,7 +695,7 @@ public:
|
|||
if (const auto *TC = D->getTypeConstraint())
|
||||
Visit(TC->getImmediatelyDeclaredConstraint());
|
||||
if (D->hasDefaultArgument())
|
||||
Visit(D->getDefaultArgument(), SourceRange(),
|
||||
Visit(D->getDefaultArgument().getArgument(), SourceRange(),
|
||||
D->getDefaultArgStorage().getInheritedFrom(),
|
||||
D->defaultArgumentWasInherited() ? "inherited from" : "previous");
|
||||
}
|
||||
|
|
@ -613,9 +704,9 @@ public:
|
|||
if (const auto *E = D->getPlaceholderTypeConstraint())
|
||||
Visit(E);
|
||||
if (D->hasDefaultArgument())
|
||||
Visit(D->getDefaultArgument(), SourceRange(),
|
||||
D->getDefaultArgStorage().getInheritedFrom(),
|
||||
D->defaultArgumentWasInherited() ? "inherited from" : "previous");
|
||||
dumpTemplateArgumentLoc(
|
||||
D->getDefaultArgument(), D->getDefaultArgStorage().getInheritedFrom(),
|
||||
D->defaultArgumentWasInherited() ? "inherited from" : "previous");
|
||||
}
|
||||
|
||||
void VisitTemplateTemplateParmDecl(const TemplateTemplateParmDecl *D) {
|
||||
|
|
@ -717,6 +808,11 @@ public:
|
|||
Visit(C);
|
||||
}
|
||||
|
||||
void VisitOpenACCConstructStmt(const OpenACCConstructStmt *Node) {
|
||||
for (const auto *C : Node->clauses())
|
||||
Visit(C);
|
||||
}
|
||||
|
||||
void VisitInitListExpr(const InitListExpr *ILE) {
|
||||
if (auto *Filler = ILE->getArrayFiller()) {
|
||||
Visit(Filler, "array_filler");
|
||||
|
|
@ -748,6 +844,12 @@ public:
|
|||
}
|
||||
}
|
||||
|
||||
void VisitUnresolvedLookupExpr(const UnresolvedLookupExpr *E) {
|
||||
if (E->hasExplicitTemplateArgs())
|
||||
for (auto Arg : E->template_arguments())
|
||||
Visit(Arg.getArgument());
|
||||
}
|
||||
|
||||
void VisitRequiresExpr(const RequiresExpr *E) {
|
||||
for (auto *D : E->getLocalParameters())
|
||||
Visit(D);
|
||||
|
|
@ -755,6 +857,12 @@ public:
|
|||
Visit(R);
|
||||
}
|
||||
|
||||
void VisitTypeTraitExpr(const TypeTraitExpr *E) {
|
||||
// Argument types are not children of the TypeTraitExpr.
|
||||
for (auto *A : E->getArgs())
|
||||
Visit(A->getType());
|
||||
}
|
||||
|
||||
void VisitLambdaExpr(const LambdaExpr *Node) {
|
||||
if (Traversal == TK_IgnoreUnlessSpelledInSource) {
|
||||
for (unsigned I = 0, N = Node->capture_size(); I != N; ++I) {
|
||||
|
|
@ -837,6 +945,14 @@ public:
|
|||
Visit(TArg);
|
||||
}
|
||||
|
||||
void VisitCXXDefaultArgExpr(const CXXDefaultArgExpr *Node) {
|
||||
Visit(Node->getExpr());
|
||||
}
|
||||
|
||||
void VisitCXXDefaultInitExpr(const CXXDefaultInitExpr *Node) {
|
||||
Visit(Node->getExpr());
|
||||
}
|
||||
|
||||
// Implements Visit methods for Attrs.
|
||||
#include "clang/AST/AttrNodeTraverse.inc"
|
||||
};
|
||||
|
|
|
|||
|
|
@ -16,6 +16,7 @@
|
|||
|
||||
#include "clang/AST/ASTVector.h"
|
||||
#include "clang/AST/DeclAccessPair.h"
|
||||
#include "clang/AST/DeclID.h"
|
||||
#include "clang/AST/UnresolvedSet.h"
|
||||
#include "clang/Basic/Specifiers.h"
|
||||
#include <cassert>
|
||||
|
|
@ -56,6 +57,10 @@ public:
|
|||
Decls.push_back(DeclAccessPair::make(D, AS), C);
|
||||
}
|
||||
|
||||
void addLazyDecl(ASTContext &C, GlobalDeclID ID, AccessSpecifier AS) {
|
||||
Decls.push_back(DeclAccessPair::makeLazy(ID.getRawValue(), AS), C);
|
||||
}
|
||||
|
||||
/// Replaces the given declaration with the new one, once.
|
||||
///
|
||||
/// \return true if the set changed
|
||||
|
|
@ -109,10 +114,10 @@ public:
|
|||
|
||||
void reserve(ASTContext &C, unsigned N) { Impl.reserve(C, N); }
|
||||
|
||||
void addLazyDecl(ASTContext &C, uintptr_t ID, AccessSpecifier AS) {
|
||||
void addLazyDecl(ASTContext &C, GlobalDeclID ID, AccessSpecifier AS) {
|
||||
assert(Impl.empty() || Impl.Decls.isLazy());
|
||||
Impl.Decls.setLazy(true);
|
||||
Impl.addDecl(C, reinterpret_cast<NamedDecl *>(ID << 2), AS);
|
||||
Impl.addLazyDecl(C, ID, AS);
|
||||
}
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -213,9 +213,9 @@ public:
|
|||
}
|
||||
|
||||
Qualifiers readQualifiers() {
|
||||
static_assert(sizeof(Qualifiers().getAsOpaqueValue()) <= sizeof(uint32_t),
|
||||
static_assert(sizeof(Qualifiers().getAsOpaqueValue()) <= sizeof(uint64_t),
|
||||
"update this if the value size changes");
|
||||
uint32_t value = asImpl().readUInt32();
|
||||
uint64_t value = asImpl().readUInt64();
|
||||
return Qualifiers::fromOpaqueValue(value);
|
||||
}
|
||||
|
||||
|
|
@ -244,6 +244,15 @@ public:
|
|||
return FunctionProtoType::ExtParameterInfo::getFromOpaqueValue(value);
|
||||
}
|
||||
|
||||
FunctionEffect readFunctionEffect() {
|
||||
uint32_t value = asImpl().readUInt32();
|
||||
return FunctionEffect::fromOpaqueInt32(value);
|
||||
}
|
||||
|
||||
EffectConditionExpr readEffectConditionExpr() {
|
||||
return EffectConditionExpr{asImpl().readExprRef()};
|
||||
}
|
||||
|
||||
NestedNameSpecifier *readNestedNameSpecifier() {
|
||||
auto &ctx = getASTContext();
|
||||
|
||||
|
|
|
|||
|
|
@ -196,9 +196,9 @@ public:
|
|||
}
|
||||
|
||||
void writeQualifiers(Qualifiers value) {
|
||||
static_assert(sizeof(value.getAsOpaqueValue()) <= sizeof(uint32_t),
|
||||
static_assert(sizeof(value.getAsOpaqueValue()) <= sizeof(uint64_t),
|
||||
"update this if the value size changes");
|
||||
asImpl().writeUInt32(value.getAsOpaqueValue());
|
||||
asImpl().writeUInt64(value.getAsOpaqueValue());
|
||||
}
|
||||
|
||||
void writeExceptionSpecInfo(
|
||||
|
|
@ -222,6 +222,14 @@ public:
|
|||
asImpl().writeUInt32(epi.getOpaqueValue());
|
||||
}
|
||||
|
||||
void writeFunctionEffect(FunctionEffect E) {
|
||||
asImpl().writeUInt32(E.toOpaqueInt32());
|
||||
}
|
||||
|
||||
void writeEffectConditionExpr(EffectConditionExpr CE) {
|
||||
asImpl().writeExprRef(CE.getCondition());
|
||||
}
|
||||
|
||||
void writeNestedNameSpecifier(NestedNameSpecifier *NNS) {
|
||||
// Nested name specifiers usually aren't too long. I think that 8 would
|
||||
// typically accommodate the vast majority.
|
||||
|
|
|
|||
|
|
@ -14,6 +14,7 @@
|
|||
#define LLVM_CLANG_AST_AVAILABILITY_H
|
||||
|
||||
#include "clang/Basic/SourceLocation.h"
|
||||
#include "llvm/ADT/SmallString.h"
|
||||
#include "llvm/ADT/StringRef.h"
|
||||
#include "llvm/Support/VersionTuple.h"
|
||||
|
||||
|
|
@ -57,6 +58,68 @@ public:
|
|||
bool isOtherPlatformSpec() const { return Version.empty(); }
|
||||
};
|
||||
|
||||
class Decl;
|
||||
|
||||
/// Storage of availability attributes for a declaration.
|
||||
struct AvailabilityInfo {
|
||||
/// The domain is the platform for which this availability info applies to.
|
||||
llvm::SmallString<32> Domain;
|
||||
VersionTuple Introduced;
|
||||
VersionTuple Deprecated;
|
||||
VersionTuple Obsoleted;
|
||||
bool Unavailable = false;
|
||||
bool UnconditionallyDeprecated = false;
|
||||
bool UnconditionallyUnavailable = false;
|
||||
|
||||
AvailabilityInfo() = default;
|
||||
|
||||
/// Determine if this AvailabilityInfo represents the default availability.
|
||||
bool isDefault() const { return *this == AvailabilityInfo(); }
|
||||
|
||||
/// Check if the symbol has been obsoleted.
|
||||
bool isObsoleted() const { return !Obsoleted.empty(); }
|
||||
|
||||
/// Check if the symbol is unavailable unconditionally or
|
||||
/// on the active platform and os version.
|
||||
bool isUnavailable() const {
|
||||
return Unavailable || isUnconditionallyUnavailable();
|
||||
}
|
||||
|
||||
/// Check if the symbol is unconditionally deprecated.
|
||||
///
|
||||
/// i.e. \code __attribute__((deprecated)) \endcode
|
||||
bool isUnconditionallyDeprecated() const { return UnconditionallyDeprecated; }
|
||||
|
||||
/// Check if the symbol is unconditionally unavailable.
|
||||
///
|
||||
/// i.e. \code __attribute__((unavailable)) \endcode
|
||||
bool isUnconditionallyUnavailable() const {
|
||||
return UnconditionallyUnavailable;
|
||||
}
|
||||
|
||||
AvailabilityInfo(StringRef Domain, VersionTuple I, VersionTuple D,
|
||||
VersionTuple O, bool U, bool UD, bool UU)
|
||||
: Domain(Domain), Introduced(I), Deprecated(D), Obsoleted(O),
|
||||
Unavailable(U), UnconditionallyDeprecated(UD),
|
||||
UnconditionallyUnavailable(UU) {}
|
||||
|
||||
friend bool operator==(const AvailabilityInfo &Lhs,
|
||||
const AvailabilityInfo &Rhs);
|
||||
|
||||
public:
|
||||
static AvailabilityInfo createFromDecl(const Decl *Decl);
|
||||
};
|
||||
|
||||
inline bool operator==(const AvailabilityInfo &Lhs,
|
||||
const AvailabilityInfo &Rhs) {
|
||||
return std::tie(Lhs.Introduced, Lhs.Deprecated, Lhs.Obsoleted,
|
||||
Lhs.Unavailable, Lhs.UnconditionallyDeprecated,
|
||||
Lhs.UnconditionallyUnavailable) ==
|
||||
std::tie(Rhs.Introduced, Rhs.Deprecated, Rhs.Obsoleted,
|
||||
Rhs.Unavailable, Rhs.UnconditionallyDeprecated,
|
||||
Rhs.UnconditionallyUnavailable);
|
||||
}
|
||||
|
||||
} // end namespace clang
|
||||
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -285,6 +285,9 @@ PLACEHOLDER_TYPE(Overload, OverloadTy)
|
|||
// x->foo # if only contains non-static members
|
||||
PLACEHOLDER_TYPE(BoundMember, BoundMemberTy)
|
||||
|
||||
// The type of an unresolved template. Used in UnresolvedLookupExpr.
|
||||
PLACEHOLDER_TYPE(UnresolvedTemplate, UnresolvedTemplateTy)
|
||||
|
||||
// The type of an expression which refers to a pseudo-object,
|
||||
// such as those introduced by Objective C's @property or
|
||||
// VS.NET's __property declarations. A placeholder type. The
|
||||
|
|
@ -320,7 +323,7 @@ PLACEHOLDER_TYPE(ARCUnbridgedCast, ARCUnbridgedCastTy)
|
|||
PLACEHOLDER_TYPE(IncompleteMatrixIdx, IncompleteMatrixIdxTy)
|
||||
|
||||
// A placeholder type for OpenMP array sections.
|
||||
PLACEHOLDER_TYPE(OMPArraySection, OMPArraySectionTy)
|
||||
PLACEHOLDER_TYPE(ArraySection, ArraySectionTy)
|
||||
|
||||
// A placeholder type for OpenMP array shaping operation.
|
||||
PLACEHOLDER_TYPE(OMPArrayShaping, OMPArrayShapingTy)
|
||||
|
|
|
|||
|
|
@ -50,52 +50,69 @@ struct CommandInfo {
|
|||
unsigned NumArgs : 4;
|
||||
|
||||
/// True if this command is a inline command (of any kind).
|
||||
LLVM_PREFERRED_TYPE(bool)
|
||||
unsigned IsInlineCommand : 1;
|
||||
|
||||
/// True if this command is a block command (of any kind).
|
||||
LLVM_PREFERRED_TYPE(bool)
|
||||
unsigned IsBlockCommand : 1;
|
||||
|
||||
/// True if this command is introducing a brief documentation
|
||||
/// paragraph (\or an alias).
|
||||
LLVM_PREFERRED_TYPE(bool)
|
||||
unsigned IsBriefCommand : 1;
|
||||
|
||||
/// True if this command is \\returns or an alias.
|
||||
LLVM_PREFERRED_TYPE(bool)
|
||||
unsigned IsReturnsCommand : 1;
|
||||
|
||||
/// True if this command is introducing documentation for a function
|
||||
/// parameter (\\param or an alias).
|
||||
LLVM_PREFERRED_TYPE(bool)
|
||||
unsigned IsParamCommand : 1;
|
||||
|
||||
/// True if this command is introducing documentation for
|
||||
/// a template parameter (\\tparam or an alias).
|
||||
LLVM_PREFERRED_TYPE(bool)
|
||||
unsigned IsTParamCommand : 1;
|
||||
|
||||
/// True if this command is \\throws or an alias.
|
||||
LLVM_PREFERRED_TYPE(bool)
|
||||
unsigned IsThrowsCommand : 1;
|
||||
|
||||
/// True if this command is \\deprecated or an alias.
|
||||
LLVM_PREFERRED_TYPE(bool)
|
||||
unsigned IsDeprecatedCommand : 1;
|
||||
|
||||
/// True if this is a \\headerfile-like command.
|
||||
LLVM_PREFERRED_TYPE(bool)
|
||||
unsigned IsHeaderfileCommand : 1;
|
||||
|
||||
/// True if this is a \\par command.
|
||||
LLVM_PREFERRED_TYPE(bool)
|
||||
unsigned IsParCommand : 1;
|
||||
|
||||
/// True if we don't want to warn about this command being passed an empty
|
||||
/// paragraph. Meaningful only for block commands.
|
||||
LLVM_PREFERRED_TYPE(bool)
|
||||
unsigned IsEmptyParagraphAllowed : 1;
|
||||
|
||||
/// True if this command is a verbatim-like block command.
|
||||
///
|
||||
/// A verbatim-like block command eats every character (except line starting
|
||||
/// decorations) until matching end command is seen or comment end is hit.
|
||||
LLVM_PREFERRED_TYPE(bool)
|
||||
unsigned IsVerbatimBlockCommand : 1;
|
||||
|
||||
/// True if this command is an end command for a verbatim-like block.
|
||||
LLVM_PREFERRED_TYPE(bool)
|
||||
unsigned IsVerbatimBlockEndCommand : 1;
|
||||
|
||||
/// True if this command is a verbatim line command.
|
||||
///
|
||||
/// A verbatim-like line command eats everything until a newline is seen or
|
||||
/// comment end is hit.
|
||||
LLVM_PREFERRED_TYPE(bool)
|
||||
unsigned IsVerbatimLineCommand : 1;
|
||||
|
||||
/// True if this command contains a declaration for the entity being
|
||||
|
|
@ -105,20 +122,25 @@ struct CommandInfo {
|
|||
/// \code
|
||||
/// \fn void f(int a);
|
||||
/// \endcode
|
||||
LLVM_PREFERRED_TYPE(bool)
|
||||
unsigned IsDeclarationCommand : 1;
|
||||
|
||||
/// True if verbatim-like line command is a function declaration.
|
||||
LLVM_PREFERRED_TYPE(bool)
|
||||
unsigned IsFunctionDeclarationCommand : 1;
|
||||
|
||||
/// True if block command is further describing a container API; such
|
||||
/// as \@coclass, \@classdesign, etc.
|
||||
LLVM_PREFERRED_TYPE(bool)
|
||||
unsigned IsRecordLikeDetailCommand : 1;
|
||||
|
||||
/// True if block command is a container API; such as \@interface.
|
||||
LLVM_PREFERRED_TYPE(bool)
|
||||
unsigned IsRecordLikeDeclarationCommand : 1;
|
||||
|
||||
/// True if this command is unknown. This \c CommandInfo object was
|
||||
/// created during parsing.
|
||||
LLVM_PREFERRED_TYPE(bool)
|
||||
unsigned IsUnknownCommand : 1;
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -18,6 +18,7 @@ class Command<string name> {
|
|||
bit IsThrowsCommand = 0;
|
||||
bit IsDeprecatedCommand = 0;
|
||||
bit IsHeaderfileCommand = 0;
|
||||
bit IsParCommand = 0;
|
||||
|
||||
bit IsEmptyParagraphAllowed = 0;
|
||||
|
||||
|
|
@ -132,9 +133,9 @@ def Tparam : BlockCommand<"tparam"> { let IsTParamCommand = 1; }
|
|||
// HeaderDoc command for template parameter documentation.
|
||||
def Templatefield : BlockCommand<"templatefield"> { let IsTParamCommand = 1; }
|
||||
|
||||
def Throws : BlockCommand<"throws"> { let IsThrowsCommand = 1; }
|
||||
def Throw : BlockCommand<"throw"> { let IsThrowsCommand = 1; }
|
||||
def Exception : BlockCommand<"exception"> { let IsThrowsCommand = 1; }
|
||||
def Throws : BlockCommand<"throws"> { let IsThrowsCommand = 1; let NumArgs = 1; }
|
||||
def Throw : BlockCommand<"throw"> { let IsThrowsCommand = 1; let NumArgs = 1; }
|
||||
def Exception : BlockCommand<"exception"> { let IsThrowsCommand = 1; let NumArgs = 1;}
|
||||
|
||||
def Deprecated : BlockCommand<"deprecated"> {
|
||||
let IsEmptyParagraphAllowed = 1;
|
||||
|
|
@ -156,7 +157,7 @@ def Date : BlockCommand<"date">;
|
|||
def Invariant : BlockCommand<"invariant">;
|
||||
def Li : BlockCommand<"li">;
|
||||
def Note : BlockCommand<"note">;
|
||||
def Par : BlockCommand<"par">;
|
||||
def Par : BlockCommand<"par"> { let IsParCommand = 1; let NumArgs = 1; }
|
||||
def Post : BlockCommand<"post">;
|
||||
def Pre : BlockCommand<"pre">;
|
||||
def Remark : BlockCommand<"remark">;
|
||||
|
|
|
|||
|
|
@ -100,6 +100,14 @@ public:
|
|||
ArrayRef<Comment::Argument>
|
||||
parseCommandArgs(TextTokenRetokenizer &Retokenizer, unsigned NumArgs);
|
||||
|
||||
/// Parse arguments for \throws command supported args are in form of class
|
||||
/// or template.
|
||||
ArrayRef<Comment::Argument>
|
||||
parseThrowCommandArgs(TextTokenRetokenizer &Retokenizer, unsigned NumArgs);
|
||||
|
||||
ArrayRef<Comment::Argument>
|
||||
parseParCommandArgs(TextTokenRetokenizer &Retokenizer, unsigned NumArgs);
|
||||
|
||||
BlockCommandComment *parseBlockCommand();
|
||||
InlineCommandComment *parseInlineCommand();
|
||||
|
||||
|
|
@ -118,4 +126,3 @@ public:
|
|||
} // end namespace clang
|
||||
|
||||
#endif
|
||||
|
||||
|
|
|
|||
|
|
@ -78,7 +78,7 @@ class ComparisonCategoryInfo {
|
|||
friend class Sema;
|
||||
|
||||
public:
|
||||
ComparisonCategoryInfo(const ASTContext &Ctx, CXXRecordDecl *RD,
|
||||
ComparisonCategoryInfo(const ASTContext &Ctx, const CXXRecordDecl *RD,
|
||||
ComparisonCategoryType Kind)
|
||||
: Ctx(Ctx), Record(RD), Kind(Kind) {}
|
||||
|
||||
|
|
|
|||
|
|
@ -63,6 +63,7 @@ class ArrayTypeTraitExpr;
|
|||
class ExpressionTraitExpr;
|
||||
class CXXNoexceptExpr;
|
||||
class PackExpansionExpr;
|
||||
class PackIndexingExpr;
|
||||
class SubstNonTypeTemplateParmExpr;
|
||||
class CoroutineSuspendExpr;
|
||||
class DependentCoawaitExpr;
|
||||
|
|
@ -93,7 +94,7 @@ class DesignatedInitExpr;
|
|||
class ParenListExpr;
|
||||
class PseudoObjectExpr;
|
||||
class AtomicExpr;
|
||||
class OMPArraySectionExpr;
|
||||
class ArraySectionExpr;
|
||||
class OMPArrayShapingExpr;
|
||||
class OMPIteratorExpr;
|
||||
class ObjCArrayLiteral;
|
||||
|
|
@ -150,6 +151,7 @@ ExprDependence computeDependence(ArrayTypeTraitExpr *E);
|
|||
ExprDependence computeDependence(ExpressionTraitExpr *E);
|
||||
ExprDependence computeDependence(CXXNoexceptExpr *E, CanThrowResult CT);
|
||||
ExprDependence computeDependence(PackExpansionExpr *E);
|
||||
ExprDependence computeDependence(PackIndexingExpr *E);
|
||||
ExprDependence computeDependence(SubstNonTypeTemplateParmExpr *E);
|
||||
ExprDependence computeDependence(CoroutineSuspendExpr *E);
|
||||
ExprDependence computeDependence(DependentCoawaitExpr *E);
|
||||
|
|
@ -187,7 +189,7 @@ ExprDependence computeDependence(ParenListExpr *E);
|
|||
ExprDependence computeDependence(PseudoObjectExpr *E);
|
||||
ExprDependence computeDependence(AtomicExpr *E);
|
||||
|
||||
ExprDependence computeDependence(OMPArraySectionExpr *E);
|
||||
ExprDependence computeDependence(ArraySectionExpr *E);
|
||||
ExprDependence computeDependence(OMPArrayShapingExpr *E);
|
||||
ExprDependence computeDependence(OMPIteratorExpr *E);
|
||||
|
||||
|
|
|
|||
|
|
@ -120,7 +120,7 @@ public:
|
|||
ASTContext &getASTContext() const { return Ctx; }
|
||||
|
||||
NamespaceDecl *getAnonymousNamespace() const { return AnonymousNamespace; }
|
||||
void setAnonymousNamespace(NamespaceDecl *D) { AnonymousNamespace = D; }
|
||||
void setAnonymousNamespace(NamespaceDecl *D);
|
||||
|
||||
static TranslationUnitDecl *Create(ASTContext &C);
|
||||
|
||||
|
|
@ -157,7 +157,7 @@ public:
|
|||
SourceLocation CommentLoc,
|
||||
PragmaMSCommentKind CommentKind,
|
||||
StringRef Arg);
|
||||
static PragmaCommentDecl *CreateDeserialized(ASTContext &C, unsigned ID,
|
||||
static PragmaCommentDecl *CreateDeserialized(ASTContext &C, GlobalDeclID ID,
|
||||
unsigned ArgSize);
|
||||
|
||||
PragmaMSCommentKind getCommentKind() const { return CommentKind; }
|
||||
|
|
@ -192,7 +192,7 @@ public:
|
|||
SourceLocation Loc, StringRef Name,
|
||||
StringRef Value);
|
||||
static PragmaDetectMismatchDecl *
|
||||
CreateDeserialized(ASTContext &C, unsigned ID, unsigned NameValueSize);
|
||||
CreateDeserialized(ASTContext &C, GlobalDeclID ID, unsigned NameValueSize);
|
||||
|
||||
StringRef getName() const { return getTrailingObjects<char>(); }
|
||||
StringRef getValue() const { return getTrailingObjects<char>() + ValueStart; }
|
||||
|
|
@ -518,7 +518,7 @@ public:
|
|||
static LabelDecl *Create(ASTContext &C, DeclContext *DC,
|
||||
SourceLocation IdentL, IdentifierInfo *II,
|
||||
SourceLocation GnuLabelL);
|
||||
static LabelDecl *CreateDeserialized(ASTContext &C, unsigned ID);
|
||||
static LabelDecl *CreateDeserialized(ASTContext &C, GlobalDeclID ID);
|
||||
|
||||
LabelStmt *getStmt() const { return TheStmt; }
|
||||
void setStmt(LabelStmt *T) { TheStmt = T; }
|
||||
|
|
@ -542,12 +542,9 @@ public:
|
|||
};
|
||||
|
||||
/// Represent a C++ namespace.
|
||||
class NamespaceDecl : public NamedDecl, public DeclContext,
|
||||
public Redeclarable<NamespaceDecl>
|
||||
{
|
||||
|
||||
enum Flags : unsigned { F_Inline = 1 << 0, F_Nested = 1 << 1 };
|
||||
|
||||
class NamespaceDecl : public NamedDecl,
|
||||
public DeclContext,
|
||||
public Redeclarable<NamespaceDecl> {
|
||||
/// The starting location of the source range, pointing
|
||||
/// to either the namespace or the inline keyword.
|
||||
SourceLocation LocStart;
|
||||
|
|
@ -555,12 +552,8 @@ class NamespaceDecl : public NamedDecl, public DeclContext,
|
|||
/// The ending location of the source range.
|
||||
SourceLocation RBraceLoc;
|
||||
|
||||
/// A pointer to either the anonymous namespace that lives just inside
|
||||
/// this namespace or to the first namespace in the chain (the latter case
|
||||
/// only when this is not the first in the chain), along with a
|
||||
/// boolean value indicating whether this is an inline namespace.
|
||||
llvm::PointerIntPair<NamespaceDecl *, 2, unsigned>
|
||||
AnonOrFirstNamespaceAndFlags;
|
||||
/// The unnamed namespace that inhabits this namespace, if any.
|
||||
NamespaceDecl *AnonymousNamespace = nullptr;
|
||||
|
||||
NamespaceDecl(ASTContext &C, DeclContext *DC, bool Inline,
|
||||
SourceLocation StartLoc, SourceLocation IdLoc,
|
||||
|
|
@ -581,7 +574,7 @@ public:
|
|||
IdentifierInfo *Id, NamespaceDecl *PrevDecl,
|
||||
bool Nested);
|
||||
|
||||
static NamespaceDecl *CreateDeserialized(ASTContext &C, unsigned ID);
|
||||
static NamespaceDecl *CreateDeserialized(ASTContext &C, GlobalDeclID ID);
|
||||
|
||||
using redecl_range = redeclarable_base::redecl_range;
|
||||
using redecl_iterator = redeclarable_base::redecl_iterator;
|
||||
|
|
@ -607,35 +600,19 @@ public:
|
|||
}
|
||||
|
||||
/// Returns true if this is an inline namespace declaration.
|
||||
bool isInline() const {
|
||||
return AnonOrFirstNamespaceAndFlags.getInt() & F_Inline;
|
||||
}
|
||||
bool isInline() const { return NamespaceDeclBits.IsInline; }
|
||||
|
||||
/// Set whether this is an inline namespace declaration.
|
||||
void setInline(bool Inline) {
|
||||
unsigned F = AnonOrFirstNamespaceAndFlags.getInt();
|
||||
if (Inline)
|
||||
AnonOrFirstNamespaceAndFlags.setInt(F | F_Inline);
|
||||
else
|
||||
AnonOrFirstNamespaceAndFlags.setInt(F & ~F_Inline);
|
||||
}
|
||||
void setInline(bool Inline) { NamespaceDeclBits.IsInline = Inline; }
|
||||
|
||||
/// Returns true if this is a nested namespace declaration.
|
||||
/// \code
|
||||
/// namespace outer::nested { }
|
||||
/// \endcode
|
||||
bool isNested() const {
|
||||
return AnonOrFirstNamespaceAndFlags.getInt() & F_Nested;
|
||||
}
|
||||
bool isNested() const { return NamespaceDeclBits.IsNested; }
|
||||
|
||||
/// 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);
|
||||
}
|
||||
void setNested(bool Nested) { NamespaceDeclBits.IsNested = Nested; }
|
||||
|
||||
/// Returns true if the inline qualifier for \c Name is redundant.
|
||||
bool isRedundantInlineQualifierFor(DeclarationName Name) const {
|
||||
|
|
@ -649,34 +626,18 @@ public:
|
|||
std::distance(Y.begin(), Y.end());
|
||||
}
|
||||
|
||||
/// Get the original (first) namespace declaration.
|
||||
NamespaceDecl *getOriginalNamespace();
|
||||
|
||||
/// Get the original (first) namespace declaration.
|
||||
const NamespaceDecl *getOriginalNamespace() const;
|
||||
|
||||
/// Return true if this declaration is an original (first) declaration
|
||||
/// of the namespace. This is false for non-original (subsequent) namespace
|
||||
/// declarations and anonymous namespaces.
|
||||
bool isOriginalNamespace() const;
|
||||
|
||||
/// Retrieve the anonymous namespace nested inside this namespace,
|
||||
/// if any.
|
||||
/// Retrieve the anonymous namespace that inhabits this namespace, if any.
|
||||
NamespaceDecl *getAnonymousNamespace() const {
|
||||
return getOriginalNamespace()->AnonOrFirstNamespaceAndFlags.getPointer();
|
||||
return getFirstDecl()->AnonymousNamespace;
|
||||
}
|
||||
|
||||
void setAnonymousNamespace(NamespaceDecl *D) {
|
||||
getOriginalNamespace()->AnonOrFirstNamespaceAndFlags.setPointer(D);
|
||||
getFirstDecl()->AnonymousNamespace = D;
|
||||
}
|
||||
|
||||
/// Retrieves the canonical declaration of this namespace.
|
||||
NamespaceDecl *getCanonicalDecl() override {
|
||||
return getOriginalNamespace();
|
||||
}
|
||||
const NamespaceDecl *getCanonicalDecl() const {
|
||||
return getOriginalNamespace();
|
||||
}
|
||||
NamespaceDecl *getCanonicalDecl() override { return getFirstDecl(); }
|
||||
const NamespaceDecl *getCanonicalDecl() const { return getFirstDecl(); }
|
||||
|
||||
SourceRange getSourceRange() const override LLVM_READONLY {
|
||||
return SourceRange(LocStart, RBraceLoc);
|
||||
|
|
@ -1100,6 +1061,9 @@ protected:
|
|||
|
||||
LLVM_PREFERRED_TYPE(bool)
|
||||
unsigned EscapingByref : 1;
|
||||
|
||||
LLVM_PREFERRED_TYPE(bool)
|
||||
unsigned IsCXXCondDecl : 1;
|
||||
};
|
||||
|
||||
union {
|
||||
|
|
@ -1143,7 +1107,7 @@ public:
|
|||
const IdentifierInfo *Id, QualType T,
|
||||
TypeSourceInfo *TInfo, StorageClass S);
|
||||
|
||||
static VarDecl *CreateDeserialized(ASTContext &C, unsigned ID);
|
||||
static VarDecl *CreateDeserialized(ASTContext &C, GlobalDeclID ID);
|
||||
|
||||
SourceRange getSourceRange() const override LLVM_READONLY;
|
||||
|
||||
|
|
@ -1589,6 +1553,15 @@ public:
|
|||
NonParmVarDeclBits.EscapingByref = true;
|
||||
}
|
||||
|
||||
bool isCXXCondDecl() const {
|
||||
return isa<ParmVarDecl>(this) ? false : NonParmVarDeclBits.IsCXXCondDecl;
|
||||
}
|
||||
|
||||
void setCXXCondDecl() {
|
||||
assert(!isa<ParmVarDecl>(this));
|
||||
NonParmVarDeclBits.IsCXXCondDecl = true;
|
||||
}
|
||||
|
||||
/// Determines if this variable's alignment is dependent.
|
||||
bool hasDependentAlignment() const;
|
||||
|
||||
|
|
@ -1716,10 +1689,10 @@ public:
|
|||
static ImplicitParamDecl *Create(ASTContext &C, QualType T,
|
||||
ImplicitParamKind ParamKind);
|
||||
|
||||
static ImplicitParamDecl *CreateDeserialized(ASTContext &C, unsigned ID);
|
||||
static ImplicitParamDecl *CreateDeserialized(ASTContext &C, GlobalDeclID ID);
|
||||
|
||||
ImplicitParamDecl(ASTContext &C, DeclContext *DC, SourceLocation IdLoc,
|
||||
IdentifierInfo *Id, QualType Type,
|
||||
const IdentifierInfo *Id, QualType Type,
|
||||
ImplicitParamKind ParamKind)
|
||||
: VarDecl(ImplicitParam, C, DC, IdLoc, IdLoc, Id, Type,
|
||||
/*TInfo=*/nullptr, SC_None) {
|
||||
|
|
@ -1753,7 +1726,7 @@ public:
|
|||
|
||||
protected:
|
||||
ParmVarDecl(Kind DK, ASTContext &C, DeclContext *DC, SourceLocation StartLoc,
|
||||
SourceLocation IdLoc, IdentifierInfo *Id, QualType T,
|
||||
SourceLocation IdLoc, const IdentifierInfo *Id, QualType T,
|
||||
TypeSourceInfo *TInfo, StorageClass S, Expr *DefArg)
|
||||
: VarDecl(DK, C, DC, StartLoc, IdLoc, Id, T, TInfo, S) {
|
||||
assert(ParmVarDeclBits.HasInheritedDefaultArg == false);
|
||||
|
|
@ -1765,12 +1738,12 @@ protected:
|
|||
|
||||
public:
|
||||
static ParmVarDecl *Create(ASTContext &C, DeclContext *DC,
|
||||
SourceLocation StartLoc,
|
||||
SourceLocation IdLoc, IdentifierInfo *Id,
|
||||
QualType T, TypeSourceInfo *TInfo,
|
||||
StorageClass S, Expr *DefArg);
|
||||
SourceLocation StartLoc, SourceLocation IdLoc,
|
||||
const IdentifierInfo *Id, QualType T,
|
||||
TypeSourceInfo *TInfo, StorageClass S,
|
||||
Expr *DefArg);
|
||||
|
||||
static ParmVarDecl *CreateDeserialized(ASTContext &C, unsigned ID);
|
||||
static ParmVarDecl *CreateDeserialized(ASTContext &C, GlobalDeclID ID);
|
||||
|
||||
SourceRange getSourceRange() const override LLVM_READONLY;
|
||||
|
||||
|
|
@ -1981,21 +1954,35 @@ public:
|
|||
|
||||
};
|
||||
|
||||
/// Stashed information about a defaulted function definition whose body has
|
||||
/// not yet been lazily generated.
|
||||
class DefaultedFunctionInfo final
|
||||
: llvm::TrailingObjects<DefaultedFunctionInfo, DeclAccessPair> {
|
||||
/// Stashed information about a defaulted/deleted function body.
|
||||
class DefaultedOrDeletedFunctionInfo final
|
||||
: llvm::TrailingObjects<DefaultedOrDeletedFunctionInfo, DeclAccessPair,
|
||||
StringLiteral *> {
|
||||
friend TrailingObjects;
|
||||
unsigned NumLookups;
|
||||
bool HasDeletedMessage;
|
||||
|
||||
size_t numTrailingObjects(OverloadToken<DeclAccessPair>) const {
|
||||
return NumLookups;
|
||||
}
|
||||
|
||||
public:
|
||||
static DefaultedFunctionInfo *Create(ASTContext &Context,
|
||||
ArrayRef<DeclAccessPair> Lookups);
|
||||
static DefaultedOrDeletedFunctionInfo *
|
||||
Create(ASTContext &Context, ArrayRef<DeclAccessPair> Lookups,
|
||||
StringLiteral *DeletedMessage = nullptr);
|
||||
|
||||
/// Get the unqualified lookup results that should be used in this
|
||||
/// defaulted function definition.
|
||||
ArrayRef<DeclAccessPair> getUnqualifiedLookups() const {
|
||||
return {getTrailingObjects<DeclAccessPair>(), NumLookups};
|
||||
}
|
||||
|
||||
StringLiteral *getDeletedMessage() const {
|
||||
return HasDeletedMessage ? *getTrailingObjects<StringLiteral *>()
|
||||
: nullptr;
|
||||
}
|
||||
|
||||
void setDeletedMessage(StringLiteral *Message);
|
||||
};
|
||||
|
||||
private:
|
||||
|
|
@ -2005,12 +1992,12 @@ private:
|
|||
ParmVarDecl **ParamInfo = nullptr;
|
||||
|
||||
/// The active member of this union is determined by
|
||||
/// FunctionDeclBits.HasDefaultedFunctionInfo.
|
||||
/// FunctionDeclBits.HasDefaultedOrDeletedInfo.
|
||||
union {
|
||||
/// The body of the function.
|
||||
LazyDeclStmtPtr Body;
|
||||
/// Information about a future defaulted function definition.
|
||||
DefaultedFunctionInfo *DefaultedInfo;
|
||||
DefaultedOrDeletedFunctionInfo *DefaultedOrDeletedInfo;
|
||||
};
|
||||
|
||||
unsigned ODRHash;
|
||||
|
|
@ -2070,13 +2057,12 @@ private:
|
|||
///
|
||||
/// \param PointOfInstantiation point at which the function template
|
||||
/// specialization was first instantiated.
|
||||
void setFunctionTemplateSpecialization(ASTContext &C,
|
||||
FunctionTemplateDecl *Template,
|
||||
const TemplateArgumentList *TemplateArgs,
|
||||
void *InsertPos,
|
||||
TemplateSpecializationKind TSK,
|
||||
const TemplateArgumentListInfo *TemplateArgsAsWritten,
|
||||
SourceLocation PointOfInstantiation);
|
||||
void setFunctionTemplateSpecialization(
|
||||
ASTContext &C, FunctionTemplateDecl *Template,
|
||||
TemplateArgumentList *TemplateArgs, void *InsertPos,
|
||||
TemplateSpecializationKind TSK,
|
||||
const TemplateArgumentListInfo *TemplateArgsAsWritten,
|
||||
SourceLocation PointOfInstantiation);
|
||||
|
||||
/// Specify that this record is an instantiation of the
|
||||
/// member function FD.
|
||||
|
|
@ -2152,7 +2138,7 @@ public:
|
|||
bool hasWrittenPrototype, ConstexprSpecKind ConstexprKind,
|
||||
Expr *TrailingRequiresClause);
|
||||
|
||||
static FunctionDecl *CreateDeserialized(ASTContext &C, unsigned ID);
|
||||
static FunctionDecl *CreateDeserialized(ASTContext &C, GlobalDeclID ID);
|
||||
|
||||
DeclarationNameInfo getNameInfo() const {
|
||||
return DeclarationNameInfo(getDeclName(), getLocation(), DNLoc);
|
||||
|
|
@ -2163,6 +2149,8 @@ public:
|
|||
|
||||
void setRangeEnd(SourceLocation E) { EndRangeLoc = E; }
|
||||
|
||||
void setDeclarationNameLoc(DeclarationNameLoc L) { DNLoc = L; }
|
||||
|
||||
/// Returns the location of the ellipsis of a variadic function.
|
||||
SourceLocation getEllipsisLoc() const {
|
||||
const auto *FPT = getType()->getAs<FunctionProtoType>();
|
||||
|
|
@ -2268,18 +2256,18 @@ public:
|
|||
|
||||
/// Returns whether this specific declaration of the function has a body.
|
||||
bool doesThisDeclarationHaveABody() const {
|
||||
return (!FunctionDeclBits.HasDefaultedFunctionInfo && Body) ||
|
||||
return (!FunctionDeclBits.HasDefaultedOrDeletedInfo && Body) ||
|
||||
isLateTemplateParsed();
|
||||
}
|
||||
|
||||
void setBody(Stmt *B);
|
||||
void setLazyBody(uint64_t Offset) {
|
||||
FunctionDeclBits.HasDefaultedFunctionInfo = false;
|
||||
FunctionDeclBits.HasDefaultedOrDeletedInfo = false;
|
||||
Body = LazyDeclStmtPtr(Offset);
|
||||
}
|
||||
|
||||
void setDefaultedFunctionInfo(DefaultedFunctionInfo *Info);
|
||||
DefaultedFunctionInfo *getDefaultedFunctionInfo() const;
|
||||
void setDefaultedOrDeletedInfo(DefaultedOrDeletedFunctionInfo *Info);
|
||||
DefaultedOrDeletedFunctionInfo *getDefalutedOrDeletedInfo() const;
|
||||
|
||||
/// Whether this function is variadic.
|
||||
bool isVariadic() const;
|
||||
|
|
@ -2482,7 +2470,7 @@ public:
|
|||
return FunctionDeclBits.IsDeleted && !isDefaulted();
|
||||
}
|
||||
|
||||
void setDeletedAsWritten(bool D = true) { FunctionDeclBits.IsDeleted = D; }
|
||||
void setDeletedAsWritten(bool D = true, StringLiteral *Message = nullptr);
|
||||
|
||||
/// Determines whether this function is "main", which is the
|
||||
/// entry point into an executable program.
|
||||
|
|
@ -2615,10 +2603,18 @@ public:
|
|||
/// the target functionality.
|
||||
bool isTargetMultiVersion() const;
|
||||
|
||||
/// True if this function is the default version of a multiversioned dispatch
|
||||
/// function as a part of the target functionality.
|
||||
bool isTargetMultiVersionDefault() const;
|
||||
|
||||
/// True if this function is a multiversioned dispatch function as a part of
|
||||
/// the target-clones functionality.
|
||||
bool isTargetClonesMultiVersion() const;
|
||||
|
||||
/// True if this function is a multiversioned dispatch function as a part of
|
||||
/// the target-version functionality.
|
||||
bool isTargetVersionMultiVersion() const;
|
||||
|
||||
/// \brief Get the associated-constraints of this function declaration.
|
||||
/// Currently, this will either be a vector of size 1 containing the
|
||||
/// trailing-requires-clause or an empty vector.
|
||||
|
|
@ -2630,6 +2626,13 @@ public:
|
|||
AC.push_back(TRC);
|
||||
}
|
||||
|
||||
/// Get the message that indicates why this function was deleted.
|
||||
StringLiteral *getDeletedMessage() const {
|
||||
return FunctionDeclBits.HasDefaultedOrDeletedInfo
|
||||
? DefaultedOrDeletedInfo->getDeletedMessage()
|
||||
: nullptr;
|
||||
}
|
||||
|
||||
void setPreviousDeclaration(FunctionDecl * PrevDecl);
|
||||
|
||||
FunctionDecl *getCanonicalDecl() override;
|
||||
|
|
@ -2940,12 +2943,12 @@ public:
|
|||
///
|
||||
/// \param PointOfInstantiation point at which the function template
|
||||
/// specialization was first instantiated.
|
||||
void setFunctionTemplateSpecialization(FunctionTemplateDecl *Template,
|
||||
const TemplateArgumentList *TemplateArgs,
|
||||
void *InsertPos,
|
||||
TemplateSpecializationKind TSK = TSK_ImplicitInstantiation,
|
||||
const TemplateArgumentListInfo *TemplateArgsAsWritten = nullptr,
|
||||
SourceLocation PointOfInstantiation = SourceLocation()) {
|
||||
void setFunctionTemplateSpecialization(
|
||||
FunctionTemplateDecl *Template, TemplateArgumentList *TemplateArgs,
|
||||
void *InsertPos,
|
||||
TemplateSpecializationKind TSK = TSK_ImplicitInstantiation,
|
||||
TemplateArgumentListInfo *TemplateArgsAsWritten = nullptr,
|
||||
SourceLocation PointOfInstantiation = SourceLocation()) {
|
||||
setFunctionTemplateSpecialization(getASTContext(), Template, TemplateArgs,
|
||||
InsertPos, TSK, TemplateArgsAsWritten,
|
||||
PointOfInstantiation);
|
||||
|
|
@ -3000,6 +3003,16 @@ public:
|
|||
/// computed and stored.
|
||||
unsigned getODRHash() const;
|
||||
|
||||
FunctionEffectsRef getFunctionEffects() const {
|
||||
// Effects may differ between declarations, but they should be propagated
|
||||
// from old to new on any redeclaration, so it suffices to look at
|
||||
// getMostRecentDecl().
|
||||
if (const auto *FPT =
|
||||
getMostRecentDecl()->getType()->getAs<FunctionProtoType>())
|
||||
return FPT->getFunctionEffects();
|
||||
return {};
|
||||
}
|
||||
|
||||
// Implement isa/cast/dyncast/etc.
|
||||
static bool classof(const Decl *D) { return classofKind(D->getKind()); }
|
||||
static bool classofKind(Kind K) {
|
||||
|
|
@ -3075,7 +3088,7 @@ class FieldDecl : public DeclaratorDecl, public Mergeable<FieldDecl> {
|
|||
|
||||
protected:
|
||||
FieldDecl(Kind DK, DeclContext *DC, SourceLocation StartLoc,
|
||||
SourceLocation IdLoc, IdentifierInfo *Id, QualType T,
|
||||
SourceLocation IdLoc, const IdentifierInfo *Id, QualType T,
|
||||
TypeSourceInfo *TInfo, Expr *BW, bool Mutable,
|
||||
InClassInitStyle InitStyle)
|
||||
: DeclaratorDecl(DK, DC, IdLoc, Id, T, TInfo, StartLoc), BitField(false),
|
||||
|
|
@ -3091,11 +3104,11 @@ public:
|
|||
|
||||
static FieldDecl *Create(const ASTContext &C, DeclContext *DC,
|
||||
SourceLocation StartLoc, SourceLocation IdLoc,
|
||||
IdentifierInfo *Id, QualType T,
|
||||
const IdentifierInfo *Id, QualType T,
|
||||
TypeSourceInfo *TInfo, Expr *BW, bool Mutable,
|
||||
InClassInitStyle InitStyle);
|
||||
|
||||
static FieldDecl *CreateDeserialized(ASTContext &C, unsigned ID);
|
||||
static FieldDecl *CreateDeserialized(ASTContext &C, GlobalDeclID ID);
|
||||
|
||||
/// Returns the index of this field within its record,
|
||||
/// as appropriate for passing to ASTRecordLayout::getFieldOffset.
|
||||
|
|
@ -3108,7 +3121,7 @@ public:
|
|||
bool isBitField() const { return BitField; }
|
||||
|
||||
/// Determines whether this is an unnamed bitfield.
|
||||
bool isUnnamedBitfield() const { return isBitField() && !getDeclName(); }
|
||||
bool isUnnamedBitField() const { return isBitField() && !getDeclName(); }
|
||||
|
||||
/// Determines whether this field is a
|
||||
/// representative for an anonymous struct or union. Such fields are
|
||||
|
|
@ -3270,7 +3283,7 @@ public:
|
|||
SourceLocation L, IdentifierInfo *Id,
|
||||
QualType T, Expr *E,
|
||||
const llvm::APSInt &V);
|
||||
static EnumConstantDecl *CreateDeserialized(ASTContext &C, unsigned ID);
|
||||
static EnumConstantDecl *CreateDeserialized(ASTContext &C, GlobalDeclID ID);
|
||||
|
||||
const Expr *getInitExpr() const { return (const Expr*) Init; }
|
||||
Expr *getInitExpr() { return (Expr*) Init; }
|
||||
|
|
@ -3312,10 +3325,11 @@ public:
|
|||
friend class ASTDeclReader;
|
||||
|
||||
static IndirectFieldDecl *Create(ASTContext &C, DeclContext *DC,
|
||||
SourceLocation L, IdentifierInfo *Id,
|
||||
QualType T, llvm::MutableArrayRef<NamedDecl *> CH);
|
||||
SourceLocation L, const IdentifierInfo *Id,
|
||||
QualType T,
|
||||
llvm::MutableArrayRef<NamedDecl *> CH);
|
||||
|
||||
static IndirectFieldDecl *CreateDeserialized(ASTContext &C, unsigned ID);
|
||||
static IndirectFieldDecl *CreateDeserialized(ASTContext &C, GlobalDeclID ID);
|
||||
|
||||
using chain_iterator = ArrayRef<NamedDecl *>::const_iterator;
|
||||
|
||||
|
|
@ -3361,9 +3375,9 @@ class TypeDecl : public NamedDecl {
|
|||
void anchor() override;
|
||||
|
||||
protected:
|
||||
TypeDecl(Kind DK, DeclContext *DC, SourceLocation L, IdentifierInfo *Id,
|
||||
TypeDecl(Kind DK, DeclContext *DC, SourceLocation L, const IdentifierInfo *Id,
|
||||
SourceLocation StartL = SourceLocation())
|
||||
: NamedDecl(DK, DC, L, Id), LocStart(StartL) {}
|
||||
: NamedDecl(DK, DC, L, Id), LocStart(StartL) {}
|
||||
|
||||
public:
|
||||
// Low-level accessor. If you just want the type defined by this node,
|
||||
|
|
@ -3405,7 +3419,7 @@ class TypedefNameDecl : public TypeDecl, public Redeclarable<TypedefNameDecl> {
|
|||
protected:
|
||||
TypedefNameDecl(Kind DK, ASTContext &C, DeclContext *DC,
|
||||
SourceLocation StartLoc, SourceLocation IdLoc,
|
||||
IdentifierInfo *Id, TypeSourceInfo *TInfo)
|
||||
const IdentifierInfo *Id, TypeSourceInfo *TInfo)
|
||||
: TypeDecl(DK, DC, IdLoc, Id, StartLoc), redeclarable_base(C),
|
||||
MaybeModedTInfo(TInfo, 0) {}
|
||||
|
||||
|
|
@ -3492,14 +3506,15 @@ private:
|
|||
/// type specifier.
|
||||
class TypedefDecl : public TypedefNameDecl {
|
||||
TypedefDecl(ASTContext &C, DeclContext *DC, SourceLocation StartLoc,
|
||||
SourceLocation IdLoc, IdentifierInfo *Id, TypeSourceInfo *TInfo)
|
||||
SourceLocation IdLoc, const IdentifierInfo *Id,
|
||||
TypeSourceInfo *TInfo)
|
||||
: TypedefNameDecl(Typedef, C, DC, StartLoc, IdLoc, Id, TInfo) {}
|
||||
|
||||
public:
|
||||
static TypedefDecl *Create(ASTContext &C, DeclContext *DC,
|
||||
SourceLocation StartLoc, SourceLocation IdLoc,
|
||||
IdentifierInfo *Id, TypeSourceInfo *TInfo);
|
||||
static TypedefDecl *CreateDeserialized(ASTContext &C, unsigned ID);
|
||||
const IdentifierInfo *Id, TypeSourceInfo *TInfo);
|
||||
static TypedefDecl *CreateDeserialized(ASTContext &C, GlobalDeclID ID);
|
||||
|
||||
SourceRange getSourceRange() const override LLVM_READONLY;
|
||||
|
||||
|
|
@ -3515,15 +3530,16 @@ class TypeAliasDecl : public TypedefNameDecl {
|
|||
TypeAliasTemplateDecl *Template;
|
||||
|
||||
TypeAliasDecl(ASTContext &C, DeclContext *DC, SourceLocation StartLoc,
|
||||
SourceLocation IdLoc, IdentifierInfo *Id, TypeSourceInfo *TInfo)
|
||||
SourceLocation IdLoc, const IdentifierInfo *Id,
|
||||
TypeSourceInfo *TInfo)
|
||||
: TypedefNameDecl(TypeAlias, C, DC, StartLoc, IdLoc, Id, TInfo),
|
||||
Template(nullptr) {}
|
||||
|
||||
public:
|
||||
static TypeAliasDecl *Create(ASTContext &C, DeclContext *DC,
|
||||
SourceLocation StartLoc, SourceLocation IdLoc,
|
||||
IdentifierInfo *Id, TypeSourceInfo *TInfo);
|
||||
static TypeAliasDecl *CreateDeserialized(ASTContext &C, unsigned ID);
|
||||
const IdentifierInfo *Id, TypeSourceInfo *TInfo);
|
||||
static TypeAliasDecl *CreateDeserialized(ASTContext &C, GlobalDeclID ID);
|
||||
|
||||
SourceRange getSourceRange() const override LLVM_READONLY;
|
||||
|
||||
|
|
@ -3933,7 +3949,7 @@ public:
|
|||
IdentifierInfo *Id, EnumDecl *PrevDecl,
|
||||
bool IsScoped, bool IsScopedUsingClassTag,
|
||||
bool IsFixed);
|
||||
static EnumDecl *CreateDeserialized(ASTContext &C, unsigned ID);
|
||||
static EnumDecl *CreateDeserialized(ASTContext &C, GlobalDeclID ID);
|
||||
|
||||
/// Overrides to provide correct range when there's an enum-base specifier
|
||||
/// with forward declarations.
|
||||
|
|
@ -4138,7 +4154,7 @@ public:
|
|||
static RecordDecl *Create(const ASTContext &C, TagKind TK, DeclContext *DC,
|
||||
SourceLocation StartLoc, SourceLocation IdLoc,
|
||||
IdentifierInfo *Id, RecordDecl* PrevDecl = nullptr);
|
||||
static RecordDecl *CreateDeserialized(const ASTContext &C, unsigned ID);
|
||||
static RecordDecl *CreateDeserialized(const ASTContext &C, GlobalDeclID ID);
|
||||
|
||||
RecordDecl *getPreviousDecl() {
|
||||
return cast_or_null<RecordDecl>(
|
||||
|
|
@ -4389,7 +4405,7 @@ public:
|
|||
StringLiteral *Str, SourceLocation AsmLoc,
|
||||
SourceLocation RParenLoc);
|
||||
|
||||
static FileScopeAsmDecl *CreateDeserialized(ASTContext &C, unsigned ID);
|
||||
static FileScopeAsmDecl *CreateDeserialized(ASTContext &C, GlobalDeclID ID);
|
||||
|
||||
SourceLocation getAsmLoc() const { return getLocation(); }
|
||||
SourceLocation getRParenLoc() const { return RParenLoc; }
|
||||
|
|
@ -4411,7 +4427,7 @@ public:
|
|||
///
|
||||
/// \note This is used in libInterpreter, clang -cc1 -fincremental-extensions
|
||||
/// and in tools such as clang-repl.
|
||||
class TopLevelStmtDecl : public Decl {
|
||||
class TopLevelStmtDecl : public Decl, public DeclContext {
|
||||
friend class ASTDeclReader;
|
||||
friend class ASTDeclWriter;
|
||||
|
||||
|
|
@ -4419,26 +4435,30 @@ class TopLevelStmtDecl : public Decl {
|
|||
bool IsSemiMissing = false;
|
||||
|
||||
TopLevelStmtDecl(DeclContext *DC, SourceLocation L, Stmt *S)
|
||||
: Decl(TopLevelStmt, DC, L), Statement(S) {}
|
||||
: Decl(TopLevelStmt, DC, L), DeclContext(TopLevelStmt), Statement(S) {}
|
||||
|
||||
virtual void anchor();
|
||||
|
||||
public:
|
||||
static TopLevelStmtDecl *Create(ASTContext &C, Stmt *Statement);
|
||||
static TopLevelStmtDecl *CreateDeserialized(ASTContext &C, unsigned ID);
|
||||
static TopLevelStmtDecl *CreateDeserialized(ASTContext &C, GlobalDeclID ID);
|
||||
|
||||
SourceRange getSourceRange() const override LLVM_READONLY;
|
||||
Stmt *getStmt() { return Statement; }
|
||||
const Stmt *getStmt() const { return Statement; }
|
||||
void setStmt(Stmt *S) {
|
||||
assert(IsSemiMissing && "Operation supported for printing values only!");
|
||||
Statement = S;
|
||||
}
|
||||
void setStmt(Stmt *S);
|
||||
bool isSemiMissing() const { return IsSemiMissing; }
|
||||
void setSemiMissing(bool Missing = true) { IsSemiMissing = Missing; }
|
||||
|
||||
static bool classof(const Decl *D) { return classofKind(D->getKind()); }
|
||||
static bool classofKind(Kind K) { return K == TopLevelStmt; }
|
||||
|
||||
static DeclContext *castToDeclContext(const TopLevelStmtDecl *D) {
|
||||
return static_cast<DeclContext *>(const_cast<TopLevelStmtDecl *>(D));
|
||||
}
|
||||
static TopLevelStmtDecl *castFromDeclContext(const DeclContext *DC) {
|
||||
return static_cast<TopLevelStmtDecl *>(const_cast<DeclContext *>(DC));
|
||||
}
|
||||
};
|
||||
|
||||
/// Represents a block literal declaration, which is like an
|
||||
|
|
@ -4515,7 +4535,7 @@ protected:
|
|||
|
||||
public:
|
||||
static BlockDecl *Create(ASTContext &C, DeclContext *DC, SourceLocation L);
|
||||
static BlockDecl *CreateDeserialized(ASTContext &C, unsigned ID);
|
||||
static BlockDecl *CreateDeserialized(ASTContext &C, GlobalDeclID ID);
|
||||
|
||||
SourceLocation getCaretLocation() const { return getLocation(); }
|
||||
|
||||
|
|
@ -4621,6 +4641,13 @@ public:
|
|||
|
||||
SourceRange getSourceRange() const override LLVM_READONLY;
|
||||
|
||||
FunctionEffectsRef getFunctionEffects() const {
|
||||
if (const TypeSourceInfo *TSI = getSignatureAsWritten())
|
||||
if (const auto *FPT = TSI->getType()->getAs<FunctionProtoType>())
|
||||
return FPT->getFunctionEffects();
|
||||
return {};
|
||||
}
|
||||
|
||||
// Implement isa/cast/dyncast/etc.
|
||||
static bool classof(const Decl *D) { return classofKind(D->getKind()); }
|
||||
static bool classofKind(Kind K) { return K == Block; }
|
||||
|
|
@ -4669,7 +4696,7 @@ public:
|
|||
|
||||
static CapturedDecl *Create(ASTContext &C, DeclContext *DC,
|
||||
unsigned NumParams);
|
||||
static CapturedDecl *CreateDeserialized(ASTContext &C, unsigned ID,
|
||||
static CapturedDecl *CreateDeserialized(ASTContext &C, GlobalDeclID ID,
|
||||
unsigned NumParams);
|
||||
|
||||
Stmt *getBody() const override;
|
||||
|
|
@ -4803,7 +4830,7 @@ public:
|
|||
SourceLocation EndLoc);
|
||||
|
||||
/// Create a new, deserialized module import declaration.
|
||||
static ImportDecl *CreateDeserialized(ASTContext &C, unsigned ID,
|
||||
static ImportDecl *CreateDeserialized(ASTContext &C, GlobalDeclID ID,
|
||||
unsigned NumLocations);
|
||||
|
||||
/// Retrieve the module that was imported by the import declaration.
|
||||
|
|
@ -4844,7 +4871,7 @@ private:
|
|||
public:
|
||||
static ExportDecl *Create(ASTContext &C, DeclContext *DC,
|
||||
SourceLocation ExportLoc);
|
||||
static ExportDecl *CreateDeserialized(ASTContext &C, unsigned ID);
|
||||
static ExportDecl *CreateDeserialized(ASTContext &C, GlobalDeclID ID);
|
||||
|
||||
SourceLocation getExportLoc() const { return getLocation(); }
|
||||
SourceLocation getRBraceLoc() const { return RBraceLoc; }
|
||||
|
|
@ -4883,7 +4910,7 @@ class EmptyDecl : public Decl {
|
|||
public:
|
||||
static EmptyDecl *Create(ASTContext &C, DeclContext *DC,
|
||||
SourceLocation L);
|
||||
static EmptyDecl *CreateDeserialized(ASTContext &C, unsigned ID);
|
||||
static EmptyDecl *CreateDeserialized(ASTContext &C, GlobalDeclID ID);
|
||||
|
||||
static bool classof(const Decl *D) { return classofKind(D->getKind()); }
|
||||
static bool classofKind(Kind K) { return K == Empty; }
|
||||
|
|
@ -4909,7 +4936,7 @@ public:
|
|||
bool CBuffer, SourceLocation KwLoc,
|
||||
IdentifierInfo *ID, SourceLocation IDLoc,
|
||||
SourceLocation LBrace);
|
||||
static HLSLBufferDecl *CreateDeserialized(ASTContext &C, unsigned ID);
|
||||
static HLSLBufferDecl *CreateDeserialized(ASTContext &C, GlobalDeclID ID);
|
||||
|
||||
SourceRange getSourceRange() const override LLVM_READONLY {
|
||||
return SourceRange(getLocStart(), RBraceLoc);
|
||||
|
|
@ -5001,6 +5028,11 @@ static constexpr StringRef getOpenMPVariantManglingSeparatorStr() {
|
|||
return "$ompvariant";
|
||||
}
|
||||
|
||||
/// Returns whether the given FunctionDecl has an __arm[_locally]_streaming
|
||||
/// attribute.
|
||||
bool IsArmStreamingFunction(const FunctionDecl *FD,
|
||||
bool IncludeLocallyStreaming);
|
||||
|
||||
} // namespace clang
|
||||
|
||||
#endif // LLVM_CLANG_AST_DECL_H
|
||||
|
|
|
|||
|
|
@ -19,6 +19,7 @@
|
|||
|
||||
#include "clang/Basic/Specifiers.h"
|
||||
#include "llvm/Support/DataTypes.h"
|
||||
#include "llvm/Support/Endian.h"
|
||||
|
||||
namespace clang {
|
||||
|
||||
|
|
@ -27,9 +28,17 @@ class NamedDecl;
|
|||
/// A POD class for pairing a NamedDecl* with an access specifier.
|
||||
/// Can be put into unions.
|
||||
class DeclAccessPair {
|
||||
uintptr_t Ptr; // we'd use llvm::PointerUnion, but it isn't trivial
|
||||
/// Use the lower 2 bit to store AccessSpecifier. Use the higher
|
||||
/// 61 bit to store the pointer to a NamedDecl or the DeclID to
|
||||
/// a NamedDecl. If the 3rd bit is set, storing the DeclID, otherwise
|
||||
/// storing the pointer.
|
||||
llvm::support::detail::packed_endian_specific_integral<
|
||||
uint64_t, llvm::endianness::native, alignof(void *)>
|
||||
Ptr;
|
||||
|
||||
enum { Mask = 0x3 };
|
||||
enum { ASMask = 0x3, Mask = 0x7 };
|
||||
|
||||
bool isDeclID() const { return (Ptr >> 2) & 0x1; }
|
||||
|
||||
public:
|
||||
static DeclAccessPair make(NamedDecl *D, AccessSpecifier AS) {
|
||||
|
|
@ -38,12 +47,22 @@ public:
|
|||
return p;
|
||||
}
|
||||
|
||||
static DeclAccessPair makeLazy(uint64_t ID, AccessSpecifier AS) {
|
||||
DeclAccessPair p;
|
||||
p.Ptr = (ID << 3) | (0x1 << 2) | uint64_t(AS);
|
||||
return p;
|
||||
}
|
||||
|
||||
uint64_t getDeclID() const {
|
||||
assert(isDeclID());
|
||||
return (~Mask & Ptr) >> 3;
|
||||
}
|
||||
|
||||
NamedDecl *getDecl() const {
|
||||
assert(!isDeclID());
|
||||
return reinterpret_cast<NamedDecl*>(~Mask & Ptr);
|
||||
}
|
||||
AccessSpecifier getAccess() const {
|
||||
return AccessSpecifier(Mask & Ptr);
|
||||
}
|
||||
AccessSpecifier getAccess() const { return AccessSpecifier(ASMask & Ptr); }
|
||||
|
||||
void setDecl(NamedDecl *D) {
|
||||
set(D, getAccess());
|
||||
|
|
@ -52,12 +71,18 @@ public:
|
|||
set(getDecl(), AS);
|
||||
}
|
||||
void set(NamedDecl *D, AccessSpecifier AS) {
|
||||
Ptr = uintptr_t(AS) | reinterpret_cast<uintptr_t>(D);
|
||||
Ptr = uint64_t(AS) | reinterpret_cast<uint64_t>(D);
|
||||
}
|
||||
|
||||
operator NamedDecl*() const { return getDecl(); }
|
||||
NamedDecl *operator->() const { return getDecl(); }
|
||||
};
|
||||
|
||||
// Make sure DeclAccessPair is pointer-aligned types.
|
||||
static_assert(alignof(DeclAccessPair) == alignof(void *));
|
||||
// Make sure DeclAccessPair is still POD.
|
||||
static_assert(std::is_standard_layout_v<DeclAccessPair> &&
|
||||
std::is_trivial_v<DeclAccessPair>);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -15,6 +15,7 @@
|
|||
|
||||
#include "clang/AST/ASTDumperUtils.h"
|
||||
#include "clang/AST/AttrIterator.h"
|
||||
#include "clang/AST/DeclID.h"
|
||||
#include "clang/AST/DeclarationName.h"
|
||||
#include "clang/AST/SelectorLocationsKind.h"
|
||||
#include "clang/Basic/IdentifierTable.h"
|
||||
|
|
@ -358,7 +359,7 @@ protected:
|
|||
/// \param Ctx The context in which we will allocate memory.
|
||||
/// \param ID The global ID of the deserialized declaration.
|
||||
/// \param Extra The amount of extra space to allocate after the object.
|
||||
void *operator new(std::size_t Size, const ASTContext &Ctx, unsigned ID,
|
||||
void *operator new(std::size_t Size, const ASTContext &Ctx, GlobalDeclID ID,
|
||||
std::size_t Extra = 0);
|
||||
|
||||
/// Allocate memory for a non-deserialized declaration.
|
||||
|
|
@ -669,19 +670,11 @@ public:
|
|||
/// Whether this declaration comes from another module unit.
|
||||
bool isInAnotherModuleUnit() const;
|
||||
|
||||
/// FIXME: Implement discarding declarations actually in global module
|
||||
/// fragment. See [module.global.frag]p3,4 for details.
|
||||
bool isDiscardedInGlobalModuleFragment() const { return false; }
|
||||
/// Whether this declaration comes from explicit global module.
|
||||
bool isFromExplicitGlobalModule() const;
|
||||
|
||||
/// Check if we should skip checking ODRHash for declaration \param D.
|
||||
///
|
||||
/// The existing ODRHash mechanism seems to be not stable enough and
|
||||
/// the false positive ODR violation reports are annoying and we rarely see
|
||||
/// true ODR violation reports. Also we learned that MSVC disabled ODR checks
|
||||
/// for declarations in GMF. So we try to disable ODR checks in the GMF to
|
||||
/// get better user experiences before we make the ODR violation checks stable
|
||||
/// enough.
|
||||
bool shouldSkipCheckingODR() const;
|
||||
/// Whether this declaration comes from a named module.
|
||||
bool isInNamedModule() const;
|
||||
|
||||
/// Return true if this declaration has an attribute which acts as
|
||||
/// definition of the entity, such as 'alias' or 'ifunc'.
|
||||
|
|
@ -711,10 +704,7 @@ public:
|
|||
|
||||
/// Set the owning module ID. This may only be called for
|
||||
/// deserialized Decls.
|
||||
void setOwningModuleID(unsigned ID) {
|
||||
assert(isFromASTFile() && "Only works on a deserialized declaration");
|
||||
*((unsigned*)this - 2) = ID;
|
||||
}
|
||||
void setOwningModuleID(unsigned ID);
|
||||
|
||||
public:
|
||||
/// Determine the availability of the given declaration.
|
||||
|
|
@ -787,19 +777,11 @@ public:
|
|||
|
||||
/// Retrieve the global declaration ID associated with this
|
||||
/// declaration, which specifies where this Decl was loaded from.
|
||||
unsigned getGlobalID() const {
|
||||
if (isFromASTFile())
|
||||
return *((const unsigned*)this - 1);
|
||||
return 0;
|
||||
}
|
||||
GlobalDeclID getGlobalID() const;
|
||||
|
||||
/// Retrieve the global ID of the module that owns this particular
|
||||
/// declaration.
|
||||
unsigned getOwningModuleID() const {
|
||||
if (isFromASTFile())
|
||||
return *((const unsigned*)this - 2);
|
||||
return 0;
|
||||
}
|
||||
unsigned getOwningModuleID() const;
|
||||
|
||||
private:
|
||||
Module *getOwningModuleSlow() const;
|
||||
|
|
@ -846,10 +828,7 @@ public:
|
|||
|
||||
/// Get the module that owns this declaration for linkage purposes.
|
||||
/// There only ever is such a standard C++ module.
|
||||
///
|
||||
/// \param IgnoreLinkage Ignore the linkage of the entity; assume that
|
||||
/// all declarations in a global module fragment are unowned.
|
||||
Module *getOwningModuleForLinkage(bool IgnoreLinkage = false) const;
|
||||
Module *getOwningModuleForLinkage() const;
|
||||
|
||||
/// Determine whether this declaration is definitely visible to name lookup,
|
||||
/// independent of whether the owning module is visible.
|
||||
|
|
@ -1508,6 +1487,27 @@ class DeclContext {
|
|||
/// Number of bits in DeclContextBitfields.
|
||||
enum { NumDeclContextBits = 13 };
|
||||
|
||||
/// Stores the bits used by NamespaceDecl.
|
||||
/// If modified NumNamespaceDeclBits and the accessor
|
||||
/// methods in NamespaceDecl should be updated appropriately.
|
||||
class NamespaceDeclBitfields {
|
||||
friend class NamespaceDecl;
|
||||
/// For the bits in DeclContextBitfields
|
||||
LLVM_PREFERRED_TYPE(DeclContextBitfields)
|
||||
uint64_t : NumDeclContextBits;
|
||||
|
||||
/// True if this is an inline namespace.
|
||||
LLVM_PREFERRED_TYPE(bool)
|
||||
uint64_t IsInline : 1;
|
||||
|
||||
/// True if this is a nested-namespace-definition.
|
||||
LLVM_PREFERRED_TYPE(bool)
|
||||
uint64_t IsNested : 1;
|
||||
};
|
||||
|
||||
/// Number of inherited and non-inherited bits in NamespaceDeclBitfields.
|
||||
enum { NumNamespaceDeclBits = NumDeclContextBits + 2 };
|
||||
|
||||
/// Stores the bits used by TagDecl.
|
||||
/// If modified NumTagDeclBits and the accessor
|
||||
/// methods in TagDecl should be updated appropriately.
|
||||
|
|
@ -1740,7 +1740,7 @@ class DeclContext {
|
|||
LLVM_PREFERRED_TYPE(bool)
|
||||
uint64_t IsExplicitlyDefaulted : 1;
|
||||
LLVM_PREFERRED_TYPE(bool)
|
||||
uint64_t HasDefaultedFunctionInfo : 1;
|
||||
uint64_t HasDefaultedOrDeletedInfo : 1;
|
||||
|
||||
/// For member functions of complete types, whether this is an ineligible
|
||||
/// special member function or an unselected destructor. See
|
||||
|
|
@ -2006,6 +2006,7 @@ protected:
|
|||
/// 8 bytes with static_asserts in the ctor of DeclContext.
|
||||
union {
|
||||
DeclContextBitfields DeclContextBits;
|
||||
NamespaceDeclBitfields NamespaceDeclBits;
|
||||
TagDeclBitfields TagDeclBits;
|
||||
EnumDeclBitfields EnumDeclBits;
|
||||
RecordDeclBitfields RecordDeclBits;
|
||||
|
|
@ -2019,6 +2020,8 @@ protected:
|
|||
|
||||
static_assert(sizeof(DeclContextBitfields) <= 8,
|
||||
"DeclContextBitfields is larger than 8 bytes!");
|
||||
static_assert(sizeof(NamespaceDeclBitfields) <= 8,
|
||||
"NamespaceDeclBitfields is larger than 8 bytes!");
|
||||
static_assert(sizeof(TagDeclBitfields) <= 8,
|
||||
"TagDeclBitfields is larger than 8 bytes!");
|
||||
static_assert(sizeof(EnumDeclBitfields) <= 8,
|
||||
|
|
@ -2130,6 +2133,7 @@ public:
|
|||
case Decl::Block:
|
||||
case Decl::Captured:
|
||||
case Decl::ObjCMethod:
|
||||
case Decl::TopLevelStmt:
|
||||
return true;
|
||||
default:
|
||||
return getDeclKind() >= Decl::firstFunction &&
|
||||
|
|
@ -2157,6 +2161,10 @@ public:
|
|||
getDeclKind() <= Decl::lastRecord;
|
||||
}
|
||||
|
||||
bool isRequiresExprBody() const {
|
||||
return getDeclKind() == Decl::RequiresExprBody;
|
||||
}
|
||||
|
||||
bool isNamespace() const { return getDeclKind() == Decl::Namespace; }
|
||||
|
||||
bool isStdNamespace() const;
|
||||
|
|
|
|||
|
|
@ -120,7 +120,7 @@ public:
|
|||
return new (C, DC) AccessSpecDecl(AS, DC, ASLoc, ColonLoc);
|
||||
}
|
||||
|
||||
static AccessSpecDecl *CreateDeserialized(ASTContext &C, unsigned ID);
|
||||
static AccessSpecDecl *CreateDeserialized(ASTContext &C, GlobalDeclID ID);
|
||||
|
||||
// Implement isa/cast/dyncast/etc.
|
||||
static bool classof(const Decl *D) { return classofKind(D->getKind()); }
|
||||
|
|
@ -579,7 +579,8 @@ public:
|
|||
TypeSourceInfo *Info, SourceLocation Loc,
|
||||
unsigned DependencyKind, bool IsGeneric,
|
||||
LambdaCaptureDefault CaptureDefault);
|
||||
static CXXRecordDecl *CreateDeserialized(const ASTContext &C, unsigned ID);
|
||||
static CXXRecordDecl *CreateDeserialized(const ASTContext &C,
|
||||
GlobalDeclID ID);
|
||||
|
||||
bool isDynamicClass() const {
|
||||
return data().Polymorphic || data().NumVBases != 0;
|
||||
|
|
@ -1869,6 +1870,10 @@ public:
|
|||
DL.MethodTyInfo = TS;
|
||||
}
|
||||
|
||||
void setLambdaDependencyKind(unsigned Kind) {
|
||||
getLambdaData().DependencyKind = Kind;
|
||||
}
|
||||
|
||||
void setLambdaIsGeneric(bool IsGeneric) {
|
||||
assert(DefinitionData && DefinitionData->IsLambda &&
|
||||
"setting lambda property of non-lambda class");
|
||||
|
|
@ -1976,7 +1981,8 @@ public:
|
|||
CXXConstructorDecl *Ctor = nullptr,
|
||||
DeductionCandidate Kind = DeductionCandidate::Normal);
|
||||
|
||||
static CXXDeductionGuideDecl *CreateDeserialized(ASTContext &C, unsigned ID);
|
||||
static CXXDeductionGuideDecl *CreateDeserialized(ASTContext &C,
|
||||
GlobalDeclID ID);
|
||||
|
||||
ExplicitSpecifier getExplicitSpecifier() { return ExplicitSpec; }
|
||||
const ExplicitSpecifier getExplicitSpecifier() const { return ExplicitSpec; }
|
||||
|
|
@ -2031,7 +2037,8 @@ public:
|
|||
static RequiresExprBodyDecl *Create(ASTContext &C, DeclContext *DC,
|
||||
SourceLocation StartLoc);
|
||||
|
||||
static RequiresExprBodyDecl *CreateDeserialized(ASTContext &C, unsigned ID);
|
||||
static RequiresExprBodyDecl *CreateDeserialized(ASTContext &C,
|
||||
GlobalDeclID ID);
|
||||
|
||||
// Implement isa/cast/dyncast/etc.
|
||||
static bool classof(const Decl *D) { return classofKind(D->getKind()); }
|
||||
|
|
@ -2074,7 +2081,7 @@ public:
|
|||
ConstexprSpecKind ConstexprKind, SourceLocation EndLocation,
|
||||
Expr *TrailingRequiresClause = nullptr);
|
||||
|
||||
static CXXMethodDecl *CreateDeserialized(ASTContext &C, unsigned ID);
|
||||
static CXXMethodDecl *CreateDeserialized(ASTContext &C, GlobalDeclID ID);
|
||||
|
||||
bool isStatic() const;
|
||||
bool isInstance() const { return !isStatic(); }
|
||||
|
|
@ -2575,7 +2582,7 @@ public:
|
|||
friend class ASTDeclWriter;
|
||||
friend TrailingObjects;
|
||||
|
||||
static CXXConstructorDecl *CreateDeserialized(ASTContext &C, unsigned ID,
|
||||
static CXXConstructorDecl *CreateDeserialized(ASTContext &C, GlobalDeclID ID,
|
||||
uint64_t AllocKind);
|
||||
static CXXConstructorDecl *
|
||||
Create(ASTContext &C, CXXRecordDecl *RD, SourceLocation StartLoc,
|
||||
|
|
@ -2818,7 +2825,7 @@ public:
|
|||
bool UsesFPIntrin, bool isInline, bool isImplicitlyDeclared,
|
||||
ConstexprSpecKind ConstexprKind,
|
||||
Expr *TrailingRequiresClause = nullptr);
|
||||
static CXXDestructorDecl *CreateDeserialized(ASTContext & C, unsigned ID);
|
||||
static CXXDestructorDecl *CreateDeserialized(ASTContext &C, GlobalDeclID ID);
|
||||
|
||||
void setOperatorDelete(FunctionDecl *OD, Expr *ThisArg);
|
||||
|
||||
|
|
@ -2877,7 +2884,7 @@ public:
|
|||
bool UsesFPIntrin, bool isInline, ExplicitSpecifier ES,
|
||||
ConstexprSpecKind ConstexprKind, SourceLocation EndLocation,
|
||||
Expr *TrailingRequiresClause = nullptr);
|
||||
static CXXConversionDecl *CreateDeserialized(ASTContext &C, unsigned ID);
|
||||
static CXXConversionDecl *CreateDeserialized(ASTContext &C, GlobalDeclID ID);
|
||||
|
||||
ExplicitSpecifier getExplicitSpecifier() {
|
||||
return getCanonicalDecl()->ExplicitSpec;
|
||||
|
|
@ -2944,7 +2951,7 @@ public:
|
|||
SourceLocation ExternLoc,
|
||||
SourceLocation LangLoc,
|
||||
LinkageSpecLanguageIDs Lang, bool HasBraces);
|
||||
static LinkageSpecDecl *CreateDeserialized(ASTContext &C, unsigned ID);
|
||||
static LinkageSpecDecl *CreateDeserialized(ASTContext &C, GlobalDeclID ID);
|
||||
|
||||
/// Return the language specified by this linkage specification.
|
||||
LinkageSpecLanguageIDs getLanguage() const {
|
||||
|
|
@ -3092,7 +3099,7 @@ public:
|
|||
SourceLocation IdentLoc,
|
||||
NamedDecl *Nominated,
|
||||
DeclContext *CommonAncestor);
|
||||
static UsingDirectiveDecl *CreateDeserialized(ASTContext &C, unsigned ID);
|
||||
static UsingDirectiveDecl *CreateDeserialized(ASTContext &C, GlobalDeclID ID);
|
||||
|
||||
SourceRange getSourceRange() const override LLVM_READONLY {
|
||||
return SourceRange(UsingLoc, getLocation());
|
||||
|
|
@ -3153,7 +3160,7 @@ public:
|
|||
SourceLocation IdentLoc,
|
||||
NamedDecl *Namespace);
|
||||
|
||||
static NamespaceAliasDecl *CreateDeserialized(ASTContext &C, unsigned ID);
|
||||
static NamespaceAliasDecl *CreateDeserialized(ASTContext &C, GlobalDeclID ID);
|
||||
|
||||
using redecl_range = redeclarable_base::redecl_range;
|
||||
using redecl_iterator = redeclarable_base::redecl_iterator;
|
||||
|
|
@ -3250,7 +3257,7 @@ public:
|
|||
LifetimeExtendedTemporaryDecl(Temp, EDec, Mangling);
|
||||
}
|
||||
static LifetimeExtendedTemporaryDecl *CreateDeserialized(ASTContext &C,
|
||||
unsigned ID) {
|
||||
GlobalDeclID ID) {
|
||||
return new (C, ID) LifetimeExtendedTemporaryDecl(EmptyShell{});
|
||||
}
|
||||
|
||||
|
|
@ -3353,7 +3360,7 @@ public:
|
|||
UsingShadowDecl(UsingShadow, C, DC, Loc, Name, Introducer, Target);
|
||||
}
|
||||
|
||||
static UsingShadowDecl *CreateDeserialized(ASTContext &C, unsigned ID);
|
||||
static UsingShadowDecl *CreateDeserialized(ASTContext &C, GlobalDeclID ID);
|
||||
|
||||
using redecl_range = redeclarable_base::redecl_range;
|
||||
using redecl_iterator = redeclarable_base::redecl_iterator;
|
||||
|
|
@ -3562,7 +3569,7 @@ public:
|
|||
const DeclarationNameInfo &NameInfo,
|
||||
bool HasTypenameKeyword);
|
||||
|
||||
static UsingDecl *CreateDeserialized(ASTContext &C, unsigned ID);
|
||||
static UsingDecl *CreateDeserialized(ASTContext &C, GlobalDeclID ID);
|
||||
|
||||
SourceRange getSourceRange() const override LLVM_READONLY;
|
||||
|
||||
|
|
@ -3641,7 +3648,7 @@ public:
|
|||
UsingDecl *Using, NamedDecl *Target,
|
||||
bool IsVirtual);
|
||||
static ConstructorUsingShadowDecl *CreateDeserialized(ASTContext &C,
|
||||
unsigned ID);
|
||||
GlobalDeclID ID);
|
||||
|
||||
/// Override the UsingShadowDecl's getIntroducer, returning the UsingDecl that
|
||||
/// introduced this.
|
||||
|
|
@ -3753,7 +3760,7 @@ public:
|
|||
SourceLocation UsingL, SourceLocation EnumL,
|
||||
SourceLocation NameL, TypeSourceInfo *EnumType);
|
||||
|
||||
static UsingEnumDecl *CreateDeserialized(ASTContext &C, unsigned ID);
|
||||
static UsingEnumDecl *CreateDeserialized(ASTContext &C, GlobalDeclID ID);
|
||||
|
||||
SourceRange getSourceRange() const override LLVM_READONLY;
|
||||
|
||||
|
|
@ -3826,7 +3833,7 @@ public:
|
|||
NamedDecl *InstantiatedFrom,
|
||||
ArrayRef<NamedDecl *> UsingDecls);
|
||||
|
||||
static UsingPackDecl *CreateDeserialized(ASTContext &C, unsigned ID,
|
||||
static UsingPackDecl *CreateDeserialized(ASTContext &C, GlobalDeclID ID,
|
||||
unsigned NumExpansions);
|
||||
|
||||
SourceRange getSourceRange() const override LLVM_READONLY {
|
||||
|
|
@ -3919,8 +3926,8 @@ public:
|
|||
NestedNameSpecifierLoc QualifierLoc,
|
||||
const DeclarationNameInfo &NameInfo, SourceLocation EllipsisLoc);
|
||||
|
||||
static UnresolvedUsingValueDecl *
|
||||
CreateDeserialized(ASTContext &C, unsigned ID);
|
||||
static UnresolvedUsingValueDecl *CreateDeserialized(ASTContext &C,
|
||||
GlobalDeclID ID);
|
||||
|
||||
SourceRange getSourceRange() const override LLVM_READONLY;
|
||||
|
||||
|
|
@ -4010,8 +4017,8 @@ public:
|
|||
SourceLocation TargetNameLoc, DeclarationName TargetName,
|
||||
SourceLocation EllipsisLoc);
|
||||
|
||||
static UnresolvedUsingTypenameDecl *
|
||||
CreateDeserialized(ASTContext &C, unsigned ID);
|
||||
static UnresolvedUsingTypenameDecl *CreateDeserialized(ASTContext &C,
|
||||
GlobalDeclID ID);
|
||||
|
||||
/// Retrieves the canonical declaration of this declaration.
|
||||
UnresolvedUsingTypenameDecl *getCanonicalDecl() override {
|
||||
|
|
@ -4041,7 +4048,7 @@ public:
|
|||
SourceLocation Loc,
|
||||
DeclarationName Name);
|
||||
static UnresolvedUsingIfExistsDecl *CreateDeserialized(ASTContext &Ctx,
|
||||
unsigned ID);
|
||||
GlobalDeclID ID);
|
||||
|
||||
static bool classof(const Decl *D) { return classofKind(D->getKind()); }
|
||||
static bool classofKind(Kind K) { return K == Decl::UnresolvedUsingIfExists; }
|
||||
|
|
@ -4069,7 +4076,7 @@ public:
|
|||
SourceLocation StaticAssertLoc,
|
||||
Expr *AssertExpr, Expr *Message,
|
||||
SourceLocation RParenLoc, bool Failed);
|
||||
static StaticAssertDecl *CreateDeserialized(ASTContext &C, unsigned ID);
|
||||
static StaticAssertDecl *CreateDeserialized(ASTContext &C, GlobalDeclID ID);
|
||||
|
||||
Expr *getAssertExpr() { return AssertExprAndFailed.getPointer(); }
|
||||
const Expr *getAssertExpr() const { return AssertExprAndFailed.getPointer(); }
|
||||
|
|
@ -4116,7 +4123,7 @@ public:
|
|||
|
||||
static BindingDecl *Create(ASTContext &C, DeclContext *DC,
|
||||
SourceLocation IdLoc, IdentifierInfo *Id);
|
||||
static BindingDecl *CreateDeserialized(ASTContext &C, unsigned ID);
|
||||
static BindingDecl *CreateDeserialized(ASTContext &C, GlobalDeclID ID);
|
||||
|
||||
/// Get the expression to which this declaration is bound. This may be null
|
||||
/// in two different cases: while parsing the initializer for the
|
||||
|
|
@ -4185,7 +4192,7 @@ public:
|
|||
QualType T, TypeSourceInfo *TInfo,
|
||||
StorageClass S,
|
||||
ArrayRef<BindingDecl *> Bindings);
|
||||
static DecompositionDecl *CreateDeserialized(ASTContext &C, unsigned ID,
|
||||
static DecompositionDecl *CreateDeserialized(ASTContext &C, GlobalDeclID ID,
|
||||
unsigned NumBindings);
|
||||
|
||||
ArrayRef<BindingDecl *> bindings() const {
|
||||
|
|
@ -4242,7 +4249,7 @@ public:
|
|||
SourceLocation L, DeclarationName N, QualType T,
|
||||
TypeSourceInfo *TInfo, SourceLocation StartL,
|
||||
IdentifierInfo *Getter, IdentifierInfo *Setter);
|
||||
static MSPropertyDecl *CreateDeserialized(ASTContext &C, unsigned ID);
|
||||
static MSPropertyDecl *CreateDeserialized(ASTContext &C, GlobalDeclID ID);
|
||||
|
||||
static bool classof(const Decl *D) { return D->getKind() == MSProperty; }
|
||||
|
||||
|
|
@ -4296,7 +4303,7 @@ private:
|
|||
MSGuidDecl(DeclContext *DC, QualType T, Parts P);
|
||||
|
||||
static MSGuidDecl *Create(const ASTContext &C, QualType T, Parts P);
|
||||
static MSGuidDecl *CreateDeserialized(ASTContext &C, unsigned ID);
|
||||
static MSGuidDecl *CreateDeserialized(ASTContext &C, GlobalDeclID ID);
|
||||
|
||||
// Only ASTContext::getMSGuidDecl and deserialization create these.
|
||||
friend class ASTContext;
|
||||
|
|
@ -4349,7 +4356,7 @@ class UnnamedGlobalConstantDecl : public ValueDecl,
|
|||
static UnnamedGlobalConstantDecl *Create(const ASTContext &C, QualType T,
|
||||
const APValue &APVal);
|
||||
static UnnamedGlobalConstantDecl *CreateDeserialized(ASTContext &C,
|
||||
unsigned ID);
|
||||
GlobalDeclID ID);
|
||||
|
||||
// Only ASTContext::getUnnamedGlobalConstantDecl and deserialization create
|
||||
// these.
|
||||
|
|
|
|||
|
|
@ -42,11 +42,12 @@ class StoredDeclsList {
|
|||
/// external declarations.
|
||||
DeclsAndHasExternalTy Data;
|
||||
|
||||
template<typename Fn>
|
||||
void erase_if(Fn ShouldErase) {
|
||||
template <typename Fn> DeclListNode::Decls *erase_if(Fn ShouldErase) {
|
||||
Decls List = Data.getPointer();
|
||||
|
||||
if (!List)
|
||||
return;
|
||||
return nullptr;
|
||||
|
||||
ASTContext &C = getASTContext();
|
||||
DeclListNode::Decls NewHead = nullptr;
|
||||
DeclListNode::Decls *NewLast = nullptr;
|
||||
|
|
@ -79,6 +80,17 @@ class StoredDeclsList {
|
|||
Data.setPointer(NewHead);
|
||||
|
||||
assert(llvm::none_of(getLookupResult(), ShouldErase) && "Still exists!");
|
||||
|
||||
if (!Data.getPointer())
|
||||
// All declarations are erased.
|
||||
return nullptr;
|
||||
else if (NewHead.is<NamedDecl *>())
|
||||
// The list only contains a declaration, the header itself.
|
||||
return (DeclListNode::Decls *)&Data;
|
||||
else {
|
||||
assert(NewLast && NewLast->is<NamedDecl *>() && "Not the tail?");
|
||||
return NewLast;
|
||||
}
|
||||
}
|
||||
|
||||
void erase(NamedDecl *ND) {
|
||||
|
|
@ -160,12 +172,16 @@ public:
|
|||
|
||||
void replaceExternalDecls(ArrayRef<NamedDecl*> Decls) {
|
||||
// Remove all declarations that are either external or are replaced with
|
||||
// external declarations.
|
||||
erase_if([Decls](NamedDecl *ND) {
|
||||
// external declarations with higher visibilities.
|
||||
DeclListNode::Decls *Tail = erase_if([Decls](NamedDecl *ND) {
|
||||
if (ND->isFromASTFile())
|
||||
return true;
|
||||
// FIXME: Can we get rid of this loop completely?
|
||||
for (NamedDecl *D : Decls)
|
||||
if (D->declarationReplaces(ND, /*IsKnownNewer=*/false))
|
||||
// Only replace the local declaration if the external declaration has
|
||||
// higher visibilities.
|
||||
if (D->getModuleOwnershipKind() <= ND->getModuleOwnershipKind() &&
|
||||
D->declarationReplaces(ND, /*IsKnownNewer=*/false))
|
||||
return true;
|
||||
return false;
|
||||
});
|
||||
|
|
@ -185,27 +201,18 @@ public:
|
|||
DeclsAsList = Node;
|
||||
}
|
||||
|
||||
DeclListNode::Decls Head = Data.getPointer();
|
||||
if (Head.isNull()) {
|
||||
if (!Data.getPointer()) {
|
||||
Data.setPointer(DeclsAsList);
|
||||
return;
|
||||
}
|
||||
|
||||
// Find the end of the existing list.
|
||||
// FIXME: It would be possible to preserve information from erase_if to
|
||||
// avoid this rescan looking for the end of the list.
|
||||
DeclListNode::Decls *Tail = &Head;
|
||||
while (DeclListNode *Node = Tail->dyn_cast<DeclListNode *>())
|
||||
Tail = &Node->Rest;
|
||||
|
||||
// Append the Decls.
|
||||
DeclListNode *Node = C.AllocateDeclListNode(Tail->get<NamedDecl *>());
|
||||
Node->Rest = DeclsAsList;
|
||||
*Tail = Node;
|
||||
Data.setPointer(Head);
|
||||
}
|
||||
|
||||
/// Return an array of all the decls that this list represents.
|
||||
/// Return the list of all the decls.
|
||||
DeclContext::lookup_result getLookupResult() const {
|
||||
return DeclContext::lookup_result(Data.getPointer());
|
||||
}
|
||||
|
|
|
|||
|
|
@ -112,7 +112,7 @@ public:
|
|||
Create(ASTContext &C, DeclContext *DC, SourceLocation L, FriendUnion Friend_,
|
||||
SourceLocation FriendL,
|
||||
ArrayRef<TemplateParameterList *> FriendTypeTPLists = std::nullopt);
|
||||
static FriendDecl *CreateDeserialized(ASTContext &C, unsigned ID,
|
||||
static FriendDecl *CreateDeserialized(ASTContext &C, GlobalDeclID ID,
|
||||
unsigned FriendTypeNumTPLists);
|
||||
|
||||
/// If this friend declaration names an (untemplated but possibly
|
||||
|
|
|
|||
274
contrib/llvm-project/clang/include/clang/AST/DeclID.h
Normal file
274
contrib/llvm-project/clang/include/clang/AST/DeclID.h
Normal file
|
|
@ -0,0 +1,274 @@
|
|||
//===--- DeclID.h - ID number for deserialized declarations ----*- 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 DeclID class family to describe the deserialized
|
||||
// declarations. The DeclID is widely used in AST via LazyDeclPtr, or calls to
|
||||
// `ExternalASTSource::getExternalDecl`. It will be helpful for type safety to
|
||||
// require the use of `DeclID` to explicit.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef LLVM_CLANG_AST_DECLID_H
|
||||
#define LLVM_CLANG_AST_DECLID_H
|
||||
|
||||
#include "llvm/ADT/DenseMapInfo.h"
|
||||
#include "llvm/ADT/Hashing.h"
|
||||
#include "llvm/ADT/iterator.h"
|
||||
|
||||
#include <climits>
|
||||
|
||||
namespace clang {
|
||||
|
||||
/// Predefined declaration IDs.
|
||||
///
|
||||
/// These declaration IDs correspond to predefined declarations in the AST
|
||||
/// context, such as the NULL declaration ID. Such declarations are never
|
||||
/// actually serialized, since they will be built by the AST context when
|
||||
/// it is created.
|
||||
enum PredefinedDeclIDs {
|
||||
/// The NULL declaration.
|
||||
PREDEF_DECL_NULL_ID = 0,
|
||||
|
||||
/// The translation unit.
|
||||
PREDEF_DECL_TRANSLATION_UNIT_ID = 1,
|
||||
|
||||
/// The Objective-C 'id' type.
|
||||
PREDEF_DECL_OBJC_ID_ID = 2,
|
||||
|
||||
/// The Objective-C 'SEL' type.
|
||||
PREDEF_DECL_OBJC_SEL_ID = 3,
|
||||
|
||||
/// The Objective-C 'Class' type.
|
||||
PREDEF_DECL_OBJC_CLASS_ID = 4,
|
||||
|
||||
/// The Objective-C 'Protocol' type.
|
||||
PREDEF_DECL_OBJC_PROTOCOL_ID = 5,
|
||||
|
||||
/// The signed 128-bit integer type.
|
||||
PREDEF_DECL_INT_128_ID = 6,
|
||||
|
||||
/// The unsigned 128-bit integer type.
|
||||
PREDEF_DECL_UNSIGNED_INT_128_ID = 7,
|
||||
|
||||
/// The internal 'instancetype' typedef.
|
||||
PREDEF_DECL_OBJC_INSTANCETYPE_ID = 8,
|
||||
|
||||
/// The internal '__builtin_va_list' typedef.
|
||||
PREDEF_DECL_BUILTIN_VA_LIST_ID = 9,
|
||||
|
||||
/// The internal '__va_list_tag' struct, if any.
|
||||
PREDEF_DECL_VA_LIST_TAG = 10,
|
||||
|
||||
/// The internal '__builtin_ms_va_list' typedef.
|
||||
PREDEF_DECL_BUILTIN_MS_VA_LIST_ID = 11,
|
||||
|
||||
/// The predeclared '_GUID' struct.
|
||||
PREDEF_DECL_BUILTIN_MS_GUID_ID = 12,
|
||||
|
||||
/// The extern "C" context.
|
||||
PREDEF_DECL_EXTERN_C_CONTEXT_ID = 13,
|
||||
|
||||
/// The internal '__make_integer_seq' template.
|
||||
PREDEF_DECL_MAKE_INTEGER_SEQ_ID = 14,
|
||||
|
||||
/// The internal '__NSConstantString' typedef.
|
||||
PREDEF_DECL_CF_CONSTANT_STRING_ID = 15,
|
||||
|
||||
/// The internal '__NSConstantString' tag type.
|
||||
PREDEF_DECL_CF_CONSTANT_STRING_TAG_ID = 16,
|
||||
|
||||
/// The internal '__type_pack_element' template.
|
||||
PREDEF_DECL_TYPE_PACK_ELEMENT_ID = 17,
|
||||
};
|
||||
|
||||
/// The number of declaration IDs that are predefined.
|
||||
///
|
||||
/// For more information about predefined declarations, see the
|
||||
/// \c PredefinedDeclIDs type and the PREDEF_DECL_*_ID constants.
|
||||
const unsigned int NUM_PREDEF_DECL_IDS = 18;
|
||||
|
||||
/// GlobalDeclID means DeclID in the current ASTContext and LocalDeclID means
|
||||
/// DeclID specific to a certain ModuleFile. Specially, in ASTWriter, the
|
||||
/// LocalDeclID to the ModuleFile been writting is equal to the GlobalDeclID.
|
||||
/// Outside the serializer, all the DeclID been used should be GlobalDeclID.
|
||||
/// We can translate a LocalDeclID to the GlobalDeclID by
|
||||
/// `ASTReader::getGlobalDeclID()`.
|
||||
|
||||
class DeclIDBase {
|
||||
public:
|
||||
/// An ID number that refers to a declaration in an AST file.
|
||||
///
|
||||
/// The ID numbers of declarations are consecutive (in order of
|
||||
/// discovery), with values below NUM_PREDEF_DECL_IDS being reserved.
|
||||
/// At the start of a chain of precompiled headers, declaration ID 1 is
|
||||
/// used for the translation unit declaration.
|
||||
///
|
||||
/// DeclID should only be used directly in serialization. All other users
|
||||
/// should use LocalDeclID or GlobalDeclID.
|
||||
using DeclID = uint64_t;
|
||||
|
||||
protected:
|
||||
DeclIDBase() : ID(PREDEF_DECL_NULL_ID) {}
|
||||
explicit DeclIDBase(DeclID ID) : ID(ID) {}
|
||||
|
||||
public:
|
||||
DeclID getRawValue() const { return ID; }
|
||||
|
||||
explicit operator DeclID() const { return ID; }
|
||||
|
||||
explicit operator PredefinedDeclIDs() const { return (PredefinedDeclIDs)ID; }
|
||||
|
||||
bool isValid() const { return ID != PREDEF_DECL_NULL_ID; }
|
||||
|
||||
bool isInvalid() const { return ID == PREDEF_DECL_NULL_ID; }
|
||||
|
||||
unsigned getModuleFileIndex() const { return ID >> 32; }
|
||||
|
||||
unsigned getLocalDeclIndex() const;
|
||||
|
||||
// The DeclID may be compared with predefined decl ID.
|
||||
friend bool operator==(const DeclIDBase &LHS, const DeclID &RHS) {
|
||||
return LHS.ID == RHS;
|
||||
}
|
||||
friend bool operator!=(const DeclIDBase &LHS, const DeclID &RHS) {
|
||||
return !operator==(LHS, RHS);
|
||||
}
|
||||
friend bool operator<(const DeclIDBase &LHS, const DeclID &RHS) {
|
||||
return LHS.ID < RHS;
|
||||
}
|
||||
friend bool operator<=(const DeclIDBase &LHS, const DeclID &RHS) {
|
||||
return LHS.ID <= RHS;
|
||||
}
|
||||
friend bool operator>(const DeclIDBase &LHS, const DeclID &RHS) {
|
||||
return LHS.ID > RHS;
|
||||
}
|
||||
friend bool operator>=(const DeclIDBase &LHS, const DeclID &RHS) {
|
||||
return LHS.ID >= RHS;
|
||||
}
|
||||
|
||||
friend bool operator==(const DeclIDBase &LHS, const DeclIDBase &RHS) {
|
||||
return LHS.ID == RHS.ID;
|
||||
}
|
||||
friend bool operator!=(const DeclIDBase &LHS, const DeclIDBase &RHS) {
|
||||
return LHS.ID != RHS.ID;
|
||||
}
|
||||
|
||||
// We may sort the decl ID.
|
||||
friend bool operator<(const DeclIDBase &LHS, const DeclIDBase &RHS) {
|
||||
return LHS.ID < RHS.ID;
|
||||
}
|
||||
friend bool operator>(const DeclIDBase &LHS, const DeclIDBase &RHS) {
|
||||
return LHS.ID > RHS.ID;
|
||||
}
|
||||
friend bool operator<=(const DeclIDBase &LHS, const DeclIDBase &RHS) {
|
||||
return LHS.ID <= RHS.ID;
|
||||
}
|
||||
friend bool operator>=(const DeclIDBase &LHS, const DeclIDBase &RHS) {
|
||||
return LHS.ID >= RHS.ID;
|
||||
}
|
||||
|
||||
protected:
|
||||
DeclID ID;
|
||||
};
|
||||
|
||||
class ASTWriter;
|
||||
class ASTReader;
|
||||
namespace serialization {
|
||||
class ModuleFile;
|
||||
} // namespace serialization
|
||||
|
||||
class LocalDeclID : public DeclIDBase {
|
||||
using Base = DeclIDBase;
|
||||
|
||||
LocalDeclID(PredefinedDeclIDs ID) : Base(ID) {}
|
||||
explicit LocalDeclID(DeclID ID) : Base(ID) {}
|
||||
|
||||
// Every Decl ID is a local decl ID to the module being writing in ASTWriter.
|
||||
friend class ASTWriter;
|
||||
friend class GlobalDeclID;
|
||||
|
||||
public:
|
||||
LocalDeclID() : Base() {}
|
||||
|
||||
static LocalDeclID get(ASTReader &Reader, serialization::ModuleFile &MF,
|
||||
DeclID ID);
|
||||
static LocalDeclID get(ASTReader &Reader, serialization::ModuleFile &MF,
|
||||
unsigned ModuleFileIndex, unsigned LocalDeclID);
|
||||
|
||||
LocalDeclID &operator++() {
|
||||
++ID;
|
||||
return *this;
|
||||
}
|
||||
|
||||
LocalDeclID operator++(int) {
|
||||
LocalDeclID Ret = *this;
|
||||
++(*this);
|
||||
return Ret;
|
||||
}
|
||||
};
|
||||
|
||||
class GlobalDeclID : public DeclIDBase {
|
||||
using Base = DeclIDBase;
|
||||
|
||||
public:
|
||||
GlobalDeclID() : Base() {}
|
||||
explicit GlobalDeclID(DeclID ID) : Base(ID) {}
|
||||
|
||||
explicit GlobalDeclID(unsigned ModuleFileIndex, unsigned LocalID)
|
||||
: Base((DeclID)ModuleFileIndex << 32 | (DeclID)LocalID) {}
|
||||
|
||||
// For DeclIDIterator<GlobalDeclID> to be able to convert a GlobalDeclID
|
||||
// to a LocalDeclID.
|
||||
explicit operator LocalDeclID() const { return LocalDeclID(this->ID); }
|
||||
};
|
||||
|
||||
/// A helper iterator adaptor to convert the iterators to
|
||||
/// `SmallVector<SomeDeclID>` to the iterators to `SmallVector<OtherDeclID>`.
|
||||
template <class FromTy, class ToTy>
|
||||
class DeclIDIterator
|
||||
: public llvm::iterator_adaptor_base<DeclIDIterator<FromTy, ToTy>,
|
||||
const FromTy *,
|
||||
std::forward_iterator_tag, ToTy> {
|
||||
public:
|
||||
DeclIDIterator() : DeclIDIterator::iterator_adaptor_base(nullptr) {}
|
||||
|
||||
DeclIDIterator(const FromTy *ID)
|
||||
: DeclIDIterator::iterator_adaptor_base(ID) {}
|
||||
|
||||
ToTy operator*() const { return ToTy(*this->I); }
|
||||
|
||||
bool operator==(const DeclIDIterator &RHS) const { return this->I == RHS.I; }
|
||||
};
|
||||
|
||||
} // namespace clang
|
||||
|
||||
namespace llvm {
|
||||
template <> struct DenseMapInfo<clang::GlobalDeclID> {
|
||||
using GlobalDeclID = clang::GlobalDeclID;
|
||||
using DeclID = GlobalDeclID::DeclID;
|
||||
|
||||
static GlobalDeclID getEmptyKey() {
|
||||
return GlobalDeclID(DenseMapInfo<DeclID>::getEmptyKey());
|
||||
}
|
||||
|
||||
static GlobalDeclID getTombstoneKey() {
|
||||
return GlobalDeclID(DenseMapInfo<DeclID>::getTombstoneKey());
|
||||
}
|
||||
|
||||
static unsigned getHashValue(const GlobalDeclID &Key) {
|
||||
return DenseMapInfo<DeclID>::getHashValue(Key.getRawValue());
|
||||
}
|
||||
|
||||
static bool isEqual(const GlobalDeclID &L, const GlobalDeclID &R) {
|
||||
return L == R;
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace llvm
|
||||
|
||||
#endif
|
||||
|
|
@ -236,7 +236,7 @@ public:
|
|||
ObjCImplementationControl impControl = ObjCImplementationControl::None,
|
||||
bool HasRelatedResultType = false);
|
||||
|
||||
static ObjCMethodDecl *CreateDeserialized(ASTContext &C, unsigned ID);
|
||||
static ObjCMethodDecl *CreateDeserialized(ASTContext &C, GlobalDeclID ID);
|
||||
|
||||
ObjCMethodDecl *getCanonicalDecl() override;
|
||||
const ObjCMethodDecl *getCanonicalDecl() const {
|
||||
|
|
@ -614,7 +614,8 @@ public:
|
|||
IdentifierInfo *name,
|
||||
SourceLocation colonLoc,
|
||||
TypeSourceInfo *boundInfo);
|
||||
static ObjCTypeParamDecl *CreateDeserialized(ASTContext &ctx, unsigned ID);
|
||||
static ObjCTypeParamDecl *CreateDeserialized(ASTContext &ctx,
|
||||
GlobalDeclID ID);
|
||||
|
||||
SourceRange getSourceRange() const override LLVM_READONLY;
|
||||
|
||||
|
|
@ -772,7 +773,7 @@ private:
|
|||
// Synthesize ivar for this property
|
||||
ObjCIvarDecl *PropertyIvarDecl = nullptr;
|
||||
|
||||
ObjCPropertyDecl(DeclContext *DC, SourceLocation L, IdentifierInfo *Id,
|
||||
ObjCPropertyDecl(DeclContext *DC, SourceLocation L, const IdentifierInfo *Id,
|
||||
SourceLocation AtLocation, SourceLocation LParenLocation,
|
||||
QualType T, TypeSourceInfo *TSI, PropertyControl propControl)
|
||||
: NamedDecl(ObjCProperty, DC, L, Id), AtLoc(AtLocation),
|
||||
|
|
@ -782,12 +783,14 @@ private:
|
|||
PropertyImplementation(propControl) {}
|
||||
|
||||
public:
|
||||
static ObjCPropertyDecl *
|
||||
Create(ASTContext &C, DeclContext *DC, SourceLocation L, IdentifierInfo *Id,
|
||||
SourceLocation AtLocation, SourceLocation LParenLocation, QualType T,
|
||||
TypeSourceInfo *TSI, PropertyControl propControl = None);
|
||||
static ObjCPropertyDecl *Create(ASTContext &C, DeclContext *DC,
|
||||
SourceLocation L, const IdentifierInfo *Id,
|
||||
SourceLocation AtLocation,
|
||||
SourceLocation LParenLocation, QualType T,
|
||||
TypeSourceInfo *TSI,
|
||||
PropertyControl propControl = None);
|
||||
|
||||
static ObjCPropertyDecl *CreateDeserialized(ASTContext &C, unsigned ID);
|
||||
static ObjCPropertyDecl *CreateDeserialized(ASTContext &C, GlobalDeclID ID);
|
||||
|
||||
SourceLocation getAtLoc() const { return AtLoc; }
|
||||
void setAtLoc(SourceLocation L) { AtLoc = L; }
|
||||
|
|
@ -952,7 +955,7 @@ class ObjCContainerDecl : public NamedDecl, public DeclContext {
|
|||
void anchor() override;
|
||||
|
||||
public:
|
||||
ObjCContainerDecl(Kind DK, DeclContext *DC, IdentifierInfo *Id,
|
||||
ObjCContainerDecl(Kind DK, DeclContext *DC, const IdentifierInfo *Id,
|
||||
SourceLocation nameLoc, SourceLocation atStartLoc);
|
||||
|
||||
// Iterator access to instance/class properties.
|
||||
|
|
@ -1240,7 +1243,7 @@ class ObjCInterfaceDecl : public ObjCContainerDecl
|
|||
llvm::PointerIntPair<DefinitionData *, 1, bool> Data;
|
||||
|
||||
ObjCInterfaceDecl(const ASTContext &C, DeclContext *DC, SourceLocation AtLoc,
|
||||
IdentifierInfo *Id, ObjCTypeParamList *typeParamList,
|
||||
const IdentifierInfo *Id, ObjCTypeParamList *typeParamList,
|
||||
SourceLocation CLoc, ObjCInterfaceDecl *PrevDecl,
|
||||
bool IsInternal);
|
||||
|
||||
|
|
@ -1271,15 +1274,14 @@ class ObjCInterfaceDecl : public ObjCContainerDecl
|
|||
}
|
||||
|
||||
public:
|
||||
static ObjCInterfaceDecl *Create(const ASTContext &C, DeclContext *DC,
|
||||
SourceLocation atLoc,
|
||||
IdentifierInfo *Id,
|
||||
ObjCTypeParamList *typeParamList,
|
||||
ObjCInterfaceDecl *PrevDecl,
|
||||
SourceLocation ClassLoc = SourceLocation(),
|
||||
bool isInternal = false);
|
||||
static ObjCInterfaceDecl *
|
||||
Create(const ASTContext &C, DeclContext *DC, SourceLocation atLoc,
|
||||
const IdentifierInfo *Id, ObjCTypeParamList *typeParamList,
|
||||
ObjCInterfaceDecl *PrevDecl,
|
||||
SourceLocation ClassLoc = SourceLocation(), bool isInternal = false);
|
||||
|
||||
static ObjCInterfaceDecl *CreateDeserialized(const ASTContext &C, unsigned ID);
|
||||
static ObjCInterfaceDecl *CreateDeserialized(const ASTContext &C,
|
||||
GlobalDeclID ID);
|
||||
|
||||
/// Retrieve the type parameters of this class.
|
||||
///
|
||||
|
|
@ -1338,7 +1340,8 @@ public:
|
|||
ObjCImplementationDecl *getImplementation() const;
|
||||
void setImplementation(ObjCImplementationDecl *ImplD);
|
||||
|
||||
ObjCCategoryDecl *FindCategoryDeclaration(IdentifierInfo *CategoryId) const;
|
||||
ObjCCategoryDecl *
|
||||
FindCategoryDeclaration(const IdentifierInfo *CategoryId) const;
|
||||
|
||||
// Get the local instance/class method declared in a category.
|
||||
ObjCMethodDecl *getCategoryInstanceMethod(Selector Sel) const;
|
||||
|
|
@ -1794,9 +1797,9 @@ public:
|
|||
data().CategoryList = category;
|
||||
}
|
||||
|
||||
ObjCPropertyDecl
|
||||
*FindPropertyVisibleInPrimaryClass(IdentifierInfo *PropertyId,
|
||||
ObjCPropertyQueryKind QueryKind) const;
|
||||
ObjCPropertyDecl *
|
||||
FindPropertyVisibleInPrimaryClass(const IdentifierInfo *PropertyId,
|
||||
ObjCPropertyQueryKind QueryKind) const;
|
||||
|
||||
void collectPropertiesToImplement(PropertyMap &PM) const override;
|
||||
|
||||
|
|
@ -1954,8 +1957,8 @@ public:
|
|||
|
||||
private:
|
||||
ObjCIvarDecl(ObjCContainerDecl *DC, SourceLocation StartLoc,
|
||||
SourceLocation IdLoc, IdentifierInfo *Id,
|
||||
QualType T, TypeSourceInfo *TInfo, AccessControl ac, Expr *BW,
|
||||
SourceLocation IdLoc, const IdentifierInfo *Id, QualType T,
|
||||
TypeSourceInfo *TInfo, AccessControl ac, Expr *BW,
|
||||
bool synthesized)
|
||||
: FieldDecl(ObjCIvar, DC, StartLoc, IdLoc, Id, T, TInfo, BW,
|
||||
/*Mutable=*/false, /*HasInit=*/ICIS_NoInit),
|
||||
|
|
@ -1964,12 +1967,11 @@ private:
|
|||
public:
|
||||
static ObjCIvarDecl *Create(ASTContext &C, ObjCContainerDecl *DC,
|
||||
SourceLocation StartLoc, SourceLocation IdLoc,
|
||||
IdentifierInfo *Id, QualType T,
|
||||
TypeSourceInfo *TInfo,
|
||||
AccessControl ac, Expr *BW = nullptr,
|
||||
bool synthesized=false);
|
||||
const IdentifierInfo *Id, QualType T,
|
||||
TypeSourceInfo *TInfo, AccessControl ac,
|
||||
Expr *BW = nullptr, bool synthesized = false);
|
||||
|
||||
static ObjCIvarDecl *CreateDeserialized(ASTContext &C, unsigned ID);
|
||||
static ObjCIvarDecl *CreateDeserialized(ASTContext &C, GlobalDeclID ID);
|
||||
|
||||
/// Return the class interface that this ivar is logically contained
|
||||
/// in; this is either the interface where the ivar was declared, or the
|
||||
|
|
@ -2039,7 +2041,8 @@ public:
|
|||
SourceLocation IdLoc, IdentifierInfo *Id,
|
||||
QualType T, Expr *BW);
|
||||
|
||||
static ObjCAtDefsFieldDecl *CreateDeserialized(ASTContext &C, unsigned ID);
|
||||
static ObjCAtDefsFieldDecl *CreateDeserialized(ASTContext &C,
|
||||
GlobalDeclID ID);
|
||||
|
||||
// Implement isa/cast/dyncast/etc.
|
||||
static bool classof(const Decl *D) { return classofKind(D->getKind()); }
|
||||
|
|
@ -2142,7 +2145,7 @@ public:
|
|||
SourceLocation atStartLoc,
|
||||
ObjCProtocolDecl *PrevDecl);
|
||||
|
||||
static ObjCProtocolDecl *CreateDeserialized(ASTContext &C, unsigned ID);
|
||||
static ObjCProtocolDecl *CreateDeserialized(ASTContext &C, GlobalDeclID ID);
|
||||
|
||||
const ObjCProtocolList &getReferencedProtocols() const {
|
||||
assert(hasDefinition() && "No definition available!");
|
||||
|
|
@ -2343,7 +2346,7 @@ class ObjCCategoryDecl : public ObjCContainerDecl {
|
|||
|
||||
ObjCCategoryDecl(DeclContext *DC, SourceLocation AtLoc,
|
||||
SourceLocation ClassNameLoc, SourceLocation CategoryNameLoc,
|
||||
IdentifierInfo *Id, ObjCInterfaceDecl *IDecl,
|
||||
const IdentifierInfo *Id, ObjCInterfaceDecl *IDecl,
|
||||
ObjCTypeParamList *typeParamList,
|
||||
SourceLocation IvarLBraceLoc = SourceLocation(),
|
||||
SourceLocation IvarRBraceLoc = SourceLocation());
|
||||
|
|
@ -2354,16 +2357,14 @@ public:
|
|||
friend class ASTDeclReader;
|
||||
friend class ASTDeclWriter;
|
||||
|
||||
static ObjCCategoryDecl *Create(ASTContext &C, DeclContext *DC,
|
||||
SourceLocation AtLoc,
|
||||
SourceLocation ClassNameLoc,
|
||||
SourceLocation CategoryNameLoc,
|
||||
IdentifierInfo *Id,
|
||||
ObjCInterfaceDecl *IDecl,
|
||||
ObjCTypeParamList *typeParamList,
|
||||
SourceLocation IvarLBraceLoc=SourceLocation(),
|
||||
SourceLocation IvarRBraceLoc=SourceLocation());
|
||||
static ObjCCategoryDecl *CreateDeserialized(ASTContext &C, unsigned ID);
|
||||
static ObjCCategoryDecl *
|
||||
Create(ASTContext &C, DeclContext *DC, SourceLocation AtLoc,
|
||||
SourceLocation ClassNameLoc, SourceLocation CategoryNameLoc,
|
||||
const IdentifierInfo *Id, ObjCInterfaceDecl *IDecl,
|
||||
ObjCTypeParamList *typeParamList,
|
||||
SourceLocation IvarLBraceLoc = SourceLocation(),
|
||||
SourceLocation IvarRBraceLoc = SourceLocation());
|
||||
static ObjCCategoryDecl *CreateDeserialized(ASTContext &C, GlobalDeclID ID);
|
||||
|
||||
ObjCInterfaceDecl *getClassInterface() { return ClassInterface; }
|
||||
const ObjCInterfaceDecl *getClassInterface() const { return ClassInterface; }
|
||||
|
|
@ -2472,10 +2473,9 @@ class ObjCImplDecl : public ObjCContainerDecl {
|
|||
void anchor() override;
|
||||
|
||||
protected:
|
||||
ObjCImplDecl(Kind DK, DeclContext *DC,
|
||||
ObjCInterfaceDecl *classInterface,
|
||||
IdentifierInfo *Id,
|
||||
SourceLocation nameLoc, SourceLocation atStartLoc)
|
||||
ObjCImplDecl(Kind DK, DeclContext *DC, ObjCInterfaceDecl *classInterface,
|
||||
const IdentifierInfo *Id, SourceLocation nameLoc,
|
||||
SourceLocation atStartLoc)
|
||||
: ObjCContainerDecl(DK, DC, Id, nameLoc, atStartLoc),
|
||||
ClassInterface(classInterface) {}
|
||||
|
||||
|
|
@ -2543,12 +2543,12 @@ class ObjCCategoryImplDecl : public ObjCImplDecl {
|
|||
// Category name location
|
||||
SourceLocation CategoryNameLoc;
|
||||
|
||||
ObjCCategoryImplDecl(DeclContext *DC, IdentifierInfo *Id,
|
||||
ObjCCategoryImplDecl(DeclContext *DC, const IdentifierInfo *Id,
|
||||
ObjCInterfaceDecl *classInterface,
|
||||
SourceLocation nameLoc, SourceLocation atStartLoc,
|
||||
SourceLocation CategoryNameLoc)
|
||||
: ObjCImplDecl(ObjCCategoryImpl, DC, classInterface, Id,
|
||||
nameLoc, atStartLoc),
|
||||
: ObjCImplDecl(ObjCCategoryImpl, DC, classInterface, Id, nameLoc,
|
||||
atStartLoc),
|
||||
CategoryNameLoc(CategoryNameLoc) {}
|
||||
|
||||
void anchor() override;
|
||||
|
|
@ -2557,13 +2557,12 @@ public:
|
|||
friend class ASTDeclReader;
|
||||
friend class ASTDeclWriter;
|
||||
|
||||
static ObjCCategoryImplDecl *Create(ASTContext &C, DeclContext *DC,
|
||||
IdentifierInfo *Id,
|
||||
ObjCInterfaceDecl *classInterface,
|
||||
SourceLocation nameLoc,
|
||||
SourceLocation atStartLoc,
|
||||
SourceLocation CategoryNameLoc);
|
||||
static ObjCCategoryImplDecl *CreateDeserialized(ASTContext &C, unsigned ID);
|
||||
static ObjCCategoryImplDecl *
|
||||
Create(ASTContext &C, DeclContext *DC, const IdentifierInfo *Id,
|
||||
ObjCInterfaceDecl *classInterface, SourceLocation nameLoc,
|
||||
SourceLocation atStartLoc, SourceLocation CategoryNameLoc);
|
||||
static ObjCCategoryImplDecl *CreateDeserialized(ASTContext &C,
|
||||
GlobalDeclID ID);
|
||||
|
||||
ObjCCategoryDecl *getCategoryDecl() const;
|
||||
|
||||
|
|
@ -2645,7 +2644,8 @@ public:
|
|||
SourceLocation IvarLBraceLoc=SourceLocation(),
|
||||
SourceLocation IvarRBraceLoc=SourceLocation());
|
||||
|
||||
static ObjCImplementationDecl *CreateDeserialized(ASTContext &C, unsigned ID);
|
||||
static ObjCImplementationDecl *CreateDeserialized(ASTContext &C,
|
||||
GlobalDeclID ID);
|
||||
|
||||
/// init_iterator - Iterates through the ivar initializer list.
|
||||
using init_iterator = CXXCtorInitializer **;
|
||||
|
|
@ -2785,7 +2785,7 @@ public:
|
|||
ObjCInterfaceDecl* aliasedClass);
|
||||
|
||||
static ObjCCompatibleAliasDecl *CreateDeserialized(ASTContext &C,
|
||||
unsigned ID);
|
||||
GlobalDeclID ID);
|
||||
|
||||
const ObjCInterfaceDecl *getClassInterface() const { return AliasedClass; }
|
||||
ObjCInterfaceDecl *getClassInterface() { return AliasedClass; }
|
||||
|
|
@ -2856,7 +2856,8 @@ public:
|
|||
ObjCIvarDecl *ivarDecl,
|
||||
SourceLocation ivarLoc);
|
||||
|
||||
static ObjCPropertyImplDecl *CreateDeserialized(ASTContext &C, unsigned ID);
|
||||
static ObjCPropertyImplDecl *CreateDeserialized(ASTContext &C,
|
||||
GlobalDeclID ID);
|
||||
|
||||
SourceRange getSourceRange() const override LLVM_READONLY;
|
||||
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
//===- DeclOpenMP.h - Classes for representing OpenMP directives -*- C++ -*-===//
|
||||
//===- DeclOpenMP.h - Classes for representing OpenMP directives -*- C++ -*-==//
|
||||
//
|
||||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
||||
// See https://llvm.org/LICENSE.txt for license information.
|
||||
|
|
@ -59,7 +59,7 @@ protected:
|
|||
}
|
||||
|
||||
template <typename T, typename... Params>
|
||||
static T *createEmptyDirective(const ASTContext &C, unsigned ID,
|
||||
static T *createEmptyDirective(const ASTContext &C, GlobalDeclID ID,
|
||||
unsigned NumClauses, unsigned NumChildren,
|
||||
Params &&... P) {
|
||||
auto *Inst = new (C, ID, size(NumClauses, NumChildren))
|
||||
|
|
@ -133,7 +133,7 @@ public:
|
|||
SourceLocation L,
|
||||
ArrayRef<Expr *> VL);
|
||||
static OMPThreadPrivateDecl *CreateDeserialized(ASTContext &C,
|
||||
unsigned ID, unsigned N);
|
||||
GlobalDeclID ID, unsigned N);
|
||||
|
||||
typedef MutableArrayRef<Expr *>::iterator varlist_iterator;
|
||||
typedef ArrayRef<const Expr *>::iterator varlist_const_iterator;
|
||||
|
|
@ -214,7 +214,7 @@ public:
|
|||
QualType T, OMPDeclareReductionDecl *PrevDeclInScope);
|
||||
/// Create deserialized declare reduction node.
|
||||
static OMPDeclareReductionDecl *CreateDeserialized(ASTContext &C,
|
||||
unsigned ID);
|
||||
GlobalDeclID ID);
|
||||
|
||||
/// Get combiner expression of the declare reduction construct.
|
||||
Expr *getCombiner() { return Combiner; }
|
||||
|
|
@ -318,8 +318,8 @@ public:
|
|||
ArrayRef<OMPClause *> Clauses,
|
||||
OMPDeclareMapperDecl *PrevDeclInScope);
|
||||
/// Creates deserialized declare mapper node.
|
||||
static OMPDeclareMapperDecl *CreateDeserialized(ASTContext &C, unsigned ID,
|
||||
unsigned N);
|
||||
static OMPDeclareMapperDecl *CreateDeserialized(ASTContext &C,
|
||||
GlobalDeclID ID, unsigned N);
|
||||
|
||||
using clauselist_iterator = MutableArrayRef<OMPClause *>::iterator;
|
||||
using clauselist_const_iterator = ArrayRef<const OMPClause *>::iterator;
|
||||
|
|
@ -397,7 +397,8 @@ public:
|
|||
IdentifierInfo *Id, QualType T,
|
||||
SourceLocation StartLoc);
|
||||
|
||||
static OMPCapturedExprDecl *CreateDeserialized(ASTContext &C, unsigned ID);
|
||||
static OMPCapturedExprDecl *CreateDeserialized(ASTContext &C,
|
||||
GlobalDeclID ID);
|
||||
|
||||
SourceRange getSourceRange() const override LLVM_READONLY;
|
||||
|
||||
|
|
@ -427,7 +428,7 @@ public:
|
|||
static OMPRequiresDecl *Create(ASTContext &C, DeclContext *DC,
|
||||
SourceLocation L, ArrayRef<OMPClause *> CL);
|
||||
/// Create deserialized requires node.
|
||||
static OMPRequiresDecl *CreateDeserialized(ASTContext &C, unsigned ID,
|
||||
static OMPRequiresDecl *CreateDeserialized(ASTContext &C, GlobalDeclID ID,
|
||||
unsigned N);
|
||||
|
||||
using clauselist_iterator = MutableArrayRef<OMPClause *>::iterator;
|
||||
|
|
@ -495,7 +496,7 @@ public:
|
|||
static OMPAllocateDecl *Create(ASTContext &C, DeclContext *DC,
|
||||
SourceLocation L, ArrayRef<Expr *> VL,
|
||||
ArrayRef<OMPClause *> CL);
|
||||
static OMPAllocateDecl *CreateDeserialized(ASTContext &C, unsigned ID,
|
||||
static OMPAllocateDecl *CreateDeserialized(ASTContext &C, GlobalDeclID ID,
|
||||
unsigned NVars, unsigned NClauses);
|
||||
|
||||
typedef MutableArrayRef<Expr *>::iterator varlist_iterator;
|
||||
|
|
|
|||
|
|
@ -134,6 +134,7 @@ public:
|
|||
const_iterator end() const { return begin() + NumParams; }
|
||||
|
||||
unsigned size() const { return NumParams; }
|
||||
bool empty() const { return NumParams == 0; }
|
||||
|
||||
ArrayRef<NamedDecl *> asArray() { return llvm::ArrayRef(begin(), end()); }
|
||||
ArrayRef<const NamedDecl*> asArray() const {
|
||||
|
|
@ -241,9 +242,6 @@ public:
|
|||
/// A template argument list.
|
||||
class TemplateArgumentList final
|
||||
: private llvm::TrailingObjects<TemplateArgumentList, TemplateArgument> {
|
||||
/// The template argument list.
|
||||
const TemplateArgument *Arguments;
|
||||
|
||||
/// The number of template arguments in this template
|
||||
/// argument list.
|
||||
unsigned NumArguments;
|
||||
|
|
@ -258,30 +256,11 @@ public:
|
|||
TemplateArgumentList(const TemplateArgumentList &) = delete;
|
||||
TemplateArgumentList &operator=(const TemplateArgumentList &) = delete;
|
||||
|
||||
/// Type used to indicate that the template argument list itself is a
|
||||
/// stack object. It does not own its template arguments.
|
||||
enum OnStackType { OnStack };
|
||||
|
||||
/// Create a new template argument list that copies the given set of
|
||||
/// template arguments.
|
||||
static TemplateArgumentList *CreateCopy(ASTContext &Context,
|
||||
ArrayRef<TemplateArgument> Args);
|
||||
|
||||
/// Construct a new, temporary template argument list on the stack.
|
||||
///
|
||||
/// The template argument list does not own the template arguments
|
||||
/// provided.
|
||||
explicit TemplateArgumentList(OnStackType, ArrayRef<TemplateArgument> Args)
|
||||
: Arguments(Args.data()), NumArguments(Args.size()) {}
|
||||
|
||||
/// Produces a shallow copy of the given template argument list.
|
||||
///
|
||||
/// This operation assumes that the input argument list outlives it.
|
||||
/// This takes the list as a pointer to avoid looking like a copy
|
||||
/// constructor, since this really isn't safe to use that way.
|
||||
explicit TemplateArgumentList(const TemplateArgumentList *Other)
|
||||
: Arguments(Other->data()), NumArguments(Other->size()) {}
|
||||
|
||||
/// Retrieve the template argument at a given index.
|
||||
const TemplateArgument &get(unsigned Idx) const {
|
||||
assert(Idx < NumArguments && "Invalid template argument index");
|
||||
|
|
@ -301,7 +280,9 @@ public:
|
|||
unsigned size() const { return NumArguments; }
|
||||
|
||||
/// Retrieve a pointer to the template argument list.
|
||||
const TemplateArgument *data() const { return Arguments; }
|
||||
const TemplateArgument *data() const {
|
||||
return getTrailingObjects<TemplateArgument>();
|
||||
}
|
||||
};
|
||||
|
||||
void *allocateDefaultArgStorageChain(const ASTContext &C);
|
||||
|
|
@ -497,7 +478,7 @@ class FunctionTemplateSpecializationInfo final
|
|||
public:
|
||||
/// The template arguments used to produce the function template
|
||||
/// specialization from the function template.
|
||||
const TemplateArgumentList *TemplateArguments;
|
||||
TemplateArgumentList *TemplateArguments;
|
||||
|
||||
/// The template arguments as written in the sources, if provided.
|
||||
/// FIXME: Normally null; tail-allocate this.
|
||||
|
|
@ -510,7 +491,7 @@ public:
|
|||
private:
|
||||
FunctionTemplateSpecializationInfo(
|
||||
FunctionDecl *FD, FunctionTemplateDecl *Template,
|
||||
TemplateSpecializationKind TSK, const TemplateArgumentList *TemplateArgs,
|
||||
TemplateSpecializationKind TSK, TemplateArgumentList *TemplateArgs,
|
||||
const ASTTemplateArgumentListInfo *TemplateArgsAsWritten,
|
||||
SourceLocation POI, MemberSpecializationInfo *MSInfo)
|
||||
: Function(FD, MSInfo ? true : false), Template(Template, TSK - 1),
|
||||
|
|
@ -530,8 +511,7 @@ public:
|
|||
|
||||
static FunctionTemplateSpecializationInfo *
|
||||
Create(ASTContext &C, FunctionDecl *FD, FunctionTemplateDecl *Template,
|
||||
TemplateSpecializationKind TSK,
|
||||
const TemplateArgumentList *TemplateArgs,
|
||||
TemplateSpecializationKind TSK, TemplateArgumentList *TemplateArgs,
|
||||
const TemplateArgumentListInfo *TemplateArgsAsWritten,
|
||||
SourceLocation POI, MemberSpecializationInfo *MSInfo);
|
||||
|
||||
|
|
@ -816,7 +796,7 @@ protected:
|
|||
///
|
||||
/// The first value in the array is the number of specializations/partial
|
||||
/// specializations that follow.
|
||||
uint32_t *LazySpecializations = nullptr;
|
||||
GlobalDeclID *LazySpecializations = nullptr;
|
||||
|
||||
/// The set of "injected" template arguments used within this
|
||||
/// template.
|
||||
|
|
@ -1106,7 +1086,8 @@ public:
|
|||
NamedDecl *Decl);
|
||||
|
||||
/// Create an empty function template node.
|
||||
static FunctionTemplateDecl *CreateDeserialized(ASTContext &C, unsigned ID);
|
||||
static FunctionTemplateDecl *CreateDeserialized(ASTContext &C,
|
||||
GlobalDeclID ID);
|
||||
|
||||
// Implement isa/cast/dyncast support
|
||||
static bool classof(const Decl *D) { return classofKind(D->getKind()); }
|
||||
|
|
@ -1204,7 +1185,7 @@ class TemplateTypeParmDecl final : public TypeDecl,
|
|||
|
||||
/// The default template argument, if any.
|
||||
using DefArgStorage =
|
||||
DefaultArgStorage<TemplateTypeParmDecl, TypeSourceInfo *>;
|
||||
DefaultArgStorage<TemplateTypeParmDecl, TemplateArgumentLoc *>;
|
||||
DefArgStorage DefaultArgument;
|
||||
|
||||
TemplateTypeParmDecl(DeclContext *DC, SourceLocation KeyLoc,
|
||||
|
|
@ -1223,9 +1204,9 @@ public:
|
|||
bool Typename, bool ParameterPack, bool HasTypeConstraint = false,
|
||||
std::optional<unsigned> NumExpanded = std::nullopt);
|
||||
static TemplateTypeParmDecl *CreateDeserialized(const ASTContext &C,
|
||||
unsigned ID);
|
||||
GlobalDeclID ID);
|
||||
static TemplateTypeParmDecl *CreateDeserialized(const ASTContext &C,
|
||||
unsigned ID,
|
||||
GlobalDeclID ID,
|
||||
bool HasTypeConstraint);
|
||||
|
||||
/// Whether this template type parameter was declared with
|
||||
|
|
@ -1244,13 +1225,9 @@ public:
|
|||
bool hasDefaultArgument() const { return DefaultArgument.isSet(); }
|
||||
|
||||
/// Retrieve the default argument, if any.
|
||||
QualType getDefaultArgument() const {
|
||||
return DefaultArgument.get()->getType();
|
||||
}
|
||||
|
||||
/// Retrieves the default argument's source information, if any.
|
||||
TypeSourceInfo *getDefaultArgumentInfo() const {
|
||||
return DefaultArgument.get();
|
||||
const TemplateArgumentLoc &getDefaultArgument() const {
|
||||
static const TemplateArgumentLoc NoneLoc;
|
||||
return DefaultArgument.isSet() ? *DefaultArgument.get() : NoneLoc;
|
||||
}
|
||||
|
||||
/// Retrieves the location of the default argument declaration.
|
||||
|
|
@ -1263,9 +1240,8 @@ public:
|
|||
}
|
||||
|
||||
/// Set the default argument for this template parameter.
|
||||
void setDefaultArgument(TypeSourceInfo *DefArg) {
|
||||
DefaultArgument.set(DefArg);
|
||||
}
|
||||
void setDefaultArgument(const ASTContext &C,
|
||||
const TemplateArgumentLoc &DefArg);
|
||||
|
||||
/// Set that this default argument was inherited from another
|
||||
/// parameter.
|
||||
|
|
@ -1384,7 +1360,8 @@ class NonTypeTemplateParmDecl final
|
|||
|
||||
/// The default template argument, if any, and whether or not
|
||||
/// it was inherited.
|
||||
using DefArgStorage = DefaultArgStorage<NonTypeTemplateParmDecl, Expr *>;
|
||||
using DefArgStorage =
|
||||
DefaultArgStorage<NonTypeTemplateParmDecl, TemplateArgumentLoc *>;
|
||||
DefArgStorage DefaultArgument;
|
||||
|
||||
// FIXME: Collapse this into TemplateParamPosition; or, just move depth/index
|
||||
|
|
@ -1408,14 +1385,14 @@ class NonTypeTemplateParmDecl final
|
|||
|
||||
NonTypeTemplateParmDecl(DeclContext *DC, SourceLocation StartLoc,
|
||||
SourceLocation IdLoc, unsigned D, unsigned P,
|
||||
IdentifierInfo *Id, QualType T,
|
||||
const IdentifierInfo *Id, QualType T,
|
||||
bool ParameterPack, TypeSourceInfo *TInfo)
|
||||
: DeclaratorDecl(NonTypeTemplateParm, DC, IdLoc, Id, T, TInfo, StartLoc),
|
||||
TemplateParmPosition(D, P), ParameterPack(ParameterPack) {}
|
||||
|
||||
NonTypeTemplateParmDecl(DeclContext *DC, SourceLocation StartLoc,
|
||||
SourceLocation IdLoc, unsigned D, unsigned P,
|
||||
IdentifierInfo *Id, QualType T,
|
||||
const IdentifierInfo *Id, QualType T,
|
||||
TypeSourceInfo *TInfo,
|
||||
ArrayRef<QualType> ExpandedTypes,
|
||||
ArrayRef<TypeSourceInfo *> ExpandedTInfos);
|
||||
|
|
@ -1423,20 +1400,19 @@ class NonTypeTemplateParmDecl final
|
|||
public:
|
||||
static NonTypeTemplateParmDecl *
|
||||
Create(const ASTContext &C, DeclContext *DC, SourceLocation StartLoc,
|
||||
SourceLocation IdLoc, unsigned D, unsigned P, IdentifierInfo *Id,
|
||||
SourceLocation IdLoc, unsigned D, unsigned P, const IdentifierInfo *Id,
|
||||
QualType T, bool ParameterPack, TypeSourceInfo *TInfo);
|
||||
|
||||
static NonTypeTemplateParmDecl *
|
||||
Create(const ASTContext &C, DeclContext *DC, SourceLocation StartLoc,
|
||||
SourceLocation IdLoc, unsigned D, unsigned P, IdentifierInfo *Id,
|
||||
SourceLocation IdLoc, unsigned D, unsigned P, const IdentifierInfo *Id,
|
||||
QualType T, TypeSourceInfo *TInfo, ArrayRef<QualType> ExpandedTypes,
|
||||
ArrayRef<TypeSourceInfo *> ExpandedTInfos);
|
||||
|
||||
static NonTypeTemplateParmDecl *
|
||||
CreateDeserialized(ASTContext &C, GlobalDeclID ID, bool HasTypeConstraint);
|
||||
static NonTypeTemplateParmDecl *CreateDeserialized(ASTContext &C,
|
||||
unsigned ID,
|
||||
bool HasTypeConstraint);
|
||||
static NonTypeTemplateParmDecl *CreateDeserialized(ASTContext &C,
|
||||
unsigned ID,
|
||||
GlobalDeclID ID,
|
||||
unsigned NumExpandedTypes,
|
||||
bool HasTypeConstraint);
|
||||
|
||||
|
|
@ -1455,7 +1431,10 @@ public:
|
|||
bool hasDefaultArgument() const { return DefaultArgument.isSet(); }
|
||||
|
||||
/// Retrieve the default argument, if any.
|
||||
Expr *getDefaultArgument() const { return DefaultArgument.get(); }
|
||||
const TemplateArgumentLoc &getDefaultArgument() const {
|
||||
static const TemplateArgumentLoc NoneLoc;
|
||||
return DefaultArgument.isSet() ? *DefaultArgument.get() : NoneLoc;
|
||||
}
|
||||
|
||||
/// Retrieve the location of the default argument, if any.
|
||||
SourceLocation getDefaultArgumentLoc() const;
|
||||
|
|
@ -1469,7 +1448,8 @@ public:
|
|||
/// Set the default argument for this template parameter, and
|
||||
/// whether that default argument was inherited from another
|
||||
/// declaration.
|
||||
void setDefaultArgument(Expr *DefArg) { DefaultArgument.set(DefArg); }
|
||||
void setDefaultArgument(const ASTContext &C,
|
||||
const TemplateArgumentLoc &DefArg);
|
||||
void setInheritedDefaultArgument(const ASTContext &C,
|
||||
NonTypeTemplateParmDecl *Parm) {
|
||||
DefaultArgument.setInherited(C, Parm);
|
||||
|
|
@ -1600,26 +1580,36 @@ class TemplateTemplateParmDecl final
|
|||
DefaultArgStorage<TemplateTemplateParmDecl, TemplateArgumentLoc *>;
|
||||
DefArgStorage DefaultArgument;
|
||||
|
||||
/// Whether this template template parameter was declaration with
|
||||
/// the 'typename' keyword.
|
||||
///
|
||||
/// If false, it was declared with the 'class' keyword.
|
||||
LLVM_PREFERRED_TYPE(bool)
|
||||
unsigned Typename : 1;
|
||||
|
||||
/// Whether this parameter is a parameter pack.
|
||||
bool ParameterPack;
|
||||
LLVM_PREFERRED_TYPE(bool)
|
||||
unsigned ParameterPack : 1;
|
||||
|
||||
/// Whether this template template parameter is an "expanded"
|
||||
/// parameter pack, meaning that it is a pack expansion and we
|
||||
/// already know the set of template parameters that expansion expands to.
|
||||
bool ExpandedParameterPack = false;
|
||||
LLVM_PREFERRED_TYPE(bool)
|
||||
unsigned ExpandedParameterPack : 1;
|
||||
|
||||
/// The number of parameters in an expanded parameter pack.
|
||||
unsigned NumExpandedParams = 0;
|
||||
|
||||
TemplateTemplateParmDecl(DeclContext *DC, SourceLocation L,
|
||||
unsigned D, unsigned P, bool ParameterPack,
|
||||
IdentifierInfo *Id, TemplateParameterList *Params)
|
||||
TemplateTemplateParmDecl(DeclContext *DC, SourceLocation L, unsigned D,
|
||||
unsigned P, bool ParameterPack, IdentifierInfo *Id,
|
||||
bool Typename, TemplateParameterList *Params)
|
||||
: TemplateDecl(TemplateTemplateParm, DC, L, Id, Params),
|
||||
TemplateParmPosition(D, P), ParameterPack(ParameterPack) {}
|
||||
TemplateParmPosition(D, P), Typename(Typename),
|
||||
ParameterPack(ParameterPack), ExpandedParameterPack(false) {}
|
||||
|
||||
TemplateTemplateParmDecl(DeclContext *DC, SourceLocation L,
|
||||
unsigned D, unsigned P,
|
||||
IdentifierInfo *Id, TemplateParameterList *Params,
|
||||
TemplateTemplateParmDecl(DeclContext *DC, SourceLocation L, unsigned D,
|
||||
unsigned P, IdentifierInfo *Id, bool Typename,
|
||||
TemplateParameterList *Params,
|
||||
ArrayRef<TemplateParameterList *> Expansions);
|
||||
|
||||
void anchor() override;
|
||||
|
|
@ -1632,20 +1622,18 @@ public:
|
|||
static TemplateTemplateParmDecl *Create(const ASTContext &C, DeclContext *DC,
|
||||
SourceLocation L, unsigned D,
|
||||
unsigned P, bool ParameterPack,
|
||||
IdentifierInfo *Id,
|
||||
IdentifierInfo *Id, bool Typename,
|
||||
TemplateParameterList *Params);
|
||||
static TemplateTemplateParmDecl *Create(const ASTContext &C, DeclContext *DC,
|
||||
SourceLocation L, unsigned D,
|
||||
unsigned P,
|
||||
IdentifierInfo *Id,
|
||||
TemplateParameterList *Params,
|
||||
ArrayRef<TemplateParameterList *> Expansions);
|
||||
static TemplateTemplateParmDecl *
|
||||
Create(const ASTContext &C, DeclContext *DC, SourceLocation L, unsigned D,
|
||||
unsigned P, IdentifierInfo *Id, bool Typename,
|
||||
TemplateParameterList *Params,
|
||||
ArrayRef<TemplateParameterList *> Expansions);
|
||||
|
||||
static TemplateTemplateParmDecl *CreateDeserialized(ASTContext &C,
|
||||
unsigned ID);
|
||||
static TemplateTemplateParmDecl *CreateDeserialized(ASTContext &C,
|
||||
unsigned ID,
|
||||
unsigned NumExpansions);
|
||||
GlobalDeclID ID);
|
||||
static TemplateTemplateParmDecl *
|
||||
CreateDeserialized(ASTContext &C, GlobalDeclID ID, unsigned NumExpansions);
|
||||
|
||||
using TemplateParmPosition::getDepth;
|
||||
using TemplateParmPosition::setDepth;
|
||||
|
|
@ -1653,6 +1641,14 @@ public:
|
|||
using TemplateParmPosition::setPosition;
|
||||
using TemplateParmPosition::getIndex;
|
||||
|
||||
/// Whether this template template parameter was declared with
|
||||
/// the 'typename' keyword.
|
||||
bool wasDeclaredWithTypename() const { return Typename; }
|
||||
|
||||
/// Set whether this template template parameter was declared with
|
||||
/// the 'typename' or 'class' keyword.
|
||||
void setDeclaredWithTypename(bool withTypename) { Typename = withTypename; }
|
||||
|
||||
/// Whether this template template parameter is a template
|
||||
/// parameter pack.
|
||||
///
|
||||
|
|
@ -1779,6 +1775,25 @@ public:
|
|||
BuiltinTemplateKind getBuiltinTemplateKind() const { return BTK; }
|
||||
};
|
||||
|
||||
/// Provides information about an explicit instantiation of a variable or class
|
||||
/// template.
|
||||
struct ExplicitInstantiationInfo {
|
||||
/// The template arguments as written..
|
||||
const ASTTemplateArgumentListInfo *TemplateArgsAsWritten = nullptr;
|
||||
|
||||
/// The location of the extern keyword.
|
||||
SourceLocation ExternKeywordLoc;
|
||||
|
||||
/// The location of the template keyword.
|
||||
SourceLocation TemplateKeywordLoc;
|
||||
|
||||
ExplicitInstantiationInfo() = default;
|
||||
};
|
||||
|
||||
using SpecializationOrInstantiationInfo =
|
||||
llvm::PointerUnion<const ASTTemplateArgumentListInfo *,
|
||||
ExplicitInstantiationInfo *>;
|
||||
|
||||
/// Represents a class template specialization, which refers to
|
||||
/// a class template with a given set of template arguments.
|
||||
///
|
||||
|
|
@ -1792,8 +1807,8 @@ public:
|
|||
/// template<>
|
||||
/// class array<bool> { }; // class template specialization array<bool>
|
||||
/// \endcode
|
||||
class ClassTemplateSpecializationDecl
|
||||
: public CXXRecordDecl, public llvm::FoldingSetNode {
|
||||
class ClassTemplateSpecializationDecl : public CXXRecordDecl,
|
||||
public llvm::FoldingSetNode {
|
||||
/// Structure that stores information about a class template
|
||||
/// specialization that was instantiated from a class template partial
|
||||
/// specialization.
|
||||
|
|
@ -1811,23 +1826,9 @@ class ClassTemplateSpecializationDecl
|
|||
llvm::PointerUnion<ClassTemplateDecl *, SpecializedPartialSpecialization *>
|
||||
SpecializedTemplate;
|
||||
|
||||
/// Further info for explicit template specialization/instantiation.
|
||||
struct ExplicitSpecializationInfo {
|
||||
/// The type-as-written.
|
||||
TypeSourceInfo *TypeAsWritten = nullptr;
|
||||
|
||||
/// The location of the extern keyword.
|
||||
SourceLocation ExternLoc;
|
||||
|
||||
/// The location of the template keyword.
|
||||
SourceLocation TemplateKeywordLoc;
|
||||
|
||||
ExplicitSpecializationInfo() = default;
|
||||
};
|
||||
|
||||
/// Further info for explicit template specialization/instantiation.
|
||||
/// Does not apply to implicit specializations.
|
||||
ExplicitSpecializationInfo *ExplicitInfo = nullptr;
|
||||
SpecializationOrInstantiationInfo ExplicitInfo = nullptr;
|
||||
|
||||
/// The template arguments used to describe this specialization.
|
||||
const TemplateArgumentList *TemplateArgs;
|
||||
|
|
@ -1859,8 +1860,8 @@ public:
|
|||
ClassTemplateDecl *SpecializedTemplate,
|
||||
ArrayRef<TemplateArgument> Args,
|
||||
ClassTemplateSpecializationDecl *PrevDecl);
|
||||
static ClassTemplateSpecializationDecl *
|
||||
CreateDeserialized(ASTContext &C, unsigned ID);
|
||||
static ClassTemplateSpecializationDecl *CreateDeserialized(ASTContext &C,
|
||||
GlobalDeclID ID);
|
||||
|
||||
void getNameForDiagnostic(raw_ostream &OS, const PrintingPolicy &Policy,
|
||||
bool Qualified) const override;
|
||||
|
|
@ -2004,44 +2005,49 @@ public:
|
|||
SpecializedTemplate = TemplDecl;
|
||||
}
|
||||
|
||||
/// Sets the type of this specialization as it was written by
|
||||
/// the user. This will be a class template specialization type.
|
||||
void setTypeAsWritten(TypeSourceInfo *T) {
|
||||
if (!ExplicitInfo)
|
||||
ExplicitInfo = new (getASTContext()) ExplicitSpecializationInfo;
|
||||
ExplicitInfo->TypeAsWritten = T;
|
||||
/// Retrieve the template argument list as written in the sources,
|
||||
/// if any.
|
||||
const ASTTemplateArgumentListInfo *getTemplateArgsAsWritten() const {
|
||||
if (auto *Info = ExplicitInfo.dyn_cast<ExplicitInstantiationInfo *>())
|
||||
return Info->TemplateArgsAsWritten;
|
||||
return ExplicitInfo.get<const ASTTemplateArgumentListInfo *>();
|
||||
}
|
||||
|
||||
/// Gets the type of this specialization as it was written by
|
||||
/// the user, if it was so written.
|
||||
TypeSourceInfo *getTypeAsWritten() const {
|
||||
return ExplicitInfo ? ExplicitInfo->TypeAsWritten : nullptr;
|
||||
/// Set the template argument list as written in the sources.
|
||||
void
|
||||
setTemplateArgsAsWritten(const ASTTemplateArgumentListInfo *ArgsWritten) {
|
||||
if (auto *Info = ExplicitInfo.dyn_cast<ExplicitInstantiationInfo *>())
|
||||
Info->TemplateArgsAsWritten = ArgsWritten;
|
||||
else
|
||||
ExplicitInfo = ArgsWritten;
|
||||
}
|
||||
|
||||
/// Set the template argument list as written in the sources.
|
||||
void setTemplateArgsAsWritten(const TemplateArgumentListInfo &ArgsInfo) {
|
||||
setTemplateArgsAsWritten(
|
||||
ASTTemplateArgumentListInfo::Create(getASTContext(), ArgsInfo));
|
||||
}
|
||||
|
||||
/// Gets the location of the extern keyword, if present.
|
||||
SourceLocation getExternLoc() const {
|
||||
return ExplicitInfo ? ExplicitInfo->ExternLoc : SourceLocation();
|
||||
SourceLocation getExternKeywordLoc() const {
|
||||
if (auto *Info = ExplicitInfo.dyn_cast<ExplicitInstantiationInfo *>())
|
||||
return Info->ExternKeywordLoc;
|
||||
return SourceLocation();
|
||||
}
|
||||
|
||||
/// Sets the location of the extern keyword.
|
||||
void setExternLoc(SourceLocation Loc) {
|
||||
if (!ExplicitInfo)
|
||||
ExplicitInfo = new (getASTContext()) ExplicitSpecializationInfo;
|
||||
ExplicitInfo->ExternLoc = Loc;
|
||||
}
|
||||
|
||||
/// Sets the location of the template keyword.
|
||||
void setTemplateKeywordLoc(SourceLocation Loc) {
|
||||
if (!ExplicitInfo)
|
||||
ExplicitInfo = new (getASTContext()) ExplicitSpecializationInfo;
|
||||
ExplicitInfo->TemplateKeywordLoc = Loc;
|
||||
}
|
||||
void setExternKeywordLoc(SourceLocation Loc);
|
||||
|
||||
/// Gets the location of the template keyword, if present.
|
||||
SourceLocation getTemplateKeywordLoc() const {
|
||||
return ExplicitInfo ? ExplicitInfo->TemplateKeywordLoc : SourceLocation();
|
||||
if (auto *Info = ExplicitInfo.dyn_cast<ExplicitInstantiationInfo *>())
|
||||
return Info->TemplateKeywordLoc;
|
||||
return SourceLocation();
|
||||
}
|
||||
|
||||
/// Sets the location of the template keyword.
|
||||
void setTemplateKeywordLoc(SourceLocation Loc);
|
||||
|
||||
SourceRange getSourceRange() const override LLVM_READONLY;
|
||||
|
||||
void Profile(llvm::FoldingSetNodeID &ID) const {
|
||||
|
|
@ -2069,10 +2075,6 @@ class ClassTemplatePartialSpecializationDecl
|
|||
/// The list of template parameters
|
||||
TemplateParameterList* TemplateParams = nullptr;
|
||||
|
||||
/// The source info for the template arguments as written.
|
||||
/// FIXME: redundant with TypeAsWritten?
|
||||
const ASTTemplateArgumentListInfo *ArgsAsWritten = nullptr;
|
||||
|
||||
/// The class template partial specialization from which this
|
||||
/// class template partial specialization was instantiated.
|
||||
///
|
||||
|
|
@ -2081,15 +2083,11 @@ class ClassTemplatePartialSpecializationDecl
|
|||
llvm::PointerIntPair<ClassTemplatePartialSpecializationDecl *, 1, bool>
|
||||
InstantiatedFromMember;
|
||||
|
||||
ClassTemplatePartialSpecializationDecl(ASTContext &Context, TagKind TK,
|
||||
DeclContext *DC,
|
||||
SourceLocation StartLoc,
|
||||
SourceLocation IdLoc,
|
||||
TemplateParameterList *Params,
|
||||
ClassTemplateDecl *SpecializedTemplate,
|
||||
ArrayRef<TemplateArgument> Args,
|
||||
const ASTTemplateArgumentListInfo *ArgsAsWritten,
|
||||
ClassTemplatePartialSpecializationDecl *PrevDecl);
|
||||
ClassTemplatePartialSpecializationDecl(
|
||||
ASTContext &Context, TagKind TK, DeclContext *DC, SourceLocation StartLoc,
|
||||
SourceLocation IdLoc, TemplateParameterList *Params,
|
||||
ClassTemplateDecl *SpecializedTemplate, ArrayRef<TemplateArgument> Args,
|
||||
ClassTemplatePartialSpecializationDecl *PrevDecl);
|
||||
|
||||
ClassTemplatePartialSpecializationDecl(ASTContext &C)
|
||||
: ClassTemplateSpecializationDecl(C, ClassTemplatePartialSpecialization),
|
||||
|
|
@ -2104,15 +2102,12 @@ public:
|
|||
static ClassTemplatePartialSpecializationDecl *
|
||||
Create(ASTContext &Context, TagKind TK, DeclContext *DC,
|
||||
SourceLocation StartLoc, SourceLocation IdLoc,
|
||||
TemplateParameterList *Params,
|
||||
ClassTemplateDecl *SpecializedTemplate,
|
||||
ArrayRef<TemplateArgument> Args,
|
||||
const TemplateArgumentListInfo &ArgInfos,
|
||||
QualType CanonInjectedType,
|
||||
TemplateParameterList *Params, ClassTemplateDecl *SpecializedTemplate,
|
||||
ArrayRef<TemplateArgument> Args, QualType CanonInjectedType,
|
||||
ClassTemplatePartialSpecializationDecl *PrevDecl);
|
||||
|
||||
static ClassTemplatePartialSpecializationDecl *
|
||||
CreateDeserialized(ASTContext &C, unsigned ID);
|
||||
CreateDeserialized(ASTContext &C, GlobalDeclID ID);
|
||||
|
||||
ClassTemplatePartialSpecializationDecl *getMostRecentDecl() {
|
||||
return cast<ClassTemplatePartialSpecializationDecl>(
|
||||
|
|
@ -2139,11 +2134,6 @@ public:
|
|||
return TemplateParams->hasAssociatedConstraints();
|
||||
}
|
||||
|
||||
/// Get the template arguments as written.
|
||||
const ASTTemplateArgumentListInfo *getTemplateArgsAsWritten() const {
|
||||
return ArgsAsWritten;
|
||||
}
|
||||
|
||||
/// Retrieve the member class template partial specialization from
|
||||
/// which this particular class template partial specialization was
|
||||
/// instantiated.
|
||||
|
|
@ -2196,7 +2186,7 @@ public:
|
|||
/// template<> template<typename T>
|
||||
/// struct X<int>::Inner<T*> { /* ... */ };
|
||||
/// \endcode
|
||||
bool isMemberSpecialization() {
|
||||
bool isMemberSpecialization() const {
|
||||
const auto *First =
|
||||
cast<ClassTemplatePartialSpecializationDecl>(getFirstDecl());
|
||||
return First->InstantiatedFromMember.getInt();
|
||||
|
|
@ -2219,6 +2209,8 @@ public:
|
|||
->getInjectedSpecializationType();
|
||||
}
|
||||
|
||||
SourceRange getSourceRange() const override LLVM_READONLY;
|
||||
|
||||
void Profile(llvm::FoldingSetNodeID &ID) const {
|
||||
Profile(ID, getTemplateArgs().asArray(), getTemplateParameters(),
|
||||
getASTContext());
|
||||
|
|
@ -2308,7 +2300,7 @@ public:
|
|||
NamedDecl *Decl);
|
||||
|
||||
/// Create an empty class template node.
|
||||
static ClassTemplateDecl *CreateDeserialized(ASTContext &C, unsigned ID);
|
||||
static ClassTemplateDecl *CreateDeserialized(ASTContext &C, GlobalDeclID ID);
|
||||
|
||||
/// Return the specialization with the provided arguments if it exists,
|
||||
/// otherwise return the insertion point.
|
||||
|
|
@ -2474,7 +2466,7 @@ public:
|
|||
MutableArrayRef<TemplateParameterList *> Params, FriendUnion Friend,
|
||||
SourceLocation FriendLoc);
|
||||
|
||||
static FriendTemplateDecl *CreateDeserialized(ASTContext &C, unsigned ID);
|
||||
static FriendTemplateDecl *CreateDeserialized(ASTContext &C, GlobalDeclID ID);
|
||||
|
||||
/// If this friend declaration names a templated type (or
|
||||
/// a dependent member type of a templated type), return that
|
||||
|
|
@ -2575,7 +2567,8 @@ public:
|
|||
NamedDecl *Decl);
|
||||
|
||||
/// Create an empty alias template node.
|
||||
static TypeAliasTemplateDecl *CreateDeserialized(ASTContext &C, unsigned ID);
|
||||
static TypeAliasTemplateDecl *CreateDeserialized(ASTContext &C,
|
||||
GlobalDeclID ID);
|
||||
|
||||
// Implement isa/cast/dyncast support
|
||||
static bool classof(const Decl *D) { return classofKind(D->getKind()); }
|
||||
|
|
@ -2615,27 +2608,12 @@ class VarTemplateSpecializationDecl : public VarDecl,
|
|||
llvm::PointerUnion<VarTemplateDecl *, SpecializedPartialSpecialization *>
|
||||
SpecializedTemplate;
|
||||
|
||||
/// Further info for explicit template specialization/instantiation.
|
||||
struct ExplicitSpecializationInfo {
|
||||
/// The type-as-written.
|
||||
TypeSourceInfo *TypeAsWritten = nullptr;
|
||||
|
||||
/// The location of the extern keyword.
|
||||
SourceLocation ExternLoc;
|
||||
|
||||
/// The location of the template keyword.
|
||||
SourceLocation TemplateKeywordLoc;
|
||||
|
||||
ExplicitSpecializationInfo() = default;
|
||||
};
|
||||
|
||||
/// Further info for explicit template specialization/instantiation.
|
||||
/// Does not apply to implicit specializations.
|
||||
ExplicitSpecializationInfo *ExplicitInfo = nullptr;
|
||||
SpecializationOrInstantiationInfo ExplicitInfo = nullptr;
|
||||
|
||||
/// The template arguments used to describe this specialization.
|
||||
const TemplateArgumentList *TemplateArgs;
|
||||
const ASTTemplateArgumentListInfo *TemplateArgsInfo = nullptr;
|
||||
|
||||
/// The point where this template was instantiated (if any).
|
||||
SourceLocation PointOfInstantiation;
|
||||
|
|
@ -2672,7 +2650,7 @@ public:
|
|||
TypeSourceInfo *TInfo, StorageClass S,
|
||||
ArrayRef<TemplateArgument> Args);
|
||||
static VarTemplateSpecializationDecl *CreateDeserialized(ASTContext &C,
|
||||
unsigned ID);
|
||||
GlobalDeclID ID);
|
||||
|
||||
void getNameForDiagnostic(raw_ostream &OS, const PrintingPolicy &Policy,
|
||||
bool Qualified) const override;
|
||||
|
|
@ -2689,14 +2667,6 @@ public:
|
|||
/// specialization.
|
||||
const TemplateArgumentList &getTemplateArgs() const { return *TemplateArgs; }
|
||||
|
||||
// TODO: Always set this when creating the new specialization?
|
||||
void setTemplateArgsInfo(const TemplateArgumentListInfo &ArgsInfo);
|
||||
void setTemplateArgsInfo(const ASTTemplateArgumentListInfo *ArgsInfo);
|
||||
|
||||
const ASTTemplateArgumentListInfo *getTemplateArgsInfo() const {
|
||||
return TemplateArgsInfo;
|
||||
}
|
||||
|
||||
/// Determine the kind of specialization that this
|
||||
/// declaration represents.
|
||||
TemplateSpecializationKind getSpecializationKind() const {
|
||||
|
|
@ -2800,44 +2770,49 @@ public:
|
|||
SpecializedTemplate = TemplDecl;
|
||||
}
|
||||
|
||||
/// Sets the type of this specialization as it was written by
|
||||
/// the user.
|
||||
void setTypeAsWritten(TypeSourceInfo *T) {
|
||||
if (!ExplicitInfo)
|
||||
ExplicitInfo = new (getASTContext()) ExplicitSpecializationInfo;
|
||||
ExplicitInfo->TypeAsWritten = T;
|
||||
/// Retrieve the template argument list as written in the sources,
|
||||
/// if any.
|
||||
const ASTTemplateArgumentListInfo *getTemplateArgsAsWritten() const {
|
||||
if (auto *Info = ExplicitInfo.dyn_cast<ExplicitInstantiationInfo *>())
|
||||
return Info->TemplateArgsAsWritten;
|
||||
return ExplicitInfo.get<const ASTTemplateArgumentListInfo *>();
|
||||
}
|
||||
|
||||
/// Gets the type of this specialization as it was written by
|
||||
/// the user, if it was so written.
|
||||
TypeSourceInfo *getTypeAsWritten() const {
|
||||
return ExplicitInfo ? ExplicitInfo->TypeAsWritten : nullptr;
|
||||
/// Set the template argument list as written in the sources.
|
||||
void
|
||||
setTemplateArgsAsWritten(const ASTTemplateArgumentListInfo *ArgsWritten) {
|
||||
if (auto *Info = ExplicitInfo.dyn_cast<ExplicitInstantiationInfo *>())
|
||||
Info->TemplateArgsAsWritten = ArgsWritten;
|
||||
else
|
||||
ExplicitInfo = ArgsWritten;
|
||||
}
|
||||
|
||||
/// Set the template argument list as written in the sources.
|
||||
void setTemplateArgsAsWritten(const TemplateArgumentListInfo &ArgsInfo) {
|
||||
setTemplateArgsAsWritten(
|
||||
ASTTemplateArgumentListInfo::Create(getASTContext(), ArgsInfo));
|
||||
}
|
||||
|
||||
/// Gets the location of the extern keyword, if present.
|
||||
SourceLocation getExternLoc() const {
|
||||
return ExplicitInfo ? ExplicitInfo->ExternLoc : SourceLocation();
|
||||
SourceLocation getExternKeywordLoc() const {
|
||||
if (auto *Info = ExplicitInfo.dyn_cast<ExplicitInstantiationInfo *>())
|
||||
return Info->ExternKeywordLoc;
|
||||
return SourceLocation();
|
||||
}
|
||||
|
||||
/// Sets the location of the extern keyword.
|
||||
void setExternLoc(SourceLocation Loc) {
|
||||
if (!ExplicitInfo)
|
||||
ExplicitInfo = new (getASTContext()) ExplicitSpecializationInfo;
|
||||
ExplicitInfo->ExternLoc = Loc;
|
||||
}
|
||||
|
||||
/// Sets the location of the template keyword.
|
||||
void setTemplateKeywordLoc(SourceLocation Loc) {
|
||||
if (!ExplicitInfo)
|
||||
ExplicitInfo = new (getASTContext()) ExplicitSpecializationInfo;
|
||||
ExplicitInfo->TemplateKeywordLoc = Loc;
|
||||
}
|
||||
void setExternKeywordLoc(SourceLocation Loc);
|
||||
|
||||
/// Gets the location of the template keyword, if present.
|
||||
SourceLocation getTemplateKeywordLoc() const {
|
||||
return ExplicitInfo ? ExplicitInfo->TemplateKeywordLoc : SourceLocation();
|
||||
if (auto *Info = ExplicitInfo.dyn_cast<ExplicitInstantiationInfo *>())
|
||||
return Info->TemplateKeywordLoc;
|
||||
return SourceLocation();
|
||||
}
|
||||
|
||||
/// Sets the location of the template keyword.
|
||||
void setTemplateKeywordLoc(SourceLocation Loc);
|
||||
|
||||
SourceRange getSourceRange() const override LLVM_READONLY;
|
||||
|
||||
void Profile(llvm::FoldingSetNodeID &ID) const {
|
||||
|
|
@ -2865,10 +2840,6 @@ class VarTemplatePartialSpecializationDecl
|
|||
/// The list of template parameters
|
||||
TemplateParameterList *TemplateParams = nullptr;
|
||||
|
||||
/// The source info for the template arguments as written.
|
||||
/// FIXME: redundant with TypeAsWritten?
|
||||
const ASTTemplateArgumentListInfo *ArgsAsWritten = nullptr;
|
||||
|
||||
/// The variable template partial specialization from which this
|
||||
/// variable template partial specialization was instantiated.
|
||||
///
|
||||
|
|
@ -2881,8 +2852,7 @@ class VarTemplatePartialSpecializationDecl
|
|||
ASTContext &Context, DeclContext *DC, SourceLocation StartLoc,
|
||||
SourceLocation IdLoc, TemplateParameterList *Params,
|
||||
VarTemplateDecl *SpecializedTemplate, QualType T, TypeSourceInfo *TInfo,
|
||||
StorageClass S, ArrayRef<TemplateArgument> Args,
|
||||
const ASTTemplateArgumentListInfo *ArgInfos);
|
||||
StorageClass S, ArrayRef<TemplateArgument> Args);
|
||||
|
||||
VarTemplatePartialSpecializationDecl(ASTContext &Context)
|
||||
: VarTemplateSpecializationDecl(VarTemplatePartialSpecialization,
|
||||
|
|
@ -2899,11 +2869,11 @@ public:
|
|||
Create(ASTContext &Context, DeclContext *DC, SourceLocation StartLoc,
|
||||
SourceLocation IdLoc, TemplateParameterList *Params,
|
||||
VarTemplateDecl *SpecializedTemplate, QualType T,
|
||||
TypeSourceInfo *TInfo, StorageClass S, ArrayRef<TemplateArgument> Args,
|
||||
const TemplateArgumentListInfo &ArgInfos);
|
||||
TypeSourceInfo *TInfo, StorageClass S,
|
||||
ArrayRef<TemplateArgument> Args);
|
||||
|
||||
static VarTemplatePartialSpecializationDecl *CreateDeserialized(ASTContext &C,
|
||||
unsigned ID);
|
||||
static VarTemplatePartialSpecializationDecl *
|
||||
CreateDeserialized(ASTContext &C, GlobalDeclID ID);
|
||||
|
||||
VarTemplatePartialSpecializationDecl *getMostRecentDecl() {
|
||||
return cast<VarTemplatePartialSpecializationDecl>(
|
||||
|
|
@ -2916,11 +2886,6 @@ public:
|
|||
return TemplateParams;
|
||||
}
|
||||
|
||||
/// Get the template arguments as written.
|
||||
const ASTTemplateArgumentListInfo *getTemplateArgsAsWritten() const {
|
||||
return ArgsAsWritten;
|
||||
}
|
||||
|
||||
/// \brief All associated constraints of this partial specialization,
|
||||
/// including the requires clause and any constraints derived from
|
||||
/// constrained-parameters.
|
||||
|
|
@ -2983,7 +2948,7 @@ public:
|
|||
/// template<> template<typename T>
|
||||
/// U* X<int>::Inner<T*> = (T*)(0) + 1;
|
||||
/// \endcode
|
||||
bool isMemberSpecialization() {
|
||||
bool isMemberSpecialization() const {
|
||||
const auto *First =
|
||||
cast<VarTemplatePartialSpecializationDecl>(getFirstDecl());
|
||||
return First->InstantiatedFromMember.getInt();
|
||||
|
|
@ -3080,7 +3045,7 @@ public:
|
|||
VarDecl *Decl);
|
||||
|
||||
/// Create an empty variable template node.
|
||||
static VarTemplateDecl *CreateDeserialized(ASTContext &C, unsigned ID);
|
||||
static VarTemplateDecl *CreateDeserialized(ASTContext &C, GlobalDeclID ID);
|
||||
|
||||
/// Return the specialization with the provided arguments if it exists,
|
||||
/// otherwise return the insertion point.
|
||||
|
|
@ -3185,7 +3150,7 @@ public:
|
|||
SourceLocation L, DeclarationName Name,
|
||||
TemplateParameterList *Params,
|
||||
Expr *ConstraintExpr);
|
||||
static ConceptDecl *CreateDeserialized(ASTContext &C, unsigned ID);
|
||||
static ConceptDecl *CreateDeserialized(ASTContext &C, GlobalDeclID ID);
|
||||
|
||||
Expr *getConstraintExpr() const {
|
||||
return ConstraintExpr;
|
||||
|
|
@ -3234,7 +3199,7 @@ public:
|
|||
Create(const ASTContext &C, DeclContext *DC, SourceLocation SL,
|
||||
ArrayRef<TemplateArgument> ConvertedArgs);
|
||||
static ImplicitConceptSpecializationDecl *
|
||||
CreateDeserialized(const ASTContext &C, unsigned ID,
|
||||
CreateDeserialized(const ASTContext &C, GlobalDeclID ID,
|
||||
unsigned NumTemplateArgs);
|
||||
|
||||
ArrayRef<TemplateArgument> getTemplateArguments() const {
|
||||
|
|
@ -3277,7 +3242,7 @@ private:
|
|||
static TemplateParamObjectDecl *Create(const ASTContext &C, QualType T,
|
||||
const APValue &V);
|
||||
static TemplateParamObjectDecl *CreateDeserialized(ASTContext &C,
|
||||
unsigned ID);
|
||||
GlobalDeclID ID);
|
||||
|
||||
/// Only ASTContext::getTemplateParamObjectDecl and deserialization
|
||||
/// create these.
|
||||
|
|
|
|||
|
|
@ -82,7 +82,7 @@ struct SubobjectAdjustment {
|
|||
|
||||
union {
|
||||
struct DTB DerivedToBase;
|
||||
FieldDecl *Field;
|
||||
const FieldDecl *Field;
|
||||
struct P Ptr;
|
||||
};
|
||||
|
||||
|
|
@ -93,8 +93,7 @@ struct SubobjectAdjustment {
|
|||
DerivedToBase.DerivedClass = DerivedClass;
|
||||
}
|
||||
|
||||
SubobjectAdjustment(FieldDecl *Field)
|
||||
: Kind(FieldAdjustment) {
|
||||
SubobjectAdjustment(const FieldDecl *Field) : Kind(FieldAdjustment) {
|
||||
this->Field = Field;
|
||||
}
|
||||
|
||||
|
|
@ -154,6 +153,12 @@ public:
|
|||
TR = t;
|
||||
}
|
||||
|
||||
/// If this expression is an enumeration constant, return the
|
||||
/// enumeration type under which said constant was declared.
|
||||
/// Otherwise return the expression's type.
|
||||
/// Note this effectively circumvents the weak typing of C's enum constants
|
||||
QualType getEnumCoercedType(const ASTContext &Ctx) const;
|
||||
|
||||
ExprDependence getDependence() const {
|
||||
return static_cast<ExprDependence>(ExprBits.Dependent);
|
||||
}
|
||||
|
|
@ -379,7 +384,7 @@ public:
|
|||
bool isRValue() const { return Kind >= CL_XValue; }
|
||||
bool isModifiable() const { return getModifiable() == CM_Modifiable; }
|
||||
|
||||
/// Create a simple, modifiably lvalue
|
||||
/// Create a simple, modifiable lvalue
|
||||
static Classification makeSimpleLValue() {
|
||||
return Classification(CL_LValue, CM_Modifiable);
|
||||
}
|
||||
|
|
@ -472,6 +477,13 @@ public:
|
|||
/// bit-fields, but it will return null for a conditional bit-field.
|
||||
FieldDecl *getSourceBitField();
|
||||
|
||||
/// If this expression refers to an enum constant, retrieve its declaration
|
||||
EnumConstantDecl *getEnumConstantDecl();
|
||||
|
||||
const EnumConstantDecl *getEnumConstantDecl() const {
|
||||
return const_cast<Expr *>(this)->getEnumConstantDecl();
|
||||
}
|
||||
|
||||
const FieldDecl *getSourceBitField() const {
|
||||
return const_cast<Expr*>(this)->getSourceBitField();
|
||||
}
|
||||
|
|
@ -775,6 +787,11 @@ public:
|
|||
const Expr *PtrExpression, ASTContext &Ctx,
|
||||
EvalResult &Status) const;
|
||||
|
||||
/// If the current Expr can be evaluated to a pointer to a null-terminated
|
||||
/// constant string, return the constant string (without the terminating
|
||||
/// null).
|
||||
std::optional<std::string> tryEvaluateString(ASTContext &Ctx) const;
|
||||
|
||||
/// Enumeration used to describe the kind of Null pointer constant
|
||||
/// returned from \c isNullPointerConstant().
|
||||
enum NullPointerConstantKind {
|
||||
|
|
@ -1275,7 +1292,7 @@ class DeclRefExpr final
|
|||
|
||||
DeclRefExpr(const ASTContext &Ctx, NestedNameSpecifierLoc QualifierLoc,
|
||||
SourceLocation TemplateKWLoc, ValueDecl *D,
|
||||
bool RefersToEnlosingVariableOrCapture,
|
||||
bool RefersToEnclosingVariableOrCapture,
|
||||
const DeclarationNameInfo &NameInfo, NamedDecl *FoundD,
|
||||
const TemplateArgumentListInfo *TemplateArgs, QualType T,
|
||||
ExprValueKind VK, NonOdrUseReason NOUR);
|
||||
|
|
@ -1641,14 +1658,14 @@ public:
|
|||
}
|
||||
|
||||
/// Get a raw enumeration value representing the floating-point semantics of
|
||||
/// this literal (32-bit IEEE, x87, ...), suitable for serialisation.
|
||||
/// this literal (32-bit IEEE, x87, ...), suitable for serialization.
|
||||
llvm::APFloatBase::Semantics getRawSemantics() const {
|
||||
return static_cast<llvm::APFloatBase::Semantics>(
|
||||
FloatingLiteralBits.Semantics);
|
||||
}
|
||||
|
||||
/// Set the raw enumeration value representing the floating-point semantics of
|
||||
/// this literal (32-bit IEEE, x87, ...), suitable for serialisation.
|
||||
/// this literal (32-bit IEEE, x87, ...), suitable for serialization.
|
||||
void setRawSemantics(llvm::APFloatBase::Semantics Sem) {
|
||||
FloatingLiteralBits.Semantics = Sem;
|
||||
}
|
||||
|
|
@ -1863,6 +1880,17 @@ public:
|
|||
llvm_unreachable("Unsupported character width!");
|
||||
}
|
||||
|
||||
// Get code unit but preserve sign info.
|
||||
int64_t getCodeUnitS(size_t I, uint64_t BitWidth) const {
|
||||
int64_t V = getCodeUnit(I);
|
||||
if (isOrdinary() || isWide()) {
|
||||
unsigned Width = getCharByteWidth() * BitWidth;
|
||||
llvm::APInt AInt(Width, (uint64_t)V);
|
||||
V = AInt.getSExtValue();
|
||||
}
|
||||
return V;
|
||||
}
|
||||
|
||||
unsigned getByteLength() const { return getCharByteWidth() * getLength(); }
|
||||
unsigned getLength() const { return *getTrailingObjects<unsigned>(); }
|
||||
unsigned getCharByteWidth() const { return StringLiteralBits.CharByteWidth; }
|
||||
|
|
@ -2022,7 +2050,8 @@ public:
|
|||
}
|
||||
|
||||
static std::string ComputeName(PredefinedIdentKind IK,
|
||||
const Decl *CurrentDecl);
|
||||
const Decl *CurrentDecl,
|
||||
bool ForceElaboratedPrinting = false);
|
||||
|
||||
SourceLocation getBeginLoc() const { return getLocation(); }
|
||||
SourceLocation getEndLoc() const { return getLocation(); }
|
||||
|
|
@ -2101,7 +2130,7 @@ public:
|
|||
static std::string ComputeName(ASTContext &Context, QualType Ty);
|
||||
};
|
||||
|
||||
/// ParenExpr - This represents a parethesized expression, e.g. "(1)". This
|
||||
/// ParenExpr - This represents a parenthesized expression, e.g. "(1)". This
|
||||
/// AST node is only formed if full location information is requested.
|
||||
class ParenExpr : public Expr {
|
||||
SourceLocation L, R;
|
||||
|
|
@ -2217,7 +2246,7 @@ public:
|
|||
bool canOverflow() const { return UnaryOperatorBits.CanOverflow; }
|
||||
void setCanOverflow(bool C) { UnaryOperatorBits.CanOverflow = C; }
|
||||
|
||||
/// Get the FP contractability status of this operator. Only meaningful for
|
||||
/// Get the FP contractibility status of this operator. Only meaningful for
|
||||
/// operations on floating point types.
|
||||
bool isFPContractableWithinStatement(const LangOptions &LO) const {
|
||||
return getFPFeaturesInEffect(LO).allowFPContractWithinStatement();
|
||||
|
|
@ -2304,6 +2333,11 @@ public:
|
|||
return getTrailingFPFeatures();
|
||||
}
|
||||
|
||||
/// Get the store FPOptionsOverride or default if not stored.
|
||||
FPOptionsOverride getStoredFPFeaturesOrDefault() const {
|
||||
return hasStoredFPFeatures() ? getStoredFPFeatures() : FPOptionsOverride();
|
||||
}
|
||||
|
||||
protected:
|
||||
/// Set FPFeatures in trailing storage, used by Serialization & ASTImporter.
|
||||
void setStoredFPFeatures(FPOptionsOverride F) { getTrailingFPFeatures() = F; }
|
||||
|
|
@ -3067,6 +3101,11 @@ public:
|
|||
*getTrailingFPFeatures() = F;
|
||||
}
|
||||
|
||||
/// Get the store FPOptionsOverride or default if not stored.
|
||||
FPOptionsOverride getStoredFPFeaturesOrDefault() const {
|
||||
return hasStoredFPFeatures() ? getStoredFPFeatures() : FPOptionsOverride();
|
||||
}
|
||||
|
||||
/// Get the FP features status of this operator. Only meaningful for
|
||||
/// operations on floating point types.
|
||||
FPOptions getFPFeaturesInEffect(const LangOptions &LO) const {
|
||||
|
|
@ -3139,23 +3178,12 @@ public:
|
|||
}
|
||||
};
|
||||
|
||||
/// Extra data stored in some MemberExpr objects.
|
||||
struct MemberExprNameQualifier {
|
||||
/// The nested-name-specifier that qualifies the name, including
|
||||
/// source-location information.
|
||||
NestedNameSpecifierLoc QualifierLoc;
|
||||
|
||||
/// The DeclAccessPair through which the MemberDecl was found due to
|
||||
/// name qualifiers.
|
||||
DeclAccessPair FoundDecl;
|
||||
};
|
||||
|
||||
/// MemberExpr - [C99 6.5.2.3] Structure and Union Members. X->F and X.F.
|
||||
///
|
||||
class MemberExpr final
|
||||
: public Expr,
|
||||
private llvm::TrailingObjects<MemberExpr, MemberExprNameQualifier,
|
||||
ASTTemplateKWAndArgsInfo,
|
||||
private llvm::TrailingObjects<MemberExpr, NestedNameSpecifierLoc,
|
||||
DeclAccessPair, ASTTemplateKWAndArgsInfo,
|
||||
TemplateArgumentLoc> {
|
||||
friend class ASTReader;
|
||||
friend class ASTStmtReader;
|
||||
|
|
@ -3177,26 +3205,30 @@ class MemberExpr final
|
|||
/// MemberLoc - This is the location of the member name.
|
||||
SourceLocation MemberLoc;
|
||||
|
||||
size_t numTrailingObjects(OverloadToken<MemberExprNameQualifier>) const {
|
||||
return hasQualifierOrFoundDecl();
|
||||
size_t numTrailingObjects(OverloadToken<NestedNameSpecifierLoc>) const {
|
||||
return hasQualifier();
|
||||
}
|
||||
|
||||
size_t numTrailingObjects(OverloadToken<DeclAccessPair>) const {
|
||||
return hasFoundDecl();
|
||||
}
|
||||
|
||||
size_t numTrailingObjects(OverloadToken<ASTTemplateKWAndArgsInfo>) const {
|
||||
return hasTemplateKWAndArgsInfo();
|
||||
}
|
||||
|
||||
bool hasQualifierOrFoundDecl() const {
|
||||
return MemberExprBits.HasQualifierOrFoundDecl;
|
||||
}
|
||||
bool hasFoundDecl() const { return MemberExprBits.HasFoundDecl; }
|
||||
|
||||
bool hasTemplateKWAndArgsInfo() const {
|
||||
return MemberExprBits.HasTemplateKWAndArgsInfo;
|
||||
}
|
||||
|
||||
MemberExpr(Expr *Base, bool IsArrow, SourceLocation OperatorLoc,
|
||||
ValueDecl *MemberDecl, const DeclarationNameInfo &NameInfo,
|
||||
QualType T, ExprValueKind VK, ExprObjectKind OK,
|
||||
NonOdrUseReason NOUR);
|
||||
NestedNameSpecifierLoc QualifierLoc, SourceLocation TemplateKWLoc,
|
||||
ValueDecl *MemberDecl, DeclAccessPair FoundDecl,
|
||||
const DeclarationNameInfo &NameInfo,
|
||||
const TemplateArgumentListInfo *TemplateArgs, QualType T,
|
||||
ExprValueKind VK, ExprObjectKind OK, NonOdrUseReason NOUR);
|
||||
MemberExpr(EmptyShell Empty)
|
||||
: Expr(MemberExprClass, Empty), Base(), MemberDecl() {}
|
||||
|
||||
|
|
@ -3240,24 +3272,24 @@ public:
|
|||
|
||||
/// Retrieves the declaration found by lookup.
|
||||
DeclAccessPair getFoundDecl() const {
|
||||
if (!hasQualifierOrFoundDecl())
|
||||
if (!hasFoundDecl())
|
||||
return DeclAccessPair::make(getMemberDecl(),
|
||||
getMemberDecl()->getAccess());
|
||||
return getTrailingObjects<MemberExprNameQualifier>()->FoundDecl;
|
||||
return *getTrailingObjects<DeclAccessPair>();
|
||||
}
|
||||
|
||||
/// Determines whether this member expression actually had
|
||||
/// a C++ nested-name-specifier prior to the name of the member, e.g.,
|
||||
/// x->Base::foo.
|
||||
bool hasQualifier() const { return getQualifier() != nullptr; }
|
||||
bool hasQualifier() const { return MemberExprBits.HasQualifier; }
|
||||
|
||||
/// If the member name was qualified, retrieves the
|
||||
/// nested-name-specifier that precedes the member name, with source-location
|
||||
/// information.
|
||||
NestedNameSpecifierLoc getQualifierLoc() const {
|
||||
if (!hasQualifierOrFoundDecl())
|
||||
if (!hasQualifier())
|
||||
return NestedNameSpecifierLoc();
|
||||
return getTrailingObjects<MemberExprNameQualifier>()->QualifierLoc;
|
||||
return *getTrailingObjects<NestedNameSpecifierLoc>();
|
||||
}
|
||||
|
||||
/// If the member name was qualified, retrieves the
|
||||
|
|
@ -3538,6 +3570,18 @@ public:
|
|||
path_const_iterator path_begin() const { return path_buffer(); }
|
||||
path_const_iterator path_end() const { return path_buffer() + path_size(); }
|
||||
|
||||
/// Path through the class hierarchy taken by casts between base and derived
|
||||
/// classes (see implementation of `CastConsistency()` for a full list of
|
||||
/// cast kinds that have a path).
|
||||
///
|
||||
/// For each derived-to-base edge in the path, the path contains a
|
||||
/// `CXXBaseSpecifier` for the base class of that edge; the entries are
|
||||
/// ordered from derived class to base class.
|
||||
///
|
||||
/// For example, given classes `Base`, `Intermediate : public Base` and
|
||||
/// `Derived : public Intermediate`, the path for a cast from `Derived *` to
|
||||
/// `Base *` contains two entries: One for `Intermediate`, and one for `Base`,
|
||||
/// in that order.
|
||||
llvm::iterator_range<path_iterator> path() {
|
||||
return llvm::make_range(path_begin(), path_end());
|
||||
}
|
||||
|
|
@ -3558,6 +3602,11 @@ public:
|
|||
return *getTrailingFPFeatures();
|
||||
}
|
||||
|
||||
/// Get the store FPOptionsOverride or default if not stored.
|
||||
FPOptionsOverride getStoredFPFeaturesOrDefault() const {
|
||||
return hasStoredFPFeatures() ? getStoredFPFeatures() : FPOptionsOverride();
|
||||
}
|
||||
|
||||
/// Get the FP features status of this operation. Only meaningful for
|
||||
/// operations on floating point types.
|
||||
FPOptions getFPFeaturesInEffect(const LangOptions &LO) const {
|
||||
|
|
@ -4004,6 +4053,10 @@ public:
|
|||
assert(BinaryOperatorBits.HasFPFeatures);
|
||||
*getTrailingFPFeatures() = F;
|
||||
}
|
||||
/// Get the store FPOptionsOverride or default if not stored.
|
||||
FPOptionsOverride getStoredFPFeaturesOrDefault() const {
|
||||
return hasStoredFPFeatures() ? getStoredFPFeatures() : FPOptionsOverride();
|
||||
}
|
||||
|
||||
/// Get the FP features status of this operator. Only meaningful for
|
||||
/// operations on floating point types.
|
||||
|
|
@ -4020,7 +4073,7 @@ public:
|
|||
return FPOptionsOverride();
|
||||
}
|
||||
|
||||
/// Get the FP contractability status of this operator. Only meaningful for
|
||||
/// Get the FP contractibility status of this operator. Only meaningful for
|
||||
/// operations on floating point types.
|
||||
bool isFPContractableWithinStatement(const LangOptions &LO) const {
|
||||
return getFPFeaturesInEffect(LO).allowFPContractWithinStatement();
|
||||
|
|
@ -4261,7 +4314,7 @@ public:
|
|||
}
|
||||
|
||||
/// getFalseExpr - Return the subexpression which will be
|
||||
/// evaluated if the condnition evaluates to false; this is
|
||||
/// evaluated if the condition evaluates to false; this is
|
||||
/// defined in terms of the opaque value.
|
||||
Expr *getFalseExpr() const {
|
||||
return cast<Expr>(SubExprs[RHS]);
|
||||
|
|
@ -4770,6 +4823,164 @@ private:
|
|||
friend class ASTStmtReader;
|
||||
};
|
||||
|
||||
/// Stores data related to a single #embed directive.
|
||||
struct EmbedDataStorage {
|
||||
StringLiteral *BinaryData;
|
||||
size_t getDataElementCount() const { return BinaryData->getByteLength(); }
|
||||
};
|
||||
|
||||
/// Represents a reference to #emded data. By default, this references the whole
|
||||
/// range. Otherwise it represents a subrange of data imported by #embed
|
||||
/// directive. Needed to handle nested initializer lists with #embed directives.
|
||||
/// Example:
|
||||
/// struct S {
|
||||
/// int x, y;
|
||||
/// };
|
||||
///
|
||||
/// struct T {
|
||||
/// int x[2];
|
||||
/// struct S s
|
||||
/// };
|
||||
///
|
||||
/// struct T t[] = {
|
||||
/// #embed "data" // data contains 10 elements;
|
||||
/// };
|
||||
///
|
||||
/// The resulting semantic form of initializer list will contain (EE stands
|
||||
/// for EmbedExpr):
|
||||
/// { {EE(first two data elements), {EE(3rd element), EE(4th element) }},
|
||||
/// { {EE(5th and 6th element), {EE(7th element), EE(8th element) }},
|
||||
/// { {EE(9th and 10th element), { zeroinitializer }}}
|
||||
///
|
||||
/// EmbedExpr inside of a semantic initializer list and referencing more than
|
||||
/// one element can only appear for arrays of scalars.
|
||||
class EmbedExpr final : public Expr {
|
||||
SourceLocation EmbedKeywordLoc;
|
||||
IntegerLiteral *FakeChildNode = nullptr;
|
||||
const ASTContext *Ctx = nullptr;
|
||||
EmbedDataStorage *Data;
|
||||
unsigned Begin = 0;
|
||||
unsigned NumOfElements;
|
||||
|
||||
public:
|
||||
EmbedExpr(const ASTContext &Ctx, SourceLocation Loc, EmbedDataStorage *Data,
|
||||
unsigned Begin, unsigned NumOfElements);
|
||||
explicit EmbedExpr(EmptyShell Empty) : Expr(SourceLocExprClass, Empty) {}
|
||||
|
||||
SourceLocation getLocation() const { return EmbedKeywordLoc; }
|
||||
SourceLocation getBeginLoc() const { return EmbedKeywordLoc; }
|
||||
SourceLocation getEndLoc() const { return EmbedKeywordLoc; }
|
||||
|
||||
StringLiteral *getDataStringLiteral() const { return Data->BinaryData; }
|
||||
EmbedDataStorage *getData() const { return Data; }
|
||||
|
||||
unsigned getStartingElementPos() const { return Begin; }
|
||||
size_t getDataElementCount() const { return NumOfElements; }
|
||||
|
||||
// Allows accessing every byte of EmbedExpr data and iterating over it.
|
||||
// An Iterator knows the EmbedExpr that it refers to, and an offset value
|
||||
// within the data.
|
||||
// Dereferencing an Iterator results in construction of IntegerLiteral AST
|
||||
// node filled with byte of data of the corresponding EmbedExpr within offset
|
||||
// that the Iterator currently has.
|
||||
template <bool Const>
|
||||
class ChildElementIter
|
||||
: public llvm::iterator_facade_base<
|
||||
ChildElementIter<Const>, std::random_access_iterator_tag,
|
||||
std::conditional_t<Const, const IntegerLiteral *,
|
||||
IntegerLiteral *>> {
|
||||
friend class EmbedExpr;
|
||||
|
||||
EmbedExpr *EExpr = nullptr;
|
||||
unsigned long long CurOffset = ULLONG_MAX;
|
||||
using BaseTy = typename ChildElementIter::iterator_facade_base;
|
||||
|
||||
ChildElementIter(EmbedExpr *E) : EExpr(E) {
|
||||
if (E)
|
||||
CurOffset = E->getStartingElementPos();
|
||||
}
|
||||
|
||||
public:
|
||||
ChildElementIter() : CurOffset(ULLONG_MAX) {}
|
||||
typename BaseTy::reference operator*() const {
|
||||
assert(EExpr && CurOffset != ULLONG_MAX &&
|
||||
"trying to dereference an invalid iterator");
|
||||
IntegerLiteral *N = EExpr->FakeChildNode;
|
||||
StringRef DataRef = EExpr->Data->BinaryData->getBytes();
|
||||
N->setValue(*EExpr->Ctx,
|
||||
llvm::APInt(N->getValue().getBitWidth(), DataRef[CurOffset],
|
||||
N->getType()->isSignedIntegerType()));
|
||||
// We want to return a reference to the fake child node in the
|
||||
// EmbedExpr, not the local variable N.
|
||||
return const_cast<typename BaseTy::reference>(EExpr->FakeChildNode);
|
||||
}
|
||||
typename BaseTy::pointer operator->() const { return **this; }
|
||||
using BaseTy::operator++;
|
||||
ChildElementIter &operator++() {
|
||||
assert(EExpr && "trying to increment an invalid iterator");
|
||||
assert(CurOffset != ULLONG_MAX &&
|
||||
"Already at the end of what we can iterate over");
|
||||
if (++CurOffset >=
|
||||
EExpr->getDataElementCount() + EExpr->getStartingElementPos()) {
|
||||
CurOffset = ULLONG_MAX;
|
||||
EExpr = nullptr;
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
bool operator==(ChildElementIter Other) const {
|
||||
return (EExpr == Other.EExpr && CurOffset == Other.CurOffset);
|
||||
}
|
||||
}; // class ChildElementIter
|
||||
|
||||
public:
|
||||
using fake_child_range = llvm::iterator_range<ChildElementIter<false>>;
|
||||
using const_fake_child_range = llvm::iterator_range<ChildElementIter<true>>;
|
||||
|
||||
fake_child_range underlying_data_elements() {
|
||||
return fake_child_range(ChildElementIter<false>(this),
|
||||
ChildElementIter<false>());
|
||||
}
|
||||
|
||||
const_fake_child_range underlying_data_elements() const {
|
||||
return const_fake_child_range(
|
||||
ChildElementIter<true>(const_cast<EmbedExpr *>(this)),
|
||||
ChildElementIter<true>());
|
||||
}
|
||||
|
||||
child_range children() {
|
||||
return child_range(child_iterator(), child_iterator());
|
||||
}
|
||||
|
||||
const_child_range children() const {
|
||||
return const_child_range(const_child_iterator(), const_child_iterator());
|
||||
}
|
||||
|
||||
static bool classof(const Stmt *T) {
|
||||
return T->getStmtClass() == EmbedExprClass;
|
||||
}
|
||||
|
||||
ChildElementIter<false> begin() { return ChildElementIter<false>(this); }
|
||||
|
||||
ChildElementIter<true> begin() const {
|
||||
return ChildElementIter<true>(const_cast<EmbedExpr *>(this));
|
||||
}
|
||||
|
||||
template <typename Call, typename... Targs>
|
||||
bool doForEachDataElement(Call &&C, unsigned &StartingIndexInArray,
|
||||
Targs &&...Fargs) const {
|
||||
for (auto It : underlying_data_elements()) {
|
||||
if (!std::invoke(std::forward<Call>(C), const_cast<IntegerLiteral *>(It),
|
||||
StartingIndexInArray, std::forward<Targs>(Fargs)...))
|
||||
return false;
|
||||
StartingIndexInArray++;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
private:
|
||||
friend class ASTStmtReader;
|
||||
};
|
||||
|
||||
/// Describes an C or C++ initializer list.
|
||||
///
|
||||
/// InitListExpr describes an initializer list, which can be used to
|
||||
|
|
@ -5811,7 +6022,7 @@ class GenericSelectionExpr final
|
|||
// if *It1 and *It2 are bound to the same objects.
|
||||
// An alternative design approach was discussed during review;
|
||||
// store an Association object inside the iterator, and return a reference
|
||||
// to it when dereferenced. This idea was discarded beacuse of nasty
|
||||
// to it when dereferenced. This idea was discarded because of nasty
|
||||
// lifetime issues:
|
||||
// AssociationIterator It = ...;
|
||||
// const Association &Assoc = *It++; // Oops, Assoc is dangling.
|
||||
|
|
@ -5820,7 +6031,7 @@ class GenericSelectionExpr final
|
|||
std::conditional_t<Const, const Stmt *const *, Stmt **>;
|
||||
using TSIPtrPtrTy = std::conditional_t<Const, const TypeSourceInfo *const *,
|
||||
TypeSourceInfo **>;
|
||||
StmtPtrPtrTy E; // = nullptr; FIXME: Once support for gcc 4.8 is dropped.
|
||||
StmtPtrPtrTy E = nullptr;
|
||||
TSIPtrPtrTy TSI; // Kept in sync with E.
|
||||
unsigned Offset = 0, SelectedOffset = 0;
|
||||
AssociationIteratorTy(StmtPtrPtrTy E, TSIPtrPtrTy TSI, unsigned Offset,
|
||||
|
|
@ -6410,7 +6621,7 @@ public:
|
|||
enum AtomicOp {
|
||||
#define BUILTIN(ID, TYPE, ATTRS)
|
||||
#define ATOMIC_BUILTIN(ID, TYPE, ATTRS) AO ## ID,
|
||||
#include "clang/Basic/Builtins.def"
|
||||
#include "clang/Basic/Builtins.inc"
|
||||
// Avoid trailing comma
|
||||
BI_First = 0
|
||||
};
|
||||
|
|
@ -6476,7 +6687,7 @@ public:
|
|||
#define ATOMIC_BUILTIN(ID, TYPE, ATTRS) \
|
||||
case AO##ID: \
|
||||
return #ID;
|
||||
#include "clang/Basic/Builtins.def"
|
||||
#include "clang/Basic/Builtins.inc"
|
||||
}
|
||||
llvm_unreachable("not an atomic operator?");
|
||||
}
|
||||
|
|
@ -6505,8 +6716,8 @@ public:
|
|||
}
|
||||
|
||||
bool isOpenCL() const {
|
||||
return getOp() >= AO__opencl_atomic_init &&
|
||||
getOp() <= AO__opencl_atomic_fetch_max;
|
||||
return getOp() >= AO__opencl_atomic_compare_exchange_strong &&
|
||||
getOp() <= AO__opencl_atomic_store;
|
||||
}
|
||||
|
||||
SourceLocation getBuiltinLoc() const { return BuiltinLoc; }
|
||||
|
|
@ -6531,11 +6742,14 @@ public:
|
|||
/// \return empty atomic scope model if the atomic op code does not have
|
||||
/// scope operand.
|
||||
static std::unique_ptr<AtomicScopeModel> getScopeModel(AtomicOp Op) {
|
||||
if (Op >= AO__opencl_atomic_load && Op <= AO__opencl_atomic_fetch_max)
|
||||
// FIXME: Allow grouping of builtins to be able to only check >= and <=
|
||||
if (Op >= AO__opencl_atomic_compare_exchange_strong &&
|
||||
Op <= AO__opencl_atomic_store && Op != AO__opencl_atomic_init)
|
||||
return AtomicScopeModel::create(AtomicScopeModelKind::OpenCL);
|
||||
else if (Op >= AO__hip_atomic_load && Op <= AO__hip_atomic_fetch_max)
|
||||
if (Op >= AO__hip_atomic_compare_exchange_strong &&
|
||||
Op <= AO__hip_atomic_store)
|
||||
return AtomicScopeModel::create(AtomicScopeModelKind::HIP);
|
||||
else if (Op >= AO__scoped_atomic_load && Op <= AO__scoped_atomic_fetch_max)
|
||||
if (Op >= AO__scoped_atomic_add_fetch && Op <= AO__scoped_atomic_xor_fetch)
|
||||
return AtomicScopeModel::create(AtomicScopeModelKind::Generic);
|
||||
return AtomicScopeModel::create(AtomicScopeModelKind::None);
|
||||
}
|
||||
|
|
@ -6578,6 +6792,275 @@ public:
|
|||
|
||||
};
|
||||
|
||||
/// This class represents BOTH the OpenMP Array Section and OpenACC 'subarray',
|
||||
/// with a boolean differentiator.
|
||||
/// OpenMP 5.0 [2.1.5, Array Sections].
|
||||
/// To specify an array section in an OpenMP construct, array subscript
|
||||
/// expressions are extended with the following syntax:
|
||||
/// \code
|
||||
/// [ lower-bound : length : stride ]
|
||||
/// [ lower-bound : length : ]
|
||||
/// [ lower-bound : length ]
|
||||
/// [ lower-bound : : stride ]
|
||||
/// [ lower-bound : : ]
|
||||
/// [ lower-bound : ]
|
||||
/// [ : length : stride ]
|
||||
/// [ : length : ]
|
||||
/// [ : length ]
|
||||
/// [ : : stride ]
|
||||
/// [ : : ]
|
||||
/// [ : ]
|
||||
/// \endcode
|
||||
/// The array section must be a subset of the original array.
|
||||
/// Array sections are allowed on multidimensional arrays. Base language array
|
||||
/// subscript expressions can be used to specify length-one dimensions of
|
||||
/// multidimensional array sections.
|
||||
/// Each of the lower-bound, length, and stride expressions if specified must be
|
||||
/// an integral type expressions of the base language. When evaluated
|
||||
/// they represent a set of integer values as follows:
|
||||
/// \code
|
||||
/// { lower-bound, lower-bound + stride, lower-bound + 2 * stride,... ,
|
||||
/// lower-bound + ((length - 1) * stride) }
|
||||
/// \endcode
|
||||
/// The lower-bound and length must evaluate to non-negative integers.
|
||||
/// The stride must evaluate to a positive integer.
|
||||
/// When the size of the array dimension is not known, the length must be
|
||||
/// specified explicitly.
|
||||
/// When the stride is absent it defaults to 1.
|
||||
/// When the length is absent it defaults to ⌈(size − lower-bound)/stride⌉,
|
||||
/// where size is the size of the array dimension. When the lower-bound is
|
||||
/// absent it defaults to 0.
|
||||
///
|
||||
///
|
||||
/// OpenACC 3.3 [2.7.1 Data Specification in Data Clauses]
|
||||
/// In C and C++, a subarray is an array name followed by an extended array
|
||||
/// range specification in brackets, with start and length, such as
|
||||
///
|
||||
/// AA[2:n]
|
||||
///
|
||||
/// If the lower bound is missing, zero is used. If the length is missing and
|
||||
/// the array has known size, the size of the array is used; otherwise the
|
||||
/// length is required. The subarray AA[2:n] means elements AA[2], AA[3], . . .
|
||||
/// , AA[2+n-1]. In C and C++, a two dimensional array may be declared in at
|
||||
/// least four ways:
|
||||
///
|
||||
/// -Statically-sized array: float AA[100][200];
|
||||
/// -Pointer to statically sized rows: typedef float row[200]; row* BB;
|
||||
/// -Statically-sized array of pointers: float* CC[200];
|
||||
/// -Pointer to pointers: float** DD;
|
||||
///
|
||||
/// Each dimension may be statically sized, or a pointer to dynamically
|
||||
/// allocated memory. Each of these may be included in a data clause using
|
||||
/// subarray notation to specify a rectangular array:
|
||||
///
|
||||
/// -AA[2:n][0:200]
|
||||
/// -BB[2:n][0:m]
|
||||
/// -CC[2:n][0:m]
|
||||
/// -DD[2:n][0:m]
|
||||
///
|
||||
/// Multidimensional rectangular subarrays in C and C++ may be specified for any
|
||||
/// array with any combination of statically-sized or dynamically-allocated
|
||||
/// dimensions. For statically sized dimensions, all dimensions except the first
|
||||
/// must specify the whole extent to preserve the contiguous data restriction,
|
||||
/// discussed below. For dynamically allocated dimensions, the implementation
|
||||
/// will allocate pointers in device memory corresponding to the pointers in
|
||||
/// local memory and will fill in those pointers as appropriate.
|
||||
///
|
||||
/// In Fortran, a subarray is an array name followed by a comma-separated list
|
||||
/// of range specifications in parentheses, with lower and upper bound
|
||||
/// subscripts, such as
|
||||
///
|
||||
/// arr(1:high,low:100)
|
||||
///
|
||||
/// If either the lower or upper bounds are missing, the declared or allocated
|
||||
/// bounds of the array, if known, are used. All dimensions except the last must
|
||||
/// specify the whole extent, to preserve the contiguous data restriction,
|
||||
/// discussed below.
|
||||
///
|
||||
/// Restrictions
|
||||
///
|
||||
/// -In Fortran, the upper bound for the last dimension of an assumed-size dummy
|
||||
/// array must be specified.
|
||||
///
|
||||
/// -In C and C++, the length for dynamically allocated dimensions of an array
|
||||
/// must be explicitly specified.
|
||||
///
|
||||
/// -In C and C++, modifying pointers in pointer arrays during the data
|
||||
/// lifetime, either on the host or on the device, may result in undefined
|
||||
/// behavior.
|
||||
///
|
||||
/// -If a subarray appears in a data clause, the implementation may choose to
|
||||
/// allocate memory for only that subarray on the accelerator.
|
||||
///
|
||||
/// -In Fortran, array pointers may appear, but pointer association is not
|
||||
/// preserved in device memory.
|
||||
///
|
||||
/// -Any array or subarray in a data clause, including Fortran array pointers,
|
||||
/// must be a contiguous section of memory, except for dynamic multidimensional
|
||||
/// C arrays.
|
||||
///
|
||||
/// -In C and C++, if a variable or array of composite type appears, all the
|
||||
/// data members of the struct or class are allocated and copied, as
|
||||
/// appropriate. If a composite member is a pointer type, the data addressed by
|
||||
/// that pointer are not implicitly copied.
|
||||
///
|
||||
/// -In Fortran, if a variable or array of composite type appears, all the
|
||||
/// members of that derived type are allocated and copied, as appropriate. If
|
||||
/// any member has the allocatable or pointer attribute, the data accessed
|
||||
/// through that member are not copied.
|
||||
///
|
||||
/// -If an expression is used in a subscript or subarray expression in a clause
|
||||
/// on a data construct, the same value is used when copying data at the end of
|
||||
/// the data region, even if the values of variables in the expression change
|
||||
/// during the data region.
|
||||
class ArraySectionExpr : public Expr {
|
||||
friend class ASTStmtReader;
|
||||
friend class ASTStmtWriter;
|
||||
|
||||
public:
|
||||
enum ArraySectionType { OMPArraySection, OpenACCArraySection };
|
||||
|
||||
private:
|
||||
enum {
|
||||
BASE,
|
||||
LOWER_BOUND,
|
||||
LENGTH,
|
||||
STRIDE,
|
||||
END_EXPR,
|
||||
OPENACC_END_EXPR = STRIDE
|
||||
};
|
||||
|
||||
ArraySectionType ASType = OMPArraySection;
|
||||
Stmt *SubExprs[END_EXPR] = {nullptr};
|
||||
SourceLocation ColonLocFirst;
|
||||
SourceLocation ColonLocSecond;
|
||||
SourceLocation RBracketLoc;
|
||||
|
||||
public:
|
||||
// Constructor for OMP array sections, which include a 'stride'.
|
||||
ArraySectionExpr(Expr *Base, Expr *LowerBound, Expr *Length, Expr *Stride,
|
||||
QualType Type, ExprValueKind VK, ExprObjectKind OK,
|
||||
SourceLocation ColonLocFirst, SourceLocation ColonLocSecond,
|
||||
SourceLocation RBracketLoc)
|
||||
: Expr(ArraySectionExprClass, Type, VK, OK), ASType(OMPArraySection),
|
||||
ColonLocFirst(ColonLocFirst), ColonLocSecond(ColonLocSecond),
|
||||
RBracketLoc(RBracketLoc) {
|
||||
setBase(Base);
|
||||
setLowerBound(LowerBound);
|
||||
setLength(Length);
|
||||
setStride(Stride);
|
||||
setDependence(computeDependence(this));
|
||||
}
|
||||
|
||||
// Constructor for OpenACC sub-arrays, which do not permit a 'stride'.
|
||||
ArraySectionExpr(Expr *Base, Expr *LowerBound, Expr *Length, QualType Type,
|
||||
ExprValueKind VK, ExprObjectKind OK, SourceLocation ColonLoc,
|
||||
SourceLocation RBracketLoc)
|
||||
: Expr(ArraySectionExprClass, Type, VK, OK), ASType(OpenACCArraySection),
|
||||
ColonLocFirst(ColonLoc), RBracketLoc(RBracketLoc) {
|
||||
setBase(Base);
|
||||
setLowerBound(LowerBound);
|
||||
setLength(Length);
|
||||
setDependence(computeDependence(this));
|
||||
}
|
||||
|
||||
/// Create an empty array section expression.
|
||||
explicit ArraySectionExpr(EmptyShell Shell)
|
||||
: Expr(ArraySectionExprClass, Shell) {}
|
||||
|
||||
/// Return original type of the base expression for array section.
|
||||
static QualType getBaseOriginalType(const Expr *Base);
|
||||
|
||||
static bool classof(const Stmt *T) {
|
||||
return T->getStmtClass() == ArraySectionExprClass;
|
||||
}
|
||||
|
||||
bool isOMPArraySection() const { return ASType == OMPArraySection; }
|
||||
bool isOpenACCArraySection() const { return ASType == OpenACCArraySection; }
|
||||
|
||||
/// Get base of the array section.
|
||||
Expr *getBase() { return cast<Expr>(SubExprs[BASE]); }
|
||||
const Expr *getBase() const { return cast<Expr>(SubExprs[BASE]); }
|
||||
|
||||
/// Get lower bound of array section.
|
||||
Expr *getLowerBound() { return cast_or_null<Expr>(SubExprs[LOWER_BOUND]); }
|
||||
const Expr *getLowerBound() const {
|
||||
return cast_or_null<Expr>(SubExprs[LOWER_BOUND]);
|
||||
}
|
||||
|
||||
/// Get length of array section.
|
||||
Expr *getLength() { return cast_or_null<Expr>(SubExprs[LENGTH]); }
|
||||
const Expr *getLength() const { return cast_or_null<Expr>(SubExprs[LENGTH]); }
|
||||
|
||||
/// Get stride of array section.
|
||||
Expr *getStride() {
|
||||
assert(ASType != OpenACCArraySection &&
|
||||
"Stride not valid in OpenACC subarrays");
|
||||
return cast_or_null<Expr>(SubExprs[STRIDE]);
|
||||
}
|
||||
|
||||
const Expr *getStride() const {
|
||||
assert(ASType != OpenACCArraySection &&
|
||||
"Stride not valid in OpenACC subarrays");
|
||||
return cast_or_null<Expr>(SubExprs[STRIDE]);
|
||||
}
|
||||
|
||||
SourceLocation getBeginLoc() const LLVM_READONLY {
|
||||
return getBase()->getBeginLoc();
|
||||
}
|
||||
SourceLocation getEndLoc() const LLVM_READONLY { return RBracketLoc; }
|
||||
|
||||
SourceLocation getColonLocFirst() const { return ColonLocFirst; }
|
||||
SourceLocation getColonLocSecond() const {
|
||||
assert(ASType != OpenACCArraySection &&
|
||||
"second colon for stride not valid in OpenACC subarrays");
|
||||
return ColonLocSecond;
|
||||
}
|
||||
SourceLocation getRBracketLoc() const { return RBracketLoc; }
|
||||
|
||||
SourceLocation getExprLoc() const LLVM_READONLY {
|
||||
return getBase()->getExprLoc();
|
||||
}
|
||||
|
||||
child_range children() {
|
||||
return child_range(
|
||||
&SubExprs[BASE],
|
||||
&SubExprs[ASType == OMPArraySection ? END_EXPR : OPENACC_END_EXPR]);
|
||||
}
|
||||
|
||||
const_child_range children() const {
|
||||
return const_child_range(
|
||||
&SubExprs[BASE],
|
||||
&SubExprs[ASType == OMPArraySection ? END_EXPR : OPENACC_END_EXPR]);
|
||||
}
|
||||
|
||||
private:
|
||||
/// Set base of the array section.
|
||||
void setBase(Expr *E) { SubExprs[BASE] = E; }
|
||||
|
||||
/// Set lower bound of the array section.
|
||||
void setLowerBound(Expr *E) { SubExprs[LOWER_BOUND] = E; }
|
||||
|
||||
/// Set length of the array section.
|
||||
void setLength(Expr *E) { SubExprs[LENGTH] = E; }
|
||||
|
||||
/// Set length of the array section.
|
||||
void setStride(Expr *E) {
|
||||
assert(ASType != OpenACCArraySection &&
|
||||
"Stride not valid in OpenACC subarrays");
|
||||
SubExprs[STRIDE] = E;
|
||||
}
|
||||
|
||||
void setColonLocFirst(SourceLocation L) { ColonLocFirst = L; }
|
||||
|
||||
void setColonLocSecond(SourceLocation L) {
|
||||
assert(ASType != OpenACCArraySection &&
|
||||
"second colon for stride not valid in OpenACC subarrays");
|
||||
ColonLocSecond = L;
|
||||
}
|
||||
void setRBracketLoc(SourceLocation L) { RBracketLoc = L; }
|
||||
};
|
||||
|
||||
/// Frontend produces RecoveryExprs on semantic errors that prevent creating
|
||||
/// other well-formed expressions. E.g. when type-checking of a binary operator
|
||||
/// fails, we cannot produce a BinaryOperator expression. Instead, we can choose
|
||||
|
|
|
|||
|
|
@ -919,6 +919,10 @@ public:
|
|||
reinterpret_cast<Stmt **>(&const_cast<CXXTypeidExpr *>(this)->Operand);
|
||||
return const_child_range(begin, begin + 1);
|
||||
}
|
||||
|
||||
/// Whether this is of a form like "typeid(*ptr)" that can throw a
|
||||
/// std::bad_typeid if a pointer is a null pointer ([expr.typeid]p2)
|
||||
bool hasNullCheck() const;
|
||||
};
|
||||
|
||||
/// A member reference to an MSPropertyDecl.
|
||||
|
|
@ -1149,6 +1153,7 @@ class CXXThisExpr : public Expr {
|
|||
CXXThisExpr(SourceLocation L, QualType Ty, bool IsImplicit, ExprValueKind VK)
|
||||
: Expr(CXXThisExprClass, Ty, VK, OK_Ordinary) {
|
||||
CXXThisExprBits.IsImplicit = IsImplicit;
|
||||
CXXThisExprBits.CapturedByCopyInLambdaWithExplicitObjectParameter = false;
|
||||
CXXThisExprBits.Loc = L;
|
||||
setDependence(computeDependence(this));
|
||||
}
|
||||
|
|
@ -1170,6 +1175,15 @@ public:
|
|||
bool isImplicit() const { return CXXThisExprBits.IsImplicit; }
|
||||
void setImplicit(bool I) { CXXThisExprBits.IsImplicit = I; }
|
||||
|
||||
bool isCapturedByCopyInLambdaWithExplicitObjectParameter() const {
|
||||
return CXXThisExprBits.CapturedByCopyInLambdaWithExplicitObjectParameter;
|
||||
}
|
||||
|
||||
void setCapturedByCopyInLambdaWithExplicitObjectParameter(bool Set) {
|
||||
CXXThisExprBits.CapturedByCopyInLambdaWithExplicitObjectParameter = Set;
|
||||
setDependence(computeDependence(this));
|
||||
}
|
||||
|
||||
static bool classof(const Stmt *T) {
|
||||
return T->getStmtClass() == CXXThisExprClass;
|
||||
}
|
||||
|
|
@ -1472,6 +1486,8 @@ public:
|
|||
/// const S &s_ref = S(); // Requires a CXXBindTemporaryExpr.
|
||||
/// }
|
||||
/// \endcode
|
||||
///
|
||||
/// Destructor might be null if destructor declaration is not valid.
|
||||
class CXXBindTemporaryExpr : public Expr {
|
||||
CXXTemporary *Temp = nullptr;
|
||||
Stmt *SubExpr = nullptr;
|
||||
|
|
@ -2549,7 +2565,7 @@ public:
|
|||
class PseudoDestructorTypeStorage {
|
||||
/// Either the type source information or the name of the type, if
|
||||
/// it couldn't be resolved due to type-dependence.
|
||||
llvm::PointerUnion<TypeSourceInfo *, IdentifierInfo *> Type;
|
||||
llvm::PointerUnion<TypeSourceInfo *, const IdentifierInfo *> Type;
|
||||
|
||||
/// The starting source location of the pseudo-destructor type.
|
||||
SourceLocation Location;
|
||||
|
|
@ -2557,7 +2573,7 @@ class PseudoDestructorTypeStorage {
|
|||
public:
|
||||
PseudoDestructorTypeStorage() = default;
|
||||
|
||||
PseudoDestructorTypeStorage(IdentifierInfo *II, SourceLocation Loc)
|
||||
PseudoDestructorTypeStorage(const IdentifierInfo *II, SourceLocation Loc)
|
||||
: Type(II), Location(Loc) {}
|
||||
|
||||
PseudoDestructorTypeStorage(TypeSourceInfo *Info);
|
||||
|
|
@ -2566,8 +2582,8 @@ public:
|
|||
return Type.dyn_cast<TypeSourceInfo *>();
|
||||
}
|
||||
|
||||
IdentifierInfo *getIdentifier() const {
|
||||
return Type.dyn_cast<IdentifierInfo *>();
|
||||
const IdentifierInfo *getIdentifier() const {
|
||||
return Type.dyn_cast<const IdentifierInfo *>();
|
||||
}
|
||||
|
||||
SourceLocation getLocation() const { return Location; }
|
||||
|
|
@ -2698,7 +2714,7 @@ public:
|
|||
/// In a dependent pseudo-destructor expression for which we do not
|
||||
/// have full type information on the destroyed type, provides the name
|
||||
/// of the destroyed type.
|
||||
IdentifierInfo *getDestroyedTypeIdentifier() const {
|
||||
const IdentifierInfo *getDestroyedTypeIdentifier() const {
|
||||
return DestroyedType.getIdentifier();
|
||||
}
|
||||
|
||||
|
|
@ -3013,9 +3029,10 @@ protected:
|
|||
|
||||
public:
|
||||
struct FindResult {
|
||||
OverloadExpr *Expression;
|
||||
bool IsAddressOfOperand;
|
||||
bool HasFormOfMemberPointer;
|
||||
OverloadExpr *Expression = nullptr;
|
||||
bool IsAddressOfOperand = false;
|
||||
bool IsAddressOfOperandWithParen = false;
|
||||
bool HasFormOfMemberPointer = false;
|
||||
};
|
||||
|
||||
/// Finds the overloaded expression in the given expression \p E of
|
||||
|
|
@ -3027,6 +3044,7 @@ public:
|
|||
assert(E->getType()->isSpecificBuiltinType(BuiltinType::Overload));
|
||||
|
||||
FindResult Result;
|
||||
bool HasParen = isa<ParenExpr>(E);
|
||||
|
||||
E = E->IgnoreParens();
|
||||
if (isa<UnaryOperator>(E)) {
|
||||
|
|
@ -3036,10 +3054,9 @@ public:
|
|||
|
||||
Result.HasFormOfMemberPointer = (E == Ovl && Ovl->getQualifier());
|
||||
Result.IsAddressOfOperand = true;
|
||||
Result.IsAddressOfOperandWithParen = HasParen;
|
||||
Result.Expression = Ovl;
|
||||
} else {
|
||||
Result.HasFormOfMemberPointer = false;
|
||||
Result.IsAddressOfOperand = false;
|
||||
Result.Expression = cast<OverloadExpr>(E);
|
||||
}
|
||||
|
||||
|
|
@ -3151,8 +3168,30 @@ public:
|
|||
/// This arises in several ways:
|
||||
/// * we might be waiting for argument-dependent lookup;
|
||||
/// * the name might resolve to an overloaded function;
|
||||
/// * the name might resolve to a non-function template; for example, in the
|
||||
/// following snippet, the return expression of the member function
|
||||
/// 'foo()' might remain unresolved until instantiation:
|
||||
///
|
||||
/// \code
|
||||
/// struct P {
|
||||
/// template <class T> using I = T;
|
||||
/// };
|
||||
///
|
||||
/// struct Q {
|
||||
/// template <class T> int foo() {
|
||||
/// return T::template I<int>;
|
||||
/// }
|
||||
/// };
|
||||
/// \endcode
|
||||
///
|
||||
/// ...which is distinct from modeling function overloads, and therefore we use
|
||||
/// a different builtin type 'UnresolvedTemplate' to avoid confusion. This is
|
||||
/// done in Sema::BuildTemplateIdExpr.
|
||||
///
|
||||
/// and eventually:
|
||||
/// * the lookup might have included a function template.
|
||||
/// * the unresolved template gets transformed in an instantiation or gets
|
||||
/// diagnosed for its direct use.
|
||||
///
|
||||
/// These never include UnresolvedUsingValueDecls, which are always class
|
||||
/// members and therefore appear only in UnresolvedMemberLookupExprs.
|
||||
|
|
@ -3188,7 +3227,6 @@ class UnresolvedLookupExpr final
|
|||
NestedNameSpecifierLoc QualifierLoc,
|
||||
SourceLocation TemplateKWLoc,
|
||||
const DeclarationNameInfo &NameInfo, bool RequiresADL,
|
||||
bool Overloaded,
|
||||
const TemplateArgumentListInfo *TemplateArgs,
|
||||
UnresolvedSetIterator Begin, UnresolvedSetIterator End,
|
||||
bool KnownDependent);
|
||||
|
|
@ -3208,8 +3246,9 @@ public:
|
|||
static UnresolvedLookupExpr *
|
||||
Create(const ASTContext &Context, CXXRecordDecl *NamingClass,
|
||||
NestedNameSpecifierLoc QualifierLoc,
|
||||
const DeclarationNameInfo &NameInfo, bool RequiresADL, bool Overloaded,
|
||||
UnresolvedSetIterator Begin, UnresolvedSetIterator End);
|
||||
const DeclarationNameInfo &NameInfo, bool RequiresADL,
|
||||
UnresolvedSetIterator Begin, UnresolvedSetIterator End,
|
||||
bool KnownDependent);
|
||||
|
||||
// After canonicalization, there may be dependent template arguments in
|
||||
// CanonicalConverted But none of Args is dependent. When any of
|
||||
|
|
@ -3230,9 +3269,6 @@ public:
|
|||
/// argument-dependent lookup.
|
||||
bool requiresADL() const { return UnresolvedLookupExprBits.RequiresADL; }
|
||||
|
||||
/// True if this lookup is overloaded.
|
||||
bool isOverloaded() const { return UnresolvedLookupExprBits.Overloaded; }
|
||||
|
||||
/// Gets the 'naming class' (in the sense of C++0x
|
||||
/// [class.access.base]p5) of the lookup. This is the scope
|
||||
/// that was looked in to find these results.
|
||||
|
|
@ -4331,6 +4367,116 @@ public:
|
|||
}
|
||||
};
|
||||
|
||||
class PackIndexingExpr final
|
||||
: public Expr,
|
||||
private llvm::TrailingObjects<PackIndexingExpr, Expr *> {
|
||||
friend class ASTStmtReader;
|
||||
friend class ASTStmtWriter;
|
||||
friend TrailingObjects;
|
||||
|
||||
SourceLocation EllipsisLoc;
|
||||
|
||||
// The location of the closing bracket
|
||||
SourceLocation RSquareLoc;
|
||||
|
||||
// The pack being indexed, followed by the index
|
||||
Stmt *SubExprs[2];
|
||||
|
||||
// The size of the trailing expressions.
|
||||
unsigned TransformedExpressions : 31;
|
||||
|
||||
LLVM_PREFERRED_TYPE(bool)
|
||||
unsigned ExpandedToEmptyPack : 1;
|
||||
|
||||
PackIndexingExpr(QualType Type, SourceLocation EllipsisLoc,
|
||||
SourceLocation RSquareLoc, Expr *PackIdExpr, Expr *IndexExpr,
|
||||
ArrayRef<Expr *> SubstitutedExprs = {},
|
||||
bool ExpandedToEmptyPack = false)
|
||||
: Expr(PackIndexingExprClass, Type, VK_LValue, OK_Ordinary),
|
||||
EllipsisLoc(EllipsisLoc), RSquareLoc(RSquareLoc),
|
||||
SubExprs{PackIdExpr, IndexExpr},
|
||||
TransformedExpressions(SubstitutedExprs.size()),
|
||||
ExpandedToEmptyPack(ExpandedToEmptyPack) {
|
||||
|
||||
auto *Exprs = getTrailingObjects<Expr *>();
|
||||
std::uninitialized_copy(SubstitutedExprs.begin(), SubstitutedExprs.end(),
|
||||
Exprs);
|
||||
|
||||
setDependence(computeDependence(this));
|
||||
if (!isInstantiationDependent())
|
||||
setValueKind(getSelectedExpr()->getValueKind());
|
||||
}
|
||||
|
||||
/// Create an empty expression.
|
||||
PackIndexingExpr(EmptyShell Empty) : Expr(PackIndexingExprClass, Empty) {}
|
||||
|
||||
unsigned numTrailingObjects(OverloadToken<Expr *>) const {
|
||||
return TransformedExpressions;
|
||||
}
|
||||
|
||||
public:
|
||||
static PackIndexingExpr *Create(ASTContext &Context,
|
||||
SourceLocation EllipsisLoc,
|
||||
SourceLocation RSquareLoc, Expr *PackIdExpr,
|
||||
Expr *IndexExpr, std::optional<int64_t> Index,
|
||||
ArrayRef<Expr *> SubstitutedExprs = {},
|
||||
bool ExpandedToEmptyPack = false);
|
||||
static PackIndexingExpr *CreateDeserialized(ASTContext &Context,
|
||||
unsigned NumTransformedExprs);
|
||||
|
||||
/// Determine if the expression was expanded to empty.
|
||||
bool expandsToEmptyPack() const { return ExpandedToEmptyPack; }
|
||||
|
||||
/// Determine the location of the 'sizeof' keyword.
|
||||
SourceLocation getEllipsisLoc() const { return EllipsisLoc; }
|
||||
|
||||
/// Determine the location of the parameter pack.
|
||||
SourceLocation getPackLoc() const { return SubExprs[0]->getBeginLoc(); }
|
||||
|
||||
/// Determine the location of the right parenthesis.
|
||||
SourceLocation getRSquareLoc() const { return RSquareLoc; }
|
||||
|
||||
SourceLocation getBeginLoc() const LLVM_READONLY { return getPackLoc(); }
|
||||
SourceLocation getEndLoc() const LLVM_READONLY { return RSquareLoc; }
|
||||
|
||||
Expr *getPackIdExpression() const { return cast<Expr>(SubExprs[0]); }
|
||||
|
||||
NamedDecl *getPackDecl() const;
|
||||
|
||||
Expr *getIndexExpr() const { return cast<Expr>(SubExprs[1]); }
|
||||
|
||||
std::optional<unsigned> getSelectedIndex() const {
|
||||
if (isInstantiationDependent())
|
||||
return std::nullopt;
|
||||
ConstantExpr *CE = cast<ConstantExpr>(getIndexExpr());
|
||||
auto Index = CE->getResultAsAPSInt();
|
||||
assert(Index.isNonNegative() && "Invalid index");
|
||||
return static_cast<unsigned>(Index.getExtValue());
|
||||
}
|
||||
|
||||
Expr *getSelectedExpr() const {
|
||||
std::optional<unsigned> Index = getSelectedIndex();
|
||||
assert(Index && "extracting the indexed expression of a dependant pack");
|
||||
return getTrailingObjects<Expr *>()[*Index];
|
||||
}
|
||||
|
||||
/// Return the trailing expressions, regardless of the expansion.
|
||||
ArrayRef<Expr *> getExpressions() const {
|
||||
return {getTrailingObjects<Expr *>(), TransformedExpressions};
|
||||
}
|
||||
|
||||
static bool classof(const Stmt *T) {
|
||||
return T->getStmtClass() == PackIndexingExprClass;
|
||||
}
|
||||
|
||||
// Iterators
|
||||
child_range children() { return child_range(SubExprs, SubExprs + 2); }
|
||||
|
||||
const_child_range children() const {
|
||||
return const_child_range(SubExprs, SubExprs + 2);
|
||||
}
|
||||
};
|
||||
|
||||
/// Represents a reference to a non-type template parameter
|
||||
/// that has been substituted with a template argument.
|
||||
class SubstNonTypeTemplateParmExpr : public Expr {
|
||||
|
|
@ -4939,6 +5085,9 @@ class CoroutineSuspendExpr : public Expr {
|
|||
OpaqueValueExpr *OpaqueValue = nullptr;
|
||||
|
||||
public:
|
||||
// These types correspond to the three C++ 'await_suspend' return variants
|
||||
enum class SuspendReturnType { SuspendVoid, SuspendBool, SuspendHandle };
|
||||
|
||||
CoroutineSuspendExpr(StmtClass SC, SourceLocation KeywordLoc, Expr *Operand,
|
||||
Expr *Common, Expr *Ready, Expr *Suspend, Expr *Resume,
|
||||
OpaqueValueExpr *OpaqueValue)
|
||||
|
|
@ -4998,6 +5147,24 @@ public:
|
|||
return static_cast<Expr *>(SubExprs[SubExpr::Operand]);
|
||||
}
|
||||
|
||||
SuspendReturnType getSuspendReturnType() const {
|
||||
auto *SuspendExpr = getSuspendExpr();
|
||||
assert(SuspendExpr);
|
||||
|
||||
auto SuspendType = SuspendExpr->getType();
|
||||
|
||||
if (SuspendType->isVoidType())
|
||||
return SuspendReturnType::SuspendVoid;
|
||||
if (SuspendType->isBooleanType())
|
||||
return SuspendReturnType::SuspendBool;
|
||||
|
||||
// Void pointer is the type of handle.address(), which is returned
|
||||
// from the await suspend wrapper so that the temporary coroutine handle
|
||||
// value won't go to the frame by mistake
|
||||
assert(SuspendType->isVoidPointerType());
|
||||
return SuspendReturnType::SuspendHandle;
|
||||
}
|
||||
|
||||
SourceLocation getKeywordLoc() const { return KeywordLoc; }
|
||||
|
||||
SourceLocation getBeginLoc() const LLVM_READONLY { return KeywordLoc; }
|
||||
|
|
|
|||
|
|
@ -17,130 +17,6 @@
|
|||
#include "clang/AST/Expr.h"
|
||||
|
||||
namespace clang {
|
||||
/// OpenMP 5.0 [2.1.5, Array Sections].
|
||||
/// To specify an array section in an OpenMP construct, array subscript
|
||||
/// expressions are extended with the following syntax:
|
||||
/// \code
|
||||
/// [ lower-bound : length : stride ]
|
||||
/// [ lower-bound : length : ]
|
||||
/// [ lower-bound : length ]
|
||||
/// [ lower-bound : : stride ]
|
||||
/// [ lower-bound : : ]
|
||||
/// [ lower-bound : ]
|
||||
/// [ : length : stride ]
|
||||
/// [ : length : ]
|
||||
/// [ : length ]
|
||||
/// [ : : stride ]
|
||||
/// [ : : ]
|
||||
/// [ : ]
|
||||
/// \endcode
|
||||
/// The array section must be a subset of the original array.
|
||||
/// Array sections are allowed on multidimensional arrays. Base language array
|
||||
/// subscript expressions can be used to specify length-one dimensions of
|
||||
/// multidimensional array sections.
|
||||
/// Each of the lower-bound, length, and stride expressions if specified must be
|
||||
/// an integral type expressions of the base language. When evaluated
|
||||
/// they represent a set of integer values as follows:
|
||||
/// \code
|
||||
/// { lower-bound, lower-bound + stride, lower-bound + 2 * stride,... ,
|
||||
/// lower-bound + ((length - 1) * stride) }
|
||||
/// \endcode
|
||||
/// The lower-bound and length must evaluate to non-negative integers.
|
||||
/// The stride must evaluate to a positive integer.
|
||||
/// When the size of the array dimension is not known, the length must be
|
||||
/// specified explicitly.
|
||||
/// When the stride is absent it defaults to 1.
|
||||
/// When the length is absent it defaults to ⌈(size − lower-bound)/stride⌉,
|
||||
/// where size is the size of the array dimension. When the lower-bound is
|
||||
/// absent it defaults to 0.
|
||||
class OMPArraySectionExpr : public Expr {
|
||||
enum { BASE, LOWER_BOUND, LENGTH, STRIDE, END_EXPR };
|
||||
Stmt *SubExprs[END_EXPR];
|
||||
SourceLocation ColonLocFirst;
|
||||
SourceLocation ColonLocSecond;
|
||||
SourceLocation RBracketLoc;
|
||||
|
||||
public:
|
||||
OMPArraySectionExpr(Expr *Base, Expr *LowerBound, Expr *Length, Expr *Stride,
|
||||
QualType Type, ExprValueKind VK, ExprObjectKind OK,
|
||||
SourceLocation ColonLocFirst,
|
||||
SourceLocation ColonLocSecond, SourceLocation RBracketLoc)
|
||||
: Expr(OMPArraySectionExprClass, Type, VK, OK),
|
||||
ColonLocFirst(ColonLocFirst), ColonLocSecond(ColonLocSecond),
|
||||
RBracketLoc(RBracketLoc) {
|
||||
SubExprs[BASE] = Base;
|
||||
SubExprs[LOWER_BOUND] = LowerBound;
|
||||
SubExprs[LENGTH] = Length;
|
||||
SubExprs[STRIDE] = Stride;
|
||||
setDependence(computeDependence(this));
|
||||
}
|
||||
|
||||
/// Create an empty array section expression.
|
||||
explicit OMPArraySectionExpr(EmptyShell Shell)
|
||||
: Expr(OMPArraySectionExprClass, Shell) {}
|
||||
|
||||
/// An array section can be written only as Base[LowerBound:Length].
|
||||
|
||||
/// Get base of the array section.
|
||||
Expr *getBase() { return cast<Expr>(SubExprs[BASE]); }
|
||||
const Expr *getBase() const { return cast<Expr>(SubExprs[BASE]); }
|
||||
/// Set base of the array section.
|
||||
void setBase(Expr *E) { SubExprs[BASE] = E; }
|
||||
|
||||
/// Return original type of the base expression for array section.
|
||||
static QualType getBaseOriginalType(const Expr *Base);
|
||||
|
||||
/// Get lower bound of array section.
|
||||
Expr *getLowerBound() { return cast_or_null<Expr>(SubExprs[LOWER_BOUND]); }
|
||||
const Expr *getLowerBound() const {
|
||||
return cast_or_null<Expr>(SubExprs[LOWER_BOUND]);
|
||||
}
|
||||
/// Set lower bound of the array section.
|
||||
void setLowerBound(Expr *E) { SubExprs[LOWER_BOUND] = E; }
|
||||
|
||||
/// Get length of array section.
|
||||
Expr *getLength() { return cast_or_null<Expr>(SubExprs[LENGTH]); }
|
||||
const Expr *getLength() const { return cast_or_null<Expr>(SubExprs[LENGTH]); }
|
||||
/// Set length of the array section.
|
||||
void setLength(Expr *E) { SubExprs[LENGTH] = E; }
|
||||
|
||||
/// Get stride of array section.
|
||||
Expr *getStride() { return cast_or_null<Expr>(SubExprs[STRIDE]); }
|
||||
const Expr *getStride() const { return cast_or_null<Expr>(SubExprs[STRIDE]); }
|
||||
/// Set length of the array section.
|
||||
void setStride(Expr *E) { SubExprs[STRIDE] = E; }
|
||||
|
||||
SourceLocation getBeginLoc() const LLVM_READONLY {
|
||||
return getBase()->getBeginLoc();
|
||||
}
|
||||
SourceLocation getEndLoc() const LLVM_READONLY { return RBracketLoc; }
|
||||
|
||||
SourceLocation getColonLocFirst() const { return ColonLocFirst; }
|
||||
void setColonLocFirst(SourceLocation L) { ColonLocFirst = L; }
|
||||
|
||||
SourceLocation getColonLocSecond() const { return ColonLocSecond; }
|
||||
void setColonLocSecond(SourceLocation L) { ColonLocSecond = L; }
|
||||
|
||||
SourceLocation getRBracketLoc() const { return RBracketLoc; }
|
||||
void setRBracketLoc(SourceLocation L) { RBracketLoc = L; }
|
||||
|
||||
SourceLocation getExprLoc() const LLVM_READONLY {
|
||||
return getBase()->getExprLoc();
|
||||
}
|
||||
|
||||
static bool classof(const Stmt *T) {
|
||||
return T->getStmtClass() == OMPArraySectionExprClass;
|
||||
}
|
||||
|
||||
child_range children() {
|
||||
return child_range(&SubExprs[BASE], &SubExprs[END_EXPR]);
|
||||
}
|
||||
|
||||
const_child_range children() const {
|
||||
return const_child_range(&SubExprs[BASE], &SubExprs[END_EXPR]);
|
||||
}
|
||||
};
|
||||
|
||||
/// An explicit cast in C or a C-style cast in C++, which uses the syntax
|
||||
/// ([s1][s2]...[sn])expr. For example: @c ([3][3])f.
|
||||
class OMPArrayShapingExpr final
|
||||
|
|
|
|||
|
|
@ -99,7 +99,7 @@ public:
|
|||
/// passes back decl sets as VisibleDeclaration objects.
|
||||
///
|
||||
/// The default implementation of this method is a no-op.
|
||||
virtual Decl *GetExternalDecl(uint32_t ID);
|
||||
virtual Decl *GetExternalDecl(GlobalDeclID ID);
|
||||
|
||||
/// Resolve a selector ID into a selector.
|
||||
///
|
||||
|
|
@ -138,7 +138,7 @@ public:
|
|||
virtual CXXBaseSpecifier *GetExternalCXXBaseSpecifiers(uint64_t Offset);
|
||||
|
||||
/// Update an out-of-date identifier.
|
||||
virtual void updateOutOfDateIdentifier(IdentifierInfo &II) {}
|
||||
virtual void updateOutOfDateIdentifier(const IdentifierInfo &II) {}
|
||||
|
||||
/// Find all declarations with the given name in the given context,
|
||||
/// and add them to the context by calling SetExternalVisibleDeclsForName
|
||||
|
|
@ -375,7 +375,7 @@ public:
|
|||
if (isOffset()) {
|
||||
assert(Source &&
|
||||
"Cannot deserialize a lazy pointer without an AST source");
|
||||
Ptr = reinterpret_cast<uint64_t>((Source->*Get)(Ptr >> 1));
|
||||
Ptr = reinterpret_cast<uint64_t>((Source->*Get)(OffsT(Ptr >> 1)));
|
||||
}
|
||||
return reinterpret_cast<T*>(Ptr);
|
||||
}
|
||||
|
|
@ -579,7 +579,7 @@ using LazyDeclStmtPtr =
|
|||
|
||||
/// A lazy pointer to a declaration.
|
||||
using LazyDeclPtr =
|
||||
LazyOffsetPtr<Decl, uint32_t, &ExternalASTSource::GetExternalDecl>;
|
||||
LazyOffsetPtr<Decl, GlobalDeclID, &ExternalASTSource::GetExternalDecl>;
|
||||
|
||||
/// A lazy pointer to a set of CXXCtorInitializers.
|
||||
using LazyCXXCtorInitializersPtr =
|
||||
|
|
|
|||
|
|
@ -171,6 +171,14 @@ public:
|
|||
|
||||
ZArg, // MS extension
|
||||
|
||||
// ISO/IEC TR 18037 (fixed-point) specific specifiers.
|
||||
kArg, // %k for signed accum types
|
||||
KArg, // %K for unsigned accum types
|
||||
rArg, // %r for signed fract types
|
||||
RArg, // %R for unsigned fract types
|
||||
FixedPointArgBeg = kArg,
|
||||
FixedPointArgEnd = RArg,
|
||||
|
||||
// Objective-C specific specifiers.
|
||||
ObjCObjArg, // '@'
|
||||
ObjCBeg = ObjCObjArg,
|
||||
|
|
@ -237,6 +245,9 @@ public:
|
|||
bool isDoubleArg() const {
|
||||
return kind >= DoubleArgBeg && kind <= DoubleArgEnd;
|
||||
}
|
||||
bool isFixedPointArg() const {
|
||||
return kind >= FixedPointArgBeg && kind <= FixedPointArgEnd;
|
||||
}
|
||||
|
||||
const char *toString() const;
|
||||
|
||||
|
|
@ -273,6 +284,8 @@ public:
|
|||
/// The conversion specifier and the argument type are disallowed by the C
|
||||
/// standard, but are in practice harmless. For instance, "%p" and int*.
|
||||
NoMatchPedantic,
|
||||
/// The conversion specifier and the argument type have different sign.
|
||||
NoMatchSignedness,
|
||||
/// The conversion specifier and the argument type are compatible, but still
|
||||
/// seems likely to be an error. For instance, "%hd" and _Bool.
|
||||
NoMatchTypeConfusion,
|
||||
|
|
|
|||
|
|
@ -145,6 +145,10 @@ public:
|
|||
LHS.MultiVersionIndex == RHS.MultiVersionIndex;
|
||||
}
|
||||
|
||||
bool operator!=(const GlobalDecl &Other) const {
|
||||
return !(*this == Other);
|
||||
}
|
||||
|
||||
void *getAsOpaquePtr() const { return Value.getOpaqueValue(); }
|
||||
|
||||
explicit operator bool() const { return getAsOpaquePtr(); }
|
||||
|
|
|
|||
|
|
@ -197,16 +197,19 @@ public:
|
|||
void Visit(const Type *T);
|
||||
void Visit(QualType T);
|
||||
void Visit(const Decl *D);
|
||||
void Visit(TypeLoc TL);
|
||||
|
||||
void Visit(const comments::Comment *C, const comments::FullComment *FC);
|
||||
void Visit(const TemplateArgument &TA, SourceRange R = {},
|
||||
const Decl *From = nullptr, StringRef Label = {});
|
||||
void Visit(const CXXCtorInitializer *Init);
|
||||
void Visit(const OpenACCClause *C);
|
||||
void Visit(const OMPClause *C);
|
||||
void Visit(const BlockDecl::Capture &C);
|
||||
void Visit(const GenericSelectionExpr::ConstAssociation &A);
|
||||
void Visit(const concepts::Requirement *R);
|
||||
void Visit(const APValue &Value, QualType Ty);
|
||||
void Visit(const ConceptReference *);
|
||||
|
||||
void VisitAliasAttr(const AliasAttr *AA);
|
||||
void VisitCleanupAttr(const CleanupAttr *CA);
|
||||
|
|
@ -307,6 +310,8 @@ public:
|
|||
void VisitMaterializeTemporaryExpr(const MaterializeTemporaryExpr *MTE);
|
||||
void VisitCXXDependentScopeMemberExpr(const CXXDependentScopeMemberExpr *ME);
|
||||
void VisitRequiresExpr(const RequiresExpr *RE);
|
||||
void VisitCXXDefaultArgExpr(const CXXDefaultArgExpr *Node);
|
||||
void VisitCXXDefaultInitExpr(const CXXDefaultInitExpr *Node);
|
||||
|
||||
void VisitObjCEncodeExpr(const ObjCEncodeExpr *OEE);
|
||||
void VisitObjCMessageExpr(const ObjCMessageExpr *OME);
|
||||
|
|
|
|||
|
|
@ -130,15 +130,15 @@ public:
|
|||
// FIXME: consider replacing raw_ostream & with something like SmallString &.
|
||||
void mangleName(GlobalDecl GD, raw_ostream &);
|
||||
virtual void mangleCXXName(GlobalDecl GD, raw_ostream &) = 0;
|
||||
virtual void mangleThunk(const CXXMethodDecl *MD,
|
||||
const ThunkInfo &Thunk,
|
||||
raw_ostream &) = 0;
|
||||
virtual void mangleThunk(const CXXMethodDecl *MD, const ThunkInfo &Thunk,
|
||||
bool ElideOverrideInfo, raw_ostream &) = 0;
|
||||
virtual void mangleCXXDtorThunk(const CXXDestructorDecl *DD, CXXDtorType Type,
|
||||
const ThisAdjustment &ThisAdjustment,
|
||||
raw_ostream &) = 0;
|
||||
const ThunkInfo &Thunk,
|
||||
bool ElideOverrideInfo, raw_ostream &) = 0;
|
||||
virtual void mangleReferenceTemporary(const VarDecl *D,
|
||||
unsigned ManglingNumber,
|
||||
raw_ostream &) = 0;
|
||||
virtual void mangleCXXVTable(const CXXRecordDecl *RD, raw_ostream &) = 0;
|
||||
virtual void mangleCXXRTTI(QualType T, raw_ostream &) = 0;
|
||||
virtual void mangleCXXRTTIName(QualType T, raw_ostream &,
|
||||
bool NormalizeIntegers = false) = 0;
|
||||
|
|
@ -192,7 +192,6 @@ public:
|
|||
bool IsAux = false)
|
||||
: MangleContext(C, D, MK_Itanium, IsAux) {}
|
||||
|
||||
virtual void mangleCXXVTable(const CXXRecordDecl *RD, raw_ostream &) = 0;
|
||||
virtual void mangleCXXVTT(const CXXRecordDecl *RD, raw_ostream &) = 0;
|
||||
virtual void mangleCXXCtorVTable(const CXXRecordDecl *RD, int64_t Offset,
|
||||
const CXXRecordDecl *Type,
|
||||
|
|
|
|||
|
|
@ -124,7 +124,7 @@ public:
|
|||
/// cannot be resolved.
|
||||
static NestedNameSpecifier *Create(const ASTContext &Context,
|
||||
NestedNameSpecifier *Prefix,
|
||||
IdentifierInfo *II);
|
||||
const IdentifierInfo *II);
|
||||
|
||||
/// Builds a nested name specifier that names a namespace.
|
||||
static NestedNameSpecifier *Create(const ASTContext &Context,
|
||||
|
|
@ -134,7 +134,7 @@ public:
|
|||
/// Builds a nested name specifier that names a namespace alias.
|
||||
static NestedNameSpecifier *Create(const ASTContext &Context,
|
||||
NestedNameSpecifier *Prefix,
|
||||
NamespaceAliasDecl *Alias);
|
||||
const NamespaceAliasDecl *Alias);
|
||||
|
||||
/// Builds a nested name specifier that names a type.
|
||||
static NestedNameSpecifier *Create(const ASTContext &Context,
|
||||
|
|
@ -148,7 +148,7 @@ public:
|
|||
/// nested name specifier, e.g., in "x->Base::f", the "x" has a dependent
|
||||
/// type.
|
||||
static NestedNameSpecifier *Create(const ASTContext &Context,
|
||||
IdentifierInfo *II);
|
||||
const IdentifierInfo *II);
|
||||
|
||||
/// Returns the nested name specifier representing the global
|
||||
/// scope.
|
||||
|
|
@ -266,7 +266,7 @@ public:
|
|||
explicit operator bool() const { return Qualifier; }
|
||||
|
||||
/// Evaluates true when this nested-name-specifier location is
|
||||
/// empty.
|
||||
/// non-empty.
|
||||
bool hasQualifier() const { return Qualifier; }
|
||||
|
||||
/// Retrieve the nested-name-specifier to which this instance
|
||||
|
|
|
|||
917
contrib/llvm-project/clang/include/clang/AST/OpenACCClause.h
Normal file
917
contrib/llvm-project/clang/include/clang/AST/OpenACCClause.h
Normal file
|
|
@ -0,0 +1,917 @@
|
|||
//===- OpenACCClause.h - Classes for OpenACC clauses ------------*- 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
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// \file
|
||||
// This file defines OpenACC AST classes for clauses.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef LLVM_CLANG_AST_OPENACCCLAUSE_H
|
||||
#define LLVM_CLANG_AST_OPENACCCLAUSE_H
|
||||
#include "clang/AST/ASTContext.h"
|
||||
#include "clang/AST/StmtIterator.h"
|
||||
#include "clang/Basic/OpenACCKinds.h"
|
||||
|
||||
#include <utility>
|
||||
|
||||
namespace clang {
|
||||
/// This is the base type for all OpenACC Clauses.
|
||||
class OpenACCClause {
|
||||
OpenACCClauseKind Kind;
|
||||
SourceRange Location;
|
||||
|
||||
protected:
|
||||
OpenACCClause(OpenACCClauseKind K, SourceLocation BeginLoc,
|
||||
SourceLocation EndLoc)
|
||||
: Kind(K), Location(BeginLoc, EndLoc) {
|
||||
assert(!BeginLoc.isInvalid() && !EndLoc.isInvalid() &&
|
||||
"Begin and end location must be valid for OpenACCClause");
|
||||
}
|
||||
|
||||
public:
|
||||
OpenACCClauseKind getClauseKind() const { return Kind; }
|
||||
SourceLocation getBeginLoc() const { return Location.getBegin(); }
|
||||
SourceLocation getEndLoc() const { return Location.getEnd(); }
|
||||
|
||||
static bool classof(const OpenACCClause *) { return false; }
|
||||
|
||||
using child_iterator = StmtIterator;
|
||||
using const_child_iterator = ConstStmtIterator;
|
||||
using child_range = llvm::iterator_range<child_iterator>;
|
||||
using const_child_range = llvm::iterator_range<const_child_iterator>;
|
||||
|
||||
child_range children();
|
||||
const_child_range children() const {
|
||||
auto Children = const_cast<OpenACCClause *>(this)->children();
|
||||
return const_child_range(Children.begin(), Children.end());
|
||||
}
|
||||
|
||||
virtual ~OpenACCClause() = default;
|
||||
};
|
||||
|
||||
// Represents the 'auto' clause.
|
||||
class OpenACCAutoClause : public OpenACCClause {
|
||||
protected:
|
||||
OpenACCAutoClause(SourceLocation BeginLoc, SourceLocation EndLoc)
|
||||
: OpenACCClause(OpenACCClauseKind::Auto, BeginLoc, EndLoc) {}
|
||||
|
||||
public:
|
||||
static bool classof(const OpenACCClause *C) {
|
||||
return C->getClauseKind() == OpenACCClauseKind::Auto;
|
||||
}
|
||||
|
||||
static OpenACCAutoClause *
|
||||
Create(const ASTContext &Ctx, SourceLocation BeginLoc, SourceLocation EndLoc);
|
||||
|
||||
child_range children() {
|
||||
return child_range(child_iterator(), child_iterator());
|
||||
}
|
||||
const_child_range children() const {
|
||||
return const_child_range(const_child_iterator(), const_child_iterator());
|
||||
}
|
||||
};
|
||||
|
||||
// Represents the 'independent' clause.
|
||||
class OpenACCIndependentClause : public OpenACCClause {
|
||||
protected:
|
||||
OpenACCIndependentClause(SourceLocation BeginLoc, SourceLocation EndLoc)
|
||||
: OpenACCClause(OpenACCClauseKind::Independent, BeginLoc, EndLoc) {}
|
||||
|
||||
public:
|
||||
static bool classof(const OpenACCClause *C) {
|
||||
return C->getClauseKind() == OpenACCClauseKind::Independent;
|
||||
}
|
||||
|
||||
static OpenACCIndependentClause *
|
||||
Create(const ASTContext &Ctx, SourceLocation BeginLoc, SourceLocation EndLoc);
|
||||
|
||||
child_range children() {
|
||||
return child_range(child_iterator(), child_iterator());
|
||||
}
|
||||
const_child_range children() const {
|
||||
return const_child_range(const_child_iterator(), const_child_iterator());
|
||||
}
|
||||
};
|
||||
// Represents the 'seq' clause.
|
||||
class OpenACCSeqClause : public OpenACCClause {
|
||||
protected:
|
||||
OpenACCSeqClause(SourceLocation BeginLoc, SourceLocation EndLoc)
|
||||
: OpenACCClause(OpenACCClauseKind::Seq, BeginLoc, EndLoc) {}
|
||||
|
||||
public:
|
||||
static bool classof(const OpenACCClause *C) {
|
||||
return C->getClauseKind() == OpenACCClauseKind::Seq;
|
||||
}
|
||||
|
||||
static OpenACCSeqClause *
|
||||
Create(const ASTContext &Ctx, SourceLocation BeginLoc, SourceLocation EndLoc);
|
||||
|
||||
child_range children() {
|
||||
return child_range(child_iterator(), child_iterator());
|
||||
}
|
||||
const_child_range children() const {
|
||||
return const_child_range(const_child_iterator(), const_child_iterator());
|
||||
}
|
||||
};
|
||||
|
||||
// Not yet implemented, but the type name is necessary for 'seq' diagnostics, so
|
||||
// this provides a basic, do-nothing implementation. We still need to add this
|
||||
// type to the visitors/etc, as well as get it to take its proper arguments.
|
||||
class OpenACCGangClause : public OpenACCClause {
|
||||
protected:
|
||||
OpenACCGangClause(SourceLocation BeginLoc, SourceLocation EndLoc)
|
||||
: OpenACCClause(OpenACCClauseKind::Gang, BeginLoc, EndLoc) {
|
||||
llvm_unreachable("Not yet implemented");
|
||||
}
|
||||
|
||||
public:
|
||||
static bool classof(const OpenACCClause *C) {
|
||||
return C->getClauseKind() == OpenACCClauseKind::Gang;
|
||||
}
|
||||
|
||||
static OpenACCGangClause *
|
||||
Create(const ASTContext &Ctx, SourceLocation BeginLoc, SourceLocation EndLoc);
|
||||
|
||||
child_range children() {
|
||||
return child_range(child_iterator(), child_iterator());
|
||||
}
|
||||
const_child_range children() const {
|
||||
return const_child_range(const_child_iterator(), const_child_iterator());
|
||||
}
|
||||
};
|
||||
|
||||
// Not yet implemented, but the type name is necessary for 'seq' diagnostics, so
|
||||
// this provides a basic, do-nothing implementation. We still need to add this
|
||||
// type to the visitors/etc, as well as get it to take its proper arguments.
|
||||
class OpenACCVectorClause : public OpenACCClause {
|
||||
protected:
|
||||
OpenACCVectorClause(SourceLocation BeginLoc, SourceLocation EndLoc)
|
||||
: OpenACCClause(OpenACCClauseKind::Vector, BeginLoc, EndLoc) {
|
||||
llvm_unreachable("Not yet implemented");
|
||||
}
|
||||
|
||||
public:
|
||||
static bool classof(const OpenACCClause *C) {
|
||||
return C->getClauseKind() == OpenACCClauseKind::Gang;
|
||||
}
|
||||
|
||||
static OpenACCVectorClause *
|
||||
Create(const ASTContext &Ctx, SourceLocation BeginLoc, SourceLocation EndLoc);
|
||||
|
||||
child_range children() {
|
||||
return child_range(child_iterator(), child_iterator());
|
||||
}
|
||||
const_child_range children() const {
|
||||
return const_child_range(const_child_iterator(), const_child_iterator());
|
||||
}
|
||||
};
|
||||
|
||||
// Not yet implemented, but the type name is necessary for 'seq' diagnostics, so
|
||||
// this provides a basic, do-nothing implementation. We still need to add this
|
||||
// type to the visitors/etc, as well as get it to take its proper arguments.
|
||||
class OpenACCWorkerClause : public OpenACCClause {
|
||||
protected:
|
||||
OpenACCWorkerClause(SourceLocation BeginLoc, SourceLocation EndLoc)
|
||||
: OpenACCClause(OpenACCClauseKind::Gang, BeginLoc, EndLoc) {
|
||||
llvm_unreachable("Not yet implemented");
|
||||
}
|
||||
|
||||
public:
|
||||
static bool classof(const OpenACCClause *C) {
|
||||
return C->getClauseKind() == OpenACCClauseKind::Gang;
|
||||
}
|
||||
|
||||
static OpenACCWorkerClause *
|
||||
Create(const ASTContext &Ctx, SourceLocation BeginLoc, SourceLocation EndLoc);
|
||||
|
||||
child_range children() {
|
||||
return child_range(child_iterator(), child_iterator());
|
||||
}
|
||||
const_child_range children() const {
|
||||
return const_child_range(const_child_iterator(), const_child_iterator());
|
||||
}
|
||||
};
|
||||
|
||||
/// Represents a clause that has a list of parameters.
|
||||
class OpenACCClauseWithParams : public OpenACCClause {
|
||||
/// Location of the '('.
|
||||
SourceLocation LParenLoc;
|
||||
|
||||
protected:
|
||||
OpenACCClauseWithParams(OpenACCClauseKind K, SourceLocation BeginLoc,
|
||||
SourceLocation LParenLoc, SourceLocation EndLoc)
|
||||
: OpenACCClause(K, BeginLoc, EndLoc), LParenLoc(LParenLoc) {}
|
||||
|
||||
public:
|
||||
static bool classof(const OpenACCClause *C);
|
||||
|
||||
SourceLocation getLParenLoc() const { return LParenLoc; }
|
||||
|
||||
child_range children() {
|
||||
return child_range(child_iterator(), child_iterator());
|
||||
}
|
||||
const_child_range children() const {
|
||||
return const_child_range(const_child_iterator(), const_child_iterator());
|
||||
}
|
||||
};
|
||||
|
||||
using DeviceTypeArgument = std::pair<IdentifierInfo *, SourceLocation>;
|
||||
/// A 'device_type' or 'dtype' clause, takes a list of either an 'asterisk' or
|
||||
/// an identifier. The 'asterisk' means 'the rest'.
|
||||
class OpenACCDeviceTypeClause final
|
||||
: public OpenACCClauseWithParams,
|
||||
public llvm::TrailingObjects<OpenACCDeviceTypeClause,
|
||||
DeviceTypeArgument> {
|
||||
// Data stored in trailing objects as IdentifierInfo* /SourceLocation pairs. A
|
||||
// nullptr IdentifierInfo* represents an asterisk.
|
||||
unsigned NumArchs;
|
||||
OpenACCDeviceTypeClause(OpenACCClauseKind K, SourceLocation BeginLoc,
|
||||
SourceLocation LParenLoc,
|
||||
ArrayRef<DeviceTypeArgument> Archs,
|
||||
SourceLocation EndLoc)
|
||||
: OpenACCClauseWithParams(K, BeginLoc, LParenLoc, EndLoc),
|
||||
NumArchs(Archs.size()) {
|
||||
assert(
|
||||
(K == OpenACCClauseKind::DeviceType || K == OpenACCClauseKind::DType) &&
|
||||
"Invalid clause kind for device-type");
|
||||
|
||||
assert(!llvm::any_of(Archs, [](const DeviceTypeArgument &Arg) {
|
||||
return Arg.second.isInvalid();
|
||||
}) && "Invalid SourceLocation for an argument");
|
||||
|
||||
assert(
|
||||
(Archs.size() == 1 || !llvm::any_of(Archs,
|
||||
[](const DeviceTypeArgument &Arg) {
|
||||
return Arg.first == nullptr;
|
||||
})) &&
|
||||
"Only a single asterisk version is permitted, and must be the "
|
||||
"only one");
|
||||
|
||||
std::uninitialized_copy(Archs.begin(), Archs.end(),
|
||||
getTrailingObjects<DeviceTypeArgument>());
|
||||
}
|
||||
|
||||
public:
|
||||
static bool classof(const OpenACCClause *C) {
|
||||
return C->getClauseKind() == OpenACCClauseKind::DType ||
|
||||
C->getClauseKind() == OpenACCClauseKind::DeviceType;
|
||||
}
|
||||
bool hasAsterisk() const {
|
||||
return getArchitectures().size() > 0 &&
|
||||
getArchitectures()[0].first == nullptr;
|
||||
}
|
||||
|
||||
ArrayRef<DeviceTypeArgument> getArchitectures() const {
|
||||
return ArrayRef<DeviceTypeArgument>(
|
||||
getTrailingObjects<DeviceTypeArgument>(), NumArchs);
|
||||
}
|
||||
|
||||
static OpenACCDeviceTypeClause *
|
||||
Create(const ASTContext &C, OpenACCClauseKind K, SourceLocation BeginLoc,
|
||||
SourceLocation LParenLoc, ArrayRef<DeviceTypeArgument> Archs,
|
||||
SourceLocation EndLoc);
|
||||
};
|
||||
|
||||
/// A 'default' clause, has the optional 'none' or 'present' argument.
|
||||
class OpenACCDefaultClause : public OpenACCClauseWithParams {
|
||||
friend class ASTReaderStmt;
|
||||
friend class ASTWriterStmt;
|
||||
|
||||
OpenACCDefaultClauseKind DefaultClauseKind;
|
||||
|
||||
protected:
|
||||
OpenACCDefaultClause(OpenACCDefaultClauseKind K, SourceLocation BeginLoc,
|
||||
SourceLocation LParenLoc, SourceLocation EndLoc)
|
||||
: OpenACCClauseWithParams(OpenACCClauseKind::Default, BeginLoc, LParenLoc,
|
||||
EndLoc),
|
||||
DefaultClauseKind(K) {
|
||||
assert((DefaultClauseKind == OpenACCDefaultClauseKind::None ||
|
||||
DefaultClauseKind == OpenACCDefaultClauseKind::Present) &&
|
||||
"Invalid Clause Kind");
|
||||
}
|
||||
|
||||
public:
|
||||
static bool classof(const OpenACCClause *C) {
|
||||
return C->getClauseKind() == OpenACCClauseKind::Default;
|
||||
}
|
||||
OpenACCDefaultClauseKind getDefaultClauseKind() const {
|
||||
return DefaultClauseKind;
|
||||
}
|
||||
|
||||
static OpenACCDefaultClause *Create(const ASTContext &C,
|
||||
OpenACCDefaultClauseKind K,
|
||||
SourceLocation BeginLoc,
|
||||
SourceLocation LParenLoc,
|
||||
SourceLocation EndLoc);
|
||||
};
|
||||
|
||||
/// Represents one of the handful of classes that has an optional/required
|
||||
/// 'condition' expression as an argument.
|
||||
class OpenACCClauseWithCondition : public OpenACCClauseWithParams {
|
||||
Expr *ConditionExpr = nullptr;
|
||||
|
||||
protected:
|
||||
OpenACCClauseWithCondition(OpenACCClauseKind K, SourceLocation BeginLoc,
|
||||
SourceLocation LParenLoc, Expr *ConditionExpr,
|
||||
SourceLocation EndLoc)
|
||||
: OpenACCClauseWithParams(K, BeginLoc, LParenLoc, EndLoc),
|
||||
ConditionExpr(ConditionExpr) {}
|
||||
|
||||
public:
|
||||
static bool classof(const OpenACCClause *C);
|
||||
|
||||
bool hasConditionExpr() const { return ConditionExpr; }
|
||||
const Expr *getConditionExpr() const { return ConditionExpr; }
|
||||
Expr *getConditionExpr() { return ConditionExpr; }
|
||||
|
||||
child_range children() {
|
||||
if (ConditionExpr)
|
||||
return child_range(reinterpret_cast<Stmt **>(&ConditionExpr),
|
||||
reinterpret_cast<Stmt **>(&ConditionExpr + 1));
|
||||
return child_range(child_iterator(), child_iterator());
|
||||
}
|
||||
|
||||
const_child_range children() const {
|
||||
if (ConditionExpr)
|
||||
return const_child_range(
|
||||
reinterpret_cast<Stmt *const *>(&ConditionExpr),
|
||||
reinterpret_cast<Stmt *const *>(&ConditionExpr + 1));
|
||||
return const_child_range(const_child_iterator(), const_child_iterator());
|
||||
}
|
||||
};
|
||||
|
||||
/// An 'if' clause, which has a required condition expression.
|
||||
class OpenACCIfClause : public OpenACCClauseWithCondition {
|
||||
protected:
|
||||
OpenACCIfClause(SourceLocation BeginLoc, SourceLocation LParenLoc,
|
||||
Expr *ConditionExpr, SourceLocation EndLoc);
|
||||
|
||||
public:
|
||||
static bool classof(const OpenACCClause *C) {
|
||||
return C->getClauseKind() == OpenACCClauseKind::If;
|
||||
}
|
||||
static OpenACCIfClause *Create(const ASTContext &C, SourceLocation BeginLoc,
|
||||
SourceLocation LParenLoc, Expr *ConditionExpr,
|
||||
SourceLocation EndLoc);
|
||||
};
|
||||
|
||||
/// A 'self' clause, which has an optional condition expression.
|
||||
class OpenACCSelfClause : public OpenACCClauseWithCondition {
|
||||
OpenACCSelfClause(SourceLocation BeginLoc, SourceLocation LParenLoc,
|
||||
Expr *ConditionExpr, SourceLocation EndLoc);
|
||||
|
||||
public:
|
||||
static bool classof(const OpenACCClause *C) {
|
||||
return C->getClauseKind() == OpenACCClauseKind::Self;
|
||||
}
|
||||
static OpenACCSelfClause *Create(const ASTContext &C, SourceLocation BeginLoc,
|
||||
SourceLocation LParenLoc,
|
||||
Expr *ConditionExpr, SourceLocation EndLoc);
|
||||
};
|
||||
|
||||
/// Represents a clause that has one or more expressions associated with it.
|
||||
class OpenACCClauseWithExprs : public OpenACCClauseWithParams {
|
||||
MutableArrayRef<Expr *> Exprs;
|
||||
|
||||
protected:
|
||||
OpenACCClauseWithExprs(OpenACCClauseKind K, SourceLocation BeginLoc,
|
||||
SourceLocation LParenLoc, SourceLocation EndLoc)
|
||||
: OpenACCClauseWithParams(K, BeginLoc, LParenLoc, EndLoc) {}
|
||||
|
||||
/// Used only for initialization, the leaf class can initialize this to
|
||||
/// trailing storage.
|
||||
void setExprs(MutableArrayRef<Expr *> NewExprs) {
|
||||
assert(Exprs.empty() && "Cannot change Exprs list");
|
||||
Exprs = NewExprs;
|
||||
}
|
||||
|
||||
/// Gets the entire list of expressions, but leave it to the
|
||||
/// individual clauses to expose this how they'd like.
|
||||
llvm::ArrayRef<Expr *> getExprs() const { return Exprs; }
|
||||
|
||||
public:
|
||||
static bool classof(const OpenACCClause *C);
|
||||
child_range children() {
|
||||
return child_range(reinterpret_cast<Stmt **>(Exprs.begin()),
|
||||
reinterpret_cast<Stmt **>(Exprs.end()));
|
||||
}
|
||||
|
||||
const_child_range children() const {
|
||||
child_range Children =
|
||||
const_cast<OpenACCClauseWithExprs *>(this)->children();
|
||||
return const_child_range(Children.begin(), Children.end());
|
||||
}
|
||||
};
|
||||
|
||||
// Represents the 'devnum' and expressions lists for the 'wait' clause.
|
||||
class OpenACCWaitClause final
|
||||
: public OpenACCClauseWithExprs,
|
||||
public llvm::TrailingObjects<OpenACCWaitClause, Expr *> {
|
||||
SourceLocation QueuesLoc;
|
||||
OpenACCWaitClause(SourceLocation BeginLoc, SourceLocation LParenLoc,
|
||||
Expr *DevNumExpr, SourceLocation QueuesLoc,
|
||||
ArrayRef<Expr *> QueueIdExprs, SourceLocation EndLoc)
|
||||
: OpenACCClauseWithExprs(OpenACCClauseKind::Wait, BeginLoc, LParenLoc,
|
||||
EndLoc),
|
||||
QueuesLoc(QueuesLoc) {
|
||||
// The first element of the trailing storage is always the devnum expr,
|
||||
// whether it is used or not.
|
||||
std::uninitialized_copy(&DevNumExpr, &DevNumExpr + 1,
|
||||
getTrailingObjects<Expr *>());
|
||||
std::uninitialized_copy(QueueIdExprs.begin(), QueueIdExprs.end(),
|
||||
getTrailingObjects<Expr *>() + 1);
|
||||
setExprs(
|
||||
MutableArrayRef(getTrailingObjects<Expr *>(), QueueIdExprs.size() + 1));
|
||||
}
|
||||
|
||||
public:
|
||||
static bool classof(const OpenACCClause *C) {
|
||||
return C->getClauseKind() == OpenACCClauseKind::Wait;
|
||||
}
|
||||
static OpenACCWaitClause *Create(const ASTContext &C, SourceLocation BeginLoc,
|
||||
SourceLocation LParenLoc, Expr *DevNumExpr,
|
||||
SourceLocation QueuesLoc,
|
||||
ArrayRef<Expr *> QueueIdExprs,
|
||||
SourceLocation EndLoc);
|
||||
|
||||
bool hasQueuesTag() const { return !QueuesLoc.isInvalid(); }
|
||||
SourceLocation getQueuesLoc() const { return QueuesLoc; }
|
||||
bool hasDevNumExpr() const { return getExprs()[0]; }
|
||||
Expr *getDevNumExpr() const { return getExprs()[0]; }
|
||||
llvm::ArrayRef<Expr *> getQueueIdExprs() {
|
||||
return OpenACCClauseWithExprs::getExprs().drop_front();
|
||||
}
|
||||
llvm::ArrayRef<Expr *> getQueueIdExprs() const {
|
||||
return OpenACCClauseWithExprs::getExprs().drop_front();
|
||||
}
|
||||
};
|
||||
|
||||
class OpenACCNumGangsClause final
|
||||
: public OpenACCClauseWithExprs,
|
||||
public llvm::TrailingObjects<OpenACCNumGangsClause, Expr *> {
|
||||
|
||||
OpenACCNumGangsClause(SourceLocation BeginLoc, SourceLocation LParenLoc,
|
||||
ArrayRef<Expr *> IntExprs, SourceLocation EndLoc)
|
||||
: OpenACCClauseWithExprs(OpenACCClauseKind::NumGangs, BeginLoc, LParenLoc,
|
||||
EndLoc) {
|
||||
std::uninitialized_copy(IntExprs.begin(), IntExprs.end(),
|
||||
getTrailingObjects<Expr *>());
|
||||
setExprs(MutableArrayRef(getTrailingObjects<Expr *>(), IntExprs.size()));
|
||||
}
|
||||
|
||||
public:
|
||||
static bool classof(const OpenACCClause *C) {
|
||||
return C->getClauseKind() == OpenACCClauseKind::NumGangs;
|
||||
}
|
||||
static OpenACCNumGangsClause *
|
||||
Create(const ASTContext &C, SourceLocation BeginLoc, SourceLocation LParenLoc,
|
||||
ArrayRef<Expr *> IntExprs, SourceLocation EndLoc);
|
||||
|
||||
llvm::ArrayRef<Expr *> getIntExprs() {
|
||||
return OpenACCClauseWithExprs::getExprs();
|
||||
}
|
||||
|
||||
llvm::ArrayRef<Expr *> getIntExprs() const {
|
||||
return OpenACCClauseWithExprs::getExprs();
|
||||
}
|
||||
};
|
||||
|
||||
/// Represents one of a handful of clauses that have a single integer
|
||||
/// expression.
|
||||
class OpenACCClauseWithSingleIntExpr : public OpenACCClauseWithExprs {
|
||||
Expr *IntExpr;
|
||||
|
||||
protected:
|
||||
OpenACCClauseWithSingleIntExpr(OpenACCClauseKind K, SourceLocation BeginLoc,
|
||||
SourceLocation LParenLoc, Expr *IntExpr,
|
||||
SourceLocation EndLoc)
|
||||
: OpenACCClauseWithExprs(K, BeginLoc, LParenLoc, EndLoc),
|
||||
IntExpr(IntExpr) {
|
||||
if (IntExpr)
|
||||
setExprs(MutableArrayRef<Expr *>{&this->IntExpr, 1});
|
||||
}
|
||||
|
||||
public:
|
||||
static bool classof(const OpenACCClause *C);
|
||||
bool hasIntExpr() const { return !getExprs().empty(); }
|
||||
const Expr *getIntExpr() const {
|
||||
return hasIntExpr() ? getExprs()[0] : nullptr;
|
||||
}
|
||||
|
||||
Expr *getIntExpr() { return hasIntExpr() ? getExprs()[0] : nullptr; };
|
||||
};
|
||||
|
||||
class OpenACCNumWorkersClause : public OpenACCClauseWithSingleIntExpr {
|
||||
OpenACCNumWorkersClause(SourceLocation BeginLoc, SourceLocation LParenLoc,
|
||||
Expr *IntExpr, SourceLocation EndLoc);
|
||||
|
||||
public:
|
||||
static bool classof(const OpenACCClause *C) {
|
||||
return C->getClauseKind() == OpenACCClauseKind::NumWorkers;
|
||||
}
|
||||
static OpenACCNumWorkersClause *Create(const ASTContext &C,
|
||||
SourceLocation BeginLoc,
|
||||
SourceLocation LParenLoc,
|
||||
Expr *IntExpr, SourceLocation EndLoc);
|
||||
};
|
||||
|
||||
class OpenACCVectorLengthClause : public OpenACCClauseWithSingleIntExpr {
|
||||
OpenACCVectorLengthClause(SourceLocation BeginLoc, SourceLocation LParenLoc,
|
||||
Expr *IntExpr, SourceLocation EndLoc);
|
||||
|
||||
public:
|
||||
static bool classof(const OpenACCClause *C) {
|
||||
return C->getClauseKind() == OpenACCClauseKind::VectorLength;
|
||||
}
|
||||
static OpenACCVectorLengthClause *
|
||||
Create(const ASTContext &C, SourceLocation BeginLoc, SourceLocation LParenLoc,
|
||||
Expr *IntExpr, SourceLocation EndLoc);
|
||||
};
|
||||
|
||||
class OpenACCAsyncClause : public OpenACCClauseWithSingleIntExpr {
|
||||
OpenACCAsyncClause(SourceLocation BeginLoc, SourceLocation LParenLoc,
|
||||
Expr *IntExpr, SourceLocation EndLoc);
|
||||
|
||||
public:
|
||||
static bool classof(const OpenACCClause *C) {
|
||||
return C->getClauseKind() == OpenACCClauseKind::Async;
|
||||
}
|
||||
static OpenACCAsyncClause *Create(const ASTContext &C,
|
||||
SourceLocation BeginLoc,
|
||||
SourceLocation LParenLoc, Expr *IntExpr,
|
||||
SourceLocation EndLoc);
|
||||
};
|
||||
|
||||
/// Represents a clause with one or more 'var' objects, represented as an expr,
|
||||
/// as its arguments. Var-list is expected to be stored in trailing storage.
|
||||
/// For now, we're just storing the original expression in its entirety, unlike
|
||||
/// OMP which has to do a bunch of work to create a private.
|
||||
class OpenACCClauseWithVarList : public OpenACCClauseWithExprs {
|
||||
protected:
|
||||
OpenACCClauseWithVarList(OpenACCClauseKind K, SourceLocation BeginLoc,
|
||||
SourceLocation LParenLoc, SourceLocation EndLoc)
|
||||
: OpenACCClauseWithExprs(K, BeginLoc, LParenLoc, EndLoc) {}
|
||||
|
||||
public:
|
||||
static bool classof(const OpenACCClause *C);
|
||||
ArrayRef<Expr *> getVarList() { return getExprs(); }
|
||||
ArrayRef<Expr *> getVarList() const { return getExprs(); }
|
||||
};
|
||||
|
||||
class OpenACCPrivateClause final
|
||||
: public OpenACCClauseWithVarList,
|
||||
public llvm::TrailingObjects<OpenACCPrivateClause, Expr *> {
|
||||
|
||||
OpenACCPrivateClause(SourceLocation BeginLoc, SourceLocation LParenLoc,
|
||||
ArrayRef<Expr *> VarList, SourceLocation EndLoc)
|
||||
: OpenACCClauseWithVarList(OpenACCClauseKind::Private, BeginLoc,
|
||||
LParenLoc, EndLoc) {
|
||||
std::uninitialized_copy(VarList.begin(), VarList.end(),
|
||||
getTrailingObjects<Expr *>());
|
||||
setExprs(MutableArrayRef(getTrailingObjects<Expr *>(), VarList.size()));
|
||||
}
|
||||
|
||||
public:
|
||||
static bool classof(const OpenACCClause *C) {
|
||||
return C->getClauseKind() == OpenACCClauseKind::Private;
|
||||
}
|
||||
static OpenACCPrivateClause *
|
||||
Create(const ASTContext &C, SourceLocation BeginLoc, SourceLocation LParenLoc,
|
||||
ArrayRef<Expr *> VarList, SourceLocation EndLoc);
|
||||
};
|
||||
|
||||
class OpenACCFirstPrivateClause final
|
||||
: public OpenACCClauseWithVarList,
|
||||
public llvm::TrailingObjects<OpenACCFirstPrivateClause, Expr *> {
|
||||
|
||||
OpenACCFirstPrivateClause(SourceLocation BeginLoc, SourceLocation LParenLoc,
|
||||
ArrayRef<Expr *> VarList, SourceLocation EndLoc)
|
||||
: OpenACCClauseWithVarList(OpenACCClauseKind::FirstPrivate, BeginLoc,
|
||||
LParenLoc, EndLoc) {
|
||||
std::uninitialized_copy(VarList.begin(), VarList.end(),
|
||||
getTrailingObjects<Expr *>());
|
||||
setExprs(MutableArrayRef(getTrailingObjects<Expr *>(), VarList.size()));
|
||||
}
|
||||
|
||||
public:
|
||||
static bool classof(const OpenACCClause *C) {
|
||||
return C->getClauseKind() == OpenACCClauseKind::FirstPrivate;
|
||||
}
|
||||
static OpenACCFirstPrivateClause *
|
||||
Create(const ASTContext &C, SourceLocation BeginLoc, SourceLocation LParenLoc,
|
||||
ArrayRef<Expr *> VarList, SourceLocation EndLoc);
|
||||
};
|
||||
|
||||
class OpenACCDevicePtrClause final
|
||||
: public OpenACCClauseWithVarList,
|
||||
public llvm::TrailingObjects<OpenACCDevicePtrClause, Expr *> {
|
||||
|
||||
OpenACCDevicePtrClause(SourceLocation BeginLoc, SourceLocation LParenLoc,
|
||||
ArrayRef<Expr *> VarList, SourceLocation EndLoc)
|
||||
: OpenACCClauseWithVarList(OpenACCClauseKind::DevicePtr, BeginLoc,
|
||||
LParenLoc, EndLoc) {
|
||||
std::uninitialized_copy(VarList.begin(), VarList.end(),
|
||||
getTrailingObjects<Expr *>());
|
||||
setExprs(MutableArrayRef(getTrailingObjects<Expr *>(), VarList.size()));
|
||||
}
|
||||
|
||||
public:
|
||||
static bool classof(const OpenACCClause *C) {
|
||||
return C->getClauseKind() == OpenACCClauseKind::DevicePtr;
|
||||
}
|
||||
static OpenACCDevicePtrClause *
|
||||
Create(const ASTContext &C, SourceLocation BeginLoc, SourceLocation LParenLoc,
|
||||
ArrayRef<Expr *> VarList, SourceLocation EndLoc);
|
||||
};
|
||||
|
||||
class OpenACCAttachClause final
|
||||
: public OpenACCClauseWithVarList,
|
||||
public llvm::TrailingObjects<OpenACCAttachClause, Expr *> {
|
||||
|
||||
OpenACCAttachClause(SourceLocation BeginLoc, SourceLocation LParenLoc,
|
||||
ArrayRef<Expr *> VarList, SourceLocation EndLoc)
|
||||
: OpenACCClauseWithVarList(OpenACCClauseKind::Attach, BeginLoc, LParenLoc,
|
||||
EndLoc) {
|
||||
std::uninitialized_copy(VarList.begin(), VarList.end(),
|
||||
getTrailingObjects<Expr *>());
|
||||
setExprs(MutableArrayRef(getTrailingObjects<Expr *>(), VarList.size()));
|
||||
}
|
||||
|
||||
public:
|
||||
static bool classof(const OpenACCClause *C) {
|
||||
return C->getClauseKind() == OpenACCClauseKind::Attach;
|
||||
}
|
||||
static OpenACCAttachClause *
|
||||
Create(const ASTContext &C, SourceLocation BeginLoc, SourceLocation LParenLoc,
|
||||
ArrayRef<Expr *> VarList, SourceLocation EndLoc);
|
||||
};
|
||||
|
||||
class OpenACCNoCreateClause final
|
||||
: public OpenACCClauseWithVarList,
|
||||
public llvm::TrailingObjects<OpenACCNoCreateClause, Expr *> {
|
||||
|
||||
OpenACCNoCreateClause(SourceLocation BeginLoc, SourceLocation LParenLoc,
|
||||
ArrayRef<Expr *> VarList, SourceLocation EndLoc)
|
||||
: OpenACCClauseWithVarList(OpenACCClauseKind::NoCreate, BeginLoc,
|
||||
LParenLoc, EndLoc) {
|
||||
std::uninitialized_copy(VarList.begin(), VarList.end(),
|
||||
getTrailingObjects<Expr *>());
|
||||
setExprs(MutableArrayRef(getTrailingObjects<Expr *>(), VarList.size()));
|
||||
}
|
||||
|
||||
public:
|
||||
static bool classof(const OpenACCClause *C) {
|
||||
return C->getClauseKind() == OpenACCClauseKind::NoCreate;
|
||||
}
|
||||
static OpenACCNoCreateClause *
|
||||
Create(const ASTContext &C, SourceLocation BeginLoc, SourceLocation LParenLoc,
|
||||
ArrayRef<Expr *> VarList, SourceLocation EndLoc);
|
||||
};
|
||||
|
||||
class OpenACCPresentClause final
|
||||
: public OpenACCClauseWithVarList,
|
||||
public llvm::TrailingObjects<OpenACCPresentClause, Expr *> {
|
||||
|
||||
OpenACCPresentClause(SourceLocation BeginLoc, SourceLocation LParenLoc,
|
||||
ArrayRef<Expr *> VarList, SourceLocation EndLoc)
|
||||
: OpenACCClauseWithVarList(OpenACCClauseKind::Present, BeginLoc,
|
||||
LParenLoc, EndLoc) {
|
||||
std::uninitialized_copy(VarList.begin(), VarList.end(),
|
||||
getTrailingObjects<Expr *>());
|
||||
setExprs(MutableArrayRef(getTrailingObjects<Expr *>(), VarList.size()));
|
||||
}
|
||||
|
||||
public:
|
||||
static bool classof(const OpenACCClause *C) {
|
||||
return C->getClauseKind() == OpenACCClauseKind::Present;
|
||||
}
|
||||
static OpenACCPresentClause *
|
||||
Create(const ASTContext &C, SourceLocation BeginLoc, SourceLocation LParenLoc,
|
||||
ArrayRef<Expr *> VarList, SourceLocation EndLoc);
|
||||
};
|
||||
|
||||
class OpenACCCopyClause final
|
||||
: public OpenACCClauseWithVarList,
|
||||
public llvm::TrailingObjects<OpenACCCopyClause, Expr *> {
|
||||
|
||||
OpenACCCopyClause(OpenACCClauseKind Spelling, SourceLocation BeginLoc,
|
||||
SourceLocation LParenLoc, ArrayRef<Expr *> VarList,
|
||||
SourceLocation EndLoc)
|
||||
: OpenACCClauseWithVarList(Spelling, BeginLoc, LParenLoc, EndLoc) {
|
||||
assert((Spelling == OpenACCClauseKind::Copy ||
|
||||
Spelling == OpenACCClauseKind::PCopy ||
|
||||
Spelling == OpenACCClauseKind::PresentOrCopy) &&
|
||||
"Invalid clause kind for copy-clause");
|
||||
std::uninitialized_copy(VarList.begin(), VarList.end(),
|
||||
getTrailingObjects<Expr *>());
|
||||
setExprs(MutableArrayRef(getTrailingObjects<Expr *>(), VarList.size()));
|
||||
}
|
||||
|
||||
public:
|
||||
static bool classof(const OpenACCClause *C) {
|
||||
return C->getClauseKind() == OpenACCClauseKind::Copy ||
|
||||
C->getClauseKind() == OpenACCClauseKind::PCopy ||
|
||||
C->getClauseKind() == OpenACCClauseKind::PresentOrCopy;
|
||||
}
|
||||
static OpenACCCopyClause *
|
||||
Create(const ASTContext &C, OpenACCClauseKind Spelling,
|
||||
SourceLocation BeginLoc, SourceLocation LParenLoc,
|
||||
ArrayRef<Expr *> VarList, SourceLocation EndLoc);
|
||||
};
|
||||
|
||||
class OpenACCCopyInClause final
|
||||
: public OpenACCClauseWithVarList,
|
||||
public llvm::TrailingObjects<OpenACCCopyInClause, Expr *> {
|
||||
bool IsReadOnly;
|
||||
|
||||
OpenACCCopyInClause(OpenACCClauseKind Spelling, SourceLocation BeginLoc,
|
||||
SourceLocation LParenLoc, bool IsReadOnly,
|
||||
ArrayRef<Expr *> VarList, SourceLocation EndLoc)
|
||||
: OpenACCClauseWithVarList(Spelling, BeginLoc, LParenLoc, EndLoc),
|
||||
IsReadOnly(IsReadOnly) {
|
||||
assert((Spelling == OpenACCClauseKind::CopyIn ||
|
||||
Spelling == OpenACCClauseKind::PCopyIn ||
|
||||
Spelling == OpenACCClauseKind::PresentOrCopyIn) &&
|
||||
"Invalid clause kind for copyin-clause");
|
||||
std::uninitialized_copy(VarList.begin(), VarList.end(),
|
||||
getTrailingObjects<Expr *>());
|
||||
setExprs(MutableArrayRef(getTrailingObjects<Expr *>(), VarList.size()));
|
||||
}
|
||||
|
||||
public:
|
||||
static bool classof(const OpenACCClause *C) {
|
||||
return C->getClauseKind() == OpenACCClauseKind::CopyIn ||
|
||||
C->getClauseKind() == OpenACCClauseKind::PCopyIn ||
|
||||
C->getClauseKind() == OpenACCClauseKind::PresentOrCopyIn;
|
||||
}
|
||||
bool isReadOnly() const { return IsReadOnly; }
|
||||
static OpenACCCopyInClause *
|
||||
Create(const ASTContext &C, OpenACCClauseKind Spelling,
|
||||
SourceLocation BeginLoc, SourceLocation LParenLoc, bool IsReadOnly,
|
||||
ArrayRef<Expr *> VarList, SourceLocation EndLoc);
|
||||
};
|
||||
|
||||
class OpenACCCopyOutClause final
|
||||
: public OpenACCClauseWithVarList,
|
||||
public llvm::TrailingObjects<OpenACCCopyOutClause, Expr *> {
|
||||
bool IsZero;
|
||||
|
||||
OpenACCCopyOutClause(OpenACCClauseKind Spelling, SourceLocation BeginLoc,
|
||||
SourceLocation LParenLoc, bool IsZero,
|
||||
ArrayRef<Expr *> VarList, SourceLocation EndLoc)
|
||||
: OpenACCClauseWithVarList(Spelling, BeginLoc, LParenLoc, EndLoc),
|
||||
IsZero(IsZero) {
|
||||
assert((Spelling == OpenACCClauseKind::CopyOut ||
|
||||
Spelling == OpenACCClauseKind::PCopyOut ||
|
||||
Spelling == OpenACCClauseKind::PresentOrCopyOut) &&
|
||||
"Invalid clause kind for copyout-clause");
|
||||
std::uninitialized_copy(VarList.begin(), VarList.end(),
|
||||
getTrailingObjects<Expr *>());
|
||||
setExprs(MutableArrayRef(getTrailingObjects<Expr *>(), VarList.size()));
|
||||
}
|
||||
|
||||
public:
|
||||
static bool classof(const OpenACCClause *C) {
|
||||
return C->getClauseKind() == OpenACCClauseKind::CopyOut ||
|
||||
C->getClauseKind() == OpenACCClauseKind::PCopyOut ||
|
||||
C->getClauseKind() == OpenACCClauseKind::PresentOrCopyOut;
|
||||
}
|
||||
bool isZero() const { return IsZero; }
|
||||
static OpenACCCopyOutClause *
|
||||
Create(const ASTContext &C, OpenACCClauseKind Spelling,
|
||||
SourceLocation BeginLoc, SourceLocation LParenLoc, bool IsZero,
|
||||
ArrayRef<Expr *> VarList, SourceLocation EndLoc);
|
||||
};
|
||||
|
||||
class OpenACCCreateClause final
|
||||
: public OpenACCClauseWithVarList,
|
||||
public llvm::TrailingObjects<OpenACCCreateClause, Expr *> {
|
||||
bool IsZero;
|
||||
|
||||
OpenACCCreateClause(OpenACCClauseKind Spelling, SourceLocation BeginLoc,
|
||||
SourceLocation LParenLoc, bool IsZero,
|
||||
ArrayRef<Expr *> VarList, SourceLocation EndLoc)
|
||||
: OpenACCClauseWithVarList(Spelling, BeginLoc, LParenLoc, EndLoc),
|
||||
IsZero(IsZero) {
|
||||
assert((Spelling == OpenACCClauseKind::Create ||
|
||||
Spelling == OpenACCClauseKind::PCreate ||
|
||||
Spelling == OpenACCClauseKind::PresentOrCreate) &&
|
||||
"Invalid clause kind for create-clause");
|
||||
std::uninitialized_copy(VarList.begin(), VarList.end(),
|
||||
getTrailingObjects<Expr *>());
|
||||
setExprs(MutableArrayRef(getTrailingObjects<Expr *>(), VarList.size()));
|
||||
}
|
||||
|
||||
public:
|
||||
static bool classof(const OpenACCClause *C) {
|
||||
return C->getClauseKind() == OpenACCClauseKind::Create ||
|
||||
C->getClauseKind() == OpenACCClauseKind::PCreate ||
|
||||
C->getClauseKind() == OpenACCClauseKind::PresentOrCreate;
|
||||
}
|
||||
bool isZero() const { return IsZero; }
|
||||
static OpenACCCreateClause *
|
||||
Create(const ASTContext &C, OpenACCClauseKind Spelling,
|
||||
SourceLocation BeginLoc, SourceLocation LParenLoc, bool IsZero,
|
||||
ArrayRef<Expr *> VarList, SourceLocation EndLoc);
|
||||
};
|
||||
|
||||
class OpenACCReductionClause final
|
||||
: public OpenACCClauseWithVarList,
|
||||
public llvm::TrailingObjects<OpenACCReductionClause, Expr *> {
|
||||
OpenACCReductionOperator Op;
|
||||
|
||||
OpenACCReductionClause(SourceLocation BeginLoc, SourceLocation LParenLoc,
|
||||
OpenACCReductionOperator Operator,
|
||||
ArrayRef<Expr *> VarList, SourceLocation EndLoc)
|
||||
: OpenACCClauseWithVarList(OpenACCClauseKind::Reduction, BeginLoc,
|
||||
LParenLoc, EndLoc),
|
||||
Op(Operator) {
|
||||
std::uninitialized_copy(VarList.begin(), VarList.end(),
|
||||
getTrailingObjects<Expr *>());
|
||||
setExprs(MutableArrayRef(getTrailingObjects<Expr *>(), VarList.size()));
|
||||
}
|
||||
|
||||
public:
|
||||
static bool classof(const OpenACCClause *C) {
|
||||
return C->getClauseKind() == OpenACCClauseKind::Reduction;
|
||||
}
|
||||
|
||||
static OpenACCReductionClause *
|
||||
Create(const ASTContext &C, SourceLocation BeginLoc, SourceLocation LParenLoc,
|
||||
OpenACCReductionOperator Operator, ArrayRef<Expr *> VarList,
|
||||
SourceLocation EndLoc);
|
||||
|
||||
OpenACCReductionOperator getReductionOp() const { return Op; }
|
||||
};
|
||||
|
||||
template <class Impl> class OpenACCClauseVisitor {
|
||||
Impl &getDerived() { return static_cast<Impl &>(*this); }
|
||||
|
||||
public:
|
||||
void VisitClauseList(ArrayRef<const OpenACCClause *> List) {
|
||||
for (const OpenACCClause *Clause : List)
|
||||
Visit(Clause);
|
||||
}
|
||||
|
||||
void Visit(const OpenACCClause *C) {
|
||||
if (!C)
|
||||
return;
|
||||
|
||||
switch (C->getClauseKind()) {
|
||||
#define VISIT_CLAUSE(CLAUSE_NAME) \
|
||||
case OpenACCClauseKind::CLAUSE_NAME: \
|
||||
Visit##CLAUSE_NAME##Clause(*cast<OpenACC##CLAUSE_NAME##Clause>(C)); \
|
||||
return;
|
||||
#define CLAUSE_ALIAS(ALIAS_NAME, CLAUSE_NAME, DEPRECATED) \
|
||||
case OpenACCClauseKind::ALIAS_NAME: \
|
||||
Visit##CLAUSE_NAME##Clause(*cast<OpenACC##CLAUSE_NAME##Clause>(C)); \
|
||||
return;
|
||||
#include "clang/Basic/OpenACCClauses.def"
|
||||
|
||||
default:
|
||||
llvm_unreachable("Clause visitor not yet implemented");
|
||||
}
|
||||
llvm_unreachable("Invalid Clause kind");
|
||||
}
|
||||
|
||||
#define VISIT_CLAUSE(CLAUSE_NAME) \
|
||||
void Visit##CLAUSE_NAME##Clause( \
|
||||
const OpenACC##CLAUSE_NAME##Clause &Clause) { \
|
||||
return getDerived().Visit##CLAUSE_NAME##Clause(Clause); \
|
||||
}
|
||||
|
||||
#include "clang/Basic/OpenACCClauses.def"
|
||||
};
|
||||
|
||||
class OpenACCClausePrinter final
|
||||
: public OpenACCClauseVisitor<OpenACCClausePrinter> {
|
||||
raw_ostream &OS;
|
||||
const PrintingPolicy &Policy;
|
||||
|
||||
void printExpr(const Expr *E);
|
||||
|
||||
public:
|
||||
void VisitClauseList(ArrayRef<const OpenACCClause *> List) {
|
||||
for (const OpenACCClause *Clause : List) {
|
||||
Visit(Clause);
|
||||
|
||||
if (Clause != List.back())
|
||||
OS << ' ';
|
||||
}
|
||||
}
|
||||
OpenACCClausePrinter(raw_ostream &OS, const PrintingPolicy &Policy)
|
||||
: OS(OS), Policy(Policy) {}
|
||||
|
||||
#define VISIT_CLAUSE(CLAUSE_NAME) \
|
||||
void Visit##CLAUSE_NAME##Clause(const OpenACC##CLAUSE_NAME##Clause &Clause);
|
||||
#include "clang/Basic/OpenACCClauses.def"
|
||||
};
|
||||
|
||||
} // namespace clang
|
||||
|
||||
#endif // LLVM_CLANG_AST_OPENACCCLAUSE_H
|
||||
|
|
@ -2513,6 +2513,46 @@ public:
|
|||
}
|
||||
};
|
||||
|
||||
/// This represents 'weak' clause in the '#pragma omp atomic'
|
||||
/// directives.
|
||||
///
|
||||
/// \code
|
||||
/// #pragma omp atomic compare weak
|
||||
/// \endcode
|
||||
/// In this example directive '#pragma omp atomic' has 'weak' clause.
|
||||
class OMPWeakClause final : public OMPClause {
|
||||
public:
|
||||
/// Build 'weak' clause.
|
||||
///
|
||||
/// \param StartLoc Starting location of the clause.
|
||||
/// \param EndLoc Ending location of the clause.
|
||||
OMPWeakClause(SourceLocation StartLoc, SourceLocation EndLoc)
|
||||
: OMPClause(llvm::omp::OMPC_weak, StartLoc, EndLoc) {}
|
||||
|
||||
/// Build an empty clause.
|
||||
OMPWeakClause()
|
||||
: OMPClause(llvm::omp::OMPC_weak, SourceLocation(), SourceLocation()) {}
|
||||
|
||||
child_range children() {
|
||||
return child_range(child_iterator(), child_iterator());
|
||||
}
|
||||
|
||||
const_child_range children() const {
|
||||
return const_child_range(const_child_iterator(), const_child_iterator());
|
||||
}
|
||||
|
||||
child_range used_children() {
|
||||
return child_range(child_iterator(), child_iterator());
|
||||
}
|
||||
const_child_range used_children() const {
|
||||
return const_child_range(const_child_iterator(), const_child_iterator());
|
||||
}
|
||||
|
||||
static bool classof(const OMPClause *T) {
|
||||
return T->getClauseKind() == llvm::omp::OMPC_weak;
|
||||
}
|
||||
};
|
||||
|
||||
/// This represents 'fail' clause in the '#pragma omp atomic'
|
||||
/// directive.
|
||||
///
|
||||
|
|
|
|||
|
|
@ -361,6 +361,12 @@ CAST_OPERATION(AddressSpaceConversion)
|
|||
// Convert an integer initializer to an OpenCL sampler.
|
||||
CAST_OPERATION(IntToOCLSampler)
|
||||
|
||||
// Truncate a vector type by dropping elements from the end (HLSL only).
|
||||
CAST_OPERATION(HLSLVectorTruncation)
|
||||
|
||||
// Non-decaying array RValue cast (HLSL only).
|
||||
CAST_OPERATION(HLSLArrayRValue)
|
||||
|
||||
//===- Binary Operations -------------------------------------------------===//
|
||||
// Operators listed in order of precedence.
|
||||
// Note that additions to this should also update the StmtVisitor class,
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
//===- ParentMapContext.h - Map of parents using DynTypedNode -------*- C++ -*-===//
|
||||
//===- ParentMapContext.h - Map of parents using DynTypedNode ---*- C++ -*-===//
|
||||
//
|
||||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
||||
// See https://llvm.org/LICENSE.txt for license information.
|
||||
|
|
|
|||
|
|
@ -77,7 +77,7 @@ struct PrintingPolicy {
|
|||
PrintCanonicalTypes(false), PrintInjectedClassNameWithArguments(true),
|
||||
UsePreferredNames(true), AlwaysIncludeTypeForTemplateArgument(false),
|
||||
CleanUglifiedParameters(false), EntireContentsOfLargeArray(true),
|
||||
UseEnumerators(true) {}
|
||||
UseEnumerators(true), UseHLSLTypes(LO.HLSL) {}
|
||||
|
||||
/// Adjust this printing policy for cases where it's known that we're
|
||||
/// printing C++ code (for instance, if AST dumping reaches a C++-only
|
||||
|
|
@ -342,6 +342,11 @@ struct PrintingPolicy {
|
|||
LLVM_PREFERRED_TYPE(bool)
|
||||
unsigned UseEnumerators : 1;
|
||||
|
||||
/// Whether or not we're printing known HLSL code and should print HLSL
|
||||
/// sugared types when possible.
|
||||
LLVM_PREFERRED_TYPE(bool)
|
||||
unsigned UseHLSLTypes : 1;
|
||||
|
||||
/// Callbacks to use to allow the behavior of printing to be customized.
|
||||
const PrintingCallbacks *Callbacks = nullptr;
|
||||
};
|
||||
|
|
|
|||
|
|
@ -117,6 +117,8 @@ def ExtParameterInfo : PropertyType<"FunctionProtoType::ExtParameterInfo">;
|
|||
def FixedPointSemantics : PropertyType<"llvm::FixedPointSemantics"> {
|
||||
let PassByReference = 1;
|
||||
}
|
||||
def FunctionEffect : PropertyType<"FunctionEffect">;
|
||||
def EffectConditionExpr : PropertyType<"EffectConditionExpr">;
|
||||
def Identifier : RefPropertyType<"IdentifierInfo"> { let ConstWhenWriting = 1; }
|
||||
def LValuePathEntry : PropertyType<"APValue::LValuePathEntry">;
|
||||
def LValuePathSerializationHelper :
|
||||
|
|
@ -143,6 +145,7 @@ def UInt32 : CountPropertyType<"uint32_t">;
|
|||
def UInt64 : CountPropertyType<"uint64_t">;
|
||||
def UnaryTypeTransformKind : EnumPropertyType<"UnaryTransformType::UTTKind">;
|
||||
def VectorKind : EnumPropertyType<"VectorKind">;
|
||||
def TypeCoupledDeclRefInfo : PropertyType;
|
||||
|
||||
def ExceptionSpecInfo : PropertyType<"FunctionProtoType::ExceptionSpecInfo"> {
|
||||
let BufferElementTypes = [ QualType ];
|
||||
|
|
|
|||
|
|
@ -175,17 +175,22 @@ private:
|
|||
mutable StringRef RawText;
|
||||
mutable const char *BriefText = nullptr;
|
||||
|
||||
mutable bool RawTextValid : 1; ///< True if RawText is valid
|
||||
mutable bool BriefTextValid : 1; ///< True if BriefText is valid
|
||||
LLVM_PREFERRED_TYPE(bool)
|
||||
mutable unsigned RawTextValid : 1;
|
||||
LLVM_PREFERRED_TYPE(bool)
|
||||
mutable unsigned BriefTextValid : 1;
|
||||
|
||||
LLVM_PREFERRED_TYPE(CommentKind)
|
||||
unsigned Kind : 3;
|
||||
|
||||
/// True if comment is attached to a declaration in ASTContext.
|
||||
bool IsAttached : 1;
|
||||
LLVM_PREFERRED_TYPE(bool)
|
||||
unsigned IsAttached : 1;
|
||||
|
||||
bool IsTrailingComment : 1;
|
||||
bool IsAlmostTrailingComment : 1;
|
||||
LLVM_PREFERRED_TYPE(bool)
|
||||
unsigned IsTrailingComment : 1;
|
||||
LLVM_PREFERRED_TYPE(bool)
|
||||
unsigned IsAlmostTrailingComment : 1;
|
||||
|
||||
/// Constructor for AST deserialization.
|
||||
RawComment(SourceRange SR, CommentKind K, bool IsTrailingComment,
|
||||
|
|
|
|||
|
|
@ -30,10 +30,12 @@
|
|||
#include "clang/AST/ExprOpenMP.h"
|
||||
#include "clang/AST/LambdaCapture.h"
|
||||
#include "clang/AST/NestedNameSpecifier.h"
|
||||
#include "clang/AST/OpenACCClause.h"
|
||||
#include "clang/AST/OpenMPClause.h"
|
||||
#include "clang/AST/Stmt.h"
|
||||
#include "clang/AST/StmtCXX.h"
|
||||
#include "clang/AST/StmtObjC.h"
|
||||
#include "clang/AST/StmtOpenACC.h"
|
||||
#include "clang/AST/StmtOpenMP.h"
|
||||
#include "clang/AST/TemplateBase.h"
|
||||
#include "clang/AST/TemplateName.h"
|
||||
|
|
@ -505,6 +507,11 @@ private:
|
|||
bool VisitOMPClauseWithPostUpdate(OMPClauseWithPostUpdate *Node);
|
||||
|
||||
bool PostVisitStmt(Stmt *S);
|
||||
bool TraverseOpenACCConstructStmt(OpenACCConstructStmt *S);
|
||||
bool
|
||||
TraverseOpenACCAssociatedStmtConstruct(OpenACCAssociatedStmtConstruct *S);
|
||||
bool VisitOpenACCClauseList(ArrayRef<const OpenACCClause *>);
|
||||
bool VisitOpenACCClause(const OpenACCClause *);
|
||||
};
|
||||
|
||||
template <typename Derived>
|
||||
|
|
@ -731,13 +738,27 @@ bool RecursiveASTVisitor<Derived>::TraverseDecl(Decl *D) {
|
|||
|
||||
// As a syntax visitor, by default we want to ignore declarations for
|
||||
// implicit declarations (ones not typed explicitly by the user).
|
||||
if (!getDerived().shouldVisitImplicitCode() && D->isImplicit()) {
|
||||
// For an implicit template type parameter, its type constraints are not
|
||||
// implicit and are not represented anywhere else. We still need to visit
|
||||
// them.
|
||||
if (auto *TTPD = dyn_cast<TemplateTypeParmDecl>(D))
|
||||
return TraverseTemplateTypeParamDeclConstraints(TTPD);
|
||||
return true;
|
||||
if (!getDerived().shouldVisitImplicitCode()) {
|
||||
if (D->isImplicit()) {
|
||||
// For an implicit template type parameter, its type constraints are not
|
||||
// implicit and are not represented anywhere else. We still need to visit
|
||||
// them.
|
||||
if (auto *TTPD = dyn_cast<TemplateTypeParmDecl>(D))
|
||||
return TraverseTemplateTypeParamDeclConstraints(TTPD);
|
||||
return true;
|
||||
}
|
||||
|
||||
// Deduction guides for alias templates are always synthesized, so they
|
||||
// should not be traversed unless shouldVisitImplicitCode() returns true.
|
||||
//
|
||||
// It's important to note that checking the implicit bit is not efficient
|
||||
// for the alias case. For deduction guides synthesized from explicit
|
||||
// user-defined deduction guides, we must maintain the explicit bit to
|
||||
// ensure correct overload resolution.
|
||||
if (auto *FTD = dyn_cast<FunctionTemplateDecl>(D))
|
||||
if (llvm::isa_and_present<TypeAliasTemplateDecl>(
|
||||
FTD->getDeclName().getCXXDeductionGuideTemplate()))
|
||||
return true;
|
||||
}
|
||||
|
||||
switch (D->getKind()) {
|
||||
|
|
@ -834,10 +855,14 @@ bool RecursiveASTVisitor<Derived>::TraverseDeclarationNameInfo(
|
|||
|
||||
template <typename Derived>
|
||||
bool RecursiveASTVisitor<Derived>::TraverseTemplateName(TemplateName Template) {
|
||||
if (DependentTemplateName *DTN = Template.getAsDependentTemplateName())
|
||||
if (DependentTemplateName *DTN = Template.getAsDependentTemplateName()) {
|
||||
TRY_TO(TraverseNestedNameSpecifier(DTN->getQualifier()));
|
||||
else if (QualifiedTemplateName *QTN = Template.getAsQualifiedTemplateName())
|
||||
TRY_TO(TraverseNestedNameSpecifier(QTN->getQualifier()));
|
||||
} else if (QualifiedTemplateName *QTN =
|
||||
Template.getAsQualifiedTemplateName()) {
|
||||
if (QTN->getQualifier()) {
|
||||
TRY_TO(TraverseNestedNameSpecifier(QTN->getQualifier()));
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
|
@ -989,6 +1014,12 @@ DEF_TRAVERSE_TYPE(ConstantArrayType, {
|
|||
TRY_TO(TraverseStmt(const_cast<Expr*>(T->getSizeExpr())));
|
||||
})
|
||||
|
||||
DEF_TRAVERSE_TYPE(ArrayParameterType, {
|
||||
TRY_TO(TraverseType(T->getElementType()));
|
||||
if (T->getSizeExpr())
|
||||
TRY_TO(TraverseStmt(const_cast<Expr *>(T->getSizeExpr())));
|
||||
})
|
||||
|
||||
DEF_TRAVERSE_TYPE(IncompleteArrayType,
|
||||
{ TRY_TO(TraverseType(T->getElementType())); })
|
||||
|
||||
|
|
@ -1065,6 +1096,11 @@ DEF_TRAVERSE_TYPE(TypeOfType, { TRY_TO(TraverseType(T->getUnmodifiedType())); })
|
|||
DEF_TRAVERSE_TYPE(DecltypeType,
|
||||
{ TRY_TO(TraverseStmt(T->getUnderlyingExpr())); })
|
||||
|
||||
DEF_TRAVERSE_TYPE(PackIndexingType, {
|
||||
TRY_TO(TraverseType(T->getPattern()));
|
||||
TRY_TO(TraverseStmt(T->getIndexExpr()));
|
||||
})
|
||||
|
||||
DEF_TRAVERSE_TYPE(UnaryTransformType, {
|
||||
TRY_TO(TraverseType(T->getBaseType()));
|
||||
TRY_TO(TraverseType(T->getUnderlyingType()));
|
||||
|
|
@ -1101,6 +1137,12 @@ DEF_TRAVERSE_TYPE(InjectedClassNameType, {})
|
|||
DEF_TRAVERSE_TYPE(AttributedType,
|
||||
{ TRY_TO(TraverseType(T->getModifiedType())); })
|
||||
|
||||
DEF_TRAVERSE_TYPE(CountAttributedType, {
|
||||
if (T->getCountExpr())
|
||||
TRY_TO(TraverseStmt(T->getCountExpr()));
|
||||
TRY_TO(TraverseType(T->desugar()));
|
||||
})
|
||||
|
||||
DEF_TRAVERSE_TYPE(BTFTagAttributedType,
|
||||
{ TRY_TO(TraverseType(T->getWrappedType())); })
|
||||
|
||||
|
|
@ -1245,6 +1287,11 @@ DEF_TRAVERSE_TYPELOC(ConstantArrayType, {
|
|||
TRY_TO(TraverseArrayTypeLocHelper(TL));
|
||||
})
|
||||
|
||||
DEF_TRAVERSE_TYPELOC(ArrayParameterType, {
|
||||
TRY_TO(TraverseTypeLoc(TL.getElementLoc()));
|
||||
TRY_TO(TraverseArrayTypeLocHelper(TL));
|
||||
})
|
||||
|
||||
DEF_TRAVERSE_TYPELOC(IncompleteArrayType, {
|
||||
TRY_TO(TraverseTypeLoc(TL.getElementLoc()));
|
||||
TRY_TO(TraverseArrayTypeLocHelper(TL));
|
||||
|
|
@ -1343,6 +1390,11 @@ DEF_TRAVERSE_TYPELOC(DecltypeType, {
|
|||
TRY_TO(TraverseStmt(TL.getTypePtr()->getUnderlyingExpr()));
|
||||
})
|
||||
|
||||
DEF_TRAVERSE_TYPELOC(PackIndexingType, {
|
||||
TRY_TO(TraverseType(TL.getPattern()));
|
||||
TRY_TO(TraverseStmt(TL.getTypePtr()->getIndexExpr()));
|
||||
})
|
||||
|
||||
DEF_TRAVERSE_TYPELOC(UnaryTransformType, {
|
||||
TRY_TO(TraverseTypeLoc(TL.getUnderlyingTInfo()->getTypeLoc()));
|
||||
})
|
||||
|
|
@ -1387,6 +1439,9 @@ DEF_TRAVERSE_TYPELOC(MacroQualifiedType,
|
|||
DEF_TRAVERSE_TYPELOC(AttributedType,
|
||||
{ TRY_TO(TraverseTypeLoc(TL.getModifiedLoc())); })
|
||||
|
||||
DEF_TRAVERSE_TYPELOC(CountAttributedType,
|
||||
{ TRY_TO(TraverseTypeLoc(TL.getInnerLoc())); })
|
||||
|
||||
DEF_TRAVERSE_TYPELOC(BTFTagAttributedType,
|
||||
{ TRY_TO(TraverseTypeLoc(TL.getWrappedLoc())); })
|
||||
|
||||
|
|
@ -1911,7 +1966,7 @@ DEF_TRAVERSE_DECL(TemplateTypeParmDecl, {
|
|||
TRY_TO(TraverseType(QualType(D->getTypeForDecl(), 0)));
|
||||
TRY_TO(TraverseTemplateTypeParamDeclConstraints(D));
|
||||
if (D->hasDefaultArgument() && !D->defaultArgumentWasInherited())
|
||||
TRY_TO(TraverseTypeLoc(D->getDefaultArgumentInfo()->getTypeLoc()));
|
||||
TRY_TO(TraverseTemplateArgumentLoc(D->getDefaultArgument()));
|
||||
})
|
||||
|
||||
DEF_TRAVERSE_DECL(TypedefDecl, {
|
||||
|
|
@ -1995,6 +2050,15 @@ DEF_TRAVERSE_DECL(RecordDecl, { TRY_TO(TraverseRecordHelper(D)); })
|
|||
|
||||
DEF_TRAVERSE_DECL(CXXRecordDecl, { TRY_TO(TraverseCXXRecordHelper(D)); })
|
||||
|
||||
template <typename Derived>
|
||||
bool RecursiveASTVisitor<Derived>::TraverseTemplateArgumentLocsHelper(
|
||||
const TemplateArgumentLoc *TAL, unsigned Count) {
|
||||
for (unsigned I = 0; I < Count; ++I) {
|
||||
TRY_TO(TraverseTemplateArgumentLoc(TAL[I]));
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
#define DEF_TRAVERSE_TMPL_SPEC_DECL(TMPLDECLKIND, DECLKIND) \
|
||||
DEF_TRAVERSE_DECL(TMPLDECLKIND##TemplateSpecializationDecl, { \
|
||||
/* For implicit instantiations ("set<int> x;"), we don't want to \
|
||||
|
|
@ -2004,9 +2068,12 @@ DEF_TRAVERSE_DECL(CXXRecordDecl, { TRY_TO(TraverseCXXRecordHelper(D)); })
|
|||
TemplateSpecializationType). For explicit instantiations \
|
||||
("template set<int>;"), we do need a callback, since this \
|
||||
is the only callback that's made for this instantiation. \
|
||||
We use getTypeAsWritten() to distinguish. */ \
|
||||
if (TypeSourceInfo *TSI = D->getTypeAsWritten()) \
|
||||
TRY_TO(TraverseTypeLoc(TSI->getTypeLoc())); \
|
||||
We use getTemplateArgsAsWritten() to distinguish. */ \
|
||||
if (const auto *ArgsWritten = D->getTemplateArgsAsWritten()) { \
|
||||
/* The args that remains unspecialized. */ \
|
||||
TRY_TO(TraverseTemplateArgumentLocsHelper( \
|
||||
ArgsWritten->getTemplateArgs(), ArgsWritten->NumTemplateArgs)); \
|
||||
} \
|
||||
\
|
||||
if (getDerived().shouldVisitTemplateInstantiations() || \
|
||||
D->getTemplateSpecializationKind() == TSK_ExplicitSpecialization) { \
|
||||
|
|
@ -2026,15 +2093,6 @@ DEF_TRAVERSE_DECL(CXXRecordDecl, { TRY_TO(TraverseCXXRecordHelper(D)); })
|
|||
DEF_TRAVERSE_TMPL_SPEC_DECL(Class, CXXRecord)
|
||||
DEF_TRAVERSE_TMPL_SPEC_DECL(Var, Var)
|
||||
|
||||
template <typename Derived>
|
||||
bool RecursiveASTVisitor<Derived>::TraverseTemplateArgumentLocsHelper(
|
||||
const TemplateArgumentLoc *TAL, unsigned Count) {
|
||||
for (unsigned I = 0; I < Count; ++I) {
|
||||
TRY_TO(TraverseTemplateArgumentLoc(TAL[I]));
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
#define DEF_TRAVERSE_TMPL_PART_SPEC_DECL(TMPLDECLKIND, DECLKIND) \
|
||||
DEF_TRAVERSE_DECL(TMPLDECLKIND##TemplatePartialSpecializationDecl, { \
|
||||
/* The partial specialization. */ \
|
||||
|
|
@ -2268,7 +2326,7 @@ DEF_TRAVERSE_DECL(NonTypeTemplateParmDecl, {
|
|||
// A non-type template parameter, e.g. "S" in template<int S> class Foo ...
|
||||
TRY_TO(TraverseDeclaratorHelper(D));
|
||||
if (D->hasDefaultArgument() && !D->defaultArgumentWasInherited())
|
||||
TRY_TO(TraverseStmt(D->getDefaultArgument()));
|
||||
TRY_TO(TraverseTemplateArgumentLoc(D->getDefaultArgument()));
|
||||
})
|
||||
|
||||
DEF_TRAVERSE_DECL(ParmVarDecl, {
|
||||
|
|
@ -2705,7 +2763,7 @@ DEF_TRAVERSE_STMT(CXXMemberCallExpr, {})
|
|||
DEF_TRAVERSE_STMT(AddrLabelExpr, {})
|
||||
DEF_TRAVERSE_STMT(ArraySubscriptExpr, {})
|
||||
DEF_TRAVERSE_STMT(MatrixSubscriptExpr, {})
|
||||
DEF_TRAVERSE_STMT(OMPArraySectionExpr, {})
|
||||
DEF_TRAVERSE_STMT(ArraySectionExpr, {})
|
||||
DEF_TRAVERSE_STMT(OMPArrayShapingExpr, {})
|
||||
DEF_TRAVERSE_STMT(OMPIteratorExpr, {})
|
||||
|
||||
|
|
@ -2806,6 +2864,11 @@ DEF_TRAVERSE_STMT(ShuffleVectorExpr, {})
|
|||
DEF_TRAVERSE_STMT(ConvertVectorExpr, {})
|
||||
DEF_TRAVERSE_STMT(StmtExpr, {})
|
||||
DEF_TRAVERSE_STMT(SourceLocExpr, {})
|
||||
DEF_TRAVERSE_STMT(EmbedExpr, {
|
||||
for (IntegerLiteral *IL : S->underlying_data_elements()) {
|
||||
TRY_TO_TRAVERSE_OR_ENQUEUE_STMT(IL);
|
||||
}
|
||||
})
|
||||
|
||||
DEF_TRAVERSE_STMT(UnresolvedLookupExpr, {
|
||||
TRY_TO(TraverseNestedNameSpecifierLoc(S->getQualifierLoc()));
|
||||
|
|
@ -2854,6 +2917,7 @@ DEF_TRAVERSE_STMT(CompoundAssignOperator, {})
|
|||
DEF_TRAVERSE_STMT(CXXNoexceptExpr, {})
|
||||
DEF_TRAVERSE_STMT(PackExpansionExpr, {})
|
||||
DEF_TRAVERSE_STMT(SizeOfPackExpr, {})
|
||||
DEF_TRAVERSE_STMT(PackIndexingExpr, {})
|
||||
DEF_TRAVERSE_STMT(SubstNonTypeTemplateParmPackExpr, {})
|
||||
DEF_TRAVERSE_STMT(SubstNonTypeTemplateParmExpr, {})
|
||||
DEF_TRAVERSE_STMT(FunctionParmPackExpr, {})
|
||||
|
|
@ -2968,6 +3032,12 @@ DEF_TRAVERSE_STMT(OMPTileDirective,
|
|||
DEF_TRAVERSE_STMT(OMPUnrollDirective,
|
||||
{ TRY_TO(TraverseOMPExecutableDirective(S)); })
|
||||
|
||||
DEF_TRAVERSE_STMT(OMPReverseDirective,
|
||||
{ TRY_TO(TraverseOMPExecutableDirective(S)); })
|
||||
|
||||
DEF_TRAVERSE_STMT(OMPInterchangeDirective,
|
||||
{ TRY_TO(TraverseOMPExecutableDirective(S)); })
|
||||
|
||||
DEF_TRAVERSE_STMT(OMPForDirective,
|
||||
{ TRY_TO(TraverseOMPExecutableDirective(S)); })
|
||||
|
||||
|
|
@ -3425,6 +3495,11 @@ bool RecursiveASTVisitor<Derived>::VisitOMPRelaxedClause(OMPRelaxedClause *) {
|
|||
return true;
|
||||
}
|
||||
|
||||
template <typename Derived>
|
||||
bool RecursiveASTVisitor<Derived>::VisitOMPWeakClause(OMPWeakClause *) {
|
||||
return true;
|
||||
}
|
||||
|
||||
template <typename Derived>
|
||||
bool RecursiveASTVisitor<Derived>::VisitOMPThreadsClause(OMPThreadsClause *) {
|
||||
return true;
|
||||
|
|
@ -3894,6 +3969,51 @@ bool RecursiveASTVisitor<Derived>::VisitOMPXBareClause(OMPXBareClause *C) {
|
|||
return true;
|
||||
}
|
||||
|
||||
template <typename Derived>
|
||||
bool RecursiveASTVisitor<Derived>::TraverseOpenACCConstructStmt(
|
||||
OpenACCConstructStmt *C) {
|
||||
TRY_TO(VisitOpenACCClauseList(C->clauses()));
|
||||
return true;
|
||||
}
|
||||
|
||||
template <typename Derived>
|
||||
bool RecursiveASTVisitor<Derived>::TraverseOpenACCAssociatedStmtConstruct(
|
||||
OpenACCAssociatedStmtConstruct *S) {
|
||||
TRY_TO(TraverseOpenACCConstructStmt(S));
|
||||
TRY_TO(TraverseStmt(S->getAssociatedStmt()));
|
||||
return true;
|
||||
}
|
||||
|
||||
template <typename Derived>
|
||||
bool RecursiveASTVisitor<Derived>::VisitOpenACCClause(const OpenACCClause *C) {
|
||||
for (const Stmt *Child : C->children())
|
||||
TRY_TO(TraverseStmt(const_cast<Stmt *>(Child)));
|
||||
return true;
|
||||
}
|
||||
|
||||
template <typename Derived>
|
||||
bool RecursiveASTVisitor<Derived>::VisitOpenACCClauseList(
|
||||
ArrayRef<const OpenACCClause *> Clauses) {
|
||||
|
||||
for (const auto *C : Clauses)
|
||||
TRY_TO(VisitOpenACCClause(C));
|
||||
// if (const auto *WithCond = dyn_cast<OopenACCClauseWithCondition>(C);
|
||||
// WithCond && WIthCond->hasConditionExpr()) {
|
||||
// TRY_TO(TraverseStmt(WithCond->getConditionExpr());
|
||||
// } else if (const auto *
|
||||
// }
|
||||
// OpenACCClauseWithCondition::getConditionExpr/hasConditionExpr
|
||||
//OpenACCClauseWithExprs::children (might be null?)
|
||||
// TODO OpenACC: When we have Clauses with expressions, we should visit them
|
||||
// here.
|
||||
return true;
|
||||
}
|
||||
|
||||
DEF_TRAVERSE_STMT(OpenACCComputeConstruct,
|
||||
{ TRY_TO(TraverseOpenACCAssociatedStmtConstruct(S)); })
|
||||
DEF_TRAVERSE_STMT(OpenACCLoopConstruct,
|
||||
{ TRY_TO(TraverseOpenACCAssociatedStmtConstruct(S)); })
|
||||
|
||||
// FIXME: look at the following tricky-seeming exprs to see if we
|
||||
// need to recurse on anything. These are ones that have methods
|
||||
// returning decls or qualtypes or nestednamespecifier -- though I'm
|
||||
|
|
|
|||
|
|
@ -281,10 +281,10 @@ public:
|
|||
return tmp;
|
||||
}
|
||||
|
||||
friend bool operator==(redecl_iterator x, redecl_iterator y) {
|
||||
friend bool operator==(const redecl_iterator &x, const redecl_iterator &y) {
|
||||
return x.Current == y.Current;
|
||||
}
|
||||
friend bool operator!=(redecl_iterator x, redecl_iterator y) {
|
||||
friend bool operator!=(const redecl_iterator &x, const redecl_iterator &y) {
|
||||
return x.Current != y.Current;
|
||||
}
|
||||
};
|
||||
|
|
|
|||
|
|
@ -460,10 +460,10 @@ protected:
|
|||
unsigned : NumExprBits;
|
||||
|
||||
static_assert(
|
||||
llvm::APFloat::S_MaxSemantics < 16,
|
||||
"Too many Semantics enum values to fit in bitfield of size 4");
|
||||
llvm::APFloat::S_MaxSemantics < 32,
|
||||
"Too many Semantics enum values to fit in bitfield of size 5");
|
||||
LLVM_PREFERRED_TYPE(llvm::APFloat::Semantics)
|
||||
unsigned Semantics : 4; // Provides semantics for APFloat construction
|
||||
unsigned Semantics : 5; // Provides semantics for APFloat construction
|
||||
LLVM_PREFERRED_TYPE(bool)
|
||||
unsigned IsExact : 1;
|
||||
};
|
||||
|
|
@ -583,11 +583,13 @@ protected:
|
|||
unsigned IsArrow : 1;
|
||||
|
||||
/// True if this member expression used a nested-name-specifier to
|
||||
/// refer to the member, e.g., "x->Base::f", or found its member via
|
||||
/// a using declaration. When true, a MemberExprNameQualifier
|
||||
/// structure is allocated immediately after the MemberExpr.
|
||||
/// refer to the member, e.g., "x->Base::f".
|
||||
LLVM_PREFERRED_TYPE(bool)
|
||||
unsigned HasQualifierOrFoundDecl : 1;
|
||||
unsigned HasQualifier : 1;
|
||||
|
||||
// True if this member expression found its member via a using declaration.
|
||||
LLVM_PREFERRED_TYPE(bool)
|
||||
unsigned HasFoundDecl : 1;
|
||||
|
||||
/// True if this member expression specified a template keyword
|
||||
/// and/or a template argument list explicitly, e.g., x->f<int>,
|
||||
|
|
@ -782,6 +784,11 @@ protected:
|
|||
LLVM_PREFERRED_TYPE(bool)
|
||||
unsigned IsImplicit : 1;
|
||||
|
||||
/// Whether there is a lambda with an explicit object parameter that
|
||||
/// captures this "this" by copy.
|
||||
LLVM_PREFERRED_TYPE(bool)
|
||||
unsigned CapturedByCopyInLambdaWithExplicitObjectParameter : 1;
|
||||
|
||||
/// The location of the "this".
|
||||
SourceLocation Loc;
|
||||
};
|
||||
|
|
@ -1060,11 +1067,6 @@ protected:
|
|||
/// argument-dependent lookup if this is the operand of a function call.
|
||||
LLVM_PREFERRED_TYPE(bool)
|
||||
unsigned RequiresADL : 1;
|
||||
|
||||
/// True if these lookup results are overloaded. This is pretty trivially
|
||||
/// rederivable if we urgently need to kill this field.
|
||||
LLVM_PREFERRED_TYPE(bool)
|
||||
unsigned Overloaded : 1;
|
||||
};
|
||||
static_assert(sizeof(UnresolvedLookupExprBitfields) <= 4,
|
||||
"UnresolvedLookupExprBitfields must be <= than 4 bytes to"
|
||||
|
|
@ -1656,6 +1658,11 @@ public:
|
|||
return *getTrailingObjects<FPOptionsOverride>();
|
||||
}
|
||||
|
||||
/// Get the store FPOptionsOverride or default if not stored.
|
||||
FPOptionsOverride getStoredFPFeaturesOrDefault() const {
|
||||
return hasStoredFPFeatures() ? getStoredFPFeatures() : FPOptionsOverride();
|
||||
}
|
||||
|
||||
using body_iterator = Stmt **;
|
||||
using body_range = llvm::iterator_range<body_iterator>;
|
||||
|
||||
|
|
|
|||
|
|
@ -177,7 +177,8 @@ class ObjCAtTryStmt final
|
|||
unsigned NumCatchStmts : 16;
|
||||
|
||||
// Whether this statement has a \@finally statement.
|
||||
bool HasFinally : 1;
|
||||
LLVM_PREFERRED_TYPE(bool)
|
||||
unsigned HasFinally : 1;
|
||||
|
||||
/// Retrieve the statements that are stored after this \@try statement.
|
||||
///
|
||||
|
|
|
|||
256
contrib/llvm-project/clang/include/clang/AST/StmtOpenACC.h
Normal file
256
contrib/llvm-project/clang/include/clang/AST/StmtOpenACC.h
Normal file
|
|
@ -0,0 +1,256 @@
|
|||
//===- StmtOpenACC.h - Classes for OpenACC directives ----------*- 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
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
/// \file
|
||||
/// This file defines OpenACC AST classes for statement-level contructs.
|
||||
///
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef LLVM_CLANG_AST_STMTOPENACC_H
|
||||
#define LLVM_CLANG_AST_STMTOPENACC_H
|
||||
|
||||
#include "clang/AST/OpenACCClause.h"
|
||||
#include "clang/AST/Stmt.h"
|
||||
#include "clang/Basic/OpenACCKinds.h"
|
||||
#include "clang/Basic/SourceLocation.h"
|
||||
#include <memory>
|
||||
|
||||
namespace clang {
|
||||
/// This is the base class for an OpenACC statement-level construct, other
|
||||
/// construct types are expected to inherit from this.
|
||||
class OpenACCConstructStmt : public Stmt {
|
||||
friend class ASTStmtWriter;
|
||||
friend class ASTStmtReader;
|
||||
/// The directive kind. Each implementation of this interface should handle
|
||||
/// specific kinds.
|
||||
OpenACCDirectiveKind Kind = OpenACCDirectiveKind::Invalid;
|
||||
/// The location of the directive statement, from the '#' to the last token of
|
||||
/// the directive.
|
||||
SourceRange Range;
|
||||
/// The location of the directive name.
|
||||
SourceLocation DirectiveLoc;
|
||||
|
||||
/// The list of clauses. This is stored here as an ArrayRef, as this is the
|
||||
/// most convienient place to access the list, however the list itself should
|
||||
/// be stored in leaf nodes, likely in trailing-storage.
|
||||
MutableArrayRef<const OpenACCClause *> Clauses;
|
||||
|
||||
protected:
|
||||
OpenACCConstructStmt(StmtClass SC, OpenACCDirectiveKind K,
|
||||
SourceLocation Start, SourceLocation DirectiveLoc,
|
||||
SourceLocation End)
|
||||
: Stmt(SC), Kind(K), Range(Start, End), DirectiveLoc(DirectiveLoc) {}
|
||||
|
||||
// Used only for initialization, the leaf class can initialize this to
|
||||
// trailing storage.
|
||||
void setClauseList(MutableArrayRef<const OpenACCClause *> NewClauses) {
|
||||
assert(Clauses.empty() && "Cannot change clause list");
|
||||
Clauses = NewClauses;
|
||||
}
|
||||
|
||||
public:
|
||||
OpenACCDirectiveKind getDirectiveKind() const { return Kind; }
|
||||
|
||||
static bool classof(const Stmt *S) {
|
||||
return S->getStmtClass() >= firstOpenACCConstructStmtConstant &&
|
||||
S->getStmtClass() <= lastOpenACCConstructStmtConstant;
|
||||
}
|
||||
|
||||
SourceLocation getBeginLoc() const { return Range.getBegin(); }
|
||||
SourceLocation getEndLoc() const { return Range.getEnd(); }
|
||||
SourceLocation getDirectiveLoc() const { return DirectiveLoc; }
|
||||
ArrayRef<const OpenACCClause *> clauses() const { return Clauses; }
|
||||
|
||||
child_range children() {
|
||||
return child_range(child_iterator(), child_iterator());
|
||||
}
|
||||
|
||||
const_child_range children() const {
|
||||
return const_cast<OpenACCConstructStmt *>(this)->children();
|
||||
}
|
||||
};
|
||||
|
||||
/// This is a base class for any OpenACC statement-level constructs that have an
|
||||
/// associated statement. This class is not intended to be instantiated, but is
|
||||
/// a convenient place to hold the associated statement.
|
||||
class OpenACCAssociatedStmtConstruct : public OpenACCConstructStmt {
|
||||
friend class ASTStmtWriter;
|
||||
friend class ASTStmtReader;
|
||||
template <typename Derived> friend class RecursiveASTVisitor;
|
||||
Stmt *AssociatedStmt = nullptr;
|
||||
|
||||
protected:
|
||||
OpenACCAssociatedStmtConstruct(StmtClass SC, OpenACCDirectiveKind K,
|
||||
SourceLocation Start,
|
||||
SourceLocation DirectiveLoc,
|
||||
SourceLocation End, Stmt *AssocStmt)
|
||||
: OpenACCConstructStmt(SC, K, Start, DirectiveLoc, End),
|
||||
AssociatedStmt(AssocStmt) {}
|
||||
|
||||
void setAssociatedStmt(Stmt *S) { AssociatedStmt = S; }
|
||||
Stmt *getAssociatedStmt() { return AssociatedStmt; }
|
||||
const Stmt *getAssociatedStmt() const {
|
||||
return const_cast<OpenACCAssociatedStmtConstruct *>(this)
|
||||
->getAssociatedStmt();
|
||||
}
|
||||
|
||||
public:
|
||||
static bool classof(const Stmt *T) {
|
||||
return false;
|
||||
}
|
||||
|
||||
child_range children() {
|
||||
if (getAssociatedStmt())
|
||||
return child_range(&AssociatedStmt, &AssociatedStmt + 1);
|
||||
return child_range(child_iterator(), child_iterator());
|
||||
}
|
||||
|
||||
const_child_range children() const {
|
||||
return const_cast<OpenACCAssociatedStmtConstruct *>(this)->children();
|
||||
}
|
||||
};
|
||||
|
||||
class OpenACCLoopConstruct;
|
||||
/// This class represents a compute construct, representing a 'Kind' of
|
||||
/// `parallel', 'serial', or 'kernel'. These constructs are associated with a
|
||||
/// 'structured block', defined as:
|
||||
///
|
||||
/// in C or C++, an executable statement, possibly compound, with a single
|
||||
/// entry at the top and a single exit at the bottom
|
||||
///
|
||||
/// At the moment there is no real motivation to have a different AST node for
|
||||
/// those three, as they are semantically identical, and have only minor
|
||||
/// differences in the permitted list of clauses, which can be differentiated by
|
||||
/// the 'Kind'.
|
||||
class OpenACCComputeConstruct final
|
||||
: public OpenACCAssociatedStmtConstruct,
|
||||
public llvm::TrailingObjects<OpenACCComputeConstruct,
|
||||
const OpenACCClause *> {
|
||||
friend class ASTStmtWriter;
|
||||
friend class ASTStmtReader;
|
||||
friend class ASTContext;
|
||||
OpenACCComputeConstruct(unsigned NumClauses)
|
||||
: OpenACCAssociatedStmtConstruct(
|
||||
OpenACCComputeConstructClass, OpenACCDirectiveKind::Invalid,
|
||||
SourceLocation{}, SourceLocation{}, SourceLocation{},
|
||||
/*AssociatedStmt=*/nullptr) {
|
||||
// We cannot send the TrailingObjects storage to the base class (which holds
|
||||
// a reference to the data) until it is constructed, so we have to set it
|
||||
// separately here.
|
||||
std::uninitialized_value_construct(
|
||||
getTrailingObjects<const OpenACCClause *>(),
|
||||
getTrailingObjects<const OpenACCClause *>() + NumClauses);
|
||||
setClauseList(MutableArrayRef(getTrailingObjects<const OpenACCClause *>(),
|
||||
NumClauses));
|
||||
}
|
||||
|
||||
OpenACCComputeConstruct(OpenACCDirectiveKind K, SourceLocation Start,
|
||||
SourceLocation DirectiveLoc, SourceLocation End,
|
||||
ArrayRef<const OpenACCClause *> Clauses,
|
||||
Stmt *StructuredBlock)
|
||||
: OpenACCAssociatedStmtConstruct(OpenACCComputeConstructClass, K, Start,
|
||||
DirectiveLoc, End, StructuredBlock) {
|
||||
assert(isOpenACCComputeDirectiveKind(K) &&
|
||||
"Only parallel, serial, and kernels constructs should be "
|
||||
"represented by this type");
|
||||
|
||||
// Initialize the trailing storage.
|
||||
std::uninitialized_copy(Clauses.begin(), Clauses.end(),
|
||||
getTrailingObjects<const OpenACCClause *>());
|
||||
|
||||
setClauseList(MutableArrayRef(getTrailingObjects<const OpenACCClause *>(),
|
||||
Clauses.size()));
|
||||
}
|
||||
|
||||
void setStructuredBlock(Stmt *S) { setAssociatedStmt(S); }
|
||||
// Serialization helper function that searches the structured block for 'loop'
|
||||
// constructs that should be associated with this, and sets their parent
|
||||
// compute construct to this one. This isn't necessary normally, since we have
|
||||
// the ability to record the state during parsing.
|
||||
void findAndSetChildLoops();
|
||||
|
||||
public:
|
||||
static bool classof(const Stmt *T) {
|
||||
return T->getStmtClass() == OpenACCComputeConstructClass;
|
||||
}
|
||||
|
||||
static OpenACCComputeConstruct *CreateEmpty(const ASTContext &C,
|
||||
unsigned NumClauses);
|
||||
static OpenACCComputeConstruct *
|
||||
Create(const ASTContext &C, OpenACCDirectiveKind K, SourceLocation BeginLoc,
|
||||
SourceLocation DirectiveLoc, SourceLocation EndLoc,
|
||||
ArrayRef<const OpenACCClause *> Clauses, Stmt *StructuredBlock,
|
||||
ArrayRef<OpenACCLoopConstruct *> AssociatedLoopConstructs);
|
||||
|
||||
Stmt *getStructuredBlock() { return getAssociatedStmt(); }
|
||||
const Stmt *getStructuredBlock() const {
|
||||
return const_cast<OpenACCComputeConstruct *>(this)->getStructuredBlock();
|
||||
}
|
||||
};
|
||||
/// This class represents a 'loop' construct. The 'loop' construct applies to a
|
||||
/// 'for' loop (or range-for loop), and is optionally associated with a Compute
|
||||
/// Construct.
|
||||
class OpenACCLoopConstruct final
|
||||
: public OpenACCAssociatedStmtConstruct,
|
||||
public llvm::TrailingObjects<OpenACCLoopConstruct,
|
||||
const OpenACCClause *> {
|
||||
// The compute construct this loop is associated with, or nullptr if this is
|
||||
// an orphaned loop construct, or if it hasn't been set yet. Because we
|
||||
// construct the directives at the end of their statement, the 'parent'
|
||||
// construct is not yet available at the time of construction, so this needs
|
||||
// to be set 'later'.
|
||||
const OpenACCComputeConstruct *ParentComputeConstruct = nullptr;
|
||||
|
||||
friend class ASTStmtWriter;
|
||||
friend class ASTStmtReader;
|
||||
friend class ASTContext;
|
||||
friend class OpenACCComputeConstruct;
|
||||
|
||||
OpenACCLoopConstruct(unsigned NumClauses);
|
||||
|
||||
OpenACCLoopConstruct(SourceLocation Start, SourceLocation DirLoc,
|
||||
SourceLocation End,
|
||||
ArrayRef<const OpenACCClause *> Clauses, Stmt *Loop);
|
||||
void setLoop(Stmt *Loop);
|
||||
|
||||
void setParentComputeConstruct(OpenACCComputeConstruct *CC) {
|
||||
assert(!ParentComputeConstruct && "Parent already set?");
|
||||
ParentComputeConstruct = CC;
|
||||
}
|
||||
|
||||
public:
|
||||
static bool classof(const Stmt *T) {
|
||||
return T->getStmtClass() == OpenACCLoopConstructClass;
|
||||
}
|
||||
|
||||
static OpenACCLoopConstruct *CreateEmpty(const ASTContext &C,
|
||||
unsigned NumClauses);
|
||||
|
||||
static OpenACCLoopConstruct *
|
||||
Create(const ASTContext &C, SourceLocation BeginLoc, SourceLocation DirLoc,
|
||||
SourceLocation EndLoc, ArrayRef<const OpenACCClause *> Clauses,
|
||||
Stmt *Loop);
|
||||
|
||||
Stmt *getLoop() { return getAssociatedStmt(); }
|
||||
const Stmt *getLoop() const {
|
||||
return const_cast<OpenACCLoopConstruct *>(this)->getLoop();
|
||||
}
|
||||
|
||||
/// OpenACC 3.3 2.9:
|
||||
/// An orphaned loop construct is a loop construct that is not lexically
|
||||
/// enclosed within a compute construct. The parent compute construct of a
|
||||
/// loop construct is the nearest compute construct that lexically contains
|
||||
/// the loop construct.
|
||||
bool isOrphanedLoopConstruct() const {
|
||||
return ParentComputeConstruct == nullptr;
|
||||
}
|
||||
const OpenACCComputeConstruct *getParentComputeConstruct() const {
|
||||
return ParentComputeConstruct;
|
||||
}
|
||||
};
|
||||
} // namespace clang
|
||||
#endif // LLVM_CLANG_AST_STMTOPENACC_H
|
||||
|
|
@ -1007,8 +1007,9 @@ public:
|
|||
Stmt *getPreInits() const;
|
||||
|
||||
static bool classof(const Stmt *T) {
|
||||
return T->getStmtClass() == OMPTileDirectiveClass ||
|
||||
T->getStmtClass() == OMPUnrollDirectiveClass;
|
||||
Stmt::StmtClass C = T->getStmtClass();
|
||||
return C == OMPTileDirectiveClass || C == OMPUnrollDirectiveClass ||
|
||||
C == OMPReverseDirectiveClass || C == OMPInterchangeDirectiveClass;
|
||||
}
|
||||
};
|
||||
|
||||
|
|
@ -2974,6 +2975,7 @@ class OMPAtomicDirective : public OMPExecutableDirective {
|
|||
/// This field is 1 for the first form of the expression and 0 for the
|
||||
/// second. Required for correct codegen of non-associative operations (like
|
||||
/// << or >>).
|
||||
LLVM_PREFERRED_TYPE(bool)
|
||||
uint8_t IsXLHSInRHSPart : 1;
|
||||
/// Used for 'atomic update' or 'atomic capture' constructs. They may
|
||||
/// have atomic expressions of forms:
|
||||
|
|
@ -2983,9 +2985,11 @@ class OMPAtomicDirective : public OMPExecutableDirective {
|
|||
/// \endcode
|
||||
/// This field is 1 for the first(postfix) form of the expression and 0
|
||||
/// otherwise.
|
||||
LLVM_PREFERRED_TYPE(bool)
|
||||
uint8_t IsPostfixUpdate : 1;
|
||||
/// 1 if 'v' is updated only when the condition is false (compare capture
|
||||
/// only).
|
||||
LLVM_PREFERRED_TYPE(bool)
|
||||
uint8_t IsFailOnly : 1;
|
||||
} Flags;
|
||||
|
||||
|
|
@ -5708,6 +5712,144 @@ public:
|
|||
}
|
||||
};
|
||||
|
||||
/// Represents the '#pragma omp reverse' loop transformation directive.
|
||||
///
|
||||
/// \code
|
||||
/// #pragma omp reverse
|
||||
/// for (int i = 0; i < n; ++i)
|
||||
/// ...
|
||||
/// \endcode
|
||||
class OMPReverseDirective final : public OMPLoopTransformationDirective {
|
||||
friend class ASTStmtReader;
|
||||
friend class OMPExecutableDirective;
|
||||
|
||||
/// Offsets of child members.
|
||||
enum {
|
||||
PreInitsOffset = 0,
|
||||
TransformedStmtOffset,
|
||||
};
|
||||
|
||||
explicit OMPReverseDirective(SourceLocation StartLoc, SourceLocation EndLoc)
|
||||
: OMPLoopTransformationDirective(OMPReverseDirectiveClass,
|
||||
llvm::omp::OMPD_reverse, StartLoc,
|
||||
EndLoc, 1) {}
|
||||
|
||||
void setPreInits(Stmt *PreInits) {
|
||||
Data->getChildren()[PreInitsOffset] = PreInits;
|
||||
}
|
||||
|
||||
void setTransformedStmt(Stmt *S) {
|
||||
Data->getChildren()[TransformedStmtOffset] = S;
|
||||
}
|
||||
|
||||
public:
|
||||
/// Create a new AST node representation for '#pragma omp reverse'.
|
||||
///
|
||||
/// \param C Context of the AST.
|
||||
/// \param StartLoc Location of the introducer (e.g. the 'omp' token).
|
||||
/// \param EndLoc Location of the directive's end (e.g. the tok::eod).
|
||||
/// \param AssociatedStmt The outermost associated loop.
|
||||
/// \param TransformedStmt The loop nest after tiling, or nullptr in
|
||||
/// dependent contexts.
|
||||
/// \param PreInits Helper preinits statements for the loop nest.
|
||||
static OMPReverseDirective *
|
||||
Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc,
|
||||
Stmt *AssociatedStmt, Stmt *TransformedStmt, Stmt *PreInits);
|
||||
|
||||
/// Build an empty '#pragma omp reverse' AST node for deserialization.
|
||||
///
|
||||
/// \param C Context of the AST.
|
||||
/// \param NumClauses Number of clauses to allocate.
|
||||
static OMPReverseDirective *CreateEmpty(const ASTContext &C);
|
||||
|
||||
/// Gets/sets the associated loops after the transformation, i.e. after
|
||||
/// de-sugaring.
|
||||
Stmt *getTransformedStmt() const {
|
||||
return Data->getChildren()[TransformedStmtOffset];
|
||||
}
|
||||
|
||||
/// Return preinits statement.
|
||||
Stmt *getPreInits() const { return Data->getChildren()[PreInitsOffset]; }
|
||||
|
||||
static bool classof(const Stmt *T) {
|
||||
return T->getStmtClass() == OMPReverseDirectiveClass;
|
||||
}
|
||||
};
|
||||
|
||||
/// Represents the '#pragma omp interchange' loop transformation directive.
|
||||
///
|
||||
/// \code{c}
|
||||
/// #pragma omp interchange
|
||||
/// for (int i = 0; i < m; ++i)
|
||||
/// for (int j = 0; j < n; ++j)
|
||||
/// ..
|
||||
/// \endcode
|
||||
class OMPInterchangeDirective final : public OMPLoopTransformationDirective {
|
||||
friend class ASTStmtReader;
|
||||
friend class OMPExecutableDirective;
|
||||
|
||||
/// Offsets of child members.
|
||||
enum {
|
||||
PreInitsOffset = 0,
|
||||
TransformedStmtOffset,
|
||||
};
|
||||
|
||||
explicit OMPInterchangeDirective(SourceLocation StartLoc,
|
||||
SourceLocation EndLoc, unsigned NumLoops)
|
||||
: OMPLoopTransformationDirective(OMPInterchangeDirectiveClass,
|
||||
llvm::omp::OMPD_interchange, StartLoc,
|
||||
EndLoc, NumLoops) {
|
||||
setNumGeneratedLoops(3 * NumLoops);
|
||||
}
|
||||
|
||||
void setPreInits(Stmt *PreInits) {
|
||||
Data->getChildren()[PreInitsOffset] = PreInits;
|
||||
}
|
||||
|
||||
void setTransformedStmt(Stmt *S) {
|
||||
Data->getChildren()[TransformedStmtOffset] = S;
|
||||
}
|
||||
|
||||
public:
|
||||
/// Create a new AST node representation for '#pragma omp interchange'.
|
||||
///
|
||||
/// \param C Context of the AST.
|
||||
/// \param StartLoc Location of the introducer (e.g. the 'omp' token).
|
||||
/// \param EndLoc Location of the directive's end (e.g. the tok::eod).
|
||||
/// \param Clauses The directive's clauses.
|
||||
/// \param NumLoops Number of affected loops
|
||||
/// (number of items in the 'permutation' clause if present).
|
||||
/// \param AssociatedStmt The outermost associated loop.
|
||||
/// \param TransformedStmt The loop nest after tiling, or nullptr in
|
||||
/// dependent contexts.
|
||||
/// \param PreInits Helper preinits statements for the loop nest.
|
||||
static OMPInterchangeDirective *
|
||||
Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc,
|
||||
ArrayRef<OMPClause *> Clauses, unsigned NumLoops, Stmt *AssociatedStmt,
|
||||
Stmt *TransformedStmt, Stmt *PreInits);
|
||||
|
||||
/// Build an empty '#pragma omp interchange' AST node for deserialization.
|
||||
///
|
||||
/// \param C Context of the AST.
|
||||
/// \param NumClauses Number of clauses to allocate.
|
||||
/// \param NumLoops Number of associated loops to allocate.
|
||||
static OMPInterchangeDirective *
|
||||
CreateEmpty(const ASTContext &C, unsigned NumClauses, unsigned NumLoops);
|
||||
|
||||
/// Gets the associated loops after the transformation. This is the de-sugared
|
||||
/// replacement or nullptr in dependent contexts.
|
||||
Stmt *getTransformedStmt() const {
|
||||
return Data->getChildren()[TransformedStmtOffset];
|
||||
}
|
||||
|
||||
/// Return preinits statement.
|
||||
Stmt *getPreInits() const { return Data->getChildren()[PreInitsOffset]; }
|
||||
|
||||
static bool classof(const Stmt *T) {
|
||||
return T->getStmtClass() == OMPInterchangeDirectiveClass;
|
||||
}
|
||||
};
|
||||
|
||||
/// This represents '#pragma omp scan' directive.
|
||||
///
|
||||
/// \code
|
||||
|
|
@ -6106,6 +6248,8 @@ public:
|
|||
class OMPTargetTeamsGenericLoopDirective final : public OMPLoopDirective {
|
||||
friend class ASTStmtReader;
|
||||
friend class OMPExecutableDirective;
|
||||
/// true if loop directive's associated loop can be a parallel for.
|
||||
bool CanBeParallelFor = false;
|
||||
/// Build directive with the given start and end location.
|
||||
///
|
||||
/// \param StartLoc Starting location of the directive kind.
|
||||
|
|
@ -6128,6 +6272,9 @@ class OMPTargetTeamsGenericLoopDirective final : public OMPLoopDirective {
|
|||
llvm::omp::OMPD_target_teams_loop, SourceLocation(),
|
||||
SourceLocation(), CollapsedNum) {}
|
||||
|
||||
/// Set whether associated loop can be a parallel for.
|
||||
void setCanBeParallelFor(bool ParFor) { CanBeParallelFor = ParFor; }
|
||||
|
||||
public:
|
||||
/// Creates directive with a list of \p Clauses.
|
||||
///
|
||||
|
|
@ -6142,7 +6289,7 @@ public:
|
|||
static OMPTargetTeamsGenericLoopDirective *
|
||||
Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc,
|
||||
unsigned CollapsedNum, ArrayRef<OMPClause *> Clauses,
|
||||
Stmt *AssociatedStmt, const HelperExprs &Exprs);
|
||||
Stmt *AssociatedStmt, const HelperExprs &Exprs, bool CanBeParallelFor);
|
||||
|
||||
/// Creates an empty directive with the place
|
||||
/// for \a NumClauses clauses.
|
||||
|
|
@ -6156,6 +6303,10 @@ public:
|
|||
unsigned CollapsedNum,
|
||||
EmptyShell);
|
||||
|
||||
/// Return true if current loop directive's associated loop can be a
|
||||
/// parallel for.
|
||||
bool canBeParallelFor() const { return CanBeParallelFor; }
|
||||
|
||||
static bool classof(const Stmt *T) {
|
||||
return T->getStmtClass() == OMPTargetTeamsGenericLoopDirectiveClass;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -13,13 +13,14 @@
|
|||
#ifndef LLVM_CLANG_AST_STMTVISITOR_H
|
||||
#define LLVM_CLANG_AST_STMTVISITOR_H
|
||||
|
||||
#include "clang/AST/ExprConcepts.h"
|
||||
#include "clang/AST/ExprCXX.h"
|
||||
#include "clang/AST/ExprConcepts.h"
|
||||
#include "clang/AST/ExprObjC.h"
|
||||
#include "clang/AST/ExprOpenMP.h"
|
||||
#include "clang/AST/Stmt.h"
|
||||
#include "clang/AST/StmtCXX.h"
|
||||
#include "clang/AST/StmtObjC.h"
|
||||
#include "clang/AST/StmtOpenACC.h"
|
||||
#include "clang/AST/StmtOpenMP.h"
|
||||
#include "clang/Basic/LLVM.h"
|
||||
#include "llvm/ADT/STLExtras.h"
|
||||
|
|
|
|||
|
|
@ -459,7 +459,7 @@ public:
|
|||
bool IncludeType) const;
|
||||
|
||||
/// Debugging aid that dumps the template argument.
|
||||
void dump(raw_ostream &Out) const;
|
||||
void dump(raw_ostream &Out, const ASTContext &Context) const;
|
||||
|
||||
/// Debugging aid that dumps the template argument to standard error.
|
||||
void dump() const;
|
||||
|
|
|
|||
|
|
@ -198,7 +198,8 @@ public:
|
|||
///
|
||||
/// Here, "apply" is treated as a template name within the typename
|
||||
/// specifier in the typedef. "apply" is a nested template, and can
|
||||
/// only be understood in the context of
|
||||
/// only be understood in the context of a template instantiation,
|
||||
/// hence is represented as a dependent template name.
|
||||
class TemplateName {
|
||||
// NameDecl is either a TemplateDecl or a UsingShadowDecl depending on the
|
||||
// NameKind.
|
||||
|
|
@ -314,11 +315,6 @@ public:
|
|||
|
||||
TemplateName getUnderlying() const;
|
||||
|
||||
/// Get the template name to substitute when this template name is used as a
|
||||
/// template template argument. This refers to the most recent declaration of
|
||||
/// the template, including any default template arguments.
|
||||
TemplateName getNameToSubstitute() const;
|
||||
|
||||
TemplateNameDependence getDependence() const;
|
||||
|
||||
/// Determines whether this is a dependent template name.
|
||||
|
|
@ -332,7 +328,7 @@ public:
|
|||
/// unexpanded parameter pack (for C++0x variadic templates).
|
||||
bool containsUnexpandedParameterPack() const;
|
||||
|
||||
enum class Qualified { None, AsWritten, Fully };
|
||||
enum class Qualified { None, AsWritten };
|
||||
/// Print the template name.
|
||||
///
|
||||
/// \param OS the output stream to which the template name will be
|
||||
|
|
@ -345,13 +341,15 @@ public:
|
|||
Qualified Qual = Qualified::AsWritten) const;
|
||||
|
||||
/// Debugging aid that dumps the template name.
|
||||
void dump(raw_ostream &OS) const;
|
||||
void dump(raw_ostream &OS, const ASTContext &Context) const;
|
||||
|
||||
/// Debugging aid that dumps the template name to standard
|
||||
/// error.
|
||||
void dump() const;
|
||||
|
||||
void Profile(llvm::FoldingSetNodeID &ID);
|
||||
void Profile(llvm::FoldingSetNodeID &ID) {
|
||||
ID.AddPointer(Storage.getOpaqueValue());
|
||||
}
|
||||
|
||||
/// Retrieve the template name as a void pointer.
|
||||
void *getAsVoidPointer() const { return Storage.getOpaqueValue(); }
|
||||
|
|
@ -360,6 +358,10 @@ public:
|
|||
static TemplateName getFromVoidPointer(void *Ptr) {
|
||||
return TemplateName(Ptr);
|
||||
}
|
||||
|
||||
/// Structural equality.
|
||||
bool operator==(TemplateName Other) const { return Storage == Other.Storage; }
|
||||
bool operator!=(TemplateName Other) const { return !operator==(Other); }
|
||||
};
|
||||
|
||||
/// Insertion operator for diagnostics. This allows sending TemplateName's
|
||||
|
|
@ -417,17 +419,18 @@ inline TemplateName TemplateName::getUnderlying() const {
|
|||
return *this;
|
||||
}
|
||||
|
||||
/// Represents a template name that was expressed as a
|
||||
/// qualified name.
|
||||
/// Represents a template name as written in source code.
|
||||
///
|
||||
/// This kind of template name refers to a template name that was
|
||||
/// This kind of template name may refer to a template name that was
|
||||
/// preceded by a nested name specifier, e.g., \c std::vector. Here,
|
||||
/// the nested name specifier is "std::" and the template name is the
|
||||
/// declaration for "vector". The QualifiedTemplateName class is only
|
||||
/// used to provide "sugar" for template names that were expressed
|
||||
/// with a qualified name, and has no semantic meaning. In this
|
||||
/// manner, it is to TemplateName what ElaboratedType is to Type,
|
||||
/// providing extra syntactic sugar for downstream clients.
|
||||
/// declaration for "vector". It may also have been written with the
|
||||
/// 'template' keyword. The QualifiedTemplateName class is only
|
||||
/// used to provide "sugar" for template names, so that they can
|
||||
/// be differentiated from canonical template names. and has no
|
||||
/// semantic meaning. In this manner, it is to TemplateName what
|
||||
/// ElaboratedType is to Type, providing extra syntactic sugar
|
||||
/// for downstream clients.
|
||||
class QualifiedTemplateName : public llvm::FoldingSetNode {
|
||||
friend class ASTContext;
|
||||
|
||||
|
|
|
|||
|
|
@ -24,6 +24,7 @@
|
|||
#include "clang/AST/StmtVisitor.h"
|
||||
#include "clang/AST/TemplateArgumentVisitor.h"
|
||||
#include "clang/AST/Type.h"
|
||||
#include "clang/AST/TypeLocVisitor.h"
|
||||
#include "clang/AST/TypeVisitor.h"
|
||||
|
||||
namespace clang {
|
||||
|
|
@ -132,6 +133,7 @@ class TextNodeDumper
|
|||
public ConstTemplateArgumentVisitor<TextNodeDumper>,
|
||||
public ConstStmtVisitor<TextNodeDumper>,
|
||||
public TypeVisitor<TextNodeDumper>,
|
||||
public TypeLocVisitor<TextNodeDumper>,
|
||||
public ConstDeclVisitor<TextNodeDumper> {
|
||||
raw_ostream &OS;
|
||||
const bool ShowColors;
|
||||
|
|
@ -179,12 +181,16 @@ public:
|
|||
|
||||
void Visit(QualType T);
|
||||
|
||||
void Visit(TypeLoc);
|
||||
|
||||
void Visit(const Decl *D);
|
||||
|
||||
void Visit(const CXXCtorInitializer *Init);
|
||||
|
||||
void Visit(const OMPClause *C);
|
||||
|
||||
void Visit(const OpenACCClause *C);
|
||||
|
||||
void Visit(const BlockDecl::Capture &C);
|
||||
|
||||
void Visit(const GenericSelectionExpr::ConstAssociation &A);
|
||||
|
|
@ -207,6 +213,9 @@ public:
|
|||
void dumpTemplateSpecializationKind(TemplateSpecializationKind TSK);
|
||||
void dumpNestedNameSpecifier(const NestedNameSpecifier *NNS);
|
||||
void dumpConceptReference(const ConceptReference *R);
|
||||
void dumpTemplateArgument(const TemplateArgument &TA);
|
||||
void dumpBareTemplateName(TemplateName TN);
|
||||
void dumpTemplateName(TemplateName TN, StringRef Label = {});
|
||||
|
||||
void dumpDeclRef(const Decl *D, StringRef Label = {});
|
||||
|
||||
|
|
@ -291,6 +300,8 @@ public:
|
|||
void VisitTypeTraitExpr(const TypeTraitExpr *Node);
|
||||
void VisitArrayTypeTraitExpr(const ArrayTypeTraitExpr *Node);
|
||||
void VisitExpressionTraitExpr(const ExpressionTraitExpr *Node);
|
||||
void VisitCXXDefaultArgExpr(const CXXDefaultArgExpr *Node);
|
||||
void VisitCXXDefaultInitExpr(const CXXDefaultInitExpr *Node);
|
||||
void VisitMaterializeTemporaryExpr(const MaterializeTemporaryExpr *Node);
|
||||
void VisitExprWithCleanups(const ExprWithCleanups *Node);
|
||||
void VisitUnresolvedLookupExpr(const UnresolvedLookupExpr *Node);
|
||||
|
|
@ -337,6 +348,8 @@ public:
|
|||
void VisitObjCInterfaceType(const ObjCInterfaceType *T);
|
||||
void VisitPackExpansionType(const PackExpansionType *T);
|
||||
|
||||
void VisitTypeLoc(TypeLoc TL);
|
||||
|
||||
void VisitLabelDecl(const LabelDecl *D);
|
||||
void VisitTypedefDecl(const TypedefDecl *D);
|
||||
void VisitEnumDecl(const EnumDecl *D);
|
||||
|
|
@ -344,6 +357,7 @@ public:
|
|||
void VisitEnumConstantDecl(const EnumConstantDecl *D);
|
||||
void VisitIndirectFieldDecl(const IndirectFieldDecl *D);
|
||||
void VisitFunctionDecl(const FunctionDecl *D);
|
||||
void VisitCXXDeductionGuideDecl(const CXXDeductionGuideDecl *D);
|
||||
void VisitFieldDecl(const FieldDecl *D);
|
||||
void VisitVarDecl(const VarDecl *D);
|
||||
void VisitBindingDecl(const BindingDecl *D);
|
||||
|
|
@ -393,6 +407,9 @@ public:
|
|||
void
|
||||
VisitLifetimeExtendedTemporaryDecl(const LifetimeExtendedTemporaryDecl *D);
|
||||
void VisitHLSLBufferDecl(const HLSLBufferDecl *D);
|
||||
void VisitOpenACCConstructStmt(const OpenACCConstructStmt *S);
|
||||
void VisitOpenACCLoopConstruct(const OpenACCLoopConstruct *S);
|
||||
void VisitEmbedExpr(const EmbedExpr *S);
|
||||
};
|
||||
|
||||
} // namespace clang
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load diff
|
|
@ -189,6 +189,9 @@ public:
|
|||
/// pointer types, but not through decltype or typedefs.
|
||||
AutoTypeLoc getContainedAutoTypeLoc() const;
|
||||
|
||||
/// Get the SourceLocation of the template keyword (if any).
|
||||
SourceLocation getTemplateKeywordLoc() const;
|
||||
|
||||
/// Initializes this to state that every location in this
|
||||
/// type is the given location.
|
||||
///
|
||||
|
|
@ -229,6 +232,9 @@ public:
|
|||
/// __nullable, or __null_unspecifier), if there is one.
|
||||
SourceLocation findNullabilityLoc() const;
|
||||
|
||||
void dump() const;
|
||||
void dump(llvm::raw_ostream &, const ASTContext &) const;
|
||||
|
||||
private:
|
||||
static bool isKind(const TypeLoc&) {
|
||||
return true;
|
||||
|
|
@ -884,6 +890,10 @@ public:
|
|||
return getInnerTypeLoc();
|
||||
}
|
||||
|
||||
TypeLoc getEquivalentTypeLoc() const {
|
||||
return TypeLoc(getTypePtr()->getEquivalentType(), getNonLocalData());
|
||||
}
|
||||
|
||||
/// The type attribute.
|
||||
const Attr *getAttr() const {
|
||||
return getLocalData()->TypeAttr;
|
||||
|
|
@ -1110,6 +1120,32 @@ public:
|
|||
}
|
||||
};
|
||||
|
||||
struct BoundsAttributedLocInfo {};
|
||||
class BoundsAttributedTypeLoc
|
||||
: public ConcreteTypeLoc<UnqualTypeLoc, BoundsAttributedTypeLoc,
|
||||
BoundsAttributedType, BoundsAttributedLocInfo> {
|
||||
public:
|
||||
TypeLoc getInnerLoc() const { return getInnerTypeLoc(); }
|
||||
QualType getInnerType() const { return getTypePtr()->desugar(); }
|
||||
void initializeLocal(ASTContext &Context, SourceLocation Loc) {
|
||||
// nothing to do
|
||||
}
|
||||
// LocalData is empty and TypeLocBuilder doesn't handle DataSize 1.
|
||||
unsigned getLocalDataSize() const { return 0; }
|
||||
};
|
||||
|
||||
class CountAttributedTypeLoc final
|
||||
: public InheritingConcreteTypeLoc<BoundsAttributedTypeLoc,
|
||||
CountAttributedTypeLoc,
|
||||
CountAttributedType> {
|
||||
public:
|
||||
Expr *getCountExpr() const { return getTypePtr()->getCountExpr(); }
|
||||
bool isCountInBytes() const { return getTypePtr()->isCountInBytes(); }
|
||||
bool isOrNull() const { return getTypePtr()->isOrNull(); }
|
||||
|
||||
SourceRange getLocalSourceRange() const;
|
||||
};
|
||||
|
||||
struct MacroQualifiedLocInfo {
|
||||
SourceLocation ExpansionLoc;
|
||||
};
|
||||
|
|
@ -1575,6 +1611,11 @@ class ConstantArrayTypeLoc :
|
|||
ConstantArrayType> {
|
||||
};
|
||||
|
||||
/// Wrapper for source info for array parameter types.
|
||||
class ArrayParameterTypeLoc
|
||||
: public InheritingConcreteTypeLoc<
|
||||
ConstantArrayTypeLoc, ArrayParameterTypeLoc, ArrayParameterType> {};
|
||||
|
||||
class IncompleteArrayTypeLoc :
|
||||
public InheritingConcreteTypeLoc<ArrayTypeLoc,
|
||||
IncompleteArrayTypeLoc,
|
||||
|
|
@ -1684,7 +1725,7 @@ public:
|
|||
}
|
||||
|
||||
void initializeLocal(ASTContext &Context, SourceLocation Loc) {
|
||||
setTemplateKeywordLoc(Loc);
|
||||
setTemplateKeywordLoc(SourceLocation());
|
||||
setTemplateNameLoc(Loc);
|
||||
setLAngleLoc(Loc);
|
||||
setRAngleLoc(Loc);
|
||||
|
|
@ -2055,6 +2096,34 @@ public:
|
|||
}
|
||||
};
|
||||
|
||||
struct PackIndexingTypeLocInfo {
|
||||
SourceLocation EllipsisLoc;
|
||||
};
|
||||
|
||||
class PackIndexingTypeLoc
|
||||
: public ConcreteTypeLoc<UnqualTypeLoc, PackIndexingTypeLoc,
|
||||
PackIndexingType, PackIndexingTypeLocInfo> {
|
||||
|
||||
public:
|
||||
Expr *getIndexExpr() const { return getTypePtr()->getIndexExpr(); }
|
||||
QualType getPattern() const { return getTypePtr()->getPattern(); }
|
||||
|
||||
SourceLocation getEllipsisLoc() const { return getLocalData()->EllipsisLoc; }
|
||||
void setEllipsisLoc(SourceLocation Loc) { getLocalData()->EllipsisLoc = Loc; }
|
||||
|
||||
void initializeLocal(ASTContext &Context, SourceLocation Loc) {
|
||||
setEllipsisLoc(Loc);
|
||||
}
|
||||
|
||||
TypeLoc getPatternLoc() const { return getInnerTypeLoc(); }
|
||||
|
||||
QualType getInnerType() const { return this->getTypePtr()->getPattern(); }
|
||||
|
||||
SourceRange getLocalSourceRange() const {
|
||||
return SourceRange(getEllipsisLoc(), getEllipsisLoc());
|
||||
}
|
||||
};
|
||||
|
||||
struct UnaryTransformTypeLocInfo {
|
||||
// FIXME: While there's only one unary transform right now, future ones may
|
||||
// need different representations
|
||||
|
|
|
|||
|
|
@ -25,6 +25,25 @@ let Class = PointerType in {
|
|||
def : Creator<[{ return ctx.getPointerType(pointeeType); }]>;
|
||||
}
|
||||
|
||||
let Class = CountAttributedType in {
|
||||
def : Property<"WrappedTy", QualType> {
|
||||
let Read = [{ node->desugar() }];
|
||||
}
|
||||
def : Property<"CountExpr", ExprRef> {
|
||||
let Read = [{ node->getCountExpr() }];
|
||||
}
|
||||
def : Property<"CountInBytes", Bool> {
|
||||
let Read = [{ node->isCountInBytes() }];
|
||||
}
|
||||
def : Property<"OrNull", Bool> {
|
||||
let Read = [{ node->isOrNull() }];
|
||||
}
|
||||
def : Property<"CoupledDecls", Array<TypeCoupledDeclRefInfo>> {
|
||||
let Read = [{ node->getCoupledDecls() }];
|
||||
}
|
||||
def : Creator<[{ return ctx.getCountAttributedType(WrappedTy, CountExpr, CountInBytes, OrNull, CoupledDecls); }]>;
|
||||
}
|
||||
|
||||
let Class = AdjustedType in {
|
||||
def : Property<"originalType", QualType> {
|
||||
let Read = [{ node->getOriginalType() }];
|
||||
|
|
@ -117,6 +136,13 @@ let Class = ConstantArrayType in {
|
|||
}]>;
|
||||
}
|
||||
|
||||
let Class = ArrayParameterType in {
|
||||
def : Creator<[{ return ctx.getAdjustedParameterType(
|
||||
ctx.getConstantArrayType(elementType,sizeValue,
|
||||
size,sizeModifier,
|
||||
indexQualifiers.getCVRQualifiers())); }]>;
|
||||
}
|
||||
|
||||
let Class = IncompleteArrayType in {
|
||||
def : Creator<[{
|
||||
return ctx.getIncompleteArrayType(elementType, sizeModifier,
|
||||
|
|
@ -326,6 +352,12 @@ let Class = FunctionProtoType in {
|
|||
def : Property<"AArch64SMEAttributes", UInt32> {
|
||||
let Read = [{ node->getAArch64SMEAttributes() }];
|
||||
}
|
||||
def : Property<"functionEffects", Array<FunctionEffect>> {
|
||||
let Read = [{ node->getFunctionEffectsWithoutConditions() }];
|
||||
}
|
||||
def : Property<"functionEffectConds", Array<EffectConditionExpr>> {
|
||||
let Read = [{ node->getFunctionEffectConditions() }];
|
||||
}
|
||||
|
||||
def : Creator<[{
|
||||
auto extInfo = FunctionType::ExtInfo(noReturn, hasRegParm, regParm,
|
||||
|
|
@ -342,6 +374,7 @@ let Class = FunctionProtoType in {
|
|||
epi.ExtParameterInfos =
|
||||
extParameterInfo.empty() ? nullptr : extParameterInfo.data();
|
||||
epi.AArch64SMEAttributes = AArch64SMEAttributes;
|
||||
epi.FunctionEffects = FunctionEffectsRef::create(functionEffects, functionEffectConds);
|
||||
return ctx.getFunctionType(returnType, parameters, epi);
|
||||
}]>;
|
||||
}
|
||||
|
|
@ -433,6 +466,20 @@ let Class = DecltypeType in {
|
|||
}]>;
|
||||
}
|
||||
|
||||
let Class = PackIndexingType in {
|
||||
def : Property<"pattern", QualType> {
|
||||
let Read = [{ node->getPattern() }];
|
||||
}
|
||||
def : Property<"indexExpression", ExprRef> {
|
||||
let Read = [{ node->getIndexExpr() }];
|
||||
}
|
||||
|
||||
def : Creator<[{
|
||||
return ctx.getPackIndexingType(pattern, indexExpression);
|
||||
}]>;
|
||||
}
|
||||
|
||||
|
||||
let Class = UnaryTransformType in {
|
||||
def : Property<"baseType", QualType> {
|
||||
let Read = [{ node->getBaseType() }];
|
||||
|
|
@ -821,6 +868,10 @@ let Class = BuiltinType in {
|
|||
case BuiltinType::ID: return ctx.SINGLETON_ID;
|
||||
#include "clang/Basic/WebAssemblyReferenceTypes.def"
|
||||
|
||||
#define AMDGPU_TYPE(NAME, ID, SINGLETON_ID) \
|
||||
case BuiltinType::ID: return ctx.SINGLETON_ID;
|
||||
#include "clang/Basic/AMDGPUTypes.def"
|
||||
|
||||
#define BUILTIN_TYPE(ID, SINGLETON_ID) \
|
||||
case BuiltinType::ID: return ctx.SINGLETON_ID;
|
||||
#include "clang/AST/BuiltinTypes.def"
|
||||
|
|
|
|||
|
|
@ -47,6 +47,7 @@ public:
|
|||
// temporaries with defaulted ctors are not zero initialized.
|
||||
UnresolvedSetIterator() : iterator_adaptor_base(nullptr) {}
|
||||
|
||||
uint64_t getDeclID() const { return I->getDeclID(); }
|
||||
NamedDecl *getDecl() const { return I->getDecl(); }
|
||||
void setDecl(NamedDecl *ND) const { return I->setDecl(ND); }
|
||||
AccessSpecifier getAccess() const { return I->getAccess(); }
|
||||
|
|
|
|||
|
|
@ -92,7 +92,7 @@ class VTTBuilder {
|
|||
using AddressPointsMapTy = llvm::DenseMap<BaseSubobject, uint64_t>;
|
||||
|
||||
/// The sub-VTT indices for the bases of the most derived class.
|
||||
llvm::DenseMap<BaseSubobject, uint64_t> SubVTTIndicies;
|
||||
llvm::DenseMap<BaseSubobject, uint64_t> SubVTTIndices;
|
||||
|
||||
/// The secondary virtual pointer indices of all subobjects of
|
||||
/// the most derived class.
|
||||
|
|
@ -148,8 +148,8 @@ public:
|
|||
}
|
||||
|
||||
/// Returns a reference to the sub-VTT indices.
|
||||
const llvm::DenseMap<BaseSubobject, uint64_t> &getSubVTTIndicies() const {
|
||||
return SubVTTIndicies;
|
||||
const llvm::DenseMap<BaseSubobject, uint64_t> &getSubVTTIndices() const {
|
||||
return SubVTTIndices;
|
||||
}
|
||||
|
||||
/// Returns a reference to the secondary virtual pointer indices.
|
||||
|
|
|
|||
|
|
@ -361,6 +361,10 @@ public:
|
|||
};
|
||||
|
||||
class ItaniumVTableContext : public VTableContextBase {
|
||||
public:
|
||||
typedef llvm::DenseMap<const CXXMethodDecl *, const CXXMethodDecl *>
|
||||
OriginalMethodMapTy;
|
||||
|
||||
private:
|
||||
|
||||
/// Contains the index (relative to the vtable address point)
|
||||
|
|
@ -384,6 +388,10 @@ private:
|
|||
VirtualBaseClassOffsetOffsetsMapTy;
|
||||
VirtualBaseClassOffsetOffsetsMapTy VirtualBaseClassOffsetOffsets;
|
||||
|
||||
/// Map from a virtual method to the nearest method in the primary base class
|
||||
/// chain that it overrides.
|
||||
OriginalMethodMapTy OriginalMethodMap;
|
||||
|
||||
void computeVTableRelatedInformation(const CXXRecordDecl *RD) override;
|
||||
|
||||
public:
|
||||
|
|
@ -425,6 +433,27 @@ public:
|
|||
CharUnits getVirtualBaseOffsetOffset(const CXXRecordDecl *RD,
|
||||
const CXXRecordDecl *VBase);
|
||||
|
||||
/// Return the method that added the v-table slot that will be used to call
|
||||
/// the given method.
|
||||
///
|
||||
/// In the Itanium ABI, where overrides always cause methods to be added to
|
||||
/// the primary v-table if they're not already there, this will be the first
|
||||
/// declaration in the primary base class chain for which the return type
|
||||
/// adjustment is trivial.
|
||||
GlobalDecl findOriginalMethod(GlobalDecl GD);
|
||||
|
||||
const CXXMethodDecl *findOriginalMethodInMap(const CXXMethodDecl *MD) const;
|
||||
|
||||
void setOriginalMethod(const CXXMethodDecl *Key, const CXXMethodDecl *Val) {
|
||||
OriginalMethodMap[Key] = Val;
|
||||
}
|
||||
|
||||
/// This method is reserved for the implementation and shouldn't be used
|
||||
/// directly.
|
||||
const OriginalMethodMapTy &getOriginalMethodMap() {
|
||||
return OriginalMethodMap;
|
||||
}
|
||||
|
||||
static bool classof(const VTableContextBase *VT) {
|
||||
return !VT->isMicrosoft();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -764,9 +764,9 @@ AST_POLYMORPHIC_MATCHER(isImplicit,
|
|||
return Node.isImplicit();
|
||||
}
|
||||
|
||||
/// Matches classTemplateSpecializations, templateSpecializationType and
|
||||
/// functionDecl that have at least one TemplateArgument matching the given
|
||||
/// InnerMatcher.
|
||||
/// Matches templateSpecializationTypes, class template specializations,
|
||||
/// variable template specializations, and function template specializations
|
||||
/// that have at least one TemplateArgument matching the given InnerMatcher.
|
||||
///
|
||||
/// Given
|
||||
/// \code
|
||||
|
|
@ -788,8 +788,8 @@ AST_POLYMORPHIC_MATCHER(isImplicit,
|
|||
AST_POLYMORPHIC_MATCHER_P(
|
||||
hasAnyTemplateArgument,
|
||||
AST_POLYMORPHIC_SUPPORTED_TYPES(ClassTemplateSpecializationDecl,
|
||||
TemplateSpecializationType,
|
||||
FunctionDecl),
|
||||
VarTemplateSpecializationDecl, FunctionDecl,
|
||||
TemplateSpecializationType),
|
||||
internal::Matcher<TemplateArgument>, InnerMatcher) {
|
||||
ArrayRef<TemplateArgument> List =
|
||||
internal::getTemplateSpecializationArgs(Node);
|
||||
|
|
@ -1047,8 +1047,9 @@ AST_MATCHER(Expr, isTypeDependent) { return Node.isTypeDependent(); }
|
|||
/// expr(isValueDependent()) matches return Size
|
||||
AST_MATCHER(Expr, isValueDependent) { return Node.isValueDependent(); }
|
||||
|
||||
/// Matches classTemplateSpecializations, templateSpecializationType and
|
||||
/// functionDecl where the n'th TemplateArgument matches the given InnerMatcher.
|
||||
/// Matches templateSpecializationType, class template specializations,
|
||||
/// variable template specializations, and function template specializations
|
||||
/// where the n'th TemplateArgument matches the given InnerMatcher.
|
||||
///
|
||||
/// Given
|
||||
/// \code
|
||||
|
|
@ -1068,8 +1069,8 @@ AST_MATCHER(Expr, isValueDependent) { return Node.isValueDependent(); }
|
|||
AST_POLYMORPHIC_MATCHER_P2(
|
||||
hasTemplateArgument,
|
||||
AST_POLYMORPHIC_SUPPORTED_TYPES(ClassTemplateSpecializationDecl,
|
||||
TemplateSpecializationType,
|
||||
FunctionDecl),
|
||||
VarTemplateSpecializationDecl, FunctionDecl,
|
||||
TemplateSpecializationType),
|
||||
unsigned, N, internal::Matcher<TemplateArgument>, InnerMatcher) {
|
||||
ArrayRef<TemplateArgument> List =
|
||||
internal::getTemplateSpecializationArgs(Node);
|
||||
|
|
@ -4066,7 +4067,7 @@ AST_POLYMORPHIC_MATCHER_P_OVERLOAD(
|
|||
/// Matcher<CXXCtorInitializer>, Matcher<CXXFunctionalCastExpr>,
|
||||
/// Matcher<CXXNewExpr>, Matcher<CXXTemporaryObjectExpr>,
|
||||
/// Matcher<CXXUnresolvedConstructExpr>,
|
||||
/// Matcher<ClassTemplateSpecializationDecl>, Matcher<CompoundLiteralExpr>,
|
||||
/// Matcher<CompoundLiteralExpr>,
|
||||
/// Matcher<DeclaratorDecl>, Matcher<ExplicitCastExpr>,
|
||||
/// Matcher<ObjCPropertyDecl>, Matcher<TemplateArgumentLoc>,
|
||||
/// Matcher<TypedefNameDecl>
|
||||
|
|
@ -4075,9 +4076,8 @@ AST_POLYMORPHIC_MATCHER_P(
|
|||
AST_POLYMORPHIC_SUPPORTED_TYPES(
|
||||
BlockDecl, CXXBaseSpecifier, CXXCtorInitializer, CXXFunctionalCastExpr,
|
||||
CXXNewExpr, CXXTemporaryObjectExpr, CXXUnresolvedConstructExpr,
|
||||
ClassTemplateSpecializationDecl, CompoundLiteralExpr, DeclaratorDecl,
|
||||
ExplicitCastExpr, ObjCPropertyDecl, TemplateArgumentLoc,
|
||||
TypedefNameDecl),
|
||||
CompoundLiteralExpr, DeclaratorDecl, ExplicitCastExpr, ObjCPropertyDecl,
|
||||
TemplateArgumentLoc, TypedefNameDecl),
|
||||
internal::Matcher<TypeLoc>, Inner) {
|
||||
TypeSourceInfo *source = internal::GetTypeSourceInfo(Node);
|
||||
if (source == nullptr) {
|
||||
|
|
@ -4580,8 +4580,7 @@ AST_POLYMORPHIC_MATCHER_P2(hasArgument,
|
|||
/// return (args * ... * 1);
|
||||
/// }
|
||||
/// \endcode
|
||||
AST_MATCHER_P(CXXFoldExpr, hasFoldInit, ast_matchers::internal::Matcher<Expr>,
|
||||
InnerMacher) {
|
||||
AST_MATCHER_P(CXXFoldExpr, hasFoldInit, internal::Matcher<Expr>, InnerMacher) {
|
||||
const auto *const Init = Node.getInit();
|
||||
return Init && InnerMacher.matches(*Init, Finder, Builder);
|
||||
}
|
||||
|
|
@ -4603,8 +4602,7 @@ AST_MATCHER_P(CXXFoldExpr, hasFoldInit, ast_matchers::internal::Matcher<Expr>,
|
|||
/// return (args * ... * 1);
|
||||
/// }
|
||||
/// \endcode
|
||||
AST_MATCHER_P(CXXFoldExpr, hasPattern, ast_matchers::internal::Matcher<Expr>,
|
||||
InnerMacher) {
|
||||
AST_MATCHER_P(CXXFoldExpr, hasPattern, internal::Matcher<Expr>, InnerMacher) {
|
||||
const Expr *const Pattern = Node.getPattern();
|
||||
return Pattern && InnerMacher.matches(*Pattern, Finder, Builder);
|
||||
}
|
||||
|
|
@ -4685,8 +4683,8 @@ AST_MATCHER(CXXFoldExpr, isBinaryFold) { return Node.getInit() != nullptr; }
|
|||
/// \code
|
||||
/// int x{y}.
|
||||
/// \endcode
|
||||
AST_MATCHER_P2(InitListExpr, hasInit, unsigned, N,
|
||||
ast_matchers::internal::Matcher<Expr>, InnerMatcher) {
|
||||
AST_MATCHER_P2(InitListExpr, hasInit, unsigned, N, internal::Matcher<Expr>,
|
||||
InnerMatcher) {
|
||||
return N < Node.getNumInits() &&
|
||||
InnerMatcher.matches(*Node.getInit(N), Finder, Builder);
|
||||
}
|
||||
|
|
@ -4963,6 +4961,8 @@ AST_MATCHER_P(LambdaExpr, hasAnyCapture, internal::Matcher<LambdaCapture>,
|
|||
/// capturesVar(hasName("x")) matches `x` and `x = 1`.
|
||||
AST_MATCHER_P(LambdaCapture, capturesVar, internal::Matcher<ValueDecl>,
|
||||
InnerMatcher) {
|
||||
if (!Node.capturesVariable())
|
||||
return false;
|
||||
auto *capturedVar = Node.getCapturedVar();
|
||||
return capturedVar && InnerMatcher.matches(*capturedVar, Finder, Builder);
|
||||
}
|
||||
|
|
@ -5034,6 +5034,25 @@ AST_POLYMORPHIC_MATCHER_P2(hasParameter,
|
|||
&& InnerMatcher.matches(*Node.parameters()[N], Finder, Builder));
|
||||
}
|
||||
|
||||
/// Matches if the given method declaration declares a member function with an
|
||||
/// explicit object parameter.
|
||||
///
|
||||
/// Given
|
||||
/// \code
|
||||
/// struct A {
|
||||
/// int operator-(this A, int);
|
||||
/// void fun(this A &&self);
|
||||
/// static int operator()(int);
|
||||
/// int operator+(int);
|
||||
/// };
|
||||
/// \endcode
|
||||
///
|
||||
/// cxxMethodDecl(isExplicitObjectMemberFunction()) matches the first two
|
||||
/// methods but not the last two.
|
||||
AST_MATCHER(CXXMethodDecl, isExplicitObjectMemberFunction) {
|
||||
return Node.isExplicitObjectMemberFunction();
|
||||
}
|
||||
|
||||
/// Matches all arguments and their respective ParmVarDecl.
|
||||
///
|
||||
/// Given
|
||||
|
|
@ -5062,10 +5081,12 @@ AST_POLYMORPHIC_MATCHER_P2(forEachArgumentWithParam,
|
|||
// argument of the method which should not be matched against a parameter, so
|
||||
// we skip over it here.
|
||||
BoundNodesTreeBuilder Matches;
|
||||
unsigned ArgIndex = cxxOperatorCallExpr(callee(cxxMethodDecl()))
|
||||
.matches(Node, Finder, &Matches)
|
||||
? 1
|
||||
: 0;
|
||||
unsigned ArgIndex =
|
||||
cxxOperatorCallExpr(
|
||||
callee(cxxMethodDecl(unless(isExplicitObjectMemberFunction()))))
|
||||
.matches(Node, Finder, &Matches)
|
||||
? 1
|
||||
: 0;
|
||||
int ParamIndex = 0;
|
||||
bool Matched = false;
|
||||
for (; ArgIndex < Node.getNumArgs(); ++ArgIndex) {
|
||||
|
|
@ -5123,11 +5144,12 @@ AST_POLYMORPHIC_MATCHER_P2(forEachArgumentWithParamType,
|
|||
// argument of the method which should not be matched against a parameter, so
|
||||
// we skip over it here.
|
||||
BoundNodesTreeBuilder Matches;
|
||||
unsigned ArgIndex = cxxOperatorCallExpr(callee(cxxMethodDecl()))
|
||||
.matches(Node, Finder, &Matches)
|
||||
? 1
|
||||
: 0;
|
||||
|
||||
unsigned ArgIndex =
|
||||
cxxOperatorCallExpr(
|
||||
callee(cxxMethodDecl(unless(isExplicitObjectMemberFunction()))))
|
||||
.matches(Node, Finder, &Matches)
|
||||
? 1
|
||||
: 0;
|
||||
const FunctionProtoType *FProto = nullptr;
|
||||
|
||||
if (const auto *Call = dyn_cast<CallExpr>(&Node)) {
|
||||
|
|
@ -5282,9 +5304,10 @@ AST_POLYMORPHIC_MATCHER_P(parameterCountIs,
|
|||
return Node.getNumParams() == N;
|
||||
}
|
||||
|
||||
/// Matches classTemplateSpecialization, templateSpecializationType and
|
||||
/// functionDecl nodes where the template argument matches the inner matcher.
|
||||
/// This matcher may produce multiple matches.
|
||||
/// Matches templateSpecializationType, class template specialization,
|
||||
/// variable template specialization, and function template specialization
|
||||
/// nodes where the template argument matches the inner matcher. This matcher
|
||||
/// may produce multiple matches.
|
||||
///
|
||||
/// Given
|
||||
/// \code
|
||||
|
|
@ -5308,8 +5331,9 @@ AST_POLYMORPHIC_MATCHER_P(parameterCountIs,
|
|||
AST_POLYMORPHIC_MATCHER_P(
|
||||
forEachTemplateArgument,
|
||||
AST_POLYMORPHIC_SUPPORTED_TYPES(ClassTemplateSpecializationDecl,
|
||||
TemplateSpecializationType, FunctionDecl),
|
||||
clang::ast_matchers::internal::Matcher<TemplateArgument>, InnerMatcher) {
|
||||
VarTemplateSpecializationDecl, FunctionDecl,
|
||||
TemplateSpecializationType),
|
||||
internal::Matcher<TemplateArgument>, InnerMatcher) {
|
||||
ArrayRef<TemplateArgument> TemplateArgs =
|
||||
clang::ast_matchers::internal::getTemplateSpecializationArgs(Node);
|
||||
clang::ast_matchers::internal::BoundNodesTreeBuilder Result;
|
||||
|
|
@ -6883,8 +6907,10 @@ extern const internal::VariadicDynCastAllOfMatcher<
|
|||
TypeLoc, TemplateSpecializationTypeLoc>
|
||||
templateSpecializationTypeLoc;
|
||||
|
||||
/// Matches template specialization `TypeLoc`s that have at least one
|
||||
/// `TemplateArgumentLoc` matching the given `InnerMatcher`.
|
||||
/// Matches template specialization `TypeLoc`s, class template specializations,
|
||||
/// variable template specializations, and function template specializations
|
||||
/// that have at least one `TemplateArgumentLoc` matching the given
|
||||
/// `InnerMatcher`.
|
||||
///
|
||||
/// Given
|
||||
/// \code
|
||||
|
|
@ -6894,20 +6920,21 @@ extern const internal::VariadicDynCastAllOfMatcher<
|
|||
/// varDecl(hasTypeLoc(templateSpecializationTypeLoc(hasAnyTemplateArgumentLoc(
|
||||
/// hasTypeLoc(loc(asString("int")))))))
|
||||
/// matches `A<int> a`.
|
||||
AST_MATCHER_P(TemplateSpecializationTypeLoc, hasAnyTemplateArgumentLoc,
|
||||
internal::Matcher<TemplateArgumentLoc>, InnerMatcher) {
|
||||
for (unsigned Index = 0, N = Node.getNumArgs(); Index < N; ++Index) {
|
||||
clang::ast_matchers::internal::BoundNodesTreeBuilder Result(*Builder);
|
||||
if (InnerMatcher.matches(Node.getArgLoc(Index), Finder, &Result)) {
|
||||
*Builder = std::move(Result);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
AST_POLYMORPHIC_MATCHER_P(
|
||||
hasAnyTemplateArgumentLoc,
|
||||
AST_POLYMORPHIC_SUPPORTED_TYPES(ClassTemplateSpecializationDecl,
|
||||
VarTemplateSpecializationDecl, FunctionDecl,
|
||||
DeclRefExpr, TemplateSpecializationTypeLoc),
|
||||
internal::Matcher<TemplateArgumentLoc>, InnerMatcher) {
|
||||
auto Args = internal::getTemplateArgsWritten(Node);
|
||||
return matchesFirstInRange(InnerMatcher, Args.begin(), Args.end(), Finder,
|
||||
Builder) != Args.end();
|
||||
return false;
|
||||
}
|
||||
|
||||
/// Matches template specialization `TypeLoc`s where the n'th
|
||||
/// `TemplateArgumentLoc` matches the given `InnerMatcher`.
|
||||
/// Matches template specialization `TypeLoc`s, class template specializations,
|
||||
/// variable template specializations, and function template specializations
|
||||
/// where the n'th `TemplateArgumentLoc` matches the given `InnerMatcher`.
|
||||
///
|
||||
/// Given
|
||||
/// \code
|
||||
|
|
@ -6920,10 +6947,13 @@ AST_MATCHER_P(TemplateSpecializationTypeLoc, hasAnyTemplateArgumentLoc,
|
|||
/// matches `A<double, int> b`, but not `A<int, double> c`.
|
||||
AST_POLYMORPHIC_MATCHER_P2(
|
||||
hasTemplateArgumentLoc,
|
||||
AST_POLYMORPHIC_SUPPORTED_TYPES(DeclRefExpr, TemplateSpecializationTypeLoc),
|
||||
AST_POLYMORPHIC_SUPPORTED_TYPES(ClassTemplateSpecializationDecl,
|
||||
VarTemplateSpecializationDecl, FunctionDecl,
|
||||
DeclRefExpr, TemplateSpecializationTypeLoc),
|
||||
unsigned, Index, internal::Matcher<TemplateArgumentLoc>, InnerMatcher) {
|
||||
return internal::MatchTemplateArgLocAt(Node, Index, InnerMatcher, Finder,
|
||||
Builder);
|
||||
auto Args = internal::getTemplateArgsWritten(Node);
|
||||
return Index < Args.size() &&
|
||||
InnerMatcher.matches(Args[Index], Finder, Builder);
|
||||
}
|
||||
|
||||
/// Matches C or C++ elaborated `TypeLoc`s.
|
||||
|
|
@ -8341,20 +8371,28 @@ AST_MATCHER_P(Stmt, forCallable, internal::Matcher<Decl>, InnerMatcher) {
|
|||
const auto &CurNode = Stack.back();
|
||||
Stack.pop_back();
|
||||
if (const auto *FuncDeclNode = CurNode.get<FunctionDecl>()) {
|
||||
if (InnerMatcher.matches(*FuncDeclNode, Finder, Builder)) {
|
||||
BoundNodesTreeBuilder B = *Builder;
|
||||
if (InnerMatcher.matches(*FuncDeclNode, Finder, &B)) {
|
||||
*Builder = std::move(B);
|
||||
return true;
|
||||
}
|
||||
} else if (const auto *LambdaExprNode = CurNode.get<LambdaExpr>()) {
|
||||
BoundNodesTreeBuilder B = *Builder;
|
||||
if (InnerMatcher.matches(*LambdaExprNode->getCallOperator(), Finder,
|
||||
Builder)) {
|
||||
&B)) {
|
||||
*Builder = std::move(B);
|
||||
return true;
|
||||
}
|
||||
} else if (const auto *ObjCMethodDeclNode = CurNode.get<ObjCMethodDecl>()) {
|
||||
if (InnerMatcher.matches(*ObjCMethodDeclNode, Finder, Builder)) {
|
||||
BoundNodesTreeBuilder B = *Builder;
|
||||
if (InnerMatcher.matches(*ObjCMethodDeclNode, Finder, &B)) {
|
||||
*Builder = std::move(B);
|
||||
return true;
|
||||
}
|
||||
} else if (const auto *BlockDeclNode = CurNode.get<BlockDecl>()) {
|
||||
if (InnerMatcher.matches(*BlockDeclNode, Finder, Builder)) {
|
||||
BoundNodesTreeBuilder B = *Builder;
|
||||
if (InnerMatcher.matches(*BlockDeclNode, Finder, &B)) {
|
||||
*Builder = std::move(B);
|
||||
return true;
|
||||
}
|
||||
} else {
|
||||
|
|
@ -8525,8 +8563,8 @@ AST_MATCHER(FunctionDecl, hasTrailingReturn) {
|
|||
///
|
||||
/// ``varDecl(hasInitializer(ignoringElidableConstructorCall(callExpr())))``
|
||||
/// matches ``H D = G()`` in C++11 through C++17 (and beyond).
|
||||
AST_MATCHER_P(Expr, ignoringElidableConstructorCall,
|
||||
ast_matchers::internal::Matcher<Expr>, InnerMatcher) {
|
||||
AST_MATCHER_P(Expr, ignoringElidableConstructorCall, internal::Matcher<Expr>,
|
||||
InnerMatcher) {
|
||||
// E tracks the node that we are examining.
|
||||
const Expr *E = &Node;
|
||||
// If present, remove an outer `ExprWithCleanups` corresponding to the
|
||||
|
|
|
|||
|
|
@ -186,10 +186,6 @@ inline TypeSourceInfo *GetTypeSourceInfo(const BlockDecl &Node) {
|
|||
inline TypeSourceInfo *GetTypeSourceInfo(const CXXNewExpr &Node) {
|
||||
return Node.getAllocatedTypeSourceInfo();
|
||||
}
|
||||
inline TypeSourceInfo *
|
||||
GetTypeSourceInfo(const ClassTemplateSpecializationDecl &Node) {
|
||||
return Node.getTypeAsWritten();
|
||||
}
|
||||
|
||||
/// Unifies obtaining the FunctionProtoType pointer from both
|
||||
/// FunctionProtoType and FunctionDecl nodes..
|
||||
|
|
@ -1939,6 +1935,11 @@ getTemplateSpecializationArgs(const ClassTemplateSpecializationDecl &D) {
|
|||
return D.getTemplateArgs().asArray();
|
||||
}
|
||||
|
||||
inline ArrayRef<TemplateArgument>
|
||||
getTemplateSpecializationArgs(const VarTemplateSpecializationDecl &D) {
|
||||
return D.getTemplateArgs().asArray();
|
||||
}
|
||||
|
||||
inline ArrayRef<TemplateArgument>
|
||||
getTemplateSpecializationArgs(const TemplateSpecializationType &T) {
|
||||
return T.template_arguments();
|
||||
|
|
@ -1948,7 +1949,46 @@ inline ArrayRef<TemplateArgument>
|
|||
getTemplateSpecializationArgs(const FunctionDecl &FD) {
|
||||
if (const auto* TemplateArgs = FD.getTemplateSpecializationArgs())
|
||||
return TemplateArgs->asArray();
|
||||
return ArrayRef<TemplateArgument>();
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
inline ArrayRef<TemplateArgumentLoc>
|
||||
getTemplateArgsWritten(const ClassTemplateSpecializationDecl &D) {
|
||||
if (const ASTTemplateArgumentListInfo *Args = D.getTemplateArgsAsWritten())
|
||||
return Args->arguments();
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
inline ArrayRef<TemplateArgumentLoc>
|
||||
getTemplateArgsWritten(const VarTemplateSpecializationDecl &D) {
|
||||
if (const ASTTemplateArgumentListInfo *Args = D.getTemplateArgsAsWritten())
|
||||
return Args->arguments();
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
inline ArrayRef<TemplateArgumentLoc>
|
||||
getTemplateArgsWritten(const FunctionDecl &FD) {
|
||||
if (const auto *Args = FD.getTemplateSpecializationArgsAsWritten())
|
||||
return Args->arguments();
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
inline ArrayRef<TemplateArgumentLoc>
|
||||
getTemplateArgsWritten(const DeclRefExpr &DRE) {
|
||||
if (const auto *Args = DRE.getTemplateArgs())
|
||||
return {Args, DRE.getNumTemplateArgs()};
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
inline SmallVector<TemplateArgumentLoc>
|
||||
getTemplateArgsWritten(const TemplateSpecializationTypeLoc &T) {
|
||||
SmallVector<TemplateArgumentLoc> Args;
|
||||
if (!T.isNull()) {
|
||||
Args.reserve(T.getNumArgs());
|
||||
for (unsigned I = 0; I < T.getNumArgs(); ++I)
|
||||
Args.emplace_back(T.getArgLoc(I));
|
||||
}
|
||||
return Args;
|
||||
}
|
||||
|
||||
struct NotEqualsBoundNodePredicate {
|
||||
|
|
|
|||
|
|
@ -8,11 +8,9 @@
|
|||
#ifndef LLVM_CLANG_ANALYSIS_ANALYSES_EXPRMUTATIONANALYZER_H
|
||||
#define LLVM_CLANG_ANALYSIS_ANALYSES_EXPRMUTATIONANALYZER_H
|
||||
|
||||
#include <type_traits>
|
||||
|
||||
#include "clang/AST/AST.h"
|
||||
#include "clang/ASTMatchers/ASTMatchers.h"
|
||||
#include "llvm/ADT/DenseMap.h"
|
||||
#include <memory>
|
||||
|
||||
namespace clang {
|
||||
|
||||
|
|
@ -21,14 +19,74 @@ class FunctionParmMutationAnalyzer;
|
|||
/// Analyzes whether any mutative operations are applied to an expression within
|
||||
/// a given statement.
|
||||
class ExprMutationAnalyzer {
|
||||
friend class FunctionParmMutationAnalyzer;
|
||||
|
||||
public:
|
||||
struct Memoized {
|
||||
using ResultMap = llvm::DenseMap<const Expr *, const Stmt *>;
|
||||
using FunctionParaAnalyzerMap =
|
||||
llvm::SmallDenseMap<const FunctionDecl *,
|
||||
std::unique_ptr<FunctionParmMutationAnalyzer>>;
|
||||
|
||||
ResultMap Results;
|
||||
ResultMap PointeeResults;
|
||||
FunctionParaAnalyzerMap FuncParmAnalyzer;
|
||||
|
||||
void clear() {
|
||||
Results.clear();
|
||||
PointeeResults.clear();
|
||||
FuncParmAnalyzer.clear();
|
||||
}
|
||||
};
|
||||
struct Analyzer {
|
||||
Analyzer(const Stmt &Stm, ASTContext &Context, Memoized &Memorized)
|
||||
: Stm(Stm), Context(Context), Memorized(Memorized) {}
|
||||
|
||||
const Stmt *findMutation(const Expr *Exp);
|
||||
const Stmt *findMutation(const Decl *Dec);
|
||||
|
||||
const Stmt *findPointeeMutation(const Expr *Exp);
|
||||
const Stmt *findPointeeMutation(const Decl *Dec);
|
||||
static bool isUnevaluated(const Stmt *Smt, const Stmt &Stm,
|
||||
ASTContext &Context);
|
||||
|
||||
private:
|
||||
using MutationFinder = const Stmt *(Analyzer::*)(const Expr *);
|
||||
|
||||
const Stmt *findMutationMemoized(const Expr *Exp,
|
||||
llvm::ArrayRef<MutationFinder> Finders,
|
||||
Memoized::ResultMap &MemoizedResults);
|
||||
const Stmt *tryEachDeclRef(const Decl *Dec, MutationFinder Finder);
|
||||
|
||||
bool isUnevaluated(const Expr *Exp);
|
||||
|
||||
const Stmt *findExprMutation(ArrayRef<ast_matchers::BoundNodes> Matches);
|
||||
const Stmt *findDeclMutation(ArrayRef<ast_matchers::BoundNodes> Matches);
|
||||
const Stmt *
|
||||
findExprPointeeMutation(ArrayRef<ast_matchers::BoundNodes> Matches);
|
||||
const Stmt *
|
||||
findDeclPointeeMutation(ArrayRef<ast_matchers::BoundNodes> Matches);
|
||||
|
||||
const Stmt *findDirectMutation(const Expr *Exp);
|
||||
const Stmt *findMemberMutation(const Expr *Exp);
|
||||
const Stmt *findArrayElementMutation(const Expr *Exp);
|
||||
const Stmt *findCastMutation(const Expr *Exp);
|
||||
const Stmt *findRangeLoopMutation(const Expr *Exp);
|
||||
const Stmt *findReferenceMutation(const Expr *Exp);
|
||||
const Stmt *findFunctionArgMutation(const Expr *Exp);
|
||||
|
||||
const Stmt &Stm;
|
||||
ASTContext &Context;
|
||||
Memoized &Memorized;
|
||||
};
|
||||
|
||||
ExprMutationAnalyzer(const Stmt &Stm, ASTContext &Context)
|
||||
: Stm(Stm), Context(Context) {}
|
||||
: Memorized(), A(Stm, Context, Memorized) {}
|
||||
|
||||
bool isMutated(const Expr *Exp) { return findMutation(Exp) != nullptr; }
|
||||
bool isMutated(const Decl *Dec) { return findMutation(Dec) != nullptr; }
|
||||
const Stmt *findMutation(const Expr *Exp);
|
||||
const Stmt *findMutation(const Decl *Dec);
|
||||
const Stmt *findMutation(const Expr *Exp) { return A.findMutation(Exp); }
|
||||
const Stmt *findMutation(const Decl *Dec) { return A.findMutation(Dec); }
|
||||
|
||||
bool isPointeeMutated(const Expr *Exp) {
|
||||
return findPointeeMutation(Exp) != nullptr;
|
||||
|
|
@ -36,51 +94,40 @@ public:
|
|||
bool isPointeeMutated(const Decl *Dec) {
|
||||
return findPointeeMutation(Dec) != nullptr;
|
||||
}
|
||||
const Stmt *findPointeeMutation(const Expr *Exp);
|
||||
const Stmt *findPointeeMutation(const Decl *Dec);
|
||||
const Stmt *findPointeeMutation(const Expr *Exp) {
|
||||
return A.findPointeeMutation(Exp);
|
||||
}
|
||||
const Stmt *findPointeeMutation(const Decl *Dec) {
|
||||
return A.findPointeeMutation(Dec);
|
||||
}
|
||||
|
||||
static bool isUnevaluated(const Stmt *Smt, const Stmt &Stm,
|
||||
ASTContext &Context);
|
||||
ASTContext &Context) {
|
||||
return Analyzer::isUnevaluated(Smt, Stm, Context);
|
||||
}
|
||||
|
||||
private:
|
||||
using MutationFinder = const Stmt *(ExprMutationAnalyzer::*)(const Expr *);
|
||||
using ResultMap = llvm::DenseMap<const Expr *, const Stmt *>;
|
||||
|
||||
const Stmt *findMutationMemoized(const Expr *Exp,
|
||||
llvm::ArrayRef<MutationFinder> Finders,
|
||||
ResultMap &MemoizedResults);
|
||||
const Stmt *tryEachDeclRef(const Decl *Dec, MutationFinder Finder);
|
||||
|
||||
bool isUnevaluated(const Expr *Exp);
|
||||
|
||||
const Stmt *findExprMutation(ArrayRef<ast_matchers::BoundNodes> Matches);
|
||||
const Stmt *findDeclMutation(ArrayRef<ast_matchers::BoundNodes> Matches);
|
||||
const Stmt *
|
||||
findExprPointeeMutation(ArrayRef<ast_matchers::BoundNodes> Matches);
|
||||
const Stmt *
|
||||
findDeclPointeeMutation(ArrayRef<ast_matchers::BoundNodes> Matches);
|
||||
|
||||
const Stmt *findDirectMutation(const Expr *Exp);
|
||||
const Stmt *findMemberMutation(const Expr *Exp);
|
||||
const Stmt *findArrayElementMutation(const Expr *Exp);
|
||||
const Stmt *findCastMutation(const Expr *Exp);
|
||||
const Stmt *findRangeLoopMutation(const Expr *Exp);
|
||||
const Stmt *findReferenceMutation(const Expr *Exp);
|
||||
const Stmt *findFunctionArgMutation(const Expr *Exp);
|
||||
|
||||
const Stmt &Stm;
|
||||
ASTContext &Context;
|
||||
llvm::DenseMap<const FunctionDecl *,
|
||||
std::unique_ptr<FunctionParmMutationAnalyzer>>
|
||||
FuncParmAnalyzer;
|
||||
ResultMap Results;
|
||||
ResultMap PointeeResults;
|
||||
Memoized Memorized;
|
||||
Analyzer A;
|
||||
};
|
||||
|
||||
// A convenient wrapper around ExprMutationAnalyzer for analyzing function
|
||||
// params.
|
||||
class FunctionParmMutationAnalyzer {
|
||||
public:
|
||||
FunctionParmMutationAnalyzer(const FunctionDecl &Func, ASTContext &Context);
|
||||
static FunctionParmMutationAnalyzer *
|
||||
getFunctionParmMutationAnalyzer(const FunctionDecl &Func, ASTContext &Context,
|
||||
ExprMutationAnalyzer::Memoized &Memorized) {
|
||||
auto it = Memorized.FuncParmAnalyzer.find(&Func);
|
||||
if (it == Memorized.FuncParmAnalyzer.end())
|
||||
it =
|
||||
Memorized.FuncParmAnalyzer
|
||||
.try_emplace(&Func, std::unique_ptr<FunctionParmMutationAnalyzer>(
|
||||
new FunctionParmMutationAnalyzer(
|
||||
Func, Context, Memorized)))
|
||||
.first;
|
||||
return it->getSecond().get();
|
||||
}
|
||||
|
||||
bool isMutated(const ParmVarDecl *Parm) {
|
||||
return findMutation(Parm) != nullptr;
|
||||
|
|
@ -88,8 +135,11 @@ public:
|
|||
const Stmt *findMutation(const ParmVarDecl *Parm);
|
||||
|
||||
private:
|
||||
ExprMutationAnalyzer BodyAnalyzer;
|
||||
ExprMutationAnalyzer::Analyzer BodyAnalyzer;
|
||||
llvm::DenseMap<const ParmVarDecl *, const Stmt *> Results;
|
||||
|
||||
FunctionParmMutationAnalyzer(const FunctionDecl &Func, ASTContext &Context,
|
||||
ExprMutationAnalyzer::Memoized &Memorized);
|
||||
};
|
||||
|
||||
} // namespace clang
|
||||
|
|
|
|||
|
|
@ -70,7 +70,41 @@ public:
|
|||
};
|
||||
|
||||
private:
|
||||
using po_iterator = llvm::po_iterator<const CFG *, CFGBlockSet, true>;
|
||||
// The CFG orders the blocks of loop bodies before those of loop successors
|
||||
// (both numerically, and in the successor order of the loop condition
|
||||
// block). So, RPO necessarily reverses that order, placing the loop successor
|
||||
// *before* the loop body. For many analyses, particularly those that converge
|
||||
// to a fixpoint, this results in potentially significant extra work because
|
||||
// loop successors will necessarily need to be reconsidered once the algorithm
|
||||
// has reached a fixpoint on the loop body.
|
||||
//
|
||||
// This definition of CFG graph traits reverses the order of children, so that
|
||||
// loop bodies will come first in an RPO.
|
||||
struct CFGLoopBodyFirstTraits {
|
||||
using NodeRef = const ::clang::CFGBlock *;
|
||||
using ChildIteratorType = ::clang::CFGBlock::const_succ_reverse_iterator;
|
||||
|
||||
static ChildIteratorType child_begin(NodeRef N) { return N->succ_rbegin(); }
|
||||
static ChildIteratorType child_end(NodeRef N) { return N->succ_rend(); }
|
||||
|
||||
using nodes_iterator = ::clang::CFG::const_iterator;
|
||||
|
||||
static NodeRef getEntryNode(const ::clang::CFG *F) {
|
||||
return &F->getEntry();
|
||||
}
|
||||
|
||||
static nodes_iterator nodes_begin(const ::clang::CFG *F) {
|
||||
return F->nodes_begin();
|
||||
}
|
||||
|
||||
static nodes_iterator nodes_end(const ::clang::CFG *F) {
|
||||
return F->nodes_end();
|
||||
}
|
||||
|
||||
static unsigned size(const ::clang::CFG *F) { return F->size(); }
|
||||
};
|
||||
using po_iterator =
|
||||
llvm::po_iterator<const CFG *, CFGBlockSet, true, CFGLoopBodyFirstTraits>;
|
||||
std::vector<const CFGBlock *> Blocks;
|
||||
|
||||
using BlockOrderTy = llvm::DenseMap<const CFGBlock *, unsigned>;
|
||||
|
|
|
|||
|
|
@ -330,9 +330,9 @@ public:
|
|||
|
||||
bool shouldIgnore() const { return sexpr() == nullptr; }
|
||||
|
||||
bool isInvalid() const { return sexpr() && isa<til::Undefined>(sexpr()); }
|
||||
bool isInvalid() const { return isa_and_nonnull<til::Undefined>(sexpr()); }
|
||||
|
||||
bool isUniversal() const { return sexpr() && isa<til::Wildcard>(sexpr()); }
|
||||
bool isUniversal() const { return isa_and_nonnull<til::Wildcard>(sexpr()); }
|
||||
};
|
||||
|
||||
// Translate clang::Expr to til::SExpr.
|
||||
|
|
@ -527,8 +527,10 @@ private:
|
|||
BlockInfo *CurrentBlockInfo = nullptr;
|
||||
};
|
||||
|
||||
#ifndef NDEBUG
|
||||
// Dump an SCFG to llvm::errs().
|
||||
void printSCFG(CFGWalker &Walker);
|
||||
#endif // NDEBUG
|
||||
|
||||
} // namespace threadSafety
|
||||
} // namespace clang
|
||||
|
|
|
|||
|
|
@ -16,6 +16,7 @@
|
|||
|
||||
#include "clang/AST/Decl.h"
|
||||
#include "clang/AST/Stmt.h"
|
||||
#include "clang/Basic/SourceLocation.h"
|
||||
#include "llvm/Support/Debug.h"
|
||||
|
||||
namespace clang {
|
||||
|
|
@ -41,6 +42,43 @@ public:
|
|||
virtual VarGrpRef getGroupOfParms() const =0;
|
||||
};
|
||||
|
||||
// FixitStrategy is a map from variables to the way we plan to emit fixes for
|
||||
// these variables. It is figured out gradually by trying different fixes
|
||||
// for different variables depending on gadgets in which these variables
|
||||
// participate.
|
||||
class FixitStrategy {
|
||||
public:
|
||||
enum class Kind {
|
||||
Wontfix, // We don't plan to emit a fixit for this variable.
|
||||
Span, // We recommend replacing the variable with std::span.
|
||||
Iterator, // We recommend replacing the variable with std::span::iterator.
|
||||
Array, // We recommend replacing the variable with std::array.
|
||||
Vector // We recommend replacing the variable with std::vector.
|
||||
};
|
||||
|
||||
private:
|
||||
using MapTy = llvm::DenseMap<const VarDecl *, Kind>;
|
||||
|
||||
MapTy Map;
|
||||
|
||||
public:
|
||||
FixitStrategy() = default;
|
||||
FixitStrategy(const FixitStrategy &) = delete; // Let's avoid copies.
|
||||
FixitStrategy &operator=(const FixitStrategy &) = delete;
|
||||
FixitStrategy(FixitStrategy &&) = default;
|
||||
FixitStrategy &operator=(FixitStrategy &&) = default;
|
||||
|
||||
void set(const VarDecl *VD, Kind K) { Map[VD] = K; }
|
||||
|
||||
Kind lookup(const VarDecl *VD) const {
|
||||
auto I = Map.find(VD);
|
||||
if (I == Map.end())
|
||||
return Kind::Wontfix;
|
||||
|
||||
return I->second;
|
||||
}
|
||||
};
|
||||
|
||||
/// The interface that lets the caller handle unsafe buffer usage analysis
|
||||
/// results by overriding this class's handle... methods.
|
||||
class UnsafeBufferUsageHandler {
|
||||
|
|
@ -68,15 +106,22 @@ public:
|
|||
virtual void handleUnsafeOperation(const Stmt *Operation,
|
||||
bool IsRelatedToDecl, ASTContext &Ctx) = 0;
|
||||
|
||||
/// Invoked when an unsafe operation with a std container is found.
|
||||
virtual void handleUnsafeOperationInContainer(const Stmt *Operation,
|
||||
bool IsRelatedToDecl,
|
||||
ASTContext &Ctx) = 0;
|
||||
|
||||
/// Invoked when a fix is suggested against a variable. This function groups
|
||||
/// all variables that must be fixed together (i.e their types must be changed
|
||||
/// to the same target type to prevent type mismatches) into a single fixit.
|
||||
///
|
||||
/// `D` is the declaration of the callable under analysis that owns `Variable`
|
||||
/// and all of its group mates.
|
||||
virtual void handleUnsafeVariableGroup(const VarDecl *Variable,
|
||||
const VariableGroupsManager &VarGrpMgr,
|
||||
FixItList &&Fixes, const Decl *D) = 0;
|
||||
virtual void
|
||||
handleUnsafeVariableGroup(const VarDecl *Variable,
|
||||
const VariableGroupsManager &VarGrpMgr,
|
||||
FixItList &&Fixes, const Decl *D,
|
||||
const FixitStrategy &VarTargetTypes) = 0;
|
||||
|
||||
#ifndef NDEBUG
|
||||
public:
|
||||
|
|
@ -98,9 +143,14 @@ public:
|
|||
#endif
|
||||
|
||||
public:
|
||||
/// Returns a reference to the `Preprocessor`:
|
||||
/// \return true iff buffer safety is opt-out at `Loc`; false otherwise.
|
||||
virtual bool isSafeBufferOptOut(const SourceLocation &Loc) const = 0;
|
||||
|
||||
/// \return true iff unsafe uses in containers should NOT be reported at
|
||||
/// `Loc`; false otherwise.
|
||||
virtual bool
|
||||
ignoreUnsafeBufferInContainer(const SourceLocation &Loc) const = 0;
|
||||
|
||||
virtual std::string
|
||||
getUnsafeBufferUsageAttributeTextAt(SourceLocation Loc,
|
||||
StringRef WSSuffix = "") const = 0;
|
||||
|
|
|
|||
|
|
@ -18,6 +18,12 @@
|
|||
#define WARNING_GADGET(name) GADGET(name)
|
||||
#endif
|
||||
|
||||
/// A `WARNING_GADGET` subset, where the code pattern of each gadget
|
||||
/// corresponds uses of a (possibly hardened) contatiner (e.g., `std::span`).
|
||||
#ifndef WARNING_CONTAINER_GADGET
|
||||
#define WARNING_CONTAINER_GADGET(name) WARNING_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.
|
||||
|
|
@ -30,7 +36,9 @@ WARNING_GADGET(Decrement)
|
|||
WARNING_GADGET(ArraySubscript)
|
||||
WARNING_GADGET(PointerArithmetic)
|
||||
WARNING_GADGET(UnsafeBufferUsageAttr)
|
||||
WARNING_GADGET(UnsafeBufferUsageCtorAttr)
|
||||
WARNING_GADGET(DataInvocation)
|
||||
WARNING_CONTAINER_GADGET(SpanTwoParamConstructor) // Uses of `std::span(arg0, arg1)`
|
||||
FIXABLE_GADGET(ULCArraySubscript) // `DRE[any]` in an Unspecified Lvalue Context
|
||||
FIXABLE_GADGET(DerefSimplePtrArithFixable)
|
||||
FIXABLE_GADGET(PointerDereference)
|
||||
|
|
@ -38,9 +46,11 @@ FIXABLE_GADGET(UPCAddressofArraySubscript) // '&DRE[any]' in an Unspecified Poin
|
|||
FIXABLE_GADGET(UPCStandalonePointer)
|
||||
FIXABLE_GADGET(UPCPreIncrement) // '++Ptr' in an Unspecified Pointer Context
|
||||
FIXABLE_GADGET(UUCAddAssign) // 'Ptr += n' in an Unspecified Untyped Context
|
||||
FIXABLE_GADGET(PointerAssignment)
|
||||
FIXABLE_GADGET(PtrToPtrAssignment)
|
||||
FIXABLE_GADGET(CArrayToPtrAssignment)
|
||||
FIXABLE_GADGET(PointerInit)
|
||||
|
||||
#undef FIXABLE_GADGET
|
||||
#undef WARNING_GADGET
|
||||
#undef WARNING_CONTAINER_GADGET
|
||||
#undef GADGET
|
||||
|
|
|
|||
|
|
@ -879,6 +879,7 @@ private:
|
|||
///
|
||||
/// Optimization Note: This bit could be profitably folded with Terminator's
|
||||
/// storage if the memory usage of CFGBlock becomes an issue.
|
||||
LLVM_PREFERRED_TYPE(bool)
|
||||
unsigned HasNoReturnElement : 1;
|
||||
|
||||
/// The parent CFG that owns this CFGBlock.
|
||||
|
|
@ -1007,7 +1008,9 @@ public:
|
|||
|
||||
class FilterOptions {
|
||||
public:
|
||||
LLVM_PREFERRED_TYPE(bool)
|
||||
unsigned IgnoreNullPredecessors : 1;
|
||||
LLVM_PREFERRED_TYPE(bool)
|
||||
unsigned IgnoreDefaultsWithCoveredEnums : 1;
|
||||
|
||||
FilterOptions()
|
||||
|
|
|
|||
|
|
@ -0,0 +1,156 @@
|
|||
//===-- ASTOps.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
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// Operations on AST nodes that are used in flow-sensitive analysis.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef LLVM_CLANG_ANALYSIS_FLOWSENSITIVE_ASTOPS_H
|
||||
#define LLVM_CLANG_ANALYSIS_FLOWSENSITIVE_ASTOPS_H
|
||||
|
||||
#include "clang/AST/Decl.h"
|
||||
#include "clang/AST/Expr.h"
|
||||
#include "clang/AST/RecursiveASTVisitor.h"
|
||||
#include "clang/AST/Type.h"
|
||||
#include "clang/Analysis/FlowSensitive/StorageLocation.h"
|
||||
#include "llvm/ADT/DenseSet.h"
|
||||
#include "llvm/ADT/SetVector.h"
|
||||
|
||||
namespace clang {
|
||||
namespace dataflow {
|
||||
|
||||
/// Skip past nodes that the CFG does not emit. These nodes are invisible to
|
||||
/// flow-sensitive analysis, and should be ignored as they will effectively not
|
||||
/// exist.
|
||||
///
|
||||
/// * `ParenExpr` - The CFG takes the operator precedence into account, but
|
||||
/// otherwise omits the node afterwards.
|
||||
///
|
||||
/// * `ExprWithCleanups` - The CFG will generate the appropriate calls to
|
||||
/// destructors and then omit the node.
|
||||
///
|
||||
const Expr &ignoreCFGOmittedNodes(const Expr &E);
|
||||
const Stmt &ignoreCFGOmittedNodes(const Stmt &S);
|
||||
|
||||
/// A set of `FieldDecl *`. Use `SmallSetVector` to guarantee deterministic
|
||||
/// iteration order.
|
||||
using FieldSet = llvm::SmallSetVector<const FieldDecl *, 4>;
|
||||
|
||||
/// Returns the set of all fields in the type.
|
||||
FieldSet getObjectFields(QualType Type);
|
||||
|
||||
/// Returns whether `Fields` and `FieldLocs` contain the same fields.
|
||||
bool containsSameFields(const FieldSet &Fields,
|
||||
const RecordStorageLocation::FieldToLoc &FieldLocs);
|
||||
|
||||
/// Helper class for initialization of a record with an `InitListExpr`.
|
||||
/// `InitListExpr::inits()` contains the initializers for both the base classes
|
||||
/// and the fields of the record; this helper class separates these out into two
|
||||
/// different lists. In addition, it deals with special cases associated with
|
||||
/// unions.
|
||||
class RecordInitListHelper {
|
||||
public:
|
||||
// `InitList` must have record type.
|
||||
RecordInitListHelper(const InitListExpr *InitList);
|
||||
RecordInitListHelper(const CXXParenListInitExpr *ParenInitList);
|
||||
|
||||
// Base classes with their associated initializer expressions.
|
||||
ArrayRef<std::pair<const CXXBaseSpecifier *, Expr *>> base_inits() const {
|
||||
return BaseInits;
|
||||
}
|
||||
|
||||
// Fields with their associated initializer expressions.
|
||||
ArrayRef<std::pair<const FieldDecl *, Expr *>> field_inits() const {
|
||||
return FieldInits;
|
||||
}
|
||||
|
||||
private:
|
||||
RecordInitListHelper(QualType Ty, std::vector<const FieldDecl *> Fields,
|
||||
ArrayRef<Expr *> Inits);
|
||||
|
||||
SmallVector<std::pair<const CXXBaseSpecifier *, Expr *>> BaseInits;
|
||||
SmallVector<std::pair<const FieldDecl *, Expr *>> FieldInits;
|
||||
|
||||
// We potentially synthesize an `ImplicitValueInitExpr` for unions. It's a
|
||||
// member variable because we store a pointer to it in `FieldInits`.
|
||||
std::optional<ImplicitValueInitExpr> ImplicitValueInitForUnion;
|
||||
};
|
||||
|
||||
/// Specialization of `RecursiveASTVisitor` that visits those nodes that are
|
||||
/// relevant to the dataflow analysis; generally, these are the ones that also
|
||||
/// appear in the CFG.
|
||||
/// To start the traversal, call `TraverseStmt()` on the statement or body of
|
||||
/// the function to analyze. Don't call `TraverseDecl()` on the function itself;
|
||||
/// this won't work as `TraverseDecl()` contains code to avoid traversing nested
|
||||
/// functions.
|
||||
template <class Derived>
|
||||
class AnalysisASTVisitor : public RecursiveASTVisitor<Derived> {
|
||||
public:
|
||||
bool shouldVisitImplicitCode() { return true; }
|
||||
|
||||
bool shouldVisitLambdaBody() const { return false; }
|
||||
|
||||
bool TraverseDecl(Decl *D) {
|
||||
// Don't traverse nested record or function declarations.
|
||||
// - We won't be analyzing code contained in these anyway
|
||||
// - We don't model fields that are used only in these nested declaration,
|
||||
// so trying to propagate a result object to initializers of such fields
|
||||
// would cause an error.
|
||||
if (isa_and_nonnull<RecordDecl>(D) || isa_and_nonnull<FunctionDecl>(D))
|
||||
return true;
|
||||
|
||||
return RecursiveASTVisitor<Derived>::TraverseDecl(D);
|
||||
}
|
||||
|
||||
// Don't traverse expressions in unevaluated contexts, as we don't model
|
||||
// fields that are only used in these.
|
||||
// Note: The operand of the `noexcept` operator is an unevaluated operand, but
|
||||
// nevertheless it appears in the Clang CFG, so we don't exclude it here.
|
||||
bool TraverseDecltypeTypeLoc(DecltypeTypeLoc) { return true; }
|
||||
bool TraverseTypeOfExprTypeLoc(TypeOfExprTypeLoc) { return true; }
|
||||
bool TraverseCXXTypeidExpr(CXXTypeidExpr *TIE) {
|
||||
if (TIE->isPotentiallyEvaluated())
|
||||
return RecursiveASTVisitor<Derived>::TraverseCXXTypeidExpr(TIE);
|
||||
return true;
|
||||
}
|
||||
bool TraverseUnaryExprOrTypeTraitExpr(UnaryExprOrTypeTraitExpr *) {
|
||||
return true;
|
||||
}
|
||||
|
||||
bool TraverseBindingDecl(BindingDecl *BD) {
|
||||
// `RecursiveASTVisitor` doesn't traverse holding variables for
|
||||
// `BindingDecl`s by itself, so we need to tell it to.
|
||||
if (VarDecl *HoldingVar = BD->getHoldingVar())
|
||||
TraverseDecl(HoldingVar);
|
||||
return RecursiveASTVisitor<Derived>::TraverseBindingDecl(BD);
|
||||
}
|
||||
};
|
||||
|
||||
/// A collection of several types of declarations, all referenced from the same
|
||||
/// function.
|
||||
struct ReferencedDecls {
|
||||
/// Non-static member variables.
|
||||
FieldSet Fields;
|
||||
/// All variables with static storage duration, notably including static
|
||||
/// member variables and static variables declared within a function.
|
||||
llvm::DenseSet<const VarDecl *> Globals;
|
||||
/// Free functions and member functions which are referenced (but not
|
||||
/// necessarily called).
|
||||
llvm::DenseSet<const FunctionDecl *> Functions;
|
||||
};
|
||||
|
||||
/// Returns declarations that are declared in or referenced from `FD`.
|
||||
ReferencedDecls getReferencedDecls(const FunctionDecl &FD);
|
||||
|
||||
/// Returns declarations that are declared in or referenced from `S`.
|
||||
ReferencedDecls getReferencedDecls(const Stmt &S);
|
||||
|
||||
} // namespace dataflow
|
||||
} // namespace clang
|
||||
|
||||
#endif // LLVM_CLANG_ANALYSIS_FLOWSENSITIVE_ASTOPS_H
|
||||
|
|
@ -0,0 +1,96 @@
|
|||
//===-- AdornedCFG.h ------------------------------------*- C++ -*-===//
|
||||
//
|
||||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
||||
// See https://llvm.org/LICENSE.txt for license information.
|
||||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// This file defines an AdornedCFG class that is used by dataflow analyses that
|
||||
// run over Control-Flow Graphs (CFGs).
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef LLVM_CLANG_ANALYSIS_FLOWSENSITIVE_ADORNEDCFG_H
|
||||
#define LLVM_CLANG_ANALYSIS_FLOWSENSITIVE_ADORNEDCFG_H
|
||||
|
||||
#include "clang/AST/ASTContext.h"
|
||||
#include "clang/AST/Decl.h"
|
||||
#include "clang/AST/Stmt.h"
|
||||
#include "clang/Analysis/CFG.h"
|
||||
#include "llvm/ADT/BitVector.h"
|
||||
#include "llvm/ADT/DenseMap.h"
|
||||
#include "llvm/Support/Error.h"
|
||||
#include <memory>
|
||||
#include <utility>
|
||||
|
||||
namespace clang {
|
||||
namespace dataflow {
|
||||
|
||||
/// Holds CFG with additional information derived from it that is needed to
|
||||
/// perform dataflow analysis.
|
||||
class AdornedCFG {
|
||||
public:
|
||||
/// Builds an `AdornedCFG` from a `FunctionDecl`.
|
||||
/// `Func.doesThisDeclarationHaveABody()` must be true, and
|
||||
/// `Func.isTemplated()` must be false.
|
||||
static llvm::Expected<AdornedCFG> build(const FunctionDecl &Func);
|
||||
|
||||
/// Builds an `AdornedCFG` from an AST node. `D` is the function in which
|
||||
/// `S` resides. `D.isTemplated()` must be false.
|
||||
static llvm::Expected<AdornedCFG> build(const Decl &D, Stmt &S,
|
||||
ASTContext &C);
|
||||
|
||||
/// Returns the `Decl` containing the statement used to construct the CFG, if
|
||||
/// available.
|
||||
const Decl &getDecl() const { return ContainingDecl; }
|
||||
|
||||
/// Returns the CFG that is stored in this context.
|
||||
const CFG &getCFG() const { return *Cfg; }
|
||||
|
||||
/// Returns a mapping from statements to basic blocks that contain them.
|
||||
const llvm::DenseMap<const Stmt *, const CFGBlock *> &getStmtToBlock() const {
|
||||
return StmtToBlock;
|
||||
}
|
||||
|
||||
/// Returns whether `B` is reachable from the entry block.
|
||||
bool isBlockReachable(const CFGBlock &B) const {
|
||||
return BlockReachable[B.getBlockID()];
|
||||
}
|
||||
|
||||
/// Returns whether `B` contains an expression that is consumed in a
|
||||
/// different block than `B` (i.e. the parent of the expression is in a
|
||||
/// different block).
|
||||
/// This happens if there is control flow within a full-expression (triggered
|
||||
/// by `&&`, `||`, or the conditional operator). Note that the operands of
|
||||
/// these operators are not the only expressions that can be consumed in a
|
||||
/// different block. For example, in the function call
|
||||
/// `f(&i, cond() ? 1 : 0)`, `&i` is in a different block than the `CallExpr`.
|
||||
bool containsExprConsumedInDifferentBlock(const CFGBlock &B) const {
|
||||
return ContainsExprConsumedInDifferentBlock.contains(&B);
|
||||
}
|
||||
|
||||
private:
|
||||
AdornedCFG(
|
||||
const Decl &D, std::unique_ptr<CFG> Cfg,
|
||||
llvm::DenseMap<const Stmt *, const CFGBlock *> StmtToBlock,
|
||||
llvm::BitVector BlockReachable,
|
||||
llvm::DenseSet<const CFGBlock *> ContainsExprConsumedInDifferentBlock)
|
||||
: ContainingDecl(D), Cfg(std::move(Cfg)),
|
||||
StmtToBlock(std::move(StmtToBlock)),
|
||||
BlockReachable(std::move(BlockReachable)),
|
||||
ContainsExprConsumedInDifferentBlock(
|
||||
std::move(ContainsExprConsumedInDifferentBlock)) {}
|
||||
|
||||
/// The `Decl` containing the statement used to construct the CFG.
|
||||
const Decl &ContainingDecl;
|
||||
std::unique_ptr<CFG> Cfg;
|
||||
llvm::DenseMap<const Stmt *, const CFGBlock *> StmtToBlock;
|
||||
llvm::BitVector BlockReachable;
|
||||
llvm::DenseSet<const CFGBlock *> ContainsExprConsumedInDifferentBlock;
|
||||
};
|
||||
|
||||
} // namespace dataflow
|
||||
} // namespace clang
|
||||
|
||||
#endif // LLVM_CLANG_ANALYSIS_FLOWSENSITIVE_ADORNEDCFG_H
|
||||
|
|
@ -0,0 +1,179 @@
|
|||
//===- CNFFormula.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
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// A representation of a boolean formula in 3-CNF.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef LLVM_CLANG_ANALYSIS_FLOWSENSITIVE_CNFFORMULA_H
|
||||
#define LLVM_CLANG_ANALYSIS_FLOWSENSITIVE_CNFFORMULA_H
|
||||
|
||||
#include <cstdint>
|
||||
#include <vector>
|
||||
|
||||
#include "clang/Analysis/FlowSensitive/Formula.h"
|
||||
|
||||
namespace clang {
|
||||
namespace dataflow {
|
||||
|
||||
/// Boolean variables are represented as positive integers.
|
||||
using Variable = uint32_t;
|
||||
|
||||
/// A null boolean variable is used as a placeholder in various data structures
|
||||
/// and algorithms.
|
||||
constexpr Variable NullVar = 0;
|
||||
|
||||
/// Literals are represented as positive integers. Specifically, for a boolean
|
||||
/// variable `V` that is represented as the positive integer `I`, the positive
|
||||
/// literal `V` is represented as the integer `2*I` and the negative literal
|
||||
/// `!V` is represented as the integer `2*I+1`.
|
||||
using Literal = uint32_t;
|
||||
|
||||
/// A null literal is used as a placeholder in various data structures and
|
||||
/// algorithms.
|
||||
constexpr Literal NullLit = 0;
|
||||
|
||||
/// Clause identifiers are represented as positive integers.
|
||||
using ClauseID = uint32_t;
|
||||
|
||||
/// A null clause identifier is used as a placeholder in various data structures
|
||||
/// and algorithms.
|
||||
constexpr ClauseID NullClause = 0;
|
||||
|
||||
/// Returns the positive literal `V`.
|
||||
inline constexpr Literal posLit(Variable V) { return 2 * V; }
|
||||
|
||||
/// Returns the negative literal `!V`.
|
||||
inline constexpr Literal negLit(Variable V) { return 2 * V + 1; }
|
||||
|
||||
/// Returns whether `L` is a positive literal.
|
||||
inline constexpr bool isPosLit(Literal L) { return 0 == (L & 1); }
|
||||
|
||||
/// Returns whether `L` is a negative literal.
|
||||
inline constexpr bool isNegLit(Literal L) { return 1 == (L & 1); }
|
||||
|
||||
/// Returns the negated literal `!L`.
|
||||
inline constexpr Literal notLit(Literal L) { return L ^ 1; }
|
||||
|
||||
/// Returns the variable of `L`.
|
||||
inline constexpr Variable var(Literal L) { return L >> 1; }
|
||||
|
||||
/// A boolean formula in 3-CNF (conjunctive normal form with at most 3 literals
|
||||
/// per clause).
|
||||
class CNFFormula {
|
||||
/// `LargestVar` is equal to the largest positive integer that represents a
|
||||
/// variable in the formula.
|
||||
const Variable LargestVar;
|
||||
|
||||
/// Literals of all clauses in the formula.
|
||||
///
|
||||
/// The element at index 0 stands for the literal in the null clause. It is
|
||||
/// set to 0 and isn't used. Literals of clauses in the formula start from the
|
||||
/// element at index 1.
|
||||
///
|
||||
/// For example, for the formula `(L1 v L2) ^ (L2 v L3 v L4)` the elements of
|
||||
/// `Clauses` will be `[0, L1, L2, L2, L3, L4]`.
|
||||
std::vector<Literal> Clauses;
|
||||
|
||||
/// Start indices of clauses of the formula in `Clauses`.
|
||||
///
|
||||
/// The element at index 0 stands for the start index of the null clause. It
|
||||
/// is set to 0 and isn't used. Start indices of clauses in the formula start
|
||||
/// from the element at index 1.
|
||||
///
|
||||
/// For example, for the formula `(L1 v L2) ^ (L2 v L3 v L4)` the elements of
|
||||
/// `ClauseStarts` will be `[0, 1, 3]`. Note that the literals of the first
|
||||
/// clause always start at index 1. The start index for the literals of the
|
||||
/// second clause depends on the size of the first clause and so on.
|
||||
std::vector<size_t> ClauseStarts;
|
||||
|
||||
/// Indicates that we already know the formula is unsatisfiable.
|
||||
/// During construction, we catch simple cases of conflicting unit-clauses.
|
||||
bool KnownContradictory;
|
||||
|
||||
public:
|
||||
explicit CNFFormula(Variable LargestVar);
|
||||
|
||||
/// Adds the `L1 v ... v Ln` clause to the formula.
|
||||
/// Requirements:
|
||||
///
|
||||
/// `Li` must not be `NullLit`.
|
||||
///
|
||||
/// All literals in the input that are not `NullLit` must be distinct.
|
||||
void addClause(ArrayRef<Literal> lits);
|
||||
|
||||
/// Returns whether the formula is known to be contradictory.
|
||||
/// This is the case if any of the clauses is empty.
|
||||
bool knownContradictory() const { return KnownContradictory; }
|
||||
|
||||
/// Returns the largest variable in the formula.
|
||||
Variable largestVar() const { return LargestVar; }
|
||||
|
||||
/// Returns the number of clauses in the formula.
|
||||
/// Valid clause IDs are in the range [1, `numClauses()`].
|
||||
ClauseID numClauses() const { return ClauseStarts.size() - 1; }
|
||||
|
||||
/// Returns the number of literals in clause `C`.
|
||||
size_t clauseSize(ClauseID C) const {
|
||||
return C == ClauseStarts.size() - 1 ? Clauses.size() - ClauseStarts[C]
|
||||
: ClauseStarts[C + 1] - ClauseStarts[C];
|
||||
}
|
||||
|
||||
/// Returns the literals of clause `C`.
|
||||
/// If `knownContradictory()` is false, each clause has at least one literal.
|
||||
llvm::ArrayRef<Literal> clauseLiterals(ClauseID C) const {
|
||||
size_t S = clauseSize(C);
|
||||
if (S == 0)
|
||||
return llvm::ArrayRef<Literal>();
|
||||
return llvm::ArrayRef<Literal>(&Clauses[ClauseStarts[C]], S);
|
||||
}
|
||||
|
||||
/// An iterator over all literals of all clauses in the formula.
|
||||
/// The iterator allows mutation of the literal through the `*` operator.
|
||||
/// This is to support solvers that mutate the formula during solving.
|
||||
class Iterator {
|
||||
friend class CNFFormula;
|
||||
CNFFormula *CNF;
|
||||
size_t Idx;
|
||||
Iterator(CNFFormula *CNF, size_t Idx) : CNF(CNF), Idx(Idx) {}
|
||||
|
||||
public:
|
||||
Iterator(const Iterator &) = default;
|
||||
Iterator &operator=(const Iterator &) = default;
|
||||
|
||||
Iterator &operator++() {
|
||||
++Idx;
|
||||
assert(Idx < CNF->Clauses.size() && "Iterator out of bounds");
|
||||
return *this;
|
||||
}
|
||||
|
||||
Iterator next() const {
|
||||
Iterator I = *this;
|
||||
++I;
|
||||
return I;
|
||||
}
|
||||
|
||||
Literal &operator*() const { return CNF->Clauses[Idx]; }
|
||||
};
|
||||
friend class Iterator;
|
||||
|
||||
/// Returns an iterator to the first literal of clause `C`.
|
||||
Iterator startOfClause(ClauseID C) { return Iterator(this, ClauseStarts[C]); }
|
||||
};
|
||||
|
||||
/// Converts the conjunction of `Vals` into a formula in conjunctive normal
|
||||
/// form where each clause has at least one and at most three literals.
|
||||
/// `Atomics` is populated with a mapping from `Variables` to the corresponding
|
||||
/// `Atom`s for atomic booleans in the input formulas.
|
||||
CNFFormula buildCNF(const llvm::ArrayRef<const Formula *> &Formulas,
|
||||
llvm::DenseMap<Variable, Atom> &Atomics);
|
||||
|
||||
} // namespace dataflow
|
||||
} // namespace clang
|
||||
|
||||
#endif // LLVM_CLANG_ANALYSIS_FLOWSENSITIVE_CNFFORMULA_H
|
||||
|
|
@ -1,79 +0,0 @@
|
|||
//===-- ControlFlowContext.h ------------------------------------*- C++ -*-===//
|
||||
//
|
||||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
||||
// See https://llvm.org/LICENSE.txt for license information.
|
||||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// This file defines a ControlFlowContext class that is used by dataflow
|
||||
// analyses that run over Control-Flow Graphs (CFGs).
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef LLVM_CLANG_ANALYSIS_FLOWSENSITIVE_CONTROLFLOWCONTEXT_H
|
||||
#define LLVM_CLANG_ANALYSIS_FLOWSENSITIVE_CONTROLFLOWCONTEXT_H
|
||||
|
||||
#include "clang/AST/ASTContext.h"
|
||||
#include "clang/AST/Decl.h"
|
||||
#include "clang/AST/Stmt.h"
|
||||
#include "clang/Analysis/CFG.h"
|
||||
#include "llvm/ADT/BitVector.h"
|
||||
#include "llvm/ADT/DenseMap.h"
|
||||
#include "llvm/Support/Error.h"
|
||||
#include <memory>
|
||||
#include <utility>
|
||||
|
||||
namespace clang {
|
||||
namespace dataflow {
|
||||
|
||||
/// Holds CFG and other derived context that is needed to perform dataflow
|
||||
/// analysis.
|
||||
class ControlFlowContext {
|
||||
public:
|
||||
/// Builds a ControlFlowContext from a `FunctionDecl`.
|
||||
/// `Func.doesThisDeclarationHaveABody()` must be true, and
|
||||
/// `Func.isTemplated()` must be false.
|
||||
static llvm::Expected<ControlFlowContext> build(const FunctionDecl &Func);
|
||||
|
||||
/// Builds a ControlFlowContext from an AST node. `D` is the function in which
|
||||
/// `S` resides. `D.isTemplated()` must be false.
|
||||
static llvm::Expected<ControlFlowContext> build(const Decl &D, Stmt &S,
|
||||
ASTContext &C);
|
||||
|
||||
/// Returns the `Decl` containing the statement used to construct the CFG, if
|
||||
/// available.
|
||||
const Decl &getDecl() const { return ContainingDecl; }
|
||||
|
||||
/// Returns the CFG that is stored in this context.
|
||||
const CFG &getCFG() const { return *Cfg; }
|
||||
|
||||
/// Returns a mapping from statements to basic blocks that contain them.
|
||||
const llvm::DenseMap<const Stmt *, const CFGBlock *> &getStmtToBlock() const {
|
||||
return StmtToBlock;
|
||||
}
|
||||
|
||||
/// Returns whether `B` is reachable from the entry block.
|
||||
bool isBlockReachable(const CFGBlock &B) const {
|
||||
return BlockReachable[B.getBlockID()];
|
||||
}
|
||||
|
||||
private:
|
||||
ControlFlowContext(const Decl &D, std::unique_ptr<CFG> Cfg,
|
||||
llvm::DenseMap<const Stmt *, const CFGBlock *> StmtToBlock,
|
||||
llvm::BitVector BlockReachable)
|
||||
: ContainingDecl(D), Cfg(std::move(Cfg)),
|
||||
StmtToBlock(std::move(StmtToBlock)),
|
||||
BlockReachable(std::move(BlockReachable)) {}
|
||||
|
||||
/// The `Decl` containing the statement used to construct the CFG.
|
||||
const Decl &ContainingDecl;
|
||||
std::unique_ptr<CFG> Cfg;
|
||||
llvm::DenseMap<const Stmt *, const CFGBlock *> StmtToBlock;
|
||||
llvm::BitVector BlockReachable;
|
||||
};
|
||||
|
||||
} // namespace dataflow
|
||||
} // namespace clang
|
||||
|
||||
#endif // LLVM_CLANG_ANALYSIS_FLOWSENSITIVE_CONTROLFLOWCONTEXT_H
|
||||
|
|
@ -22,7 +22,7 @@
|
|||
|
||||
#include "clang/AST/ASTContext.h"
|
||||
#include "clang/Analysis/CFG.h"
|
||||
#include "clang/Analysis/FlowSensitive/ControlFlowContext.h"
|
||||
#include "clang/Analysis/FlowSensitive/AdornedCFG.h"
|
||||
#include "clang/Analysis/FlowSensitive/DataflowEnvironment.h"
|
||||
#include "clang/Analysis/FlowSensitive/DataflowLattice.h"
|
||||
#include "clang/Analysis/FlowSensitive/MatchSwitch.h"
|
||||
|
|
@ -54,10 +54,9 @@ namespace dataflow {
|
|||
/// Environment &Env)` - applies the analysis transfer
|
||||
/// function for a given edge from a CFG block of a conditional statement.
|
||||
///
|
||||
/// `Derived` can optionally override the following members:
|
||||
/// * `bool merge(QualType, const Value &, const Value &, Value &,
|
||||
/// Environment &)` - joins distinct values. This could be a strict
|
||||
/// lattice join or a more general widening operation.
|
||||
/// `Derived` can optionally override the virtual functions in the
|
||||
/// `Environment::ValueModel` interface (which is an indirect base class of
|
||||
/// this class).
|
||||
///
|
||||
/// `LatticeT` is a bounded join-semilattice that is used by `Derived` and must
|
||||
/// provide the following public members:
|
||||
|
|
@ -179,13 +178,50 @@ template <typename LatticeT> struct DataflowAnalysisState {
|
|||
Environment Env;
|
||||
};
|
||||
|
||||
/// A callback to be called with the state before or after visiting a CFG
|
||||
/// element.
|
||||
template <typename AnalysisT>
|
||||
using CFGEltCallback = std::function<void(
|
||||
const CFGElement &,
|
||||
const DataflowAnalysisState<typename AnalysisT::Lattice> &)>;
|
||||
|
||||
/// A pair of callbacks to be called with the state before and after visiting a
|
||||
/// CFG element.
|
||||
/// Either or both of the callbacks may be null.
|
||||
template <typename AnalysisT> struct CFGEltCallbacks {
|
||||
CFGEltCallback<AnalysisT> Before;
|
||||
CFGEltCallback<AnalysisT> After;
|
||||
};
|
||||
|
||||
/// A callback for performing diagnosis on a CFG element, called with the state
|
||||
/// before or after visiting that CFG element. Returns a list of diagnostics
|
||||
/// to emit (if any).
|
||||
template <typename AnalysisT, typename Diagnostic>
|
||||
using DiagnosisCallback = llvm::function_ref<llvm::SmallVector<Diagnostic>(
|
||||
const CFGElement &, ASTContext &,
|
||||
const TransferStateForDiagnostics<typename AnalysisT::Lattice> &)>;
|
||||
|
||||
/// A pair of callbacks for performing diagnosis on a CFG element, called with
|
||||
/// the state before and after visiting that CFG element.
|
||||
/// Either or both of the callbacks may be null.
|
||||
template <typename AnalysisT, typename Diagnostic> struct DiagnosisCallbacks {
|
||||
DiagnosisCallback<AnalysisT, Diagnostic> Before;
|
||||
DiagnosisCallback<AnalysisT, Diagnostic> After;
|
||||
};
|
||||
|
||||
/// Default for the maximum number of SAT solver iterations during analysis.
|
||||
inline constexpr std::int64_t kDefaultMaxSATIterations = 1'000'000'000;
|
||||
|
||||
/// Default for the maximum number of block visits during analysis.
|
||||
inline constexpr std::int32_t kDefaultMaxBlockVisits = 20'000;
|
||||
|
||||
/// Performs dataflow analysis and returns a mapping from basic block IDs to
|
||||
/// dataflow analysis states that model the respective basic blocks. The
|
||||
/// returned vector, if any, will have the same size as the number of CFG
|
||||
/// blocks, with indices corresponding to basic block IDs. Returns an error if
|
||||
/// the dataflow analysis cannot be performed successfully. Otherwise, calls
|
||||
/// `PostVisitCFG` on each CFG element with the final analysis results at that
|
||||
/// program point.
|
||||
/// `PostAnalysisCallbacks` on each CFG element with the final analysis results
|
||||
/// before and after that program point.
|
||||
///
|
||||
/// `MaxBlockVisits` caps the number of block visits during analysis. See
|
||||
/// `runTypeErasedDataflowAnalysis` for a full description. The default value is
|
||||
|
|
@ -195,31 +231,40 @@ template <typename LatticeT> struct DataflowAnalysisState {
|
|||
template <typename AnalysisT>
|
||||
llvm::Expected<std::vector<
|
||||
std::optional<DataflowAnalysisState<typename AnalysisT::Lattice>>>>
|
||||
runDataflowAnalysis(
|
||||
const ControlFlowContext &CFCtx, AnalysisT &Analysis,
|
||||
const Environment &InitEnv,
|
||||
std::function<void(const CFGElement &, const DataflowAnalysisState<
|
||||
typename AnalysisT::Lattice> &)>
|
||||
PostVisitCFG = nullptr,
|
||||
std::int32_t MaxBlockVisits = 20'000) {
|
||||
std::function<void(const CFGElement &,
|
||||
const TypeErasedDataflowAnalysisState &)>
|
||||
PostVisitCFGClosure = nullptr;
|
||||
if (PostVisitCFG) {
|
||||
PostVisitCFGClosure = [&PostVisitCFG](
|
||||
const CFGElement &Element,
|
||||
const TypeErasedDataflowAnalysisState &State) {
|
||||
auto *Lattice =
|
||||
llvm::any_cast<typename AnalysisT::Lattice>(&State.Lattice.Value);
|
||||
// FIXME: we should not be copying the environment here!
|
||||
// Ultimately the PostVisitCFG only gets a const reference anyway.
|
||||
PostVisitCFG(Element, DataflowAnalysisState<typename AnalysisT::Lattice>{
|
||||
*Lattice, State.Env.fork()});
|
||||
};
|
||||
runDataflowAnalysis(const AdornedCFG &ACFG, AnalysisT &Analysis,
|
||||
const Environment &InitEnv,
|
||||
CFGEltCallbacks<AnalysisT> PostAnalysisCallbacks,
|
||||
std::int32_t MaxBlockVisits = kDefaultMaxBlockVisits) {
|
||||
CFGEltCallbacksTypeErased TypeErasedCallbacks;
|
||||
if (PostAnalysisCallbacks.Before) {
|
||||
TypeErasedCallbacks.Before =
|
||||
[&PostAnalysisCallbacks](const CFGElement &Element,
|
||||
const TypeErasedDataflowAnalysisState &State) {
|
||||
auto *Lattice =
|
||||
llvm::any_cast<typename AnalysisT::Lattice>(&State.Lattice.Value);
|
||||
// FIXME: we should not be copying the environment here!
|
||||
// Ultimately the `CFGEltCallback` only gets a const reference anyway.
|
||||
PostAnalysisCallbacks.Before(
|
||||
Element, DataflowAnalysisState<typename AnalysisT::Lattice>{
|
||||
*Lattice, State.Env.fork()});
|
||||
};
|
||||
}
|
||||
if (PostAnalysisCallbacks.After) {
|
||||
TypeErasedCallbacks.After =
|
||||
[&PostAnalysisCallbacks](const CFGElement &Element,
|
||||
const TypeErasedDataflowAnalysisState &State) {
|
||||
auto *Lattice =
|
||||
llvm::any_cast<typename AnalysisT::Lattice>(&State.Lattice.Value);
|
||||
// FIXME: we should not be copying the environment here!
|
||||
// Ultimately the `CFGEltCallback` only gets a const reference anyway.
|
||||
PostAnalysisCallbacks.After(
|
||||
Element, DataflowAnalysisState<typename AnalysisT::Lattice>{
|
||||
*Lattice, State.Env.fork()});
|
||||
};
|
||||
}
|
||||
|
||||
auto TypeErasedBlockStates = runTypeErasedDataflowAnalysis(
|
||||
CFCtx, Analysis, InitEnv, PostVisitCFGClosure, MaxBlockVisits);
|
||||
ACFG, Analysis, InitEnv, TypeErasedCallbacks, MaxBlockVisits);
|
||||
if (!TypeErasedBlockStates)
|
||||
return TypeErasedBlockStates.takeError();
|
||||
|
||||
|
|
@ -241,6 +286,22 @@ runDataflowAnalysis(
|
|||
return std::move(BlockStates);
|
||||
}
|
||||
|
||||
/// Overload that takes only one post-analysis callback, which is run on the
|
||||
/// state after visiting the `CFGElement`. This is provided for backwards
|
||||
/// compatibility; new callers should call the overload taking `CFGEltCallbacks`
|
||||
/// instead.
|
||||
template <typename AnalysisT>
|
||||
llvm::Expected<std::vector<
|
||||
std::optional<DataflowAnalysisState<typename AnalysisT::Lattice>>>>
|
||||
runDataflowAnalysis(
|
||||
const AdornedCFG &ACFG, AnalysisT &Analysis, const Environment &InitEnv,
|
||||
CFGEltCallback<AnalysisT> PostAnalysisCallbackAfterElt = nullptr,
|
||||
std::int32_t MaxBlockVisits = kDefaultMaxBlockVisits) {
|
||||
return runDataflowAnalysis(ACFG, Analysis, InitEnv,
|
||||
{nullptr, PostAnalysisCallbackAfterElt},
|
||||
MaxBlockVisits);
|
||||
}
|
||||
|
||||
// Create an analysis class that is derived from `DataflowAnalysis`. This is an
|
||||
// SFINAE adapter that allows us to call two different variants of constructor
|
||||
// (either with or without the optional `Environment` parameter).
|
||||
|
|
@ -273,40 +334,52 @@ auto createAnalysis(ASTContext &ASTCtx, Environment &Env)
|
|||
/// `runDataflowAnalysis` for a full description and explanation of the default
|
||||
/// value.
|
||||
template <typename AnalysisT, typename Diagnostic>
|
||||
llvm::Expected<llvm::SmallVector<Diagnostic>> diagnoseFunction(
|
||||
const FunctionDecl &FuncDecl, ASTContext &ASTCtx,
|
||||
llvm::function_ref<llvm::SmallVector<Diagnostic>(
|
||||
const CFGElement &, ASTContext &,
|
||||
const TransferStateForDiagnostics<typename AnalysisT::Lattice> &)>
|
||||
Diagnoser,
|
||||
std::int64_t MaxSATIterations = 1'000'000'000,
|
||||
std::int32_t MaxBlockVisits = 20'000) {
|
||||
llvm::Expected<ControlFlowContext> Context =
|
||||
ControlFlowContext::build(FuncDecl);
|
||||
llvm::Expected<llvm::SmallVector<Diagnostic>>
|
||||
diagnoseFunction(const FunctionDecl &FuncDecl, ASTContext &ASTCtx,
|
||||
DiagnosisCallbacks<AnalysisT, Diagnostic> Diagnoser,
|
||||
std::int64_t MaxSATIterations = kDefaultMaxSATIterations,
|
||||
std::int32_t MaxBlockVisits = kDefaultMaxBlockVisits) {
|
||||
llvm::Expected<AdornedCFG> Context = AdornedCFG::build(FuncDecl);
|
||||
if (!Context)
|
||||
return Context.takeError();
|
||||
|
||||
auto OwnedSolver = std::make_unique<WatchedLiteralsSolver>(MaxSATIterations);
|
||||
const WatchedLiteralsSolver *Solver = OwnedSolver.get();
|
||||
DataflowAnalysisContext AnalysisContext(std::move(OwnedSolver));
|
||||
auto Solver = std::make_unique<WatchedLiteralsSolver>(MaxSATIterations);
|
||||
DataflowAnalysisContext AnalysisContext(*Solver);
|
||||
Environment Env(AnalysisContext, FuncDecl);
|
||||
AnalysisT Analysis = createAnalysis<AnalysisT>(ASTCtx, Env);
|
||||
llvm::SmallVector<Diagnostic> Diagnostics;
|
||||
CFGEltCallbacksTypeErased PostAnalysisCallbacks;
|
||||
if (Diagnoser.Before) {
|
||||
PostAnalysisCallbacks.Before =
|
||||
[&ASTCtx, &Diagnoser,
|
||||
&Diagnostics](const CFGElement &Elt,
|
||||
const TypeErasedDataflowAnalysisState &State) mutable {
|
||||
auto EltDiagnostics = Diagnoser.Before(
|
||||
Elt, ASTCtx,
|
||||
TransferStateForDiagnostics<typename AnalysisT::Lattice>(
|
||||
llvm::any_cast<const typename AnalysisT::Lattice &>(
|
||||
State.Lattice.Value),
|
||||
State.Env));
|
||||
llvm::move(EltDiagnostics, std::back_inserter(Diagnostics));
|
||||
};
|
||||
}
|
||||
if (Diagnoser.After) {
|
||||
PostAnalysisCallbacks.After =
|
||||
[&ASTCtx, &Diagnoser,
|
||||
&Diagnostics](const CFGElement &Elt,
|
||||
const TypeErasedDataflowAnalysisState &State) mutable {
|
||||
auto EltDiagnostics = Diagnoser.After(
|
||||
Elt, ASTCtx,
|
||||
TransferStateForDiagnostics<typename AnalysisT::Lattice>(
|
||||
llvm::any_cast<const typename AnalysisT::Lattice &>(
|
||||
State.Lattice.Value),
|
||||
State.Env));
|
||||
llvm::move(EltDiagnostics, std::back_inserter(Diagnostics));
|
||||
};
|
||||
}
|
||||
if (llvm::Error Err =
|
||||
runTypeErasedDataflowAnalysis(
|
||||
*Context, Analysis, Env,
|
||||
[&ASTCtx, &Diagnoser, &Diagnostics](
|
||||
const CFGElement &Elt,
|
||||
const TypeErasedDataflowAnalysisState &State) mutable {
|
||||
auto EltDiagnostics = Diagnoser(
|
||||
Elt, ASTCtx,
|
||||
TransferStateForDiagnostics<typename AnalysisT::Lattice>(
|
||||
llvm::any_cast<const typename AnalysisT::Lattice &>(
|
||||
State.Lattice.Value),
|
||||
State.Env));
|
||||
llvm::move(EltDiagnostics, std::back_inserter(Diagnostics));
|
||||
},
|
||||
MaxBlockVisits)
|
||||
runTypeErasedDataflowAnalysis(*Context, Analysis, Env,
|
||||
PostAnalysisCallbacks, MaxBlockVisits)
|
||||
.takeError())
|
||||
return std::move(Err);
|
||||
|
||||
|
|
@ -317,6 +390,21 @@ llvm::Expected<llvm::SmallVector<Diagnostic>> diagnoseFunction(
|
|||
return Diagnostics;
|
||||
}
|
||||
|
||||
/// Overload that takes only one diagnosis callback, which is run on the state
|
||||
/// after visiting the `CFGElement`. This is provided for backwards
|
||||
/// compatibility; new callers should call the overload taking
|
||||
/// `DiagnosisCallbacks` instead.
|
||||
template <typename AnalysisT, typename Diagnostic>
|
||||
llvm::Expected<llvm::SmallVector<Diagnostic>>
|
||||
diagnoseFunction(const FunctionDecl &FuncDecl, ASTContext &ASTCtx,
|
||||
DiagnosisCallback<AnalysisT, Diagnostic> Diagnoser,
|
||||
std::int64_t MaxSATIterations = kDefaultMaxSATIterations,
|
||||
std::int32_t MaxBlockVisits = kDefaultMaxBlockVisits) {
|
||||
DiagnosisCallbacks<AnalysisT, Diagnostic> Callbacks = {nullptr, Diagnoser};
|
||||
return diagnoseFunction(FuncDecl, ASTCtx, Callbacks, MaxSATIterations,
|
||||
MaxBlockVisits);
|
||||
}
|
||||
|
||||
/// Abstract base class for dataflow "models": reusable analysis components that
|
||||
/// model a particular aspect of program semantics in the `Environment`. For
|
||||
/// example, a model may capture a type and its related functions.
|
||||
|
|
|
|||
|
|
@ -18,8 +18,9 @@
|
|||
#include "clang/AST/Decl.h"
|
||||
#include "clang/AST/Expr.h"
|
||||
#include "clang/AST/TypeOrdering.h"
|
||||
#include "clang/Analysis/FlowSensitive/ASTOps.h"
|
||||
#include "clang/Analysis/FlowSensitive/AdornedCFG.h"
|
||||
#include "clang/Analysis/FlowSensitive/Arena.h"
|
||||
#include "clang/Analysis/FlowSensitive/ControlFlowContext.h"
|
||||
#include "clang/Analysis/FlowSensitive/Solver.h"
|
||||
#include "clang/Analysis/FlowSensitive/StorageLocation.h"
|
||||
#include "clang/Analysis/FlowSensitive/Value.h"
|
||||
|
|
@ -30,38 +31,11 @@
|
|||
#include <cassert>
|
||||
#include <memory>
|
||||
#include <optional>
|
||||
#include <type_traits>
|
||||
#include <utility>
|
||||
#include <vector>
|
||||
|
||||
namespace clang {
|
||||
namespace dataflow {
|
||||
class Logger;
|
||||
|
||||
/// Skip past nodes that the CFG does not emit. These nodes are invisible to
|
||||
/// flow-sensitive analysis, and should be ignored as they will effectively not
|
||||
/// exist.
|
||||
///
|
||||
/// * `ParenExpr` - The CFG takes the operator precedence into account, but
|
||||
/// otherwise omits the node afterwards.
|
||||
///
|
||||
/// * `ExprWithCleanups` - The CFG will generate the appropriate calls to
|
||||
/// destructors and then omit the node.
|
||||
///
|
||||
const Expr &ignoreCFGOmittedNodes(const Expr &E);
|
||||
const Stmt &ignoreCFGOmittedNodes(const Stmt &S);
|
||||
|
||||
/// A set of `FieldDecl *`. Use `SmallSetVector` to guarantee deterministic
|
||||
/// iteration order.
|
||||
using FieldSet = llvm::SmallSetVector<const FieldDecl *, 4>;
|
||||
|
||||
/// Returns the set of all fields in the type.
|
||||
FieldSet getObjectFields(QualType Type);
|
||||
|
||||
/// Returns whether `Fields` and `FieldLocs` contain the same fields.
|
||||
bool containsSameFields(const FieldSet &Fields,
|
||||
const RecordStorageLocation::FieldToLoc &FieldLocs);
|
||||
|
||||
struct ContextSensitiveOptions {
|
||||
/// The maximum depth to analyze. A value of zero is equivalent to disabling
|
||||
/// context-sensitive analysis entirely.
|
||||
|
|
@ -93,13 +67,27 @@ public:
|
|||
DataflowAnalysisContext(std::unique_ptr<Solver> S,
|
||||
Options Opts = Options{
|
||||
/*ContextSensitiveOpts=*/std::nullopt,
|
||||
/*Logger=*/nullptr});
|
||||
/*Logger=*/nullptr})
|
||||
: DataflowAnalysisContext(*S, std::move(S), Opts) {}
|
||||
|
||||
/// Constructs a dataflow analysis context.
|
||||
///
|
||||
/// Requirements:
|
||||
///
|
||||
/// `S` must outlive the `DataflowAnalysisContext`.
|
||||
DataflowAnalysisContext(Solver &S, Options Opts = Options{
|
||||
/*ContextSensitiveOpts=*/std::nullopt,
|
||||
/*Logger=*/nullptr})
|
||||
: DataflowAnalysisContext(S, nullptr, Opts) {}
|
||||
|
||||
~DataflowAnalysisContext();
|
||||
|
||||
/// Sets a callback that returns the names and types of the synthetic fields
|
||||
/// to add to a `RecordStorageLocation` of a given type.
|
||||
/// Typically, this is called from the constructor of a `DataflowAnalysis`
|
||||
///
|
||||
/// The field types returned by the callback may not have reference type.
|
||||
///
|
||||
/// To maintain the invariant that all `RecordStorageLocation`s of a given
|
||||
/// type have the same fields:
|
||||
/// * The callback must always return the same result for a given type
|
||||
|
|
@ -181,9 +169,9 @@ public:
|
|||
LLVM_DUMP_METHOD void dumpFlowCondition(Atom Token,
|
||||
llvm::raw_ostream &OS = llvm::dbgs());
|
||||
|
||||
/// Returns the `ControlFlowContext` registered for `F`, if any. Otherwise,
|
||||
/// Returns the `AdornedCFG` registered for `F`, if any. Otherwise,
|
||||
/// returns null.
|
||||
const ControlFlowContext *getControlFlowContext(const FunctionDecl *F);
|
||||
const AdornedCFG *getAdornedCFG(const FunctionDecl *F);
|
||||
|
||||
const Options &getOptions() { return Opts; }
|
||||
|
||||
|
|
@ -205,8 +193,17 @@ public:
|
|||
/// type.
|
||||
llvm::StringMap<QualType> getSyntheticFields(QualType Type) {
|
||||
assert(Type->isRecordType());
|
||||
if (SyntheticFieldCallback)
|
||||
return SyntheticFieldCallback(Type);
|
||||
if (SyntheticFieldCallback) {
|
||||
llvm::StringMap<QualType> Result = SyntheticFieldCallback(Type);
|
||||
// Synthetic fields are not allowed to have reference type.
|
||||
assert([&Result] {
|
||||
for (const auto &Entry : Result)
|
||||
if (Entry.getValue()->isReferenceType())
|
||||
return false;
|
||||
return true;
|
||||
}());
|
||||
return Result;
|
||||
}
|
||||
return {};
|
||||
}
|
||||
|
||||
|
|
@ -224,6 +221,13 @@ private:
|
|||
using DenseMapInfo::isEqual;
|
||||
};
|
||||
|
||||
/// `S` is the solver to use. `OwnedSolver` may be:
|
||||
/// * Null (in which case `S` is non-onwed and must outlive this object), or
|
||||
/// * Non-null (in which case it must refer to `S`, and the
|
||||
/// `DataflowAnalysisContext will take ownership of `OwnedSolver`).
|
||||
DataflowAnalysisContext(Solver &S, std::unique_ptr<Solver> &&OwnedSolver,
|
||||
Options Opts);
|
||||
|
||||
// Extends the set of modeled field declarations.
|
||||
void addModeledFields(const FieldSet &Fields);
|
||||
|
||||
|
|
@ -247,7 +251,8 @@ private:
|
|||
Solver::Result::Status::Unsatisfiable;
|
||||
}
|
||||
|
||||
std::unique_ptr<Solver> S;
|
||||
Solver &S;
|
||||
std::unique_ptr<Solver> OwnedSolver;
|
||||
std::unique_ptr<Arena> A;
|
||||
|
||||
// Maps from program declarations and statements to storage locations that are
|
||||
|
|
@ -285,7 +290,7 @@ private:
|
|||
llvm::DenseMap<Atom, const Formula *> FlowConditionConstraints;
|
||||
const Formula *Invariant = nullptr;
|
||||
|
||||
llvm::DenseMap<const FunctionDecl *, ControlFlowContext> FunctionContexts;
|
||||
llvm::DenseMap<const FunctionDecl *, AdornedCFG> FunctionContexts;
|
||||
|
||||
// Fields modeled by environments covered by this context.
|
||||
FieldSet ModeledFields;
|
||||
|
|
|
|||
|
|
@ -19,7 +19,7 @@
|
|||
#include "clang/AST/DeclBase.h"
|
||||
#include "clang/AST/Expr.h"
|
||||
#include "clang/AST/Type.h"
|
||||
#include "clang/Analysis/FlowSensitive/ControlFlowContext.h"
|
||||
#include "clang/Analysis/FlowSensitive/ASTOps.h"
|
||||
#include "clang/Analysis/FlowSensitive/DataflowAnalysisContext.h"
|
||||
#include "clang/Analysis/FlowSensitive/DataflowLattice.h"
|
||||
#include "clang/Analysis/FlowSensitive/Formula.h"
|
||||
|
|
@ -31,9 +31,11 @@
|
|||
#include "llvm/ADT/MapVector.h"
|
||||
#include "llvm/Support/Compiler.h"
|
||||
#include "llvm/Support/ErrorHandling.h"
|
||||
#include <cassert>
|
||||
#include <memory>
|
||||
#include <type_traits>
|
||||
#include <utility>
|
||||
#include <vector>
|
||||
|
||||
namespace clang {
|
||||
namespace dataflow {
|
||||
|
|
@ -45,6 +47,15 @@ enum class ComparisonResult {
|
|||
Unknown,
|
||||
};
|
||||
|
||||
/// The result of a `widen` operation.
|
||||
struct WidenResult {
|
||||
/// Non-null pointer to a potentially widened version of the input value.
|
||||
Value *V;
|
||||
/// Whether `V` represents a "change" (that is, a different value) with
|
||||
/// respect to the previous value in the sequence.
|
||||
LatticeEffect Effect;
|
||||
};
|
||||
|
||||
/// 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
|
||||
|
|
@ -76,16 +87,13 @@ public:
|
|||
virtual ComparisonResult compare(QualType Type, const Value &Val1,
|
||||
const Environment &Env1, const Value &Val2,
|
||||
const Environment &Env2) {
|
||||
// FIXME: Consider adding QualType to RecordValue and removing the Type
|
||||
// FIXME: Consider adding `QualType` to `Value` and removing the `Type`
|
||||
// argument here.
|
||||
return ComparisonResult::Unknown;
|
||||
}
|
||||
|
||||
/// Modifies `MergedVal` to approximate both `Val1` and `Val2`. This could
|
||||
/// be a strict lattice join or a more general widening operation.
|
||||
///
|
||||
/// If this function returns true, `MergedVal` will be assigned to a storage
|
||||
/// location of type `Type` in `MergedEnv`.
|
||||
/// Modifies `JoinedVal` to approximate both `Val1` and `Val2`. This should
|
||||
/// obey the properties of a lattice join.
|
||||
///
|
||||
/// `Env1` and `Env2` can be used to query child values and path condition
|
||||
/// implications of `Val1` and `Val2` respectively.
|
||||
|
|
@ -94,16 +102,13 @@ public:
|
|||
///
|
||||
/// `Val1` and `Val2` must be distinct.
|
||||
///
|
||||
/// `Val1`, `Val2`, and `MergedVal` must model values of type `Type`.
|
||||
/// `Val1`, `Val2`, and `JoinedVal` must model values of type `Type`.
|
||||
///
|
||||
/// `Val1` and `Val2` must be assigned to the same storage location in
|
||||
/// `Env1` and `Env2` respectively.
|
||||
virtual bool merge(QualType Type, const Value &Val1,
|
||||
const Environment &Env1, const Value &Val2,
|
||||
const Environment &Env2, Value &MergedVal,
|
||||
Environment &MergedEnv) {
|
||||
return true;
|
||||
}
|
||||
virtual void join(QualType Type, const Value &Val1, const Environment &Env1,
|
||||
const Value &Val2, const Environment &Env2,
|
||||
Value &JoinedVal, Environment &JoinedEnv) {}
|
||||
|
||||
/// This function may widen the current value -- replace it with an
|
||||
/// approximation that can reach a fixed point more quickly than iterated
|
||||
|
|
@ -112,14 +117,17 @@ public:
|
|||
/// 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.
|
||||
/// Returns one of the folowing:
|
||||
/// * `std::nullopt`, if this value is not of interest to the
|
||||
/// model.
|
||||
/// * A `WidenResult` with:
|
||||
/// * A non-null `Value *` that points either to `Current` or a widened
|
||||
/// version of `Current`. This value must be consistent with
|
||||
/// the flow condition of `CurrentEnv`. We particularly caution
|
||||
/// against using `Prev`, which is rarely consistent.
|
||||
/// * A `LatticeEffect` indicating whether the value should be
|
||||
/// considered a new value (`Changed`) or one *equivalent* (if not
|
||||
/// necessarily equal) to `Prev` (`Unchanged`).
|
||||
///
|
||||
/// `PrevEnv` and `CurrentEnv` can be used to query child values and path
|
||||
/// condition implications of `Prev` and `Current`, respectively.
|
||||
|
|
@ -130,17 +138,19 @@ public:
|
|||
///
|
||||
/// `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) {
|
||||
virtual std::optional<WidenResult> 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;
|
||||
case ComparisonResult::Unknown:
|
||||
return std::nullopt;
|
||||
case ComparisonResult::Same:
|
||||
return WidenResult{&Current, LatticeEffect::Unchanged};
|
||||
case ComparisonResult::Different:
|
||||
return WidenResult{&Current, LatticeEffect::Changed};
|
||||
}
|
||||
llvm_unreachable("all cases in switch covered");
|
||||
}
|
||||
|
|
@ -148,7 +158,28 @@ public:
|
|||
|
||||
/// Creates an environment that uses `DACtx` to store objects that encompass
|
||||
/// the state of a program.
|
||||
explicit Environment(DataflowAnalysisContext &DACtx);
|
||||
explicit Environment(DataflowAnalysisContext &DACtx)
|
||||
: DACtx(&DACtx),
|
||||
FlowConditionToken(DACtx.arena().makeFlowConditionToken()) {}
|
||||
|
||||
/// Creates an environment that uses `DACtx` to store objects that encompass
|
||||
/// the state of a program, with `S` as the statement to analyze.
|
||||
Environment(DataflowAnalysisContext &DACtx, Stmt &S) : Environment(DACtx) {
|
||||
InitialTargetStmt = &S;
|
||||
}
|
||||
|
||||
/// Creates an environment that uses `DACtx` to store objects that encompass
|
||||
/// the state of a program, with `FD` as the function to analyze.
|
||||
///
|
||||
/// Requirements:
|
||||
///
|
||||
/// The function must have a body, i.e.
|
||||
/// `FunctionDecl::doesThisDecalarationHaveABody()` must be true.
|
||||
Environment(DataflowAnalysisContext &DACtx, const FunctionDecl &FD)
|
||||
: Environment(DACtx, *FD.getBody()) {
|
||||
assert(FD.doesThisDeclarationHaveABody());
|
||||
InitialTargetFunc = &FD;
|
||||
}
|
||||
|
||||
// Copy-constructor is private, Environments should not be copied. See fork().
|
||||
Environment &operator=(const Environment &Other) = delete;
|
||||
|
|
@ -156,24 +187,11 @@ public:
|
|||
Environment(Environment &&Other) = default;
|
||||
Environment &operator=(Environment &&Other) = default;
|
||||
|
||||
/// Creates an environment that uses `DACtx` to store objects that encompass
|
||||
/// the state of a program.
|
||||
///
|
||||
/// If `DeclCtx` is a function, initializes the environment with symbolic
|
||||
/// representations of the function parameters.
|
||||
///
|
||||
/// If `DeclCtx` is a non-static member function, initializes the environment
|
||||
/// with a symbolic representation of the `this` pointee.
|
||||
Environment(DataflowAnalysisContext &DACtx, const DeclContext &DeclCtx);
|
||||
|
||||
/// Assigns storage locations and values to all parameters, captures, global
|
||||
/// variables, fields and functions referenced in the function currently being
|
||||
/// analyzed.
|
||||
/// variables, fields and functions referenced in the `Stmt` or `FunctionDecl`
|
||||
/// passed to the constructor.
|
||||
///
|
||||
/// Requirements:
|
||||
///
|
||||
/// The function must have a body, i.e.
|
||||
/// `FunctionDecl::doesThisDecalarationHaveABody()` must be true.
|
||||
/// If no `Stmt` or `FunctionDecl` was supplied, this function does nothing.
|
||||
void initialize();
|
||||
|
||||
/// Returns a new environment that is a copy of this one.
|
||||
|
|
@ -186,7 +204,7 @@ public:
|
|||
/// forked flow condition references the original).
|
||||
Environment fork() const;
|
||||
|
||||
/// 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
|
||||
/// storage location for the corresponding parameter in the callee.
|
||||
///
|
||||
|
|
@ -218,6 +236,14 @@ public:
|
|||
bool equivalentTo(const Environment &Other,
|
||||
Environment::ValueModel &Model) const;
|
||||
|
||||
/// How to treat expression state (`ExprToLoc` and `ExprToVal`) in a join.
|
||||
/// If the join happens within a full expression, expression state should be
|
||||
/// kept; otherwise, we can discard it.
|
||||
enum ExprJoinBehavior {
|
||||
DiscardExprState,
|
||||
KeepExprState,
|
||||
};
|
||||
|
||||
/// Joins two environments by taking the intersection of storage locations and
|
||||
/// values that are stored in them. Distinct values that are assigned to the
|
||||
/// same storage locations in `EnvA` and `EnvB` are merged using `Model`.
|
||||
|
|
@ -226,7 +252,23 @@ public:
|
|||
///
|
||||
/// `EnvA` and `EnvB` must use the same `DataflowAnalysisContext`.
|
||||
static Environment join(const Environment &EnvA, const Environment &EnvB,
|
||||
Environment::ValueModel &Model);
|
||||
Environment::ValueModel &Model,
|
||||
ExprJoinBehavior ExprBehavior);
|
||||
|
||||
/// Returns a value that approximates both `Val1` and `Val2`, or null if no
|
||||
/// such value can be produced.
|
||||
///
|
||||
/// `Env1` and `Env2` can be used to query child values and path condition
|
||||
/// implications of `Val1` and `Val2` respectively. The joined value will be
|
||||
/// produced in `JoinedEnv`.
|
||||
///
|
||||
/// Requirements:
|
||||
///
|
||||
/// `Val1` and `Val2` must model values of type `Type`.
|
||||
static Value *joinValues(QualType Ty, Value *Val1, const Environment &Env1,
|
||||
Value *Val2, const Environment &Env2,
|
||||
Environment &JoinedEnv,
|
||||
Environment::ValueModel &Model);
|
||||
|
||||
/// Widens the environment point-wise, using `PrevEnv` as needed to inform the
|
||||
/// approximation.
|
||||
|
|
@ -235,8 +277,8 @@ public:
|
|||
///
|
||||
/// `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);
|
||||
LatticeEffect widen(const Environment &PrevEnv,
|
||||
Environment::ValueModel &Model);
|
||||
|
||||
// FIXME: Rename `createOrGetStorageLocation` to `getOrCreateStorageLocation`,
|
||||
// `getStableStorageLocation`, or something more appropriate.
|
||||
|
|
@ -329,62 +371,56 @@ public:
|
|||
/// location of the result object to pass in `this`, even though prvalues are
|
||||
/// otherwise not associated with storage locations.
|
||||
///
|
||||
/// FIXME: Currently, this simply returns a stable storage location for `E`,
|
||||
/// but this doesn't do the right thing in scenarios like the following:
|
||||
/// ```
|
||||
/// MyClass c = some_condition()? MyClass(foo) : MyClass(bar);
|
||||
/// ```
|
||||
/// Here, `MyClass(foo)` and `MyClass(bar)` will have two different storage
|
||||
/// locations, when in fact their storage locations should be the same.
|
||||
/// Eventually, we want to propagate storage locations from result objects
|
||||
/// down to the prvalues that initialize them, similar to the way that this is
|
||||
/// done in Clang's CodeGen.
|
||||
///
|
||||
/// Requirements:
|
||||
/// `E` must be a prvalue of record type.
|
||||
RecordStorageLocation &
|
||||
getResultObjectLocation(const Expr &RecordPRValue) const;
|
||||
|
||||
/// Returns the return value of the current function. This can be null if:
|
||||
/// Returns the return value of the function currently being analyzed.
|
||||
/// This can be null if:
|
||||
/// - The function has a void return type
|
||||
/// - No return value could be determined for the function, for example
|
||||
/// because it calls a function without a body.
|
||||
///
|
||||
/// Requirements:
|
||||
/// The current function must have a non-reference return type.
|
||||
/// The current analysis target must be a function and must have a
|
||||
/// non-reference return type.
|
||||
Value *getReturnValue() const {
|
||||
assert(getCurrentFunc() != nullptr &&
|
||||
!getCurrentFunc()->getReturnType()->isReferenceType());
|
||||
return ReturnVal;
|
||||
}
|
||||
|
||||
/// Returns the storage location for the reference returned by the current
|
||||
/// function. This can be null if function doesn't return a single consistent
|
||||
/// reference.
|
||||
/// Returns the storage location for the reference returned by the function
|
||||
/// currently being analyzed. This can be null if the function doesn't return
|
||||
/// a single consistent reference.
|
||||
///
|
||||
/// Requirements:
|
||||
/// The current function must have a reference return type.
|
||||
/// The current analysis target must be a function and must have a reference
|
||||
/// return type.
|
||||
StorageLocation *getReturnStorageLocation() const {
|
||||
assert(getCurrentFunc() != nullptr &&
|
||||
getCurrentFunc()->getReturnType()->isReferenceType());
|
||||
return ReturnLoc;
|
||||
}
|
||||
|
||||
/// Sets the return value of the current function.
|
||||
/// Sets the return value of the function currently being analyzed.
|
||||
///
|
||||
/// Requirements:
|
||||
/// The current function must have a non-reference return type.
|
||||
/// The current analysis target must be a function and must have a
|
||||
/// non-reference return type.
|
||||
void setReturnValue(Value *Val) {
|
||||
assert(getCurrentFunc() != nullptr &&
|
||||
!getCurrentFunc()->getReturnType()->isReferenceType());
|
||||
ReturnVal = Val;
|
||||
}
|
||||
|
||||
/// Sets the storage location for the reference returned by the current
|
||||
/// function.
|
||||
/// Sets the storage location for the reference returned by the function
|
||||
/// currently being analyzed.
|
||||
///
|
||||
/// Requirements:
|
||||
/// The current function must have a reference return type.
|
||||
/// The current analysis target must be a function and must have a reference
|
||||
/// return type.
|
||||
void setReturnStorageLocation(StorageLocation *Loc) {
|
||||
assert(getCurrentFunc() != nullptr &&
|
||||
getCurrentFunc()->getReturnType()->isReferenceType());
|
||||
|
|
@ -402,20 +438,15 @@ public:
|
|||
/// storage locations and values for indirections until it finds a
|
||||
/// non-pointer/non-reference type.
|
||||
///
|
||||
/// If `Type` is a class, struct, or union type, creates values for all
|
||||
/// modeled fields (including synthetic fields) and calls `setValue()` to
|
||||
/// associate the `RecordValue` with its storage location
|
||||
/// (`RecordValue::getLoc()`).
|
||||
///
|
||||
/// If `Type` is one of the following types, this function will always return
|
||||
/// a non-null pointer:
|
||||
/// - `bool`
|
||||
/// - Any integer type
|
||||
/// - Any class, struct, or union type
|
||||
///
|
||||
/// Requirements:
|
||||
///
|
||||
/// `Type` must not be null.
|
||||
/// - `Type` must not be null.
|
||||
/// - `Type` must not be a reference type or record type.
|
||||
Value *createValue(QualType Type);
|
||||
|
||||
/// Creates an object (i.e. a storage location with an associated value) of
|
||||
|
|
@ -444,7 +475,23 @@ public:
|
|||
return createObjectInternal(&D, D.getType(), InitExpr);
|
||||
}
|
||||
|
||||
/// Initializes the fields (including synthetic fields) of `Loc` with values,
|
||||
/// unless values of the field type are not supported or we hit one of the
|
||||
/// limits at which we stop producing values.
|
||||
/// If a field already has a value, that value is preserved.
|
||||
/// If `Type` is provided, initializes only those fields that are modeled for
|
||||
/// `Type`; this is intended for use in cases where `Loc` is a derived type
|
||||
/// and we only want to initialize the fields of a base type.
|
||||
void initializeFieldsWithValues(RecordStorageLocation &Loc, QualType Type);
|
||||
void initializeFieldsWithValues(RecordStorageLocation &Loc) {
|
||||
initializeFieldsWithValues(Loc, Loc.getType());
|
||||
}
|
||||
|
||||
/// Assigns `Val` as the value of `Loc` in the environment.
|
||||
///
|
||||
/// Requirements:
|
||||
///
|
||||
/// `Loc` must not be a `RecordStorageLocation`.
|
||||
void setValue(const StorageLocation &Loc, Value &Val);
|
||||
|
||||
/// Clears any association between `Loc` and a value in the environment.
|
||||
|
|
@ -454,20 +501,24 @@ public:
|
|||
///
|
||||
/// Requirements:
|
||||
///
|
||||
/// - `E` must be a prvalue
|
||||
/// - If `Val` is a `RecordValue`, its `RecordStorageLocation` must be
|
||||
/// `getResultObjectLocation(E)`. An exception to this is if `E` is an
|
||||
/// expression that originally creates a `RecordValue` (such as a
|
||||
/// `CXXConstructExpr` or `CallExpr`), as these establish the location of
|
||||
/// the result object in the first place.
|
||||
/// - `E` must be a prvalue.
|
||||
/// - `E` must not have record type.
|
||||
void setValue(const Expr &E, Value &Val);
|
||||
|
||||
/// Returns the value assigned to `Loc` in the environment or null if `Loc`
|
||||
/// isn't assigned a value in the environment.
|
||||
///
|
||||
/// Requirements:
|
||||
///
|
||||
/// `Loc` must not be a `RecordStorageLocation`.
|
||||
Value *getValue(const StorageLocation &Loc) const;
|
||||
|
||||
/// Equivalent to `getValue(getStorageLocation(D))` if `D` is assigned a
|
||||
/// storage location in the environment, otherwise returns null.
|
||||
///
|
||||
/// Requirements:
|
||||
///
|
||||
/// `D` must not have record type.
|
||||
Value *getValue(const ValueDecl &D) const;
|
||||
|
||||
/// Equivalent to `getValue(getStorageLocation(E, SP))` if `E` is assigned a
|
||||
|
|
@ -606,23 +657,21 @@ public:
|
|||
/// (or the flow condition is overly constraining) or if the solver times out.
|
||||
bool allows(const Formula &) const;
|
||||
|
||||
/// Returns the `DeclContext` of the block being analysed, if any. Otherwise,
|
||||
/// returns null.
|
||||
const DeclContext *getDeclCtx() const { return CallStack.back(); }
|
||||
|
||||
/// Returns the function currently being analyzed, or null if the code being
|
||||
/// analyzed isn't part of a function.
|
||||
const FunctionDecl *getCurrentFunc() const {
|
||||
return dyn_cast<FunctionDecl>(getDeclCtx());
|
||||
return CallStack.empty() ? InitialTargetFunc : CallStack.back();
|
||||
}
|
||||
|
||||
/// Returns the size of the call stack.
|
||||
/// Returns the size of the call stack, not counting the initial analysis
|
||||
/// target.
|
||||
size_t callStackSize() const { return CallStack.size(); }
|
||||
|
||||
/// 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;
|
||||
/// `Callee` (i.e. if `pushCall` can be used).
|
||||
/// Recursion is not allowed. `MaxDepth` is the maximum size of the call stack
|
||||
/// (i.e. the maximum value that `callStackSize()` may assume after the call).
|
||||
bool canDescend(unsigned MaxDepth, const FunctionDecl *Callee) const;
|
||||
|
||||
/// Returns the `DataflowAnalysisContext` used by the environment.
|
||||
DataflowAnalysisContext &getDataflowAnalysisContext() const { return *DACtx; }
|
||||
|
|
@ -633,6 +682,9 @@ public:
|
|||
LLVM_DUMP_METHOD void dump(raw_ostream &OS) const;
|
||||
|
||||
private:
|
||||
using PrValueToResultObject =
|
||||
llvm::DenseMap<const Expr *, RecordStorageLocation *>;
|
||||
|
||||
// The copy-constructor is for use in fork() only.
|
||||
Environment(const Environment &) = default;
|
||||
|
||||
|
|
@ -659,6 +711,16 @@ private:
|
|||
llvm::DenseSet<QualType> &Visited,
|
||||
int Depth, int &CreatedValuesCount);
|
||||
|
||||
/// Initializes the fields (including synthetic fields) of `Loc` with values,
|
||||
/// unless values of the field type are not supported or we hit one of the
|
||||
/// limits at which we stop producing values (controlled by `Visited`,
|
||||
/// `Depth`, and `CreatedValuesCount`). If `Type` is different from
|
||||
/// `Loc.getType()`, initializes only those fields that are modeled for
|
||||
/// `Type`.
|
||||
void initializeFieldsWithValues(RecordStorageLocation &Loc, QualType Type,
|
||||
llvm::DenseSet<QualType> &Visited, int Depth,
|
||||
int &CreatedValuesCount);
|
||||
|
||||
/// Shared implementation of `createObject()` overloads.
|
||||
/// `D` and `InitExpr` may be null.
|
||||
StorageLocation &createObjectInternal(const ValueDecl *D, QualType Ty,
|
||||
|
|
@ -671,27 +733,64 @@ private:
|
|||
ArrayRef<const Expr *> Args);
|
||||
|
||||
/// Assigns storage locations and values to all global variables, fields
|
||||
/// and functions referenced in `FuncDecl`. `FuncDecl` must have a body.
|
||||
void initFieldsGlobalsAndFuncs(const FunctionDecl *FuncDecl);
|
||||
/// and functions in `Referenced`.
|
||||
void initFieldsGlobalsAndFuncs(const ReferencedDecls &Referenced);
|
||||
|
||||
static PrValueToResultObject
|
||||
buildResultObjectMap(DataflowAnalysisContext *DACtx,
|
||||
const FunctionDecl *FuncDecl,
|
||||
RecordStorageLocation *ThisPointeeLoc,
|
||||
RecordStorageLocation *LocForRecordReturnVal);
|
||||
|
||||
static PrValueToResultObject
|
||||
buildResultObjectMap(DataflowAnalysisContext *DACtx, Stmt *S,
|
||||
RecordStorageLocation *ThisPointeeLoc,
|
||||
RecordStorageLocation *LocForRecordReturnVal);
|
||||
|
||||
// `DACtx` is not null and not owned by this object.
|
||||
DataflowAnalysisContext *DACtx;
|
||||
|
||||
// FIXME: move the fields `CallStack`, `ReturnVal`, `ReturnLoc` and
|
||||
// `ThisPointeeLoc` into a separate call-context object, shared between
|
||||
// environments in the same call.
|
||||
// FIXME: move the fields `CallStack`, `ResultObjectMap`, `ReturnVal`,
|
||||
// `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;
|
||||
// The stack of functions called from the initial analysis target.
|
||||
std::vector<const FunctionDecl *> CallStack;
|
||||
|
||||
// Value returned by the function (if it has non-reference return type).
|
||||
// Initial function to analyze, if a function was passed to the constructor.
|
||||
// Null otherwise.
|
||||
const FunctionDecl *InitialTargetFunc = nullptr;
|
||||
// Top-level statement of the initial analysis target.
|
||||
// If a function was passed to the constructor, this is its body.
|
||||
// If a statement was passed to the constructor, this is that statement.
|
||||
// Null if no analysis target was passed to the constructor.
|
||||
Stmt *InitialTargetStmt = nullptr;
|
||||
|
||||
// Maps from prvalues of record type to their result objects. Shared between
|
||||
// all environments for the same analysis target.
|
||||
// FIXME: It's somewhat unsatisfactory that we have to use a `shared_ptr`
|
||||
// here, though the cost is acceptable: The overhead of a `shared_ptr` is
|
||||
// incurred when it is copied, and this happens only relatively rarely (when
|
||||
// we fork the environment). The need for a `shared_ptr` will go away once we
|
||||
// introduce a shared call-context object (see above).
|
||||
std::shared_ptr<PrValueToResultObject> ResultObjectMap;
|
||||
|
||||
// The following three member variables handle various different types of
|
||||
// return values when the current analysis target is a function.
|
||||
// - If the return type is not a reference and not a record: Value returned
|
||||
// by the function.
|
||||
Value *ReturnVal = nullptr;
|
||||
// Storage location of the reference returned by the function (if it has
|
||||
// reference return type).
|
||||
// - If the return type is a reference: Storage location of the reference
|
||||
// returned by the function.
|
||||
StorageLocation *ReturnLoc = nullptr;
|
||||
// - If the return type is a record or the function being analyzed is a
|
||||
// constructor: Storage location into which the return value should be
|
||||
// constructed.
|
||||
RecordStorageLocation *LocForRecordReturnVal = 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.
|
||||
// analysis target is not a method.
|
||||
RecordStorageLocation *ThisPointeeLoc = nullptr;
|
||||
|
||||
// Maps from declarations and glvalue expression to storage locations that are
|
||||
|
|
@ -723,16 +822,6 @@ RecordStorageLocation *getImplicitObjectLocation(const CXXMemberCallExpr &MCE,
|
|||
RecordStorageLocation *getBaseObjectLocation(const MemberExpr &ME,
|
||||
const Environment &Env);
|
||||
|
||||
/// Returns the fields of `RD` that are initialized by an `InitListExpr`, in the
|
||||
/// order in which they appear in `InitListExpr::inits()`.
|
||||
std::vector<FieldDecl *> getFieldsForInitListExpr(const RecordDecl *RD);
|
||||
|
||||
/// Associates a new `RecordValue` with `Loc` and returns the new value.
|
||||
RecordValue &refreshRecordValue(RecordStorageLocation &Loc, Environment &Env);
|
||||
|
||||
/// Associates a new `RecordValue` with `Expr` and returns the new value.
|
||||
RecordValue &refreshRecordValue(const Expr &Expr, Environment &Env);
|
||||
|
||||
} // namespace dataflow
|
||||
} // namespace clang
|
||||
|
||||
|
|
|
|||
|
|
@ -17,13 +17,13 @@
|
|||
namespace clang {
|
||||
namespace dataflow {
|
||||
|
||||
/// Effect indicating whether a lattice join operation resulted in a new value.
|
||||
// FIXME: Rename to `LatticeEffect` since `widen` uses it as well, and we are
|
||||
// likely removing it from `join`.
|
||||
enum class LatticeJoinEffect {
|
||||
/// Effect indicating whether a lattice operation resulted in a new value.
|
||||
enum class LatticeEffect {
|
||||
Unchanged,
|
||||
Changed,
|
||||
};
|
||||
// DEPRECATED. Use `LatticeEffect`.
|
||||
using LatticeJoinEffect = LatticeEffect;
|
||||
|
||||
} // namespace dataflow
|
||||
} // namespace clang
|
||||
|
|
|
|||
|
|
@ -45,12 +45,12 @@ class DataflowValues {
|
|||
//===--------------------------------------------------------------------===//
|
||||
|
||||
public:
|
||||
typedef typename ValueTypes::ValTy ValTy;
|
||||
typedef typename ValueTypes::AnalysisDataTy AnalysisDataTy;
|
||||
typedef _AnalysisDirTag AnalysisDirTag;
|
||||
typedef llvm::DenseMap<ProgramPoint, ValTy> EdgeDataMapTy;
|
||||
typedef llvm::DenseMap<const CFGBlock*, ValTy> BlockDataMapTy;
|
||||
typedef llvm::DenseMap<const Stmt*, ValTy> StmtDataMapTy;
|
||||
using ValTy = typename ValueTypes::ValTy;
|
||||
using AnalysisDataTy = typename ValueTypes::AnalysisDataTy;
|
||||
using AnalysisDirTag = _AnalysisDirTag;
|
||||
using EdgeDataMapTy = llvm::DenseMap<ProgramPoint, ValTy>;
|
||||
using BlockDataMapTy = llvm::DenseMap<const CFGBlock *, ValTy>;
|
||||
using StmtDataMapTy = llvm::DenseMap<const Stmt *, ValTy>;
|
||||
|
||||
//===--------------------------------------------------------------------===//
|
||||
// Predicates.
|
||||
|
|
|
|||
|
|
@ -15,7 +15,7 @@
|
|||
|
||||
namespace clang::dataflow {
|
||||
// Forward declarations so we can use Logger anywhere in the framework.
|
||||
class ControlFlowContext;
|
||||
class AdornedCFG;
|
||||
class TypeErasedDataflowAnalysis;
|
||||
struct TypeErasedDataflowAnalysisState;
|
||||
|
||||
|
|
@ -40,8 +40,8 @@ public:
|
|||
|
||||
/// Called by the framework as we start analyzing a new function or statement.
|
||||
/// Forms a pair with endAnalysis().
|
||||
virtual void beginAnalysis(const ControlFlowContext &,
|
||||
TypeErasedDataflowAnalysis &) {}
|
||||
virtual void beginAnalysis(const AdornedCFG &, TypeErasedDataflowAnalysis &) {
|
||||
}
|
||||
virtual void endAnalysis() {}
|
||||
|
||||
// At any time during the analysis, we're computing the state for some target
|
||||
|
|
|
|||
|
|
@ -31,7 +31,11 @@ namespace dataflow {
|
|||
///
|
||||
/// Requirements:
|
||||
///
|
||||
/// `Src` and `Dst` must have the same canonical unqualified type.
|
||||
/// Either:
|
||||
/// - `Src` and `Dest` must have the same canonical unqualified type, or
|
||||
/// - The type of `Src` must be derived from `Dest`, or
|
||||
/// - The type of `Dest` must be derived from `Src` (in this case, any fields
|
||||
/// that are only present in `Dest` are not overwritten).
|
||||
void copyRecord(RecordStorageLocation &Src, RecordStorageLocation &Dst,
|
||||
Environment &Env);
|
||||
|
||||
|
|
|
|||
|
|
@ -87,6 +87,9 @@ public:
|
|||
///
|
||||
/// All elements in `Vals` must not be null.
|
||||
virtual Result solve(llvm::ArrayRef<const Formula *> Vals) = 0;
|
||||
|
||||
// Did the solver reach its resource limit?
|
||||
virtual bool reachedLimit() const = 0;
|
||||
};
|
||||
|
||||
llvm::raw_ostream &operator<<(llvm::raw_ostream &, const Solver::Result &);
|
||||
|
|
|
|||
|
|
@ -29,12 +29,12 @@ public:
|
|||
// `CurState` is the pending state currently associated with this block. These
|
||||
// are supplied separately as the pending state for the current block may not
|
||||
// yet be represented in `BlockToState`.
|
||||
StmtToEnvMap(const ControlFlowContext &CFCtx,
|
||||
StmtToEnvMap(const AdornedCFG &ACFG,
|
||||
llvm::ArrayRef<std::optional<TypeErasedDataflowAnalysisState>>
|
||||
BlockToState,
|
||||
unsigned CurBlockID,
|
||||
const TypeErasedDataflowAnalysisState &CurState)
|
||||
: CFCtx(CFCtx), BlockToState(BlockToState), CurBlockID(CurBlockID),
|
||||
: ACFG(ACFG), BlockToState(BlockToState), CurBlockID(CurBlockID),
|
||||
CurState(CurState) {}
|
||||
|
||||
/// Returns the environment of the basic block that contains `S`.
|
||||
|
|
@ -42,7 +42,7 @@ public:
|
|||
const Environment *getEnvironment(const Stmt &S) const;
|
||||
|
||||
private:
|
||||
const ControlFlowContext &CFCtx;
|
||||
const AdornedCFG &ACFG;
|
||||
llvm::ArrayRef<std::optional<TypeErasedDataflowAnalysisState>> BlockToState;
|
||||
unsigned CurBlockID;
|
||||
const TypeErasedDataflowAnalysisState &CurState;
|
||||
|
|
@ -53,7 +53,8 @@ private:
|
|||
/// Requirements:
|
||||
///
|
||||
/// `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,
|
||||
Environment::ValueModel &Model);
|
||||
|
||||
} // namespace dataflow
|
||||
} // namespace clang
|
||||
|
|
|
|||
|
|
@ -21,7 +21,7 @@
|
|||
#include "clang/AST/ASTContext.h"
|
||||
#include "clang/AST/Stmt.h"
|
||||
#include "clang/Analysis/CFG.h"
|
||||
#include "clang/Analysis/FlowSensitive/ControlFlowContext.h"
|
||||
#include "clang/Analysis/FlowSensitive/AdornedCFG.h"
|
||||
#include "clang/Analysis/FlowSensitive/DataflowAnalysisContext.h"
|
||||
#include "clang/Analysis/FlowSensitive/DataflowEnvironment.h"
|
||||
#include "clang/Analysis/FlowSensitive/DataflowLattice.h"
|
||||
|
|
@ -132,12 +132,25 @@ struct TypeErasedDataflowAnalysisState {
|
|||
}
|
||||
};
|
||||
|
||||
/// A callback to be called with the state before or after visiting a CFG
|
||||
/// element.
|
||||
using CFGEltCallbackTypeErased = std::function<void(
|
||||
const CFGElement &, const TypeErasedDataflowAnalysisState &)>;
|
||||
|
||||
/// A pair of callbacks to be called with the state before and after visiting a
|
||||
/// CFG element.
|
||||
/// Either or both of the callbacks may be null.
|
||||
struct CFGEltCallbacksTypeErased {
|
||||
CFGEltCallbackTypeErased Before;
|
||||
CFGEltCallbackTypeErased After;
|
||||
};
|
||||
|
||||
/// Performs dataflow analysis and returns a mapping from basic block IDs to
|
||||
/// dataflow analysis states that model the respective basic blocks. Indices of
|
||||
/// the returned vector correspond to basic block IDs. Returns an error if the
|
||||
/// dataflow analysis cannot be performed successfully. Otherwise, calls
|
||||
/// `PostVisitCFG` on each CFG element with the final analysis results at that
|
||||
/// program point.
|
||||
/// `PostAnalysisCallbacks` on each CFG element with the final analysis results
|
||||
/// before and after that program point.
|
||||
///
|
||||
/// `MaxBlockVisits` caps the number of block visits during analysis. It doesn't
|
||||
/// distinguish between repeat visits to the same block and visits to distinct
|
||||
|
|
@ -146,11 +159,9 @@ struct TypeErasedDataflowAnalysisState {
|
|||
/// from converging.
|
||||
llvm::Expected<std::vector<std::optional<TypeErasedDataflowAnalysisState>>>
|
||||
runTypeErasedDataflowAnalysis(
|
||||
const ControlFlowContext &CFCtx, TypeErasedDataflowAnalysis &Analysis,
|
||||
const AdornedCFG &ACFG, TypeErasedDataflowAnalysis &Analysis,
|
||||
const Environment &InitEnv,
|
||||
std::function<void(const CFGElement &,
|
||||
const TypeErasedDataflowAnalysisState &)>
|
||||
PostVisitCFG,
|
||||
const CFGEltCallbacksTypeErased &PostAnalysisCallbacks,
|
||||
std::int32_t MaxBlockVisits);
|
||||
|
||||
} // namespace dataflow
|
||||
|
|
|
|||
|
|
@ -35,7 +35,6 @@ public:
|
|||
enum class Kind {
|
||||
Integer,
|
||||
Pointer,
|
||||
Record,
|
||||
|
||||
// TODO: Top values should not be need to be type-specific.
|
||||
TopBool,
|
||||
|
|
@ -67,7 +66,6 @@ public:
|
|||
/// Properties may not be set on `RecordValue`s; use synthetic fields instead
|
||||
/// (for details, see documentation for `RecordStorageLocation`).
|
||||
void setProperty(llvm::StringRef Name, Value &Val) {
|
||||
assert(getKind() != Kind::Record);
|
||||
Properties.insert_or_assign(Name, &Val);
|
||||
}
|
||||
|
||||
|
|
@ -184,45 +182,6 @@ private:
|
|||
StorageLocation &PointeeLoc;
|
||||
};
|
||||
|
||||
/// Models a value of `struct` or `class` type.
|
||||
/// In C++, prvalues of class type serve only a limited purpose: They can only
|
||||
/// be used to initialize a result object. It is not possible to access member
|
||||
/// variables or call member functions on a prvalue of class type.
|
||||
/// Correspondingly, `RecordValue` also serves only a limited purpose: It
|
||||
/// conveys a prvalue of class type from the place where the object is
|
||||
/// constructed to the result object that it initializes.
|
||||
///
|
||||
/// When creating a prvalue of class type, we already need a storage location
|
||||
/// for `this`, even though prvalues are otherwise not associated with storage
|
||||
/// locations. `RecordValue` is therefore essentially a wrapper for a storage
|
||||
/// location, which is then used to set the storage location for the result
|
||||
/// object when we process the AST node for that result object.
|
||||
///
|
||||
/// For example:
|
||||
/// MyStruct S = MyStruct(3);
|
||||
///
|
||||
/// In this example, `MyStruct(3) is a prvalue, which is modeled as a
|
||||
/// `RecordValue` that wraps a `RecordStorageLocation`. This
|
||||
/// `RecordStorageLocation` is then used as the storage location for `S`.
|
||||
///
|
||||
/// Over time, we may eliminate `RecordValue` entirely. See also the discussion
|
||||
/// here: https://reviews.llvm.org/D155204#inline-1503204
|
||||
class RecordValue final : public Value {
|
||||
public:
|
||||
explicit RecordValue(RecordStorageLocation &Loc)
|
||||
: Value(Kind::Record), Loc(Loc) {}
|
||||
|
||||
static bool classof(const Value *Val) {
|
||||
return Val->getKind() == Kind::Record;
|
||||
}
|
||||
|
||||
/// Returns the storage location that this `RecordValue` is associated with.
|
||||
RecordStorageLocation &getLoc() const { return Loc; }
|
||||
|
||||
private:
|
||||
RecordStorageLocation &Loc;
|
||||
};
|
||||
|
||||
raw_ostream &operator<<(raw_ostream &OS, const Value &Val);
|
||||
|
||||
} // namespace dataflow
|
||||
|
|
|
|||
|
|
@ -17,16 +17,17 @@
|
|||
#include "clang/Analysis/FlowSensitive/Formula.h"
|
||||
#include "clang/Analysis/FlowSensitive/Solver.h"
|
||||
#include "llvm/ADT/ArrayRef.h"
|
||||
#include <limits>
|
||||
|
||||
namespace clang {
|
||||
namespace dataflow {
|
||||
|
||||
/// A SAT solver that is an implementation of Algorithm D from Knuth's The Art
|
||||
/// of Computer Programming Volume 4: Satisfiability, Fascicle 6. It is based on
|
||||
/// the Davis-Putnam-Logemann-Loveland (DPLL) algorithm, keeps references to a
|
||||
/// single "watched" literal per clause, and uses a set of "active" variables
|
||||
/// the Davis-Putnam-Logemann-Loveland (DPLL) algorithm [1], keeps references to
|
||||
/// a single "watched" literal per clause, and uses a set of "active" variables
|
||||
/// for unit propagation.
|
||||
//
|
||||
// [1] https://en.wikipedia.org/wiki/DPLL_algorithm
|
||||
class WatchedLiteralsSolver : public Solver {
|
||||
// Count of the iterations of the main loop of the solver. This spans *all*
|
||||
// calls to the underlying solver across the life of this object. It is
|
||||
|
|
@ -48,8 +49,7 @@ public:
|
|||
|
||||
Result solve(llvm::ArrayRef<const Formula *> Vals) override;
|
||||
|
||||
// The solver reached its maximum number of iterations.
|
||||
bool reachedLimit() const { return MaxIterations == 0; }
|
||||
bool reachedLimit() const override { return MaxIterations == 0; }
|
||||
};
|
||||
|
||||
} // namespace dataflow
|
||||
|
|
|
|||
|
|
@ -780,6 +780,9 @@ class PathDiagnostic : public llvm::FoldingSetNode {
|
|||
PathDiagnosticLocation UniqueingLoc;
|
||||
const Decl *UniqueingDecl;
|
||||
|
||||
/// The top-level entry point from which this issue was discovered.
|
||||
const Decl *AnalysisEntryPoint = nullptr;
|
||||
|
||||
/// Lines executed in the path.
|
||||
std::unique_ptr<FilesToLineNumsMap> ExecutedLines;
|
||||
|
||||
|
|
@ -788,7 +791,7 @@ public:
|
|||
PathDiagnostic(StringRef CheckerName, const Decl *DeclWithIssue,
|
||||
StringRef bugtype, StringRef verboseDesc, StringRef shortDesc,
|
||||
StringRef category, PathDiagnosticLocation LocationToUnique,
|
||||
const Decl *DeclToUnique,
|
||||
const Decl *DeclToUnique, const Decl *AnalysisEntryPoint,
|
||||
std::unique_ptr<FilesToLineNumsMap> ExecutedLines);
|
||||
~PathDiagnostic();
|
||||
|
||||
|
|
@ -852,6 +855,9 @@ public:
|
|||
return *ExecutedLines;
|
||||
}
|
||||
|
||||
/// Get the top-level entry point from which this issue was discovered.
|
||||
const Decl *getAnalysisEntryPoint() const { return AnalysisEntryPoint; }
|
||||
|
||||
/// Return the semantic context where an issue occurred. If the
|
||||
/// issue occurs along a path, this represents the "central" area
|
||||
/// where the bug manifests.
|
||||
|
|
|
|||
|
|
@ -15,10 +15,10 @@ namespace clang {
|
|||
|
||||
template <typename... IdentifierInfos>
|
||||
static inline Selector getKeywordSelector(ASTContext &Ctx,
|
||||
IdentifierInfos *... IIs) {
|
||||
const IdentifierInfos *...IIs) {
|
||||
static_assert(sizeof...(IdentifierInfos) > 0,
|
||||
"keyword selectors must have at least one argument");
|
||||
SmallVector<IdentifierInfo *, 10> II({&Ctx.Idents.get(IIs)...});
|
||||
SmallVector<const IdentifierInfo *, 10> II({&Ctx.Idents.get(IIs)...});
|
||||
|
||||
return Ctx.Selectors.getSelector(II.size(), &II[0]);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,21 @@
|
|||
//===-- AMDGPUTypes.def - Metadata about AMDGPU types -----------*- 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 various AMDGPU builtin types.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef AMDGPU_OPAQUE_PTR_TYPE
|
||||
#define AMDGPU_OPAQUE_PTR_TYPE(Name, MangledName, AS, Width, Align, Id, SingletonId) \
|
||||
AMDGPU_TYPE(Name, Id, SingletonId)
|
||||
#endif
|
||||
|
||||
AMDGPU_OPAQUE_PTR_TYPE("__amdgpu_buffer_rsrc_t", "__amdgpu_buffer_rsrc_t", 8, 128, 128, AMDGPUBufferRsrc, AMDGPUBufferRsrcTy)
|
||||
|
||||
#undef AMDGPU_TYPE
|
||||
#undef AMDGPU_OPAQUE_PTR_TYPE
|
||||
|
|
@ -0,0 +1,52 @@
|
|||
//===- ASTSourceDescriptor.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
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
/// \file
|
||||
/// Defines the clang::ASTSourceDescriptor class, which abstracts clang modules
|
||||
/// and precompiled header files
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef LLVM_CLANG_BASIC_ASTSOURCEDESCRIPTOR_H
|
||||
#define LLVM_CLANG_BASIC_ASTSOURCEDESCRIPTOR_H
|
||||
|
||||
#include "clang/Basic/Module.h"
|
||||
#include "llvm/ADT/StringRef.h"
|
||||
#include <string>
|
||||
#include <utility>
|
||||
|
||||
namespace clang {
|
||||
|
||||
/// Abstracts clang modules and precompiled header files and holds
|
||||
/// everything needed to generate debug info for an imported module
|
||||
/// or PCH.
|
||||
class ASTSourceDescriptor {
|
||||
StringRef PCHModuleName;
|
||||
StringRef Path;
|
||||
StringRef ASTFile;
|
||||
ASTFileSignature Signature;
|
||||
Module *ClangModule = nullptr;
|
||||
|
||||
public:
|
||||
ASTSourceDescriptor() = default;
|
||||
ASTSourceDescriptor(StringRef Name, StringRef Path, StringRef ASTFile,
|
||||
ASTFileSignature Signature)
|
||||
: PCHModuleName(std::move(Name)), Path(std::move(Path)),
|
||||
ASTFile(std::move(ASTFile)), Signature(Signature) {}
|
||||
ASTSourceDescriptor(Module &M);
|
||||
|
||||
std::string getModuleName() const;
|
||||
StringRef getPath() const { return Path; }
|
||||
StringRef getASTFile() const { return ASTFile; }
|
||||
ASTFileSignature getSignature() const { return Signature; }
|
||||
Module *getModuleOrNull() const { return ClangModule; }
|
||||
};
|
||||
|
||||
} // namespace clang
|
||||
|
||||
#endif // LLVM_CLANG_BASIC_ASTSOURCEDESCRIPTOR_H
|
||||
|
|
@ -20,6 +20,7 @@
|
|||
#include "clang/Basic/DiagnosticCrossTU.h"
|
||||
#include "clang/Basic/DiagnosticDriver.h"
|
||||
#include "clang/Basic/DiagnosticFrontend.h"
|
||||
#include "clang/Basic/DiagnosticInstallAPI.h"
|
||||
#include "clang/Basic/DiagnosticLex.h"
|
||||
#include "clang/Basic/DiagnosticParse.h"
|
||||
#include "clang/Basic/DiagnosticSema.h"
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load diff
|
|
@ -1593,6 +1593,11 @@ replacement=\ *string-literal*
|
|||
a warning about use of a deprecated declaration. The Fix-It will replace
|
||||
the deprecated declaration with the new declaration specified.
|
||||
|
||||
environment=\ *identifier*
|
||||
Target environment in which this declaration is available. If present,
|
||||
the availability attribute applies only to targets with the same platform
|
||||
and environment. The parameter is currently supported only in HLSL.
|
||||
|
||||
Multiple availability attributes can be placed on a declaration, which may
|
||||
correspond to different platforms. For most platforms, the availability
|
||||
attribute with the platform corresponding to the target platform will be used;
|
||||
|
|
@ -1604,27 +1609,40 @@ specifies availability for the current target platform, the availability
|
|||
attributes are ignored. Supported platforms are:
|
||||
|
||||
``ios``
|
||||
Apple's iOS operating system. The minimum deployment target is specified by
|
||||
the ``-mios-version-min=*version*`` or ``-miphoneos-version-min=*version*``
|
||||
command-line arguments.
|
||||
Apple's iOS operating system. The minimum deployment target is specified
|
||||
as part of the ``-target *arch*-apple-ios*version*`` command line argument.
|
||||
Alternatively, it can be specified by the ``-mtargetos=ios*version*``
|
||||
command-line argument.
|
||||
|
||||
``macos``
|
||||
Apple's macOS operating system. The minimum deployment target is
|
||||
specified by the ``-mmacosx-version-min=*version*`` command-line argument.
|
||||
``macosx`` is supported for backward-compatibility reasons, but it is
|
||||
deprecated.
|
||||
Apple's macOS operating system. The minimum deployment target is specified
|
||||
as part of the ``-target *arch*-apple-macos*version*`` command line argument.
|
||||
Alternatively, it can be specified by the ``-mtargetos=macos*version*``
|
||||
command-line argument. ``macosx`` is supported for
|
||||
backward-compatibility reasons, but it is deprecated.
|
||||
|
||||
``tvos``
|
||||
Apple's tvOS operating system. The minimum deployment target is specified by
|
||||
the ``-mtvos-version-min=*version*`` command-line argument.
|
||||
Apple's tvOS operating system. The minimum deployment target is specified
|
||||
as part of the ``-target *arch*-apple-tvos*version*`` command line argument.
|
||||
Alternatively, it can be specified by the ``-mtargetos=tvos*version*``
|
||||
command-line argument.
|
||||
|
||||
``watchos``
|
||||
Apple's watchOS operating system. The minimum deployment target is specified by
|
||||
the ``-mwatchos-version-min=*version*`` command-line argument.
|
||||
Apple's watchOS operating system. The minimum deployment target is specified
|
||||
as part of the ``-target *arch*-apple-watchos*version*`` command line argument.
|
||||
Alternatively, it can be specified by the ``-mtargetos=watchos*version*``
|
||||
command-line argument.
|
||||
|
||||
``visionos``
|
||||
Apple's visionOS operating system. The minimum deployment target is specified
|
||||
as part of the ``-target *arch*-apple-visionos*version*`` command line argument.
|
||||
Alternatively, it can be specified by the ``-mtargetos=visionos*version*``
|
||||
command-line argument.
|
||||
|
||||
``driverkit``
|
||||
Apple's DriverKit userspace kernel extensions. The minimum deployment target
|
||||
is specified as part of the triple.
|
||||
is specified as part of the ``-target *arch*-apple-driverkit*version*``
|
||||
command line argument.
|
||||
|
||||
A declaration can typically be used even when deploying back to a platform
|
||||
version prior to when the declaration was introduced. When this happens, the
|
||||
|
|
@ -1996,6 +2014,31 @@ Here is an example:
|
|||
}];
|
||||
}
|
||||
|
||||
def CXXAssumeDocs : Documentation {
|
||||
let Category = DocCatStmt;
|
||||
let Heading = "assume";
|
||||
let Content = [{
|
||||
The ``assume`` attribute is used to indicate to the optimizer that a
|
||||
certain condition is assumed to be true at a certain point in the
|
||||
program. If this condition is violated at runtime, the behavior is
|
||||
undefined. ``assume`` can only be applied to a null statement.
|
||||
|
||||
Different optimisers are likely to react differently to the presence of
|
||||
this attribute; in some cases, adding ``assume`` may affect performance
|
||||
negatively. It should be used with parsimony and care.
|
||||
|
||||
Example:
|
||||
|
||||
.. code-block:: c++
|
||||
|
||||
int f(int x, int y) {
|
||||
[[assume(x == 27)]];
|
||||
[[assume(x == y)]];
|
||||
return y + 1; // May be optimised to `return 28`.
|
||||
}
|
||||
}];
|
||||
}
|
||||
|
||||
def LikelihoodDocs : Documentation {
|
||||
let Category = DocCatStmt;
|
||||
let Heading = "likely and unlikely";
|
||||
|
|
@ -2486,6 +2529,9 @@ Example "subtarget features" from the x86 backend include: "mmx", "sse", "sse4.2
|
|||
"avx", "xop" and largely correspond to the machine specific options handled by
|
||||
the front end.
|
||||
|
||||
Note that this attribute does not apply transitively to nested functions such
|
||||
as blocks or C++ lambdas.
|
||||
|
||||
Additionally, this attribute supports function multiversioning for ELF based
|
||||
x86/x86-64 targets, which can be used to create multiple implementations of the
|
||||
same function that will be resolved at runtime based on the priority of their
|
||||
|
|
@ -2517,6 +2563,14 @@ function it instructs compiler to emit multiple function versions based on
|
|||
priority and target features availability. One of the versions is always
|
||||
( implicitly or explicitly ) the ``default`` (fallback). Attribute strings can
|
||||
contain dependent features names joined by the "+" sign.
|
||||
|
||||
For targets that support the GNU indirect function (IFUNC) feature, dispatch
|
||||
is performed by emitting an indirect function that is resolved to the appropriate
|
||||
target clone at load time. The indirect function is given the name the
|
||||
multiversioned function would have if it had been declared without the attribute.
|
||||
For backward compatibility with earlier Clang releases, a function alias with an
|
||||
``.ifunc`` suffix is also emitted. The ``.ifunc`` suffixed symbol is a deprecated
|
||||
feature and support for it may be removed in the future.
|
||||
}];
|
||||
}
|
||||
|
||||
|
|
@ -2705,6 +2759,33 @@ An error will be given if:
|
|||
}];
|
||||
}
|
||||
|
||||
def AMDGPUMaxNumWorkGroupsDocs : Documentation {
|
||||
let Category = DocCatAMDGPUAttributes;
|
||||
let Content = [{
|
||||
This attribute specifies the max number of work groups when the kernel
|
||||
is dispatched.
|
||||
|
||||
Clang supports the
|
||||
``__attribute__((amdgpu_max_num_work_groups(<x>, <y>, <z>)))`` or
|
||||
``[[clang::amdgpu_max_num_work_groups(<x>, <y>, <z>)]]`` attribute for the
|
||||
AMDGPU target. This attribute may be attached to HIP or OpenCL kernel function
|
||||
definitions and is an optimization hint.
|
||||
|
||||
The ``<x>`` parameter specifies the maximum number of work groups in the x dimension.
|
||||
Similarly ``<y>`` and ``<z>`` are for the y and z dimensions respectively.
|
||||
Each of the three values must be greater than 0 when provided. The ``<x>`` parameter
|
||||
is required, while ``<y>`` and ``<z>`` are optional with default value of 1.
|
||||
|
||||
If specified, the AMDGPU target backend might be able to produce better machine
|
||||
code.
|
||||
|
||||
An error will be given if:
|
||||
- Specified values violate subtarget specifications;
|
||||
- Specified values are not compatible with values provided through other
|
||||
attributes.
|
||||
}];
|
||||
}
|
||||
|
||||
def DocCatCallingConvs : DocumentationCategory<"Calling Conventions"> {
|
||||
let Content = [{
|
||||
Clang supports several different calling conventions, depending on the target
|
||||
|
|
@ -3706,6 +3787,12 @@ for that function.
|
|||
|
||||
This attribute is incompatible with the ``always_inline`` and ``minsize``
|
||||
attributes.
|
||||
|
||||
Note that this attribute does not apply recursively to nested functions such as
|
||||
lambdas or blocks when using declaration-specific attribute syntaxes such as double
|
||||
square brackets (``[[]]``) or ``__attribute__``. The ``#pragma`` syntax can be
|
||||
used to apply the attribute to all functions, including nested functions, in a
|
||||
range of source code.
|
||||
}];
|
||||
}
|
||||
|
||||
|
|
@ -4088,6 +4175,20 @@ non-underscored keywords. For example:
|
|||
@property (assign, nullable) NSView *superview;
|
||||
@property (readonly, nonnull) NSArray *subviews;
|
||||
@end
|
||||
|
||||
As well as built-in pointer types, the nullability attributes can be attached
|
||||
to C++ classes marked with the ``_Nullable`` attribute.
|
||||
|
||||
The following C++ standard library types are considered nullable:
|
||||
``unique_ptr``, ``shared_ptr``, ``auto_ptr``, ``exception_ptr``, ``function``,
|
||||
``move_only_function`` and ``coroutine_handle``.
|
||||
|
||||
Types should be marked nullable only where the type itself leaves nullability
|
||||
ambiguous. For example, ``std::optional`` is not marked ``_Nullable``, because
|
||||
``optional<int> _Nullable`` is redundant and ``optional<int> _Nonnull`` is
|
||||
not a useful type. ``std::weak_ptr`` is not nullable, because its nullability
|
||||
can change with no visible modification, so static annotation is unlikely to be
|
||||
unhelpful.
|
||||
}];
|
||||
}
|
||||
|
||||
|
|
@ -4122,6 +4223,17 @@ The ``_Nullable`` nullability qualifier indicates that a value of the
|
|||
int fetch_or_zero(int * _Nullable ptr);
|
||||
|
||||
a caller of ``fetch_or_zero`` can provide null.
|
||||
|
||||
The ``_Nullable`` attribute on classes indicates that the given class can
|
||||
represent null values, and so the ``_Nullable``, ``_Nonnull`` etc qualifiers
|
||||
make sense for this type. For example:
|
||||
|
||||
.. code-block:: c
|
||||
|
||||
class _Nullable ArenaPointer { ... };
|
||||
|
||||
ArenaPointer _Nonnull x = ...;
|
||||
ArenaPointer _Nullable y = nullptr;
|
||||
}];
|
||||
}
|
||||
|
||||
|
|
@ -4621,11 +4733,11 @@ For more information see
|
|||
}];
|
||||
}
|
||||
|
||||
def AssumptionDocs : Documentation {
|
||||
def OMPAssumeDocs : Documentation {
|
||||
let Category = DocCatFunction;
|
||||
let Heading = "assume";
|
||||
let Content = [{
|
||||
Clang supports the ``__attribute__((assume("assumption")))`` attribute to
|
||||
Clang supports the ``[[omp::assume("assumption")]]`` attribute to
|
||||
provide additional information to the optimizer. The string-literal, here
|
||||
"assumption", will be attached to the function declaration such that later
|
||||
analysis and optimization passes can assume the "assumption" to hold.
|
||||
|
|
@ -4637,7 +4749,7 @@ A function can have multiple assume attributes and they propagate from prior
|
|||
declarations to later definitions. Multiple assumptions are aggregated into a
|
||||
single comma separated string. Thus, one can provide multiple assumptions via
|
||||
a comma separated string, i.a.,
|
||||
``__attribute__((assume("assumption1,assumption2")))``.
|
||||
``[[omp::assume("assumption1,assumption2")]]``.
|
||||
|
||||
While LLVM plugins might provide more assumption strings, the default LLVM
|
||||
optimization passes are aware of the following assumptions:
|
||||
|
|
@ -5074,10 +5186,11 @@ that does not. A single parameter may not have multiple ABI treatment
|
|||
attributes.
|
||||
|
||||
Support for this feature is target-dependent, although it should be
|
||||
supported on every target that Swift supports. Query for this support
|
||||
with ``__has_attribute(swiftcall)``. This implies support for the
|
||||
``swift_context``, ``swift_error_result``, and ``swift_indirect_result``
|
||||
attributes.
|
||||
supported on every target that Swift supports. Query for this attribute
|
||||
with ``__has_attribute(swiftcall)``. Query if the target supports the
|
||||
calling convention with ``__has_extension(swiftcc)``. This implies
|
||||
support for the ``swift_context``, ``swift_error_result``, and
|
||||
``swift_indirect_result`` attributes.
|
||||
}];
|
||||
}
|
||||
|
||||
|
|
@ -5124,6 +5237,10 @@ the following:
|
|||
semantically be performed after a guaranteed tail call, such as the
|
||||
non-trivial destruction of a local variable or temporary,
|
||||
then the program is ill-formed.
|
||||
|
||||
Query for this attribute with ``__has_attribute(swiftasynccall)``. Query if
|
||||
the target supports the calling convention with
|
||||
``__has_extension(swiftasynccc)``.
|
||||
}];
|
||||
}
|
||||
|
||||
|
|
@ -5313,6 +5430,29 @@ Putting the attribute on a compound statement suppresses all warnings in scope:
|
|||
}
|
||||
}
|
||||
|
||||
The attribute can also be placed on entire declarations of functions, classes,
|
||||
variables, member variables, and so on, to suppress warnings related
|
||||
to the declarations themselves. When used this way, the attribute additionally
|
||||
suppresses all warnings in the lexical scope of the declaration:
|
||||
|
||||
.. code-block:: c++
|
||||
|
||||
class [[clang::suppress]] C {
|
||||
int foo() {
|
||||
int *x = nullptr;
|
||||
...
|
||||
return *x; // warnings suppressed in the entire class scope
|
||||
}
|
||||
|
||||
int bar();
|
||||
};
|
||||
|
||||
int C::bar() {
|
||||
int *x = nullptr;
|
||||
...
|
||||
return *x; // warning NOT suppressed! - not lexically nested in 'class C{}'
|
||||
}
|
||||
|
||||
Some static analysis warnings are accompanied by one or more notes, and the
|
||||
line of code against which the warning is emitted isn't necessarily the best
|
||||
for suppression purposes. In such cases the tools are allowed to implement
|
||||
|
|
@ -5403,6 +5543,17 @@ for clang builtin functions.
|
|||
}];
|
||||
}
|
||||
|
||||
def RISCVVectorCCDocs : Documentation {
|
||||
let Category = DocCatCallingConvs;
|
||||
let Heading = "riscv::vector_cc, riscv_vector_cc, clang::riscv_vector_cc";
|
||||
let Content = [{
|
||||
The ``riscv_vector_cc`` attribute can be applied to a function. It preserves 15
|
||||
registers namely, v1-v7 and v24-v31 as callee-saved. Callers thus don't need
|
||||
to save these registers before function calls, and callees only need to save
|
||||
them if they use them.
|
||||
}];
|
||||
}
|
||||
|
||||
def PreferredNameDocs : Documentation {
|
||||
let Category = DocCatDecl;
|
||||
let Content = [{
|
||||
|
|
@ -5506,6 +5657,28 @@ experimental at this time.
|
|||
}];
|
||||
}
|
||||
|
||||
def PreserveNoneDocs : Documentation {
|
||||
let Category = DocCatCallingConvs;
|
||||
let Content = [{
|
||||
On X86-64 and AArch64 targets, this attribute changes the calling convention of a function.
|
||||
The ``preserve_none`` calling convention tries to preserve as few general
|
||||
registers as possible. So all general registers are caller saved registers. It
|
||||
also uses more general registers to pass arguments. This attribute doesn't
|
||||
impact floating-point registers. ``preserve_none``'s ABI is still unstable, and
|
||||
may be changed in the future.
|
||||
|
||||
- On X86-64, only RSP and RBP are preserved by the callee.
|
||||
Registers R12, R13, R14, R15, RDI, RSI, RDX, RCX, R8, R9, R11, and RAX now can
|
||||
be used to pass function arguments. Floating-point registers (XMMs/YMMs) still
|
||||
follow the C calling convention.
|
||||
- On AArch64, only LR and FP are preserved by the callee.
|
||||
Registers X20-X28, X0-X7, and X9-X14 are used to pass function arguments.
|
||||
X8, X16-X19, SIMD and floating-point registers follow the AAPCS calling
|
||||
convention. X15 is not available for argument passing on Windows, but is
|
||||
used to pass arguments on other platforms.
|
||||
}];
|
||||
}
|
||||
|
||||
def DeprecatedDocs : Documentation {
|
||||
let Category = DocCatDecl;
|
||||
let Content = [{
|
||||
|
|
@ -5560,6 +5733,25 @@ See :doc:`LTOVisibility`.
|
|||
}];
|
||||
}
|
||||
|
||||
def TypeVisibilityDocs : Documentation {
|
||||
let Category = DocCatType;
|
||||
let Content = [{
|
||||
The ``type_visibility`` attribute allows the visibility of a type and its vague
|
||||
linkage objects (vtable, typeinfo, typeinfo name) to be controlled separately from
|
||||
the visibility of functions and data members of the type.
|
||||
|
||||
For example, this can be used to give default visibility to the typeinfo and the vtable
|
||||
of a type while still keeping hidden visibility on its member functions and static data
|
||||
members.
|
||||
|
||||
This attribute can only be applied to types and namespaces.
|
||||
|
||||
If both ``visibility`` and ``type_visibility`` are applied to a type or a namespace, the
|
||||
visibility specified with the ``type_visibility`` attribute overrides the visibility
|
||||
provided with the regular ``visibility`` attribute.
|
||||
}];
|
||||
}
|
||||
|
||||
def RenderScriptKernelAttributeDocs : Documentation {
|
||||
let Category = DocCatFunction;
|
||||
let Content = [{
|
||||
|
|
@ -5608,7 +5800,8 @@ takes precedence over the command line option ``-fpatchable-function-entry=N,M``
|
|||
``M`` defaults to 0 if omitted.
|
||||
|
||||
This attribute is only supported on
|
||||
aarch64/aarch64-be/loongarch32/loongarch64/riscv32/riscv64/i386/x86-64 targets.
|
||||
aarch64/aarch64-be/loongarch32/loongarch64/riscv32/riscv64/i386/x86-64/ppc/ppc64 targets.
|
||||
For ppc/ppc64 targets, AIX is still not supported.
|
||||
}];
|
||||
}
|
||||
|
||||
|
|
@ -5942,6 +6135,9 @@ def AlwaysDestroyDocs : Documentation {
|
|||
The ``always_destroy`` attribute specifies that a variable with static or thread
|
||||
storage duration should have its exit-time destructor run. This attribute is the
|
||||
default unless clang was invoked with -fno-c++-static-destructors.
|
||||
|
||||
If a variable is explicitly declared with this attribute, Clang will silence
|
||||
otherwise applicable ``-Wexit-time-destructors`` warnings.
|
||||
}];
|
||||
}
|
||||
|
||||
|
|
@ -6390,7 +6586,8 @@ like pointers to an object of type ``T``:
|
|||
private:
|
||||
int *valuePointer;
|
||||
public:
|
||||
int *getInt() { return &valuePointer; }
|
||||
IntPointer(const IntOwner&);
|
||||
int *getInt() { return valuePointer; }
|
||||
};
|
||||
|
||||
The argument ``T`` is optional and is ignored.
|
||||
|
|
@ -6406,12 +6603,8 @@ When the Owner's lifetime ends, it will consider the Pointer to be dangling.
|
|||
.. code-block:: c++
|
||||
|
||||
int f() {
|
||||
IntPointer P;
|
||||
if (true) {
|
||||
IntOwner O(7);
|
||||
P = IntPointer(O); // P "points into" O
|
||||
} // P is dangling
|
||||
return P.get(); // error: Using a dangling Pointer.
|
||||
IntPointer P(IntOwner{}); // P "points into" a temporary IntOwner object
|
||||
P.getInt(); // P is dangling
|
||||
}
|
||||
|
||||
}];
|
||||
|
|
@ -7151,6 +7344,100 @@ where shaders must be compiled into a library and linked at runtime.
|
|||
}];
|
||||
}
|
||||
|
||||
def HLSLLoopHintDocs : Documentation {
|
||||
let Category = DocCatStmt;
|
||||
let Heading = "[loop]";
|
||||
let Content = [{
|
||||
The ``[loop]`` directive allows loop optimization hints to be
|
||||
specified for the subsequent loop. The directive allows unrolling to
|
||||
be disabled and is not compatible with [unroll(x)].
|
||||
|
||||
Specifying the parameter, ``[loop]``, directs the
|
||||
unroller to not unroll the loop.
|
||||
|
||||
.. code-block:: hlsl
|
||||
|
||||
[loop]
|
||||
for (...) {
|
||||
...
|
||||
}
|
||||
|
||||
.. code-block:: hlsl
|
||||
|
||||
[loop]
|
||||
while (...) {
|
||||
...
|
||||
}
|
||||
|
||||
.. code-block:: hlsl
|
||||
|
||||
[loop]
|
||||
do {
|
||||
...
|
||||
} while (...)
|
||||
|
||||
See `hlsl loop extensions <https://learn.microsoft.com/en-us/windows/win32/direct3dhlsl/dx-graphics-hlsl-for>`_
|
||||
for details.
|
||||
}];
|
||||
}
|
||||
|
||||
def HLSLUnrollHintDocs : Documentation {
|
||||
let Category = DocCatStmt;
|
||||
let Heading = "[unroll(x)], [unroll]";
|
||||
let Content = [{
|
||||
Loop unrolling optimization hints can be specified with ``[unroll(x)]``
|
||||
. The attribute is placed immediately before a for, while,
|
||||
or do-while.
|
||||
Specifying the parameter, ``[unroll(_value_)]``, directs the
|
||||
unroller to unroll the loop ``_value_`` times. Note: [unroll(x)] is not compatible with [loop].
|
||||
|
||||
.. code-block:: hlsl
|
||||
|
||||
[unroll(4)]
|
||||
for (...) {
|
||||
...
|
||||
}
|
||||
|
||||
.. code-block:: hlsl
|
||||
|
||||
[unroll]
|
||||
for (...) {
|
||||
...
|
||||
}
|
||||
|
||||
.. code-block:: hlsl
|
||||
|
||||
[unroll(4)]
|
||||
while (...) {
|
||||
...
|
||||
}
|
||||
|
||||
.. code-block:: hlsl
|
||||
|
||||
[unroll]
|
||||
while (...) {
|
||||
...
|
||||
}
|
||||
|
||||
.. code-block:: hlsl
|
||||
|
||||
[unroll(4)]
|
||||
do {
|
||||
...
|
||||
} while (...)
|
||||
|
||||
.. code-block:: hlsl
|
||||
|
||||
[unroll]
|
||||
do {
|
||||
...
|
||||
} while (...)
|
||||
|
||||
See `hlsl loop extensions <https://learn.microsoft.com/en-us/windows/win32/direct3dhlsl/dx-graphics-hlsl-for>`_
|
||||
for details.
|
||||
}];
|
||||
}
|
||||
|
||||
def ClangRandomizeLayoutDocs : Documentation {
|
||||
let Category = DocCatDecl;
|
||||
let Heading = "randomize_layout, no_randomize_layout";
|
||||
|
|
@ -7210,7 +7497,8 @@ b for constant buffer views (CBV).
|
|||
|
||||
Register space is specified in the format ``space[number]`` and defaults to ``space0`` if omitted.
|
||||
Here're resource binding examples with and without space:
|
||||
.. code-block:: c++
|
||||
|
||||
.. code-block:: hlsl
|
||||
|
||||
RWBuffer<float> Uav : register(u3, space1);
|
||||
Buffer<float> Buf : register(t1);
|
||||
|
|
@ -7219,6 +7507,26 @@ The full documentation is available here: https://docs.microsoft.com/en-us/windo
|
|||
}];
|
||||
}
|
||||
|
||||
def HLSLPackOffsetDocs : Documentation {
|
||||
let Category = DocCatFunction;
|
||||
let Content = [{
|
||||
The packoffset attribute is used to change the layout of a cbuffer.
|
||||
Attribute spelling in HLSL is: ``packoffset( c[Subcomponent][.component] )``.
|
||||
A subcomponent is a register number, which is an integer. A component is in the form of [.xyzw].
|
||||
|
||||
Examples:
|
||||
|
||||
.. code-block:: hlsl
|
||||
|
||||
cbuffer A {
|
||||
float3 a : packoffset(c0.y);
|
||||
float4 b : packoffset(c4);
|
||||
}
|
||||
|
||||
The full documentation is available here: https://learn.microsoft.com/en-us/windows/win32/direct3dhlsl/dx-graphics-hlsl-variable-packoffset
|
||||
}];
|
||||
}
|
||||
|
||||
def HLSLSV_DispatchThreadIDDocs : Documentation {
|
||||
let Category = DocCatFunction;
|
||||
let Content = [{
|
||||
|
|
@ -7343,7 +7651,7 @@ means that it can e.g no longer be part of an initializer expression.
|
|||
|
||||
/* This may print something else than "6 * 7 = 42",
|
||||
if there is a non-weak definition of "ANSWER" in
|
||||
an object linked in */
|
||||
an object linked in */
|
||||
printf("6 * 7 = %d\n", ANSWER);
|
||||
|
||||
return 0;
|
||||
|
|
@ -7878,3 +8186,86 @@ requirement:
|
|||
}
|
||||
}];
|
||||
}
|
||||
|
||||
def ClspvLibclcBuiltinDoc : Documentation {
|
||||
let Category = DocCatFunction;
|
||||
let Content = [{
|
||||
Attribute used by `clspv`_ (OpenCL-C to Vulkan SPIR-V compiler) to identify functions coming from `libclc`_ (OpenCL-C builtin library).
|
||||
|
||||
.. code-block:: c
|
||||
|
||||
void __attribute__((clspv_libclc_builtin)) libclc_builtin() {}
|
||||
|
||||
.. _`clspv`: https://github.com/google/clspv
|
||||
.. _`libclc`: https://libclc.llvm.org
|
||||
}];
|
||||
}
|
||||
|
||||
def DocCatNonBlockingNonAllocating : DocumentationCategory<"Performance Constraint Attributes"> {
|
||||
let Content = [{
|
||||
The ``nonblocking``, ``blocking``, ``nonallocating`` and ``allocating`` attributes can be attached
|
||||
to function types, including blocks, C++ lambdas, and member functions. The attributes declare
|
||||
constraints about a function's behavior pertaining to blocking and heap memory allocation.
|
||||
|
||||
There are several rules for function types with these attributes, enforced with
|
||||
compiler warnings:
|
||||
|
||||
- When assigning or otherwise converting to a function pointer of ``nonblocking`` or
|
||||
``nonallocating`` type, the source must also be a function or function pointer of
|
||||
that type, unless it is a null pointer, i.e. the attributes should not be "spoofed". Conversions
|
||||
that remove the attributes are transparent and valid.
|
||||
|
||||
- An override of a ``nonblocking`` or ``nonallocating`` virtual method must also be declared
|
||||
with that same attribute (or a stronger one.) An overriding method may add an attribute.
|
||||
|
||||
- A redeclaration of a ``nonblocking`` or ``nonallocating`` function must also be declared with
|
||||
the same attribute (or a stronger one). A redeclaration may add an attribute.
|
||||
|
||||
The warnings are controlled by ``-Wfunction-effects``, which is enabled by default.
|
||||
|
||||
In a future commit, the compiler will diagnose function calls from ``nonblocking`` and ``nonallocating``
|
||||
functions to other functions which lack the appropriate attribute.
|
||||
}];
|
||||
}
|
||||
|
||||
def NonBlockingDocs : Documentation {
|
||||
let Category = DocCatNonBlockingNonAllocating;
|
||||
let Heading = "nonblocking";
|
||||
let Content = [{
|
||||
Declares that a function or function type either does or does not block in any way, according
|
||||
to the optional, compile-time constant boolean argument, which defaults to true. When the argument
|
||||
is false, the attribute is equivalent to ``blocking``.
|
||||
|
||||
For the purposes of diagnostics, ``nonblocking`` is considered to include the
|
||||
``nonallocating`` guarantee and is therefore a "stronger" constraint or attribute.
|
||||
}];
|
||||
}
|
||||
|
||||
def NonAllocatingDocs : Documentation {
|
||||
let Category = DocCatNonBlockingNonAllocating;
|
||||
let Heading = "nonallocating";
|
||||
let Content = [{
|
||||
Declares that a function or function type either does or does not allocate heap memory, according
|
||||
to the optional, compile-time constant boolean argument, which defaults to true. When the argument
|
||||
is false, the attribute is equivalent to ``allocating``.
|
||||
}];
|
||||
}
|
||||
|
||||
def BlockingDocs : Documentation {
|
||||
let Category = DocCatNonBlockingNonAllocating;
|
||||
let Heading = "blocking";
|
||||
let Content = [{
|
||||
Declares that a function potentially blocks, and prevents any potential inference of ``nonblocking``
|
||||
by the compiler.
|
||||
}];
|
||||
}
|
||||
|
||||
def AllocatingDocs : Documentation {
|
||||
let Category = DocCatNonBlockingNonAllocating;
|
||||
let Heading = "allocating";
|
||||
let Content = [{
|
||||
Declares that a function potentially allocates heap memory, and prevents any potential inference
|
||||
of ``nonallocating`` by the compiler.
|
||||
}];
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -52,8 +52,8 @@ public:
|
|||
/// Context-sensitive version of a keyword attribute.
|
||||
AS_ContextSensitiveKeyword,
|
||||
|
||||
/// <vardecl> : <semantic>
|
||||
AS_HLSLSemantic,
|
||||
/// <vardecl> : <annotation>
|
||||
AS_HLSLAnnotation,
|
||||
|
||||
/// The attibute has no source code manifestation and is only created
|
||||
/// implicitly.
|
||||
|
|
@ -120,7 +120,7 @@ public:
|
|||
}
|
||||
static Form Pragma() { return AS_Pragma; }
|
||||
static Form ContextSensitiveKeyword() { return AS_ContextSensitiveKeyword; }
|
||||
static Form HLSLSemantic() { return AS_HLSLSemantic; }
|
||||
static Form HLSLAnnotation() { return AS_HLSLAnnotation; }
|
||||
static Form Implicit() { return AS_Implicit; }
|
||||
|
||||
private:
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load diff
|
|
@ -64,7 +64,7 @@ namespace Builtin {
|
|||
enum ID {
|
||||
NotBuiltin = 0, // This is not a builtin function.
|
||||
#define BUILTIN(ID, TYPE, ATTRS) BI##ID,
|
||||
#include "clang/Basic/Builtins.def"
|
||||
#include "clang/Basic/Builtins.inc"
|
||||
FirstTSBuiltin
|
||||
};
|
||||
|
||||
|
|
@ -280,6 +280,11 @@ public:
|
|||
return strchr(getRecord(ID).Attributes, 'E') != nullptr;
|
||||
}
|
||||
|
||||
/// Returns true if this is an immediate (consteval) function
|
||||
bool isImmediate(unsigned ID) const {
|
||||
return strchr(getRecord(ID).Attributes, 'G') != nullptr;
|
||||
}
|
||||
|
||||
private:
|
||||
const Info &getRecord(unsigned ID) const;
|
||||
|
||||
|
|
|
|||
4770
contrib/llvm-project/clang/include/clang/Basic/Builtins.td
Normal file
4770
contrib/llvm-project/clang/include/clang/Basic/Builtins.td
Normal file
File diff suppressed because it is too large
Load diff
|
|
@ -49,6 +49,10 @@ BUILTIN(__builtin_arm_wfe, "v", "")
|
|||
BUILTIN(__builtin_arm_wfi, "v", "")
|
||||
BUILTIN(__builtin_arm_sev, "v", "")
|
||||
BUILTIN(__builtin_arm_sevl, "v", "")
|
||||
BUILTIN(__builtin_arm_chkfeat, "WUiWUi", "")
|
||||
|
||||
// Like __builtin_trap but provide an 16-bit immediate reason code (which goes into `brk #N`).
|
||||
BUILTIN(__builtin_arm_trap, "vUIs", "nr")
|
||||
|
||||
// CRC32
|
||||
TARGET_BUILTIN(__builtin_arm_crc32b, "UiUiUc", "nc", "crc")
|
||||
|
|
@ -69,7 +73,7 @@ TARGET_BUILTIN(__builtin_arm_stg, "vv*", "t", "mte")
|
|||
TARGET_BUILTIN(__builtin_arm_subp, "Uiv*v*", "t", "mte")
|
||||
|
||||
// SME state function
|
||||
BUILTIN(__builtin_arm_get_sme_state, "vULi*ULi*", "n")
|
||||
BUILTIN(__builtin_arm_get_sme_state, "vWUi*WUi*", "n")
|
||||
|
||||
// Memory Operations
|
||||
TARGET_BUILTIN(__builtin_arm_mops_memset_tag, "v*v*iz", "", "mte,mops")
|
||||
|
|
@ -133,12 +137,17 @@ TARGET_BUILTIN(__builtin_arm_st64b, "vv*WUiC*", "n", "ls64")
|
|||
TARGET_BUILTIN(__builtin_arm_st64bv, "WUiv*WUiC*", "n", "ls64")
|
||||
TARGET_BUILTIN(__builtin_arm_st64bv0, "WUiv*WUiC*", "n", "ls64")
|
||||
|
||||
// Armv9.3-A Guarded Control Stack
|
||||
TARGET_BUILTIN(__builtin_arm_gcspopm, "WUiWUi", "n", "gcs")
|
||||
TARGET_BUILTIN(__builtin_arm_gcsss, "vC*vC*", "n", "gcs")
|
||||
|
||||
TARGET_HEADER_BUILTIN(_BitScanForward, "UcUNi*UNi", "nh", INTRIN_H, ALL_MS_LANGUAGES, "")
|
||||
TARGET_HEADER_BUILTIN(_BitScanReverse, "UcUNi*UNi", "nh", INTRIN_H, ALL_MS_LANGUAGES, "")
|
||||
TARGET_HEADER_BUILTIN(_BitScanForward64, "UcUNi*ULLi", "nh", INTRIN_H, ALL_MS_LANGUAGES, "")
|
||||
TARGET_HEADER_BUILTIN(_BitScanReverse64, "UcUNi*ULLi", "nh", INTRIN_H, ALL_MS_LANGUAGES, "")
|
||||
|
||||
TARGET_HEADER_BUILTIN(_InterlockedAdd, "NiNiD*Ni", "nh", INTRIN_H, ALL_MS_LANGUAGES, "")
|
||||
TARGET_HEADER_BUILTIN(_InterlockedAdd64, "LLiLLiD*LLi", "nh", INTRIN_H, ALL_MS_LANGUAGES, "")
|
||||
TARGET_HEADER_BUILTIN(_InterlockedAnd64, "LLiLLiD*LLi", "nh", INTRIN_H, ALL_MS_LANGUAGES, "")
|
||||
TARGET_HEADER_BUILTIN(_InterlockedDecrement64, "LLiLLiD*", "nh", INTRIN_H, ALL_MS_LANGUAGES, "")
|
||||
TARGET_HEADER_BUILTIN(_InterlockedExchange64, "LLiLLiD*LLi", "nh", INTRIN_H, ALL_MS_LANGUAGES, "")
|
||||
|
|
@ -286,7 +295,9 @@ TARGET_HEADER_BUILTIN(_CountLeadingZeros64, "UiULLi", "nh", INTRIN_H, ALL_MS_LAN
|
|||
TARGET_HEADER_BUILTIN(_CountOneBits, "UiUNi", "nh", INTRIN_H, ALL_MS_LANGUAGES, "")
|
||||
TARGET_HEADER_BUILTIN(_CountOneBits64, "UiULLi", "nh", INTRIN_H, ALL_MS_LANGUAGES, "")
|
||||
|
||||
TARGET_HEADER_BUILTIN(__prefetch, "vv*", "nh", INTRIN_H, ALL_MS_LANGUAGES, "")
|
||||
TARGET_HEADER_BUILTIN(__prefetch, "vvC*", "nh", INTRIN_H, ALL_MS_LANGUAGES, "")
|
||||
|
||||
TARGET_HEADER_BUILTIN(__hlt, "UiUi.", "nh", INTRIN_H, ALL_MS_LANGUAGES, "")
|
||||
|
||||
#undef BUILTIN
|
||||
#undef LANGBUILTIN
|
||||
|
|
|
|||
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue