diff options
Diffstat (limited to 'clang')
95 files changed, 2410 insertions, 872 deletions
diff --git a/clang/cmake/caches/Fuchsia-stage2.cmake b/clang/cmake/caches/Fuchsia-stage2.cmake index 674eb2a..3d4d71a 100644 --- a/clang/cmake/caches/Fuchsia-stage2.cmake +++ b/clang/cmake/caches/Fuchsia-stage2.cmake @@ -340,7 +340,7 @@ foreach(target armv6m-none-eabi;armv7m-none-eabi;armv7em-none-eabi;armv8m.main-n foreach(lang C;CXX;ASM) # TODO: The preprocessor defines workaround various issues in libc and libc++ integration. # These should be addressed and removed over time. - set(RUNTIMES_${target}_CMAKE_${lang}_local_flags "--target=${target} -Wno-atomic-alignment \"-Dvfprintf(stream, format, vlist)=vprintf(format, vlist)\" \"-Dfprintf(stream, format, ...)=printf(format)\" -D_LIBCPP_PRINT=1") + set(RUNTIMES_${target}_CMAKE_${lang}_local_flags "--target=${target} -Wno-atomic-alignment \"-Dvfprintf(stream, format, vlist)=vprintf(format, vlist)\" \"-Dfprintf(stream, format, ...)=printf(format)\" \"-Dfputs(string, stream)=puts(string)\" -D_LIBCPP_PRINT=1") if(NOT ${target} STREQUAL "aarch64-none-elf") set(RUNTIMES_${target}_CMAKE_${lang}_local_flags "${RUNTIMES_${target}_CMAKE_${lang}_local_flags} -mthumb") endif() @@ -405,7 +405,7 @@ foreach(target riscv32-unknown-elf) foreach(lang C;CXX;ASM) # TODO: The preprocessor defines workaround various issues in libc and libc++ integration. # These should be addressed and removed over time. - set(RUNTIMES_${target}_CMAKE_${lang}_FLAGS "--target=${target} -march=rv32imafc -mabi=ilp32f -Wno-atomic-alignment \"-Dvfprintf(stream, format, vlist)=vprintf(format, vlist)\" \"-Dfprintf(stream, format, ...)=printf(format)\" -D_LIBCPP_PRINT=1" CACHE STRING "") + set(RUNTIMES_${target}_CMAKE_${lang}_FLAGS "--target=${target} -march=rv32imafc -mabi=ilp32f -Wno-atomic-alignment \"-Dvfprintf(stream, format, vlist)=vprintf(format, vlist)\" \"-Dfprintf(stream, format, ...)=printf(format)\" \"-Dfputs(string, stream)=puts(string)\" -D_LIBCPP_PRINT=1" CACHE STRING "") endforeach() foreach(type SHARED;MODULE;EXE) set(RUNTIMES_${target}_CMAKE_${type}_LINKER_FLAGS "-fuse-ld=lld" CACHE STRING "") diff --git a/clang/docs/ClangFormatStyleOptions.rst b/clang/docs/ClangFormatStyleOptions.rst index 7f970f6..02986a9 100644 --- a/clang/docs/ClangFormatStyleOptions.rst +++ b/clang/docs/ClangFormatStyleOptions.rst @@ -1912,7 +1912,7 @@ the configuration (without a prefix: ``Auto``). * ``SFS_InlineOnly`` (in configuration: ``InlineOnly``) Only merge functions defined inside a class. Same as ``inline``, - except it does not implies ``empty``: i.e. top level empty functions + except it does not imply ``empty``: i.e. top level empty functions are not merged either. .. code-block:: c++ diff --git a/clang/docs/OpenMPSupport.rst b/clang/docs/OpenMPSupport.rst index fc44f4c..58cd10a 100644 --- a/clang/docs/OpenMPSupport.rst +++ b/clang/docs/OpenMPSupport.rst @@ -1,500 +1,506 @@ -.. raw:: html - - <style type="text/css"> - .none { background-color: #FFCCCC } - .part { background-color: #FFFF99 } - .good { background-color: #CCFF99 } - </style> - -.. role:: none -.. role:: part -.. role:: good - -.. contents:: - :local: - -============== -OpenMP Support -============== - -Clang fully supports OpenMP 4.5, almost all of 5.0 and most of 5.1/2. -Clang supports offloading to X86_64, AArch64, PPC64[LE], NVIDIA GPUs (all models) and AMD GPUs (all models). - -In addition, the LLVM OpenMP runtime `libomp` supports the OpenMP Tools -Interface (OMPT) on x86, x86_64, AArch64, and PPC64 on Linux, Windows, and macOS. -OMPT is also supported for NVIDIA and AMD GPUs. - -For the list of supported features from OpenMP 5.0 and 5.1 -see `OpenMP implementation details`_ and `OpenMP 51 implementation details`_. - -General improvements -==================== -- New collapse clause scheme to avoid expensive remainder operations. - Compute loop index variables after collapsing a loop nest via the - collapse clause by replacing the expensive remainder operation with - multiplications and additions. - -- When using the collapse clause on a loop nest the default behavior - is to automatically extend the representation of the loop counter to - 64 bits for the cases where the sizes of the collapsed loops are not - known at compile time. To prevent this conservative choice and use - at most 32 bits, compile your program with the - `-fopenmp-optimistic-collapse`. - - -GPU devices support -=================== - -Data-sharing modes ------------------- - -Clang supports two data-sharing models for Cuda devices: `Generic` and `Cuda` -modes. The default mode is `Generic`. `Cuda` mode can give an additional -performance and can be activated using the `-fopenmp-cuda-mode` flag. In -`Generic` mode all local variables that can be shared in the parallel regions -are stored in the global memory. In `Cuda` mode local variables are not shared -between the threads and it is user responsibility to share the required data -between the threads in the parallel regions. Often, the optimizer is able to -reduce the cost of `Generic` mode to the level of `Cuda` mode, but the flag, -as well as other assumption flags, can be used for tuning. - -Features not supported or with limited support for Cuda devices ---------------------------------------------------------------- - -- Cancellation constructs are not supported. - -- Doacross loop nest is not supported. - -- User-defined reductions are supported only for trivial types. - -- Nested parallelism: inner parallel regions are executed sequentially. - -- Debug information for OpenMP target regions is supported, but sometimes it may - be required to manually specify the address class of the inspected variables. - In some cases the local variables are actually allocated in the global memory, - but the debug info may be not aware of it. - - -.. _OpenMP implementation details: - -OpenMP 5.0 Implementation Details -================================= - -The following table provides a quick overview over various OpenMP 5.0 features -and their implementation status. Please post on the -`Discourse forums (Runtimes - OpenMP category)`_ for more -information or if you want to help with the -implementation. - -+------------------------------+--------------------------------------------------------------+--------------------------+-----------------------------------------------------------------------+ -|Category | Feature | Status | Reviews | -+==============================+==============================================================+==========================+=======================================================================+ -| loop | support != in the canonical loop form | :good:`done` | D54441 | -+------------------------------+--------------------------------------------------------------+--------------------------+-----------------------------------------------------------------------+ -| loop | #pragma omp loop (directive) | :part:`partial` | D145823 (combined forms) | -+------------------------------+--------------------------------------------------------------+--------------------------+-----------------------------------------------------------------------+ -| loop | #pragma omp loop bind | :part:`worked on` | D144634 (needs review) | -+------------------------------+--------------------------------------------------------------+--------------------------+-----------------------------------------------------------------------+ -| loop | collapse imperfectly nested loop | :good:`done` | | -+------------------------------+--------------------------------------------------------------+--------------------------+-----------------------------------------------------------------------+ -| loop | collapse non-rectangular nested loop | :good:`done` | | -+------------------------------+--------------------------------------------------------------+--------------------------+-----------------------------------------------------------------------+ -| loop | C++ range-base for loop | :good:`done` | | -+------------------------------+--------------------------------------------------------------+--------------------------+-----------------------------------------------------------------------+ -| loop | clause: if for SIMD directives | :good:`done` | | -+------------------------------+--------------------------------------------------------------+--------------------------+-----------------------------------------------------------------------+ -| loop | inclusive scan (matching C++17 PSTL) | :good:`done` | | -+------------------------------+--------------------------------------------------------------+--------------------------+-----------------------------------------------------------------------+ -| memory management | memory allocators | :good:`done` | r341687,r357929 | -+------------------------------+--------------------------------------------------------------+--------------------------+-----------------------------------------------------------------------+ -| memory management | allocate directive and allocate clause | :good:`done` | r355614,r335952 | -+------------------------------+--------------------------------------------------------------+--------------------------+-----------------------------------------------------------------------+ -| OMPD | OMPD interfaces | :good:`done` | https://reviews.llvm.org/D99914 (Supports only HOST(CPU) and Linux | -+------------------------------+--------------------------------------------------------------+--------------------------+-----------------------------------------------------------------------+ -| OMPT | OMPT interfaces (callback support) | :good:`done` | | -+------------------------------+--------------------------------------------------------------+--------------------------+-----------------------------------------------------------------------+ -| thread affinity | thread affinity | :good:`done` | | -+------------------------------+--------------------------------------------------------------+--------------------------+-----------------------------------------------------------------------+ -| task | taskloop reduction | :good:`done` | | -+------------------------------+--------------------------------------------------------------+--------------------------+-----------------------------------------------------------------------+ -| task | task affinity | :part:`not upstream` | https://github.com/jklinkenberg/openmp/tree/task-affinity | -+------------------------------+--------------------------------------------------------------+--------------------------+-----------------------------------------------------------------------+ -| task | clause: depend on the taskwait construct | :good:`done` | D113540 (regular codegen only) | -+------------------------------+--------------------------------------------------------------+--------------------------+-----------------------------------------------------------------------+ -| task | depend objects and detachable tasks | :good:`done` | | -+------------------------------+--------------------------------------------------------------+--------------------------+-----------------------------------------------------------------------+ -| task | mutexinoutset dependence-type for tasks | :good:`done` | D53380,D57576 | -+------------------------------+--------------------------------------------------------------+--------------------------+-----------------------------------------------------------------------+ -| task | combined taskloop constructs | :good:`done` | | -+------------------------------+--------------------------------------------------------------+--------------------------+-----------------------------------------------------------------------+ -| task | master taskloop | :good:`done` | | -+------------------------------+--------------------------------------------------------------+--------------------------+-----------------------------------------------------------------------+ -| task | parallel master taskloop | :good:`done` | | -+------------------------------+--------------------------------------------------------------+--------------------------+-----------------------------------------------------------------------+ -| task | master taskloop simd | :good:`done` | | -+------------------------------+--------------------------------------------------------------+--------------------------+-----------------------------------------------------------------------+ -| task | parallel master taskloop simd | :good:`done` | | -+------------------------------+--------------------------------------------------------------+--------------------------+-----------------------------------------------------------------------+ -| SIMD | atomic and simd constructs inside SIMD code | :good:`done` | | -+------------------------------+--------------------------------------------------------------+--------------------------+-----------------------------------------------------------------------+ -| SIMD | SIMD nontemporal | :good:`done` | | -+------------------------------+--------------------------------------------------------------+--------------------------+-----------------------------------------------------------------------+ -| device | infer target functions from initializers | :part:`worked on` | | -+------------------------------+--------------------------------------------------------------+--------------------------+-----------------------------------------------------------------------+ -| device | infer target variables from initializers | :good:`done` | D146418 | -+------------------------------+--------------------------------------------------------------+--------------------------+-----------------------------------------------------------------------+ -| device | OMP_TARGET_OFFLOAD environment variable | :good:`done` | D50522 | -+------------------------------+--------------------------------------------------------------+--------------------------+-----------------------------------------------------------------------+ -| device | support full 'defaultmap' functionality | :good:`done` | D69204 | -+------------------------------+--------------------------------------------------------------+--------------------------+-----------------------------------------------------------------------+ -| device | device specific functions | :good:`done` | | -+------------------------------+--------------------------------------------------------------+--------------------------+-----------------------------------------------------------------------+ -| device | clause: device_type | :good:`done` | | -+------------------------------+--------------------------------------------------------------+--------------------------+-----------------------------------------------------------------------+ -| device | clause: extended device | :good:`done` | | -+------------------------------+--------------------------------------------------------------+--------------------------+-----------------------------------------------------------------------+ -| device | clause: uses_allocators clause | :good:`done` | | -+------------------------------+--------------------------------------------------------------+--------------------------+-----------------------------------------------------------------------+ -| device | clause: in_reduction | :part:`worked on` | r308768 | -+------------------------------+--------------------------------------------------------------+--------------------------+-----------------------------------------------------------------------+ -| device | omp_get_device_num() | :good:`done` | D54342,D128347 | -+------------------------------+--------------------------------------------------------------+--------------------------+-----------------------------------------------------------------------+ -| device | structure mapping of references | :none:`unclaimed` | | -+------------------------------+--------------------------------------------------------------+--------------------------+-----------------------------------------------------------------------+ -| device | nested target declare | :good:`done` | D51378 | -+------------------------------+--------------------------------------------------------------+--------------------------+-----------------------------------------------------------------------+ -| device | implicitly map 'this' (this[:1]) | :good:`done` | D55982 | -+------------------------------+--------------------------------------------------------------+--------------------------+-----------------------------------------------------------------------+ -| device | allow access to the reference count (omp_target_is_present) | :good:`done` | | -+------------------------------+--------------------------------------------------------------+--------------------------+-----------------------------------------------------------------------+ -| device | requires directive | :good:`done` | | -+------------------------------+--------------------------------------------------------------+--------------------------+-----------------------------------------------------------------------+ -| device | clause: unified_shared_memory | :good:`done` | D52625,D52359 | -+------------------------------+--------------------------------------------------------------+--------------------------+-----------------------------------------------------------------------+ -| device | clause: unified_address | :part:`partial` | | -+------------------------------+--------------------------------------------------------------+--------------------------+-----------------------------------------------------------------------+ -| device | clause: reverse_offload | :part:`partial` | D52780,D155003 | -+------------------------------+--------------------------------------------------------------+--------------------------+-----------------------------------------------------------------------+ -| device | clause: atomic_default_mem_order | :good:`done` | D53513 | -+------------------------------+--------------------------------------------------------------+--------------------------+-----------------------------------------------------------------------+ -| device | clause: dynamic_allocators | :part:`unclaimed parts` | D53079 | -+------------------------------+--------------------------------------------------------------+--------------------------+-----------------------------------------------------------------------+ -| device | user-defined mappers | :good:`done` | D56326,D58638,D58523,D58074,D60972,D59474 | -+------------------------------+--------------------------------------------------------------+--------------------------+-----------------------------------------------------------------------+ -| device | map array-section with implicit mapper | :good:`done` | https://github.com/llvm/llvm-project/pull/101101 | -+------------------------------+--------------------------------------------------------------+--------------------------+-----------------------------------------------------------------------+ -| device | mapping lambda expression | :good:`done` | D51107 | -+------------------------------+--------------------------------------------------------------+--------------------------+-----------------------------------------------------------------------+ -| device | clause: use_device_addr for target data | :good:`done` | | -+------------------------------+--------------------------------------------------------------+--------------------------+-----------------------------------------------------------------------+ -| device | support close modifier on map clause | :good:`done` | D55719,D55892 | -+------------------------------+--------------------------------------------------------------+--------------------------+-----------------------------------------------------------------------+ -| device | teams construct on the host device | :good:`done` | r371553 | -+------------------------------+--------------------------------------------------------------+--------------------------+-----------------------------------------------------------------------+ -| device | support non-contiguous array sections for target update | :good:`done` | | -+------------------------------+--------------------------------------------------------------+--------------------------+-----------------------------------------------------------------------+ -| device | pointer attachment | :good:`done` | | -+------------------------------+--------------------------------------------------------------+--------------------------+-----------------------------------------------------------------------+ -| atomic | hints for the atomic construct | :good:`done` | D51233 | -+------------------------------+--------------------------------------------------------------+--------------------------+-----------------------------------------------------------------------+ -| base language | C11 support | :good:`done` | | -+------------------------------+--------------------------------------------------------------+--------------------------+-----------------------------------------------------------------------+ -| base language | C++11/14/17 support | :good:`done` | | -+------------------------------+--------------------------------------------------------------+--------------------------+-----------------------------------------------------------------------+ -| base language | lambda support | :good:`done` | | -+------------------------------+--------------------------------------------------------------+--------------------------+-----------------------------------------------------------------------+ -| misc | array shaping | :good:`done` | D74144 | -+------------------------------+--------------------------------------------------------------+--------------------------+-----------------------------------------------------------------------+ -| misc | library shutdown (omp_pause_resource[_all]) | :good:`done` | D55078 | -+------------------------------+--------------------------------------------------------------+--------------------------+-----------------------------------------------------------------------+ -| misc | metadirectives | :part:`mostly done` | D91944, https://github.com/llvm/llvm-project/pull/128640 | -+------------------------------+--------------------------------------------------------------+--------------------------+-----------------------------------------------------------------------+ -| misc | conditional modifier for lastprivate clause | :good:`done` | | -+------------------------------+--------------------------------------------------------------+--------------------------+-----------------------------------------------------------------------+ -| misc | iterator and multidependences | :good:`done` | | -+------------------------------+--------------------------------------------------------------+--------------------------+-----------------------------------------------------------------------+ -| misc | depobj directive and depobj dependency kind | :good:`done` | | -+------------------------------+--------------------------------------------------------------+--------------------------+-----------------------------------------------------------------------+ -| misc | user-defined function variants | :good:`done`. | D67294, D64095, D71847, D71830, D109635 | -+------------------------------+--------------------------------------------------------------+--------------------------+-----------------------------------------------------------------------+ -| misc | pointer/reference to pointer based array reductions | :good:`done` | | -+------------------------------+--------------------------------------------------------------+--------------------------+-----------------------------------------------------------------------+ -| misc | prevent new type definitions in clauses | :good:`done` | | -+------------------------------+--------------------------------------------------------------+--------------------------+-----------------------------------------------------------------------+ -| memory model | memory model update (seq_cst, acq_rel, release, acquire,...) | :good:`done` | | -+------------------------------+--------------------------------------------------------------+--------------------------+-----------------------------------------------------------------------+ - - -.. _OpenMP 51 implementation details: - -OpenMP 5.1 Implementation Details -================================= - -The following table provides a quick overview over various OpenMP 5.1 features -and their implementation status. -Please post on the -`Discourse forums (Runtimes - OpenMP category)`_ for more -information or if you want to help with the -implementation. - -+------------------------------+--------------------------------------------------------------+--------------------------+-----------------------------------------------------------------------+ -|Category | Feature | Status | Reviews | -+==============================+==============================================================+==========================+=======================================================================+ -| atomic | 'compare' clause on atomic construct | :good:`done` | D120290, D120007, D118632, D120200, D116261, D118547, D116637 | -+------------------------------+--------------------------------------------------------------+--------------------------+-----------------------------------------------------------------------+ -| atomic | 'fail' clause on atomic construct | :part:`worked on` | D123235 (in progress) | -+------------------------------+--------------------------------------------------------------+--------------------------+-----------------------------------------------------------------------+ -| base language | C++ attribute specifier syntax | :good:`done` | D105648 | -+------------------------------+--------------------------------------------------------------+--------------------------+-----------------------------------------------------------------------+ -| device | 'present' map type modifier | :good:`done` | D83061, D83062, D84422 | -+------------------------------+--------------------------------------------------------------+--------------------------+-----------------------------------------------------------------------+ -| device | 'present' motion modifier | :good:`done` | D84711, D84712 | -+------------------------------+--------------------------------------------------------------+--------------------------+-----------------------------------------------------------------------+ -| device | 'present' in defaultmap clause | :good:`done` | D92427 | -+------------------------------+--------------------------------------------------------------+--------------------------+-----------------------------------------------------------------------+ -| device | map clause reordering based on 'present' modifier | :none:`unclaimed` | | -+------------------------------+--------------------------------------------------------------+--------------------------+-----------------------------------------------------------------------+ -| device | device-specific environment variables | :none:`unclaimed` | | -+------------------------------+--------------------------------------------------------------+--------------------------+-----------------------------------------------------------------------+ -| device | omp_target_is_accessible routine | :none:`unclaimed` | | -+------------------------------+--------------------------------------------------------------+--------------------------+-----------------------------------------------------------------------+ -| device | omp_get_mapped_ptr routine | :good:`done` | D141545 | -+------------------------------+--------------------------------------------------------------+--------------------------+-----------------------------------------------------------------------+ -| device | new async target memory copy routines | :good:`done` | D136103 | -+------------------------------+--------------------------------------------------------------+--------------------------+-----------------------------------------------------------------------+ -| device | thread_limit clause on target construct | :part:`partial` | D141540 (offload), D152054 (host, in progress) | -+------------------------------+--------------------------------------------------------------+--------------------------+-----------------------------------------------------------------------+ -| device | has_device_addr clause on target construct | :none:`unclaimed` | | -+------------------------------+--------------------------------------------------------------+--------------------------+-----------------------------------------------------------------------+ -| device | iterators in map clause or motion clauses | :none:`unclaimed` | | -+------------------------------+--------------------------------------------------------------+--------------------------+-----------------------------------------------------------------------+ -| device | indirect clause on declare target directive | :none:`unclaimed` | | -+------------------------------+--------------------------------------------------------------+--------------------------+-----------------------------------------------------------------------+ -| device | allow virtual functions calls for mapped object on device | :part:`partial` | | -+------------------------------+--------------------------------------------------------------+--------------------------+-----------------------------------------------------------------------+ -| device | interop construct | :part:`partial` | parsing/sema done: D98558, D98834, D98815 | -+------------------------------+--------------------------------------------------------------+--------------------------+-----------------------------------------------------------------------+ -| device | assorted routines for querying interoperable properties | :part:`partial` | D106674 | -+------------------------------+--------------------------------------------------------------+--------------------------+-----------------------------------------------------------------------+ -| loop | Loop tiling transformation | :good:`done` | D76342 | -+------------------------------+--------------------------------------------------------------+--------------------------+-----------------------------------------------------------------------+ -| loop | Loop unrolling transformation | :good:`done` | D99459 | -+------------------------------+--------------------------------------------------------------+--------------------------+-----------------------------------------------------------------------+ -| loop | 'reproducible'/'unconstrained' modifiers in 'order' clause | :part:`partial` | D127855 | -+------------------------------+--------------------------------------------------------------+--------------------------+-----------------------------------------------------------------------+ -| memory management | alignment for allocate directive and clause | :good:`done` | D115683 | -+------------------------------+--------------------------------------------------------------+--------------------------+-----------------------------------------------------------------------+ -| memory management | 'allocator' modifier for allocate clause | :good:`done` | https://github.com/llvm/llvm-project/pull/114883 | -+------------------------------+--------------------------------------------------------------+--------------------------+-----------------------------------------------------------------------+ -| memory management | 'align' modifier for allocate clause | :good:`done` | https://github.com/llvm/llvm-project/pull/121814 | -+------------------------------+--------------------------------------------------------------+--------------------------+-----------------------------------------------------------------------+ -| memory management | new memory management routines | :none:`unclaimed` | | -+------------------------------+--------------------------------------------------------------+--------------------------+-----------------------------------------------------------------------+ -| memory management | changes to omp_alloctrait_key enum | :none:`unclaimed` | | -+------------------------------+--------------------------------------------------------------+--------------------------+-----------------------------------------------------------------------+ -| memory model | seq_cst clause on flush construct | :good:`done` | https://github.com/llvm/llvm-project/pull/114072 | -+------------------------------+--------------------------------------------------------------+--------------------------+-----------------------------------------------------------------------+ -| misc | 'omp_all_memory' keyword and use in 'depend' clause | :good:`done` | D125828, D126321 | -+------------------------------+--------------------------------------------------------------+--------------------------+-----------------------------------------------------------------------+ -| misc | error directive | :good:`done` | D139166 | -+------------------------------+--------------------------------------------------------------+--------------------------+-----------------------------------------------------------------------+ -| misc | scope construct | :good:`done` | D157933, https://github.com/llvm/llvm-project/pull/109197 | -+------------------------------+--------------------------------------------------------------+--------------------------+-----------------------------------------------------------------------+ -| misc | routines for controlling and querying team regions | :part:`partial` | D95003 (libomp only) | -+------------------------------+--------------------------------------------------------------+--------------------------+-----------------------------------------------------------------------+ -| misc | changes to ompt_scope_endpoint_t enum | :none:`unclaimed` | | -+------------------------------+--------------------------------------------------------------+--------------------------+-----------------------------------------------------------------------+ -| misc | omp_display_env routine | :good:`done` | D74956 | -+------------------------------+--------------------------------------------------------------+--------------------------+-----------------------------------------------------------------------+ -| misc | extended OMP_PLACES syntax | :none:`unclaimed` | | -+------------------------------+--------------------------------------------------------------+--------------------------+-----------------------------------------------------------------------+ -| misc | OMP_NUM_TEAMS and OMP_TEAMS_THREAD_LIMIT env vars | :good:`done` | D138769 | -+------------------------------+--------------------------------------------------------------+--------------------------+-----------------------------------------------------------------------+ -| misc | 'target_device' selector in context specifier | :none:`worked on` | | -+------------------------------+--------------------------------------------------------------+--------------------------+-----------------------------------------------------------------------+ -| misc | begin/end declare variant | :good:`done` | D71179 | -+------------------------------+--------------------------------------------------------------+--------------------------+-----------------------------------------------------------------------+ -| misc | dispatch construct and function variant argument adjustment | :part:`worked on` | D99537, D99679 | -+------------------------------+--------------------------------------------------------------+--------------------------+-----------------------------------------------------------------------+ -| misc | assumes directives | :part:`worked on` | | -+------------------------------+--------------------------------------------------------------+--------------------------+-----------------------------------------------------------------------+ -| misc | assume directive | :good:`done` | | -+------------------------------+--------------------------------------------------------------+--------------------------+-----------------------------------------------------------------------+ -| misc | nothing directive | :good:`done` | D123286 | -+------------------------------+--------------------------------------------------------------+--------------------------+-----------------------------------------------------------------------+ -| misc | masked construct and related combined constructs | :good:`done` | D99995, D100514, PR-121741(parallel_masked_taskloop) | -| | | | PR-121746(parallel_masked_task_loop_simd),PR-121914(masked_taskloop) | -| | | | PR-121916(masked_taskloop_simd) | -+------------------------------+--------------------------------------------------------------+--------------------------+-----------------------------------------------------------------------+ -| misc | default(firstprivate) & default(private) | :good:`done` | D75591 (firstprivate), D125912 (private) | -+------------------------------+--------------------------------------------------------------+--------------------------+-----------------------------------------------------------------------+ -| other | deprecating master construct | :none:`unclaimed` | | -+------------------------------+--------------------------------------------------------------+--------------------------+-----------------------------------------------------------------------+ -| OMPT | new barrier types added to ompt_sync_region_t enum | :none:`unclaimed` | | -+------------------------------+--------------------------------------------------------------+--------------------------+-----------------------------------------------------------------------+ -| OMPT | async data transfers added to ompt_target_data_op_t enum | :none:`unclaimed` | | -+------------------------------+--------------------------------------------------------------+--------------------------+-----------------------------------------------------------------------+ -| OMPT | new barrier state values added to ompt_state_t enum | :none:`unclaimed` | | -+------------------------------+--------------------------------------------------------------+--------------------------+-----------------------------------------------------------------------+ -| OMPT | new 'emi' callbacks for external monitoring interfaces | :good:`done` | | -+------------------------------+--------------------------------------------------------------+--------------------------+-----------------------------------------------------------------------+ -| OMPT | device tracing interface | :none:`unclaimed` | | -+------------------------------+--------------------------------------------------------------+--------------------------+-----------------------------------------------------------------------+ -| task | 'strict' modifier for taskloop construct | :none:`unclaimed` | | -+------------------------------+--------------------------------------------------------------+--------------------------+-----------------------------------------------------------------------+ -| task | inoutset in depend clause | :good:`done` | D97085, D118383 | -+------------------------------+--------------------------------------------------------------+--------------------------+-----------------------------------------------------------------------+ -| task | nowait clause on taskwait | :part:`partial` | parsing/sema done: D131830, D141531 | -+------------------------------+--------------------------------------------------------------+--------------------------+-----------------------------------------------------------------------+ - - -.. _OpenMP 6.0 implementation details: - -OpenMP 6.0 Implementation Details -================================= - -The following table provides a quick overview over various OpenMP 6.0 features -and their implementation status. Please post on the -`Discourse forums (Runtimes - OpenMP category)`_ for more -information or if you want to help with the -implementation. - -+-------------------------------------------------------------+---------------------------+---------------------------+--------------------------------------------------------------------------+ -|Feature | C/C++ Status | Fortran Status | Reviews | -+=============================================================+===========================+===========================+==========================================================================+ -| free-agent threads | :none:`unclaimed` | :none:`unclaimed` | | -+-------------------------------------------------------------+---------------------------+---------------------------+--------------------------------------------------------------------------+ -| threadset clause | :`worked on` | :none:`unclaimed` | | -+-------------------------------------------------------------+---------------------------+---------------------------+--------------------------------------------------------------------------+ -| Recording of task graphs | :none:`unclaimed` | :none:`unclaimed` | | -+-------------------------------------------------------------+---------------------------+---------------------------+--------------------------------------------------------------------------+ -| Parallel inductions | :none:`unclaimed` | :none:`unclaimed` | | -+-------------------------------------------------------------+---------------------------+---------------------------+--------------------------------------------------------------------------+ -| init_complete for scan directive | :none:`unclaimed` | :none:`unclaimed` | | -+-------------------------------------------------------------+---------------------------+---------------------------+--------------------------------------------------------------------------+ -| Loop transformation constructs | :none:`unclaimed` | :none:`unclaimed` | | -+-------------------------------------------------------------+---------------------------+---------------------------+--------------------------------------------------------------------------+ -| loop stripe transformation | :good:`done` | https://github.com/llvm/llvm-project/pull/119891 | -+-------------------------------------------------------------+---------------------------+---------------------------+--------------------------------------------------------------------------+ -| work distribute construct | :none:`unclaimed` | :none:`unclaimed` | | -+-------------------------------------------------------------+---------------------------+---------------------------+--------------------------------------------------------------------------+ -| task_iteration | :none:`unclaimed` | :none:`unclaimed` | | -+-------------------------------------------------------------+---------------------------+---------------------------+--------------------------------------------------------------------------+ -| memscope clause for atomic and flush | :none:`unclaimed` | :none:`unclaimed` | | -+-------------------------------------------------------------+---------------------------+---------------------------+--------------------------------------------------------------------------+ -| transparent clause (hull tasks) | :none:`unclaimed` | :none:`unclaimed` | | -+-------------------------------------------------------------+---------------------------+---------------------------+--------------------------------------------------------------------------+ -| rule-based compound directives | :none:`unclaimed` | :none:`unclaimed` | | -+-------------------------------------------------------------+---------------------------+---------------------------+--------------------------------------------------------------------------+ -| C23, C++23 | :none:`unclaimed` | :none:`unclaimed` | | -+-------------------------------------------------------------+---------------------------+---------------------------+--------------------------------------------------------------------------+ -| Fortran 2023 | :none:`unclaimed` | :none:`unclaimed` | | -+-------------------------------------------------------------+---------------------------+---------------------------+--------------------------------------------------------------------------+ -| decl attribute for declarative directives | :none:`unclaimed` | :none:`unclaimed` | | -+-------------------------------------------------------------+---------------------------+---------------------------+--------------------------------------------------------------------------+ -| C attribute syntax | :none:`unclaimed` | :none:`unclaimed` | | -+-------------------------------------------------------------+---------------------------+---------------------------+--------------------------------------------------------------------------+ -| pure directives in DO CONCURRENT | :none:`unclaimed` | :none:`unclaimed` | | -+-------------------------------------------------------------+---------------------------+---------------------------+--------------------------------------------------------------------------+ -| Optional argument for all clauses | :none:`unclaimed` | :none:`unclaimed` | | -+-------------------------------------------------------------+---------------------------+---------------------------+--------------------------------------------------------------------------+ -| Function references for locator list items | :none:`unclaimed` | :none:`unclaimed` | | -+-------------------------------------------------------------+---------------------------+---------------------------+--------------------------------------------------------------------------+ -| All clauses accept directive name modifier | :none:`unclaimed` | :none:`unclaimed` | | -+-------------------------------------------------------------+---------------------------+---------------------------+--------------------------------------------------------------------------+ -| Extensions to depobj construct | :none:`unclaimed` | :none:`unclaimed` | | -+-------------------------------------------------------------+---------------------------+---------------------------+--------------------------------------------------------------------------+ -| Extensions to atomic construct | :none:`unclaimed` | :none:`unclaimed` | | -+-------------------------------------------------------------+---------------------------+---------------------------+--------------------------------------------------------------------------+ -| Private reductions | :good:`mostly` | :none:`unclaimed` | Parse/Sema:https://github.com/llvm/llvm-project/pull/129938 | -| | | | Codegen: https://github.com/llvm/llvm-project/pull/134709 | -+-------------------------------------------------------------+---------------------------+---------------------------+--------------------------------------------------------------------------+ -| Self maps | :part:`partial` | :none:`unclaimed` | parsing/sema done: https://github.com/llvm/llvm-project/pull/129888 | -+-------------------------------------------------------------+---------------------------+---------------------------+--------------------------------------------------------------------------+ -| Release map type for declare mapper | :none:`unclaimed` | :none:`unclaimed` | | -+-------------------------------------------------------------+---------------------------+---------------------------+--------------------------------------------------------------------------+ -| Extensions to interop construct | :none:`unclaimed` | :none:`unclaimed` | | -+-------------------------------------------------------------+---------------------------+---------------------------+--------------------------------------------------------------------------+ -| no_openmp_constructs | :good:`done` | :none:`unclaimed` | https://github.com/llvm/llvm-project/pull/125933 | -+-------------------------------------------------------------+---------------------------+---------------------------+--------------------------------------------------------------------------+ -| safe_sync and progress with identifier and API | :none:`unclaimed` | :none:`unclaimed` | | -+-------------------------------------------------------------+---------------------------+---------------------------+--------------------------------------------------------------------------+ -| OpenMP directives in concurrent loop regions | :good:`done` | :none:`unclaimed` | https://github.com/llvm/llvm-project/pull/125621 | -+-------------------------------------------------------------+---------------------------+---------------------------+--------------------------------------------------------------------------+ -| atomics constructs on concurrent loop regions | :good:`done` | :none:`unclaimed` | https://github.com/llvm/llvm-project/pull/125621 | -+-------------------------------------------------------------+---------------------------+---------------------------+--------------------------------------------------------------------------+ -| Loop construct with DO CONCURRENT | :none:`unclaimed` | :none:`unclaimed` | | -+-------------------------------------------------------------+---------------------------+---------------------------+--------------------------------------------------------------------------+ -| device_type clause for target construct | :none:`unclaimed` | :none:`unclaimed` | | -+-------------------------------------------------------------+---------------------------+---------------------------+--------------------------------------------------------------------------+ -| nowait for ancestor target directives | :none:`unclaimed` | :none:`unclaimed` | | -+-------------------------------------------------------------+---------------------------+---------------------------+--------------------------------------------------------------------------+ -| New API for devices' num_teams/thread_limit | :none:`unclaimed` | :none:`unclaimed` | | -+-------------------------------------------------------------+---------------------------+---------------------------+--------------------------------------------------------------------------+ -| Host and device environment variables | :none:`unclaimed` | :none:`unclaimed` | | -+-------------------------------------------------------------+---------------------------+---------------------------+--------------------------------------------------------------------------+ -| num_threads ICV and clause accepts list | :none:`unclaimed` | :none:`unclaimed` | | -+-------------------------------------------------------------+---------------------------+---------------------------+--------------------------------------------------------------------------+ -| Numeric names for environment variables | :none:`unclaimed` | :none:`unclaimed` | | -+-------------------------------------------------------------+---------------------------+---------------------------+--------------------------------------------------------------------------+ -| Increment between places for OMP_PLACES | :none:`unclaimed` | :none:`unclaimed` | | -+-------------------------------------------------------------+---------------------------+---------------------------+--------------------------------------------------------------------------+ -| OMP_AVAILABLE_DEVICES envirable | :none:`unclaimed` | :none:`unclaimed` | | -+-------------------------------------------------------------+---------------------------+---------------------------+--------------------------------------------------------------------------+ -| Traits for default device envirable | :none:`unclaimed` | :none:`unclaimed` | | -+-------------------------------------------------------------+---------------------------+---------------------------+--------------------------------------------------------------------------+ -| Optionally omit array length expression | :good:`done` | :none:`unclaimed` | https://github.com/llvm/llvm-project/pull/148048 | -+-------------------------------------------------------------+---------------------------+---------------------------+--------------------------------------------------------------------------+ -| Canonical loop sequences | :none:`unclaimed` | :none:`unclaimed` | | -+-------------------------------------------------------------+---------------------------+---------------------------+--------------------------------------------------------------------------+ -| Clarifications to Fortran map semantics | :none:`unclaimed` | :none:`unclaimed` | | -+-------------------------------------------------------------+---------------------------+---------------------------+--------------------------------------------------------------------------+ -| default clause at target construct | :none:`unclaimed` | :none:`unclaimed` | | -+-------------------------------------------------------------+---------------------------+---------------------------+--------------------------------------------------------------------------+ -| ref count update use_device_{ptr, addr} | :none:`unclaimed` | :none:`unclaimed` | | -+-------------------------------------------------------------+---------------------------+---------------------------+--------------------------------------------------------------------------+ -| Clarifications to implicit reductions | :none:`unclaimed` | :none:`unclaimed` | | -+-------------------------------------------------------------+---------------------------+---------------------------+--------------------------------------------------------------------------+ -| ref modifier for map clauses | :none:`unclaimed` | :none:`unclaimed` | | -+-------------------------------------------------------------+---------------------------+---------------------------+--------------------------------------------------------------------------+ -| map-type modifiers in arbitrary position | :good:`done` | :none:`unclaimed` | https://github.com/llvm/llvm-project/pull/90499 | -+-------------------------------------------------------------+---------------------------+---------------------------+--------------------------------------------------------------------------+ -| Lift nesting restriction on concurrent loop | :good:`done` | :none:`unclaimed` | https://github.com/llvm/llvm-project/pull/125621 | -+-------------------------------------------------------------+---------------------------+---------------------------+--------------------------------------------------------------------------+ -| priority clause for target constructs | :none:`unclaimed` | :none:`unclaimed` | | -+-------------------------------------------------------------+---------------------------+---------------------------+--------------------------------------------------------------------------+ -| changes to target_data construct | :none:`unclaimed` | :none:`unclaimed` | | -+-------------------------------------------------------------+---------------------------+---------------------------+--------------------------------------------------------------------------+ -| Non-const do_not_sync for nowait/nogroup | :none:`unclaimed` | :none:`unclaimed` | | -+-------------------------------------------------------------+---------------------------+---------------------------+--------------------------------------------------------------------------+ -| need_device_addr modifier for adjust_args clause | :part:`partial` | :none:`unclaimed` | Parsing/Sema: https://github.com/llvm/llvm-project/pull/143442 | -| | | | https://github.com/llvm/llvm-project/pull/149586 | -+-------------------------------------------------------------+---------------------------+---------------------------+--------------------------------------------------------------------------+ - -OpenMP Extensions -================= - -The following table provides a quick overview over various OpenMP -extensions and their implementation status. These extensions are not -currently defined by any standard, so links to associated LLVM -documentation are provided. As these extensions mature, they will be -considered for standardization. Please post on the -`Discourse forums (Runtimes - OpenMP category)`_ to provide feedback. - -+------------------------------+-----------------------------------------------------------------------------------+--------------------------+--------------------------------------------------------+ -|Category | Feature | Status | Reviews | -+==============================+===================================================================================+==========================+========================================================+ -| atomic extension | `'atomic' strictly nested within 'teams' | :good:`prototyped` | D126323 | -| | <https://openmp.llvm.org/docs/openacc/OpenMPExtensions.html#atomicWithinTeams>`_ | | | -+------------------------------+-----------------------------------------------------------------------------------+--------------------------+--------------------------------------------------------+ -| device extension | `'ompx_hold' map type modifier | :good:`prototyped` | D106509, D106510 | -| | <https://openmp.llvm.org/docs/openacc/OpenMPExtensions.html#ompx-hold>`_ | | | -+------------------------------+-----------------------------------------------------------------------------------+--------------------------+--------------------------------------------------------+ -| device extension | `'ompx_bare' clause on 'target teams' construct | :good:`prototyped` | #66844, #70612 | -| | <https://www.osti.gov/servlets/purl/2205717>`_ | | | -+------------------------------+-----------------------------------------------------------------------------------+--------------------------+--------------------------------------------------------+ -| device extension | Multi-dim 'num_teams' and 'thread_limit' clause on 'target teams ompx_bare' | :good:`partial` | #99732, #101407, #102715 | -| | construct | | | -+------------------------------+-----------------------------------------------------------------------------------+--------------------------+--------------------------------------------------------+ - -.. _Discourse forums (Runtimes - OpenMP category): https://discourse.llvm.org/c/runtimes/openmp/35 +.. raw:: html
+
+ <style type="text/css">
+ .none { background-color: #FFCCCC }
+ .part { background-color: #FFFF99 }
+ .good { background-color: #CCFF99 }
+ </style>
+
+.. role:: none
+.. role:: part
+.. role:: good
+
+.. contents::
+ :local:
+
+==============
+OpenMP Support
+==============
+
+Clang fully supports OpenMP 4.5, almost all of 5.0 and most of 5.1/2.
+Clang supports offloading to X86_64, AArch64, PPC64[LE], NVIDIA GPUs (all models) and AMD GPUs (all models).
+
+In addition, the LLVM OpenMP runtime `libomp` supports the OpenMP Tools
+Interface (OMPT) on x86, x86_64, AArch64, and PPC64 on Linux, Windows, and macOS.
+OMPT is also supported for NVIDIA and AMD GPUs.
+
+For the list of supported features from OpenMP 5.0 and 5.1
+see `OpenMP implementation details`_ and `OpenMP 51 implementation details`_.
+
+General improvements
+====================
+- New collapse clause scheme to avoid expensive remainder operations.
+ Compute loop index variables after collapsing a loop nest via the
+ collapse clause by replacing the expensive remainder operation with
+ multiplications and additions.
+
+- When using the collapse clause on a loop nest the default behavior
+ is to automatically extend the representation of the loop counter to
+ 64 bits for the cases where the sizes of the collapsed loops are not
+ known at compile time. To prevent this conservative choice and use
+ at most 32 bits, compile your program with the
+ `-fopenmp-optimistic-collapse`.
+
+
+GPU devices support
+===================
+
+Data-sharing modes
+------------------
+
+Clang supports two data-sharing models for Cuda devices: `Generic` and `Cuda`
+modes. The default mode is `Generic`. `Cuda` mode can give an additional
+performance and can be activated using the `-fopenmp-cuda-mode` flag. In
+`Generic` mode all local variables that can be shared in the parallel regions
+are stored in the global memory. In `Cuda` mode local variables are not shared
+between the threads and it is user responsibility to share the required data
+between the threads in the parallel regions. Often, the optimizer is able to
+reduce the cost of `Generic` mode to the level of `Cuda` mode, but the flag,
+as well as other assumption flags, can be used for tuning.
+
+Features not supported or with limited support for Cuda devices
+---------------------------------------------------------------
+
+- Cancellation constructs are not supported.
+
+- Doacross loop nest is not supported.
+
+- User-defined reductions are supported only for trivial types.
+
+- Nested parallelism: inner parallel regions are executed sequentially.
+
+- Debug information for OpenMP target regions is supported, but sometimes it may
+ be required to manually specify the address class of the inspected variables.
+ In some cases the local variables are actually allocated in the global memory,
+ but the debug info may be not aware of it.
+
+
+.. _OpenMP implementation details:
+
+OpenMP 5.0 Implementation Details
+=================================
+
+The following table provides a quick overview over various OpenMP 5.0 features
+and their implementation status. Please post on the
+`Discourse forums (Runtimes - OpenMP category)`_ for more
+information or if you want to help with the
+implementation.
+
++------------------------------+--------------------------------------------------------------+--------------------------+-----------------------------------------------------------------------+
+|Category | Feature | Status | Reviews |
++==============================+==============================================================+==========================+=======================================================================+
+| loop | support != in the canonical loop form | :good:`done` | D54441 |
++------------------------------+--------------------------------------------------------------+--------------------------+-----------------------------------------------------------------------+
+| loop | #pragma omp loop (directive) | :part:`partial` | D145823 (combined forms) |
++------------------------------+--------------------------------------------------------------+--------------------------+-----------------------------------------------------------------------+
+| loop | #pragma omp loop bind | :part:`worked on` | D144634 (needs review) |
++------------------------------+--------------------------------------------------------------+--------------------------+-----------------------------------------------------------------------+
+| loop | collapse imperfectly nested loop | :good:`done` | |
++------------------------------+--------------------------------------------------------------+--------------------------+-----------------------------------------------------------------------+
+| loop | collapse non-rectangular nested loop | :good:`done` | |
++------------------------------+--------------------------------------------------------------+--------------------------+-----------------------------------------------------------------------+
+| loop | C++ range-base for loop | :good:`done` | |
++------------------------------+--------------------------------------------------------------+--------------------------+-----------------------------------------------------------------------+
+| loop | clause: if for SIMD directives | :good:`done` | |
++------------------------------+--------------------------------------------------------------+--------------------------+-----------------------------------------------------------------------+
+| loop | inclusive scan (matching C++17 PSTL) | :good:`done` | |
++------------------------------+--------------------------------------------------------------+--------------------------+-----------------------------------------------------------------------+
+| memory management | memory allocators | :good:`done` | r341687,r357929 |
++------------------------------+--------------------------------------------------------------+--------------------------+-----------------------------------------------------------------------+
+| memory management | allocate directive and allocate clause | :good:`done` | r355614,r335952 |
++------------------------------+--------------------------------------------------------------+--------------------------+-----------------------------------------------------------------------+
+| OMPD | OMPD interfaces | :good:`done` | https://reviews.llvm.org/D99914 (Supports only HOST(CPU) and Linux |
++------------------------------+--------------------------------------------------------------+--------------------------+-----------------------------------------------------------------------+
+| OMPT | OMPT interfaces (callback support) | :good:`done` | |
++------------------------------+--------------------------------------------------------------+--------------------------+-----------------------------------------------------------------------+
+| thread affinity | thread affinity | :good:`done` | |
++------------------------------+--------------------------------------------------------------+--------------------------+-----------------------------------------------------------------------+
+| task | taskloop reduction | :good:`done` | |
++------------------------------+--------------------------------------------------------------+--------------------------+-----------------------------------------------------------------------+
+| task | task affinity | :part:`not upstream` | https://github.com/jklinkenberg/openmp/tree/task-affinity |
++------------------------------+--------------------------------------------------------------+--------------------------+-----------------------------------------------------------------------+
+| task | clause: depend on the taskwait construct | :good:`done` | D113540 (regular codegen only) |
++------------------------------+--------------------------------------------------------------+--------------------------+-----------------------------------------------------------------------+
+| task | depend objects and detachable tasks | :good:`done` | |
++------------------------------+--------------------------------------------------------------+--------------------------+-----------------------------------------------------------------------+
+| task | mutexinoutset dependence-type for tasks | :good:`done` | D53380,D57576 |
++------------------------------+--------------------------------------------------------------+--------------------------+-----------------------------------------------------------------------+
+| task | combined taskloop constructs | :good:`done` | |
++------------------------------+--------------------------------------------------------------+--------------------------+-----------------------------------------------------------------------+
+| task | master taskloop | :good:`done` | |
++------------------------------+--------------------------------------------------------------+--------------------------+-----------------------------------------------------------------------+
+| task | parallel master taskloop | :good:`done` | |
++------------------------------+--------------------------------------------------------------+--------------------------+-----------------------------------------------------------------------+
+| task | master taskloop simd | :good:`done` | |
++------------------------------+--------------------------------------------------------------+--------------------------+-----------------------------------------------------------------------+
+| task | parallel master taskloop simd | :good:`done` | |
++------------------------------+--------------------------------------------------------------+--------------------------+-----------------------------------------------------------------------+
+| SIMD | atomic and simd constructs inside SIMD code | :good:`done` | |
++------------------------------+--------------------------------------------------------------+--------------------------+-----------------------------------------------------------------------+
+| SIMD | SIMD nontemporal | :good:`done` | |
++------------------------------+--------------------------------------------------------------+--------------------------+-----------------------------------------------------------------------+
+| device | infer target functions from initializers | :part:`worked on` | |
++------------------------------+--------------------------------------------------------------+--------------------------+-----------------------------------------------------------------------+
+| device | infer target variables from initializers | :good:`done` | D146418 |
++------------------------------+--------------------------------------------------------------+--------------------------+-----------------------------------------------------------------------+
+| device | OMP_TARGET_OFFLOAD environment variable | :good:`done` | D50522 |
++------------------------------+--------------------------------------------------------------+--------------------------+-----------------------------------------------------------------------+
+| device | support full 'defaultmap' functionality | :good:`done` | D69204 |
++------------------------------+--------------------------------------------------------------+--------------------------+-----------------------------------------------------------------------+
+| device | device specific functions | :good:`done` | |
++------------------------------+--------------------------------------------------------------+--------------------------+-----------------------------------------------------------------------+
+| device | clause: device_type | :good:`done` | |
++------------------------------+--------------------------------------------------------------+--------------------------+-----------------------------------------------------------------------+
+| device | clause: extended device | :good:`done` | |
++------------------------------+--------------------------------------------------------------+--------------------------+-----------------------------------------------------------------------+
+| device | clause: uses_allocators clause | :good:`done` | |
++------------------------------+--------------------------------------------------------------+--------------------------+-----------------------------------------------------------------------+
+| device | clause: in_reduction | :part:`worked on` | r308768 |
++------------------------------+--------------------------------------------------------------+--------------------------+-----------------------------------------------------------------------+
+| device | omp_get_device_num() | :good:`done` | D54342,D128347 |
++------------------------------+--------------------------------------------------------------+--------------------------+-----------------------------------------------------------------------+
+| device | structure mapping of references | :none:`unclaimed` | |
++------------------------------+--------------------------------------------------------------+--------------------------+-----------------------------------------------------------------------+
+| device | nested target declare | :good:`done` | D51378 |
++------------------------------+--------------------------------------------------------------+--------------------------+-----------------------------------------------------------------------+
+| device | implicitly map 'this' (this[:1]) | :good:`done` | D55982 |
++------------------------------+--------------------------------------------------------------+--------------------------+-----------------------------------------------------------------------+
+| device | allow access to the reference count (omp_target_is_present) | :good:`done` | |
++------------------------------+--------------------------------------------------------------+--------------------------+-----------------------------------------------------------------------+
+| device | requires directive | :good:`done` | |
++------------------------------+--------------------------------------------------------------+--------------------------+-----------------------------------------------------------------------+
+| device | clause: unified_shared_memory | :good:`done` | D52625,D52359 |
++------------------------------+--------------------------------------------------------------+--------------------------+-----------------------------------------------------------------------+
+| device | clause: unified_address | :part:`partial` | |
++------------------------------+--------------------------------------------------------------+--------------------------+-----------------------------------------------------------------------+
+| device | clause: reverse_offload | :part:`partial` | D52780,D155003 |
++------------------------------+--------------------------------------------------------------+--------------------------+-----------------------------------------------------------------------+
+| device | clause: atomic_default_mem_order | :good:`done` | D53513 |
++------------------------------+--------------------------------------------------------------+--------------------------+-----------------------------------------------------------------------+
+| device | clause: dynamic_allocators | :part:`unclaimed parts` | D53079 |
++------------------------------+--------------------------------------------------------------+--------------------------+-----------------------------------------------------------------------+
+| device | user-defined mappers | :good:`done` | D56326,D58638,D58523,D58074,D60972,D59474 |
++------------------------------+--------------------------------------------------------------+--------------------------+-----------------------------------------------------------------------+
+| device | map array-section with implicit mapper | :good:`done` | https://github.com/llvm/llvm-project/pull/101101 |
++------------------------------+--------------------------------------------------------------+--------------------------+-----------------------------------------------------------------------+
+| device | mapping lambda expression | :good:`done` | D51107 |
++------------------------------+--------------------------------------------------------------+--------------------------+-----------------------------------------------------------------------+
+| device | clause: use_device_addr for target data | :good:`done` | |
++------------------------------+--------------------------------------------------------------+--------------------------+-----------------------------------------------------------------------+
+| device | support close modifier on map clause | :good:`done` | D55719,D55892 |
++------------------------------+--------------------------------------------------------------+--------------------------+-----------------------------------------------------------------------+
+| device | teams construct on the host device | :good:`done` | r371553 |
++------------------------------+--------------------------------------------------------------+--------------------------+-----------------------------------------------------------------------+
+| device | support non-contiguous array sections for target update | :good:`done` | |
++------------------------------+--------------------------------------------------------------+--------------------------+-----------------------------------------------------------------------+
+| device | pointer attachment | :good:`done` | |
++------------------------------+--------------------------------------------------------------+--------------------------+-----------------------------------------------------------------------+
+| atomic | hints for the atomic construct | :good:`done` | D51233 |
++------------------------------+--------------------------------------------------------------+--------------------------+-----------------------------------------------------------------------+
+| base language | C11 support | :good:`done` | |
++------------------------------+--------------------------------------------------------------+--------------------------+-----------------------------------------------------------------------+
+| base language | C++11/14/17 support | :good:`done` | |
++------------------------------+--------------------------------------------------------------+--------------------------+-----------------------------------------------------------------------+
+| base language | lambda support | :good:`done` | |
++------------------------------+--------------------------------------------------------------+--------------------------+-----------------------------------------------------------------------+
+| misc | array shaping | :good:`done` | D74144 |
++------------------------------+--------------------------------------------------------------+--------------------------+-----------------------------------------------------------------------+
+| misc | library shutdown (omp_pause_resource[_all]) | :good:`done` | D55078 |
++------------------------------+--------------------------------------------------------------+--------------------------+-----------------------------------------------------------------------+
+| misc | metadirectives | :part:`mostly done` | D91944, https://github.com/llvm/llvm-project/pull/128640 |
++------------------------------+--------------------------------------------------------------+--------------------------+-----------------------------------------------------------------------+
+| misc | conditional modifier for lastprivate clause | :good:`done` | |
++------------------------------+--------------------------------------------------------------+--------------------------+-----------------------------------------------------------------------+
+| misc | iterator and multidependences | :good:`done` | |
++------------------------------+--------------------------------------------------------------+--------------------------+-----------------------------------------------------------------------+
+| misc | depobj directive and depobj dependency kind | :good:`done` | |
++------------------------------+--------------------------------------------------------------+--------------------------+-----------------------------------------------------------------------+
+| misc | user-defined function variants | :good:`done`. | D67294, D64095, D71847, D71830, D109635 |
++------------------------------+--------------------------------------------------------------+--------------------------+-----------------------------------------------------------------------+
+| misc | pointer/reference to pointer based array reductions | :good:`done` | |
++------------------------------+--------------------------------------------------------------+--------------------------+-----------------------------------------------------------------------+
+| misc | prevent new type definitions in clauses | :good:`done` | |
++------------------------------+--------------------------------------------------------------+--------------------------+-----------------------------------------------------------------------+
+| memory model | memory model update (seq_cst, acq_rel, release, acquire,...) | :good:`done` | |
++------------------------------+--------------------------------------------------------------+--------------------------+-----------------------------------------------------------------------+
+
+
+.. _OpenMP 51 implementation details:
+
+OpenMP 5.1 Implementation Details
+=================================
+
+The following table provides a quick overview over various OpenMP 5.1 features
+and their implementation status.
+Please post on the
+`Discourse forums (Runtimes - OpenMP category)`_ for more
+information or if you want to help with the
+implementation.
+
++------------------------------+--------------------------------------------------------------+--------------------------+-----------------------------------------------------------------------+
+|Category | Feature | Status | Reviews |
++==============================+==============================================================+==========================+=======================================================================+
+| atomic | 'compare' clause on atomic construct | :good:`done` | D120290, D120007, D118632, D120200, D116261, D118547, D116637 |
++------------------------------+--------------------------------------------------------------+--------------------------+-----------------------------------------------------------------------+
+| atomic | 'fail' clause on atomic construct | :part:`worked on` | D123235 (in progress) |
++------------------------------+--------------------------------------------------------------+--------------------------+-----------------------------------------------------------------------+
+| base language | C++ attribute specifier syntax | :good:`done` | D105648 |
++------------------------------+--------------------------------------------------------------+--------------------------+-----------------------------------------------------------------------+
+| device | 'present' map type modifier | :good:`done` | D83061, D83062, D84422 |
++------------------------------+--------------------------------------------------------------+--------------------------+-----------------------------------------------------------------------+
+| device | 'present' motion modifier | :good:`done` | D84711, D84712 |
++------------------------------+--------------------------------------------------------------+--------------------------+-----------------------------------------------------------------------+
+| device | 'present' in defaultmap clause | :good:`done` | D92427 |
++------------------------------+--------------------------------------------------------------+--------------------------+-----------------------------------------------------------------------+
+| device | map clause reordering based on 'present' modifier | :none:`unclaimed` | |
++------------------------------+--------------------------------------------------------------+--------------------------+-----------------------------------------------------------------------+
+| device | device-specific environment variables | :none:`unclaimed` | |
++------------------------------+--------------------------------------------------------------+--------------------------+-----------------------------------------------------------------------+
+| device | omp_target_is_accessible routine | :none:`unclaimed` | |
++------------------------------+--------------------------------------------------------------+--------------------------+-----------------------------------------------------------------------+
+| device | omp_get_mapped_ptr routine | :good:`done` | D141545 |
++------------------------------+--------------------------------------------------------------+--------------------------+-----------------------------------------------------------------------+
+| device | new async target memory copy routines | :good:`done` | D136103 |
++------------------------------+--------------------------------------------------------------+--------------------------+-----------------------------------------------------------------------+
+| device | thread_limit clause on target construct | :part:`partial` | D141540 (offload), D152054 (host, in progress) |
++------------------------------+--------------------------------------------------------------+--------------------------+-----------------------------------------------------------------------+
+| device | has_device_addr clause on target construct | :none:`unclaimed` | |
++------------------------------+--------------------------------------------------------------+--------------------------+-----------------------------------------------------------------------+
+| device | iterators in map clause or motion clauses | :none:`unclaimed` | |
++------------------------------+--------------------------------------------------------------+--------------------------+-----------------------------------------------------------------------+
+| device | indirect clause on declare target directive | :part:`In Progress` | |
++------------------------------+--------------------------------------------------------------+--------------------------+-----------------------------------------------------------------------+
+| device | allow virtual functions calls for mapped object on device | :part:`partial` | |
++------------------------------+--------------------------------------------------------------+--------------------------+-----------------------------------------------------------------------+
+| device | interop construct | :part:`partial` | parsing/sema done: D98558, D98834, D98815 |
++------------------------------+--------------------------------------------------------------+--------------------------+-----------------------------------------------------------------------+
+| device | assorted routines for querying interoperable properties | :part:`partial` | D106674 |
++------------------------------+--------------------------------------------------------------+--------------------------+-----------------------------------------------------------------------+
+| loop | Loop tiling transformation | :good:`done` | D76342 |
++------------------------------+--------------------------------------------------------------+--------------------------+-----------------------------------------------------------------------+
+| loop | Loop unrolling transformation | :good:`done` | D99459 |
++------------------------------+--------------------------------------------------------------+--------------------------+-----------------------------------------------------------------------+
+| loop | 'reproducible'/'unconstrained' modifiers in 'order' clause | :part:`partial` | D127855 |
++------------------------------+--------------------------------------------------------------+--------------------------+-----------------------------------------------------------------------+
+| memory management | alignment for allocate directive and clause | :good:`done` | D115683 |
++------------------------------+--------------------------------------------------------------+--------------------------+-----------------------------------------------------------------------+
+| memory management | 'allocator' modifier for allocate clause | :good:`done` | https://github.com/llvm/llvm-project/pull/114883 |
++------------------------------+--------------------------------------------------------------+--------------------------+-----------------------------------------------------------------------+
+| memory management | 'align' modifier for allocate clause | :good:`done` | https://github.com/llvm/llvm-project/pull/121814 |
++------------------------------+--------------------------------------------------------------+--------------------------+-----------------------------------------------------------------------+
+| memory management | new memory management routines | :none:`unclaimed` | |
++------------------------------+--------------------------------------------------------------+--------------------------+-----------------------------------------------------------------------+
+| memory management | changes to omp_alloctrait_key enum | :none:`unclaimed` | |
++------------------------------+--------------------------------------------------------------+--------------------------+-----------------------------------------------------------------------+
+| memory model | seq_cst clause on flush construct | :good:`done` | https://github.com/llvm/llvm-project/pull/114072 |
++------------------------------+--------------------------------------------------------------+--------------------------+-----------------------------------------------------------------------+
+| misc | 'omp_all_memory' keyword and use in 'depend' clause | :good:`done` | D125828, D126321 |
++------------------------------+--------------------------------------------------------------+--------------------------+-----------------------------------------------------------------------+
+| misc | error directive | :good:`done` | D139166 |
++------------------------------+--------------------------------------------------------------+--------------------------+-----------------------------------------------------------------------+
+| misc | scope construct | :good:`done` | D157933, https://github.com/llvm/llvm-project/pull/109197 |
++------------------------------+--------------------------------------------------------------+--------------------------+-----------------------------------------------------------------------+
+| misc | routines for controlling and querying team regions | :part:`partial` | D95003 (libomp only) |
++------------------------------+--------------------------------------------------------------+--------------------------+-----------------------------------------------------------------------+
+| misc | changes to ompt_scope_endpoint_t enum | :none:`unclaimed` | |
++------------------------------+--------------------------------------------------------------+--------------------------+-----------------------------------------------------------------------+
+| misc | omp_display_env routine | :good:`done` | D74956 |
++------------------------------+--------------------------------------------------------------+--------------------------+-----------------------------------------------------------------------+
+| misc | extended OMP_PLACES syntax | :none:`unclaimed` | |
++------------------------------+--------------------------------------------------------------+--------------------------+-----------------------------------------------------------------------+
+| misc | OMP_NUM_TEAMS and OMP_TEAMS_THREAD_LIMIT env vars | :good:`done` | D138769 |
++------------------------------+--------------------------------------------------------------+--------------------------+-----------------------------------------------------------------------+
+| misc | 'target_device' selector in context specifier | :none:`worked on` | |
++------------------------------+--------------------------------------------------------------+--------------------------+-----------------------------------------------------------------------+
+| misc | begin/end declare variant | :good:`done` | D71179 |
++------------------------------+--------------------------------------------------------------+--------------------------+-----------------------------------------------------------------------+
+| misc | dispatch construct and function variant argument adjustment | :part:`worked on` | D99537, D99679 |
++------------------------------+--------------------------------------------------------------+--------------------------+-----------------------------------------------------------------------+
+| misc | assumes directives | :part:`worked on` | |
++------------------------------+--------------------------------------------------------------+--------------------------+-----------------------------------------------------------------------+
+| misc | assume directive | :good:`done` | |
++------------------------------+--------------------------------------------------------------+--------------------------+-----------------------------------------------------------------------+
+| misc | nothing directive | :good:`done` | D123286 |
++------------------------------+--------------------------------------------------------------+--------------------------+-----------------------------------------------------------------------+
+| misc | masked construct and related combined constructs | :good:`done` | D99995, D100514, PR-121741(parallel_masked_taskloop) |
+| | | | PR-121746(parallel_masked_task_loop_simd),PR-121914(masked_taskloop) |
+| | | | PR-121916(masked_taskloop_simd) |
++------------------------------+--------------------------------------------------------------+--------------------------+-----------------------------------------------------------------------+
+| misc | default(firstprivate) & default(private) | :good:`done` | D75591 (firstprivate), D125912 (private) |
++------------------------------+--------------------------------------------------------------+--------------------------+-----------------------------------------------------------------------+
+| other | deprecating master construct | :none:`unclaimed` | |
++------------------------------+--------------------------------------------------------------+--------------------------+-----------------------------------------------------------------------+
+| OMPT | new barrier types added to ompt_sync_region_t enum | :none:`unclaimed` | |
++------------------------------+--------------------------------------------------------------+--------------------------+-----------------------------------------------------------------------+
+| OMPT | async data transfers added to ompt_target_data_op_t enum | :none:`unclaimed` | |
++------------------------------+--------------------------------------------------------------+--------------------------+-----------------------------------------------------------------------+
+| OMPT | new barrier state values added to ompt_state_t enum | :none:`unclaimed` | |
++------------------------------+--------------------------------------------------------------+--------------------------+-----------------------------------------------------------------------+
+| OMPT | new 'emi' callbacks for external monitoring interfaces | :good:`done` | |
++------------------------------+--------------------------------------------------------------+--------------------------+-----------------------------------------------------------------------+
+| OMPT | device tracing interface | :none:`unclaimed` | |
++------------------------------+--------------------------------------------------------------+--------------------------+-----------------------------------------------------------------------+
+| task | 'strict' modifier for taskloop construct | :none:`unclaimed` | |
++------------------------------+--------------------------------------------------------------+--------------------------+-----------------------------------------------------------------------+
+| task | inoutset in depend clause | :good:`done` | D97085, D118383 |
++------------------------------+--------------------------------------------------------------+--------------------------+-----------------------------------------------------------------------+
+| task | nowait clause on taskwait | :part:`partial` | parsing/sema done: D131830, D141531 |
++------------------------------+--------------------------------------------------------------+--------------------------+-----------------------------------------------------------------------+
+
+
+.. _OpenMP 6.0 implementation details:
+
+OpenMP 6.0 Implementation Details
+=================================
+
+The following table provides a quick overview over various OpenMP 6.0 features
+and their implementation status. Please post on the
+`Discourse forums (Runtimes - OpenMP category)`_ for more
+information or if you want to help with the
+implementation.
+
++-------------------------------------------------------------+---------------------------+---------------------------+--------------------------------------------------------------------------+
+|Feature | C/C++ Status | Fortran Status | Reviews |
++=============================================================+===========================+===========================+==========================================================================+
+| free-agent threads | :none:`unclaimed` | :none:`unclaimed` | |
++-------------------------------------------------------------+---------------------------+---------------------------+--------------------------------------------------------------------------+
+| threadset clause | :`worked on` | :none:`unclaimed` | |
++-------------------------------------------------------------+---------------------------+---------------------------+--------------------------------------------------------------------------+
+| Recording of task graphs | :none:`unclaimed` | :none:`unclaimed` | |
++-------------------------------------------------------------+---------------------------+---------------------------+--------------------------------------------------------------------------+
+| Parallel inductions | :none:`unclaimed` | :none:`unclaimed` | |
++-------------------------------------------------------------+---------------------------+---------------------------+--------------------------------------------------------------------------+
+| init_complete for scan directive | :none:`unclaimed` | :none:`unclaimed` | |
++-------------------------------------------------------------+---------------------------+---------------------------+--------------------------------------------------------------------------+
+| Loop transformation constructs | :none:`unclaimed` | :none:`unclaimed` | |
++-------------------------------------------------------------+---------------------------+---------------------------+--------------------------------------------------------------------------+
+| loop stripe transformation | :good:`done` | https://github.com/llvm/llvm-project/pull/119891 |
++-------------------------------------------------------------+---------------------------+---------------------------+--------------------------------------------------------------------------+
+| work distribute construct | :none:`unclaimed` | :none:`unclaimed` | |
++-------------------------------------------------------------+---------------------------+---------------------------+--------------------------------------------------------------------------+
+| task_iteration | :none:`unclaimed` | :none:`unclaimed` | |
++-------------------------------------------------------------+---------------------------+---------------------------+--------------------------------------------------------------------------+
+| memscope clause for atomic and flush | :none:`unclaimed` | :none:`unclaimed` | |
++-------------------------------------------------------------+---------------------------+---------------------------+--------------------------------------------------------------------------+
+| transparent clause (hull tasks) | :none:`unclaimed` | :none:`unclaimed` | |
++-------------------------------------------------------------+---------------------------+---------------------------+--------------------------------------------------------------------------+
+| rule-based compound directives | :none:`unclaimed` | :part:`In Progress` | Testing for Fortran missing |
++-------------------------------------------------------------+---------------------------+---------------------------+--------------------------------------------------------------------------+
+| C23, C++23 | :none:`unclaimed` | :none:`unclaimed` | |
++-------------------------------------------------------------+---------------------------+---------------------------+--------------------------------------------------------------------------+
+| Fortran 2023 | :none:`unclaimed` | :none:`unclaimed` | |
++-------------------------------------------------------------+---------------------------+---------------------------+--------------------------------------------------------------------------+
+| decl attribute for declarative directives | :none:`unclaimed` | :none:`unclaimed` | |
++-------------------------------------------------------------+---------------------------+---------------------------+--------------------------------------------------------------------------+
+| C attribute syntax | :none:`unclaimed` | :none:`unclaimed` | |
++-------------------------------------------------------------+---------------------------+---------------------------+--------------------------------------------------------------------------+
+| pure directives in DO CONCURRENT | :none:`unclaimed` | :none:`unclaimed` | |
++-------------------------------------------------------------+---------------------------+---------------------------+--------------------------------------------------------------------------+
+| Optional argument for all clauses | :none:`unclaimed` | :none:`unclaimed` | |
++-------------------------------------------------------------+---------------------------+---------------------------+--------------------------------------------------------------------------+
+| Function references for locator list items | :none:`unclaimed` | :none:`unclaimed` | |
++-------------------------------------------------------------+---------------------------+---------------------------+--------------------------------------------------------------------------+
+| All clauses accept directive name modifier | :none:`unclaimed` | :none:`unclaimed` | |
++-------------------------------------------------------------+---------------------------+---------------------------+--------------------------------------------------------------------------+
+| Extensions to depobj construct | :none:`unclaimed` | :none:`unclaimed` | |
++-------------------------------------------------------------+---------------------------+---------------------------+--------------------------------------------------------------------------+
+| Extensions to atomic construct | :none:`unclaimed` | :none:`unclaimed` | |
++-------------------------------------------------------------+---------------------------+---------------------------+--------------------------------------------------------------------------+
+| Private reductions | :good:`mostly` | :none:`unclaimed` | Parse/Sema:https://github.com/llvm/llvm-project/pull/129938 |
+| | | | Codegen: https://github.com/llvm/llvm-project/pull/134709 |
++-------------------------------------------------------------+---------------------------+---------------------------+--------------------------------------------------------------------------+
+| Self maps | :part:`partial` | :none:`unclaimed` | parsing/sema done: https://github.com/llvm/llvm-project/pull/129888 |
++-------------------------------------------------------------+---------------------------+---------------------------+--------------------------------------------------------------------------+
+| Release map type for declare mapper | :none:`unclaimed` | :none:`unclaimed` | |
++-------------------------------------------------------------+---------------------------+---------------------------+--------------------------------------------------------------------------+
+| Extensions to interop construct | :none:`unclaimed` | :none:`unclaimed` | |
++-------------------------------------------------------------+---------------------------+---------------------------+--------------------------------------------------------------------------+
+| no_openmp_constructs | :good:`done` | :none:`unclaimed` | https://github.com/llvm/llvm-project/pull/125933 |
++-------------------------------------------------------------+---------------------------+---------------------------+--------------------------------------------------------------------------+
+| safe_sync and progress with identifier and API | :none:`unclaimed` | :none:`unclaimed` | |
++-------------------------------------------------------------+---------------------------+---------------------------+--------------------------------------------------------------------------+
+| OpenMP directives in concurrent loop regions | :good:`done` | :none:`unclaimed` | https://github.com/llvm/llvm-project/pull/125621 |
++-------------------------------------------------------------+---------------------------+---------------------------+--------------------------------------------------------------------------+
+| atomics constructs on concurrent loop regions | :good:`done` | :none:`unclaimed` | https://github.com/llvm/llvm-project/pull/125621 |
++-------------------------------------------------------------+---------------------------+---------------------------+--------------------------------------------------------------------------+
+| Loop construct with DO CONCURRENT | :none:`unclaimed` | :part:`In Progress` | |
++-------------------------------------------------------------+---------------------------+---------------------------+--------------------------------------------------------------------------+
+| device_type clause for target construct | :none:`unclaimed` | :none:`unclaimed` | |
++-------------------------------------------------------------+---------------------------+---------------------------+--------------------------------------------------------------------------+
+| nowait for ancestor target directives | :none:`unclaimed` | :none:`unclaimed` | |
++-------------------------------------------------------------+---------------------------+---------------------------+--------------------------------------------------------------------------+
+| New API for devices' num_teams/thread_limit | :none:`unclaimed` | :none:`unclaimed` | |
++-------------------------------------------------------------+---------------------------+---------------------------+--------------------------------------------------------------------------+
+| Host and device environment variables | :none:`unclaimed` | :none:`unclaimed` | |
++-------------------------------------------------------------+---------------------------+---------------------------+--------------------------------------------------------------------------+
+| num_threads ICV and clause accepts list | :none:`unclaimed` | :none:`unclaimed` | |
++-------------------------------------------------------------+---------------------------+---------------------------+--------------------------------------------------------------------------+
+| Numeric names for environment variables | :none:`unclaimed` | :none:`unclaimed` | |
++-------------------------------------------------------------+---------------------------+---------------------------+--------------------------------------------------------------------------+
+| Increment between places for OMP_PLACES | :none:`unclaimed` | :none:`unclaimed` | |
++-------------------------------------------------------------+---------------------------+---------------------------+--------------------------------------------------------------------------+
+| OMP_AVAILABLE_DEVICES envirable | :none:`unclaimed` | :none:`unclaimed` | |
++-------------------------------------------------------------+---------------------------+---------------------------+--------------------------------------------------------------------------+
+| Traits for default device envirable | :none:`unclaimed` | :none:`unclaimed` | |
++-------------------------------------------------------------+---------------------------+---------------------------+--------------------------------------------------------------------------+
+| Optionally omit array length expression | :good:`done` | :none:`unclaimed` | https://github.com/llvm/llvm-project/pull/148048 |
++-------------------------------------------------------------+---------------------------+---------------------------+--------------------------------------------------------------------------+
+| Canonical loop sequences | :none:`unclaimed` | :part:`In Progress` | |
++-------------------------------------------------------------+---------------------------+---------------------------+--------------------------------------------------------------------------+
+| Clarifications to Fortran map semantics | :none:`unclaimed` | :none:`unclaimed` | |
++-------------------------------------------------------------+---------------------------+---------------------------+--------------------------------------------------------------------------+
+| default clause at target construct | :part:`In Progress` | :none:`unclaimed` | |
++-------------------------------------------------------------+---------------------------+---------------------------+--------------------------------------------------------------------------+
+| ref count update use_device_{ptr, addr} | :none:`unclaimed` | :none:`unclaimed` | |
++-------------------------------------------------------------+---------------------------+---------------------------+--------------------------------------------------------------------------+
+| Clarifications to implicit reductions | :none:`unclaimed` | :none:`unclaimed` | |
++-------------------------------------------------------------+---------------------------+---------------------------+--------------------------------------------------------------------------+
+| ref modifier for map clauses | :part:`In Progress` | :none:`unclaimed` | |
++-------------------------------------------------------------+---------------------------+---------------------------+--------------------------------------------------------------------------+
+| map-type modifiers in arbitrary position | :good:`done` | :none:`unclaimed` | https://github.com/llvm/llvm-project/pull/90499 |
++-------------------------------------------------------------+---------------------------+---------------------------+--------------------------------------------------------------------------+
+| Lift nesting restriction on concurrent loop | :good:`done` | :none:`unclaimed` | https://github.com/llvm/llvm-project/pull/125621 |
++-------------------------------------------------------------+---------------------------+---------------------------+--------------------------------------------------------------------------+
+| priority clause for target constructs | :none:`unclaimed` | :none:`unclaimed` | |
++-------------------------------------------------------------+---------------------------+---------------------------+--------------------------------------------------------------------------+
+| changes to target_data construct | :none:`unclaimed` | :none:`unclaimed` | |
++-------------------------------------------------------------+---------------------------+---------------------------+--------------------------------------------------------------------------+
+| Non-const do_not_sync for nowait/nogroup | :none:`unclaimed` | :none:`unclaimed` | |
++-------------------------------------------------------------+---------------------------+---------------------------+--------------------------------------------------------------------------+
+| need_device_addr modifier for adjust_args clause | :part:`partial` | :none:`unclaimed` | Parsing/Sema: https://github.com/llvm/llvm-project/pull/143442 |
+| | | | https://github.com/llvm/llvm-project/pull/149586 |
++-------------------------------------------------------------+---------------------------+---------------------------+--------------------------------------------------------------------------+
+| Prescriptive num_threads | :part:`In Progress` | :none:`unclaimed` | |
++-------------------------------------------------------------+---------------------------+---------------------------+--------------------------------------------------------------------------+
+| Message and severity clauses | :part:`In Progress` | :none:`unclaimed` | |
++-------------------------------------------------------------+---------------------------+---------------------------+--------------------------------------------------------------------------+
+| Local clause on declare target | :part:`In Progress` | :none:`unclaimed` | |
++-------------------------------------------------------------+---------------------------+---------------------------+--------------------------------------------------------------------------+
+
+OpenMP Extensions
+=================
+
+The following table provides a quick overview over various OpenMP
+extensions and their implementation status. These extensions are not
+currently defined by any standard, so links to associated LLVM
+documentation are provided. As these extensions mature, they will be
+considered for standardization. Please post on the
+`Discourse forums (Runtimes - OpenMP category)`_ to provide feedback.
+
++------------------------------+-----------------------------------------------------------------------------------+--------------------------+--------------------------------------------------------+
+|Category | Feature | Status | Reviews |
++==============================+===================================================================================+==========================+========================================================+
+| atomic extension | `'atomic' strictly nested within 'teams' | :good:`prototyped` | D126323 |
+| | <https://openmp.llvm.org/docs/openacc/OpenMPExtensions.html#atomicWithinTeams>`_ | | |
++------------------------------+-----------------------------------------------------------------------------------+--------------------------+--------------------------------------------------------+
+| device extension | `'ompx_hold' map type modifier | :good:`prototyped` | D106509, D106510 |
+| | <https://openmp.llvm.org/docs/openacc/OpenMPExtensions.html#ompx-hold>`_ | | |
++------------------------------+-----------------------------------------------------------------------------------+--------------------------+--------------------------------------------------------+
+| device extension | `'ompx_bare' clause on 'target teams' construct | :good:`prototyped` | #66844, #70612 |
+| | <https://www.osti.gov/servlets/purl/2205717>`_ | | |
++------------------------------+-----------------------------------------------------------------------------------+--------------------------+--------------------------------------------------------+
+| device extension | Multi-dim 'num_teams' and 'thread_limit' clause on 'target teams ompx_bare' | :good:`partial` | #99732, #101407, #102715 |
+| | construct | | |
++------------------------------+-----------------------------------------------------------------------------------+--------------------------+--------------------------------------------------------+
+
+.. _Discourse forums (Runtimes - OpenMP category): https://discourse.llvm.org/c/runtimes/openmp/35
diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst index ec51ffd..95a0bbf 100644 --- a/clang/docs/ReleaseNotes.rst +++ b/clang/docs/ReleaseNotes.rst @@ -89,9 +89,18 @@ Non-comprehensive list of changes in this release ------------------------------------------------- - Added ``__builtin_elementwise_minnumnum`` and ``__builtin_elementwise_maxnumnum``. +- Trapping UBSan (e.g. ``-fsanitize-trap=undefined``) now emits a string describing the reason for + trapping into the generated debug info. This feature allows debuggers (e.g. LLDB) to display + the reason for trapping if the trap is reached. The string is currently encoded in the debug + info as an artificial frame that claims to be inlined at the trap location. The function used + for the artificial frame is an artificial function whose name encodes the reason for trapping. + The encoding used is currently the same as ``__builtin_verbose_trap`` but might change in the future. + This feature is enabled by default but can be disabled by compiling with + ``-fno-sanitize-annotate-debug-info-traps``. New Compiler Flags ------------------ +- New option ``-fno-sanitize-annotate-debug-info-traps`` added to disable emitting trap reasons into the debug info when compiling with trapping UBSan (e.g. ``-fsanitize-trap=undefined``). Deprecated Compiler Flags ------------------------- diff --git a/clang/include/clang/AST/ASTContext.h b/clang/include/clang/AST/ASTContext.h index 17cbfb2..0273109 100644 --- a/clang/include/clang/AST/ASTContext.h +++ b/clang/include/clang/AST/ASTContext.h @@ -238,9 +238,9 @@ class ASTContext : public RefCountedBase<ASTContext> { mutable llvm::FoldingSet<ElaboratedType> ElaboratedTypes{ GeneralTypesLog2InitSize}; mutable llvm::FoldingSet<DependentNameType> DependentNameTypes; - mutable llvm::ContextualFoldingSet<DependentTemplateSpecializationType, - ASTContext&> - DependentTemplateSpecializationTypes; + mutable llvm::DenseMap<llvm::FoldingSetNodeID, + DependentTemplateSpecializationType *> + DependentTemplateSpecializationTypes; mutable llvm::FoldingSet<PackExpansionType> PackExpansionTypes; mutable llvm::FoldingSet<ObjCObjectTypeImpl> ObjCObjectTypes; mutable llvm::FoldingSet<ObjCObjectPointerType> ObjCObjectPointerTypes; diff --git a/clang/include/clang/AST/Type.h b/clang/include/clang/AST/Type.h index 764e9d50..98810fb 100644 --- a/clang/include/clang/AST/Type.h +++ b/clang/include/clang/AST/Type.h @@ -7276,8 +7276,7 @@ public: /// Represents a template specialization type whose template cannot be /// resolved, e.g. /// A<T>::template B<T> -class DependentTemplateSpecializationType : public TypeWithKeyword, - public llvm::FoldingSetNode { +class DependentTemplateSpecializationType : public TypeWithKeyword { friend class ASTContext; // ASTContext creates these DependentTemplateStorage Name; diff --git a/clang/include/clang/Basic/BuiltinsAMDGPU.def b/clang/include/clang/Basic/BuiltinsAMDGPU.def index 0b16e12..945e11b 100644 --- a/clang/include/clang/Basic/BuiltinsAMDGPU.def +++ b/clang/include/clang/Basic/BuiltinsAMDGPU.def @@ -645,6 +645,13 @@ TARGET_BUILTIN(__builtin_amdgcn_cvt_sr_f16_f32, "V2hV2hfUiIb", "nc", "f32-to-f16 TARGET_BUILTIN(__builtin_amdgcn_flat_prefetch, "vvC*0Ii", "nc", "vmem-pref-insts") TARGET_BUILTIN(__builtin_amdgcn_global_prefetch, "vvC*1Ii", "nc", "vmem-pref-insts") +TARGET_BUILTIN(__builtin_amdgcn_global_load_monitor_b32, "ii*1Ii", "nc", "gfx1250-insts") +TARGET_BUILTIN(__builtin_amdgcn_global_load_monitor_b64, "V2iV2i*1Ii", "nc", "gfx1250-insts") +TARGET_BUILTIN(__builtin_amdgcn_global_load_monitor_b128, "V4iV4i*1Ii", "nc", "gfx1250-insts") +TARGET_BUILTIN(__builtin_amdgcn_flat_load_monitor_b32, "ii*0Ii", "nc", "gfx1250-insts") +TARGET_BUILTIN(__builtin_amdgcn_flat_load_monitor_b64, "V2iV2i*0Ii", "nc", "gfx1250-insts") +TARGET_BUILTIN(__builtin_amdgcn_flat_load_monitor_b128, "V4iV4i*0Ii", "nc", "gfx1250-insts") + TARGET_BUILTIN(__builtin_amdgcn_tensor_load_to_lds, "vV4iV8iV4iV4iIi", "nc", "gfx1250-insts") TARGET_BUILTIN(__builtin_amdgcn_tensor_load_to_lds_d2, "vV4iV8iIi", "nc", "gfx1250-insts") TARGET_BUILTIN(__builtin_amdgcn_tensor_store_from_lds, "vV4iV8iV4iV4iIi", "nc", "gfx1250-insts") diff --git a/clang/include/clang/Basic/BuiltinsWebAssembly.def b/clang/include/clang/Basic/BuiltinsWebAssembly.def index e2afcc0..d31b726 100644 --- a/clang/include/clang/Basic/BuiltinsWebAssembly.def +++ b/clang/include/clang/Basic/BuiltinsWebAssembly.def @@ -199,6 +199,12 @@ TARGET_BUILTIN(__builtin_wasm_ref_is_null_extern, "ii", "nct", "reference-types" // return type. TARGET_BUILTIN(__builtin_wasm_ref_null_func, "i", "nct", "reference-types") +// Check if the runtime type of a function pointer matches its static type. Used +// to avoid "function signature mismatch" traps. Takes a function pointer, uses +// table.get to look up the pointer in __indirect_function_table and then +// ref.test to test the type. +TARGET_BUILTIN(__builtin_wasm_test_function_pointer_signature, "i.", "nct", "gc") + // Table builtins TARGET_BUILTIN(__builtin_wasm_table_set, "viii", "t", "reference-types") TARGET_BUILTIN(__builtin_wasm_table_get, "iii", "t", "reference-types") diff --git a/clang/include/clang/Basic/CodeGenOptions.def b/clang/include/clang/Basic/CodeGenOptions.def index e137738..423b696 100644 --- a/clang/include/clang/Basic/CodeGenOptions.def +++ b/clang/include/clang/Basic/CodeGenOptions.def @@ -307,6 +307,7 @@ CODEGENOPT(SanitizeBinaryMetadataAtomics, 1, 0, Benign) ///< Emit PCs for atomic CODEGENOPT(SanitizeBinaryMetadataUAR, 1, 0, Benign) ///< Emit PCs for start of functions ///< that are subject for use-after-return checking. CODEGENOPT(SanitizeStats , 1, 0, Benign) ///< Collect statistics for sanitizers. +CODEGENOPT(SanitizeDebugTrapReasons, 1, 1 , Benign) ///< Enable UBSan trapping messages CODEGENOPT(SimplifyLibCalls , 1, 1, Benign) ///< Set when -fbuiltin is enabled. CODEGENOPT(SoftFloat , 1, 0, Benign) ///< -soft-float. CODEGENOPT(SpeculativeLoadHardening, 1, 0, Benign) ///< Enable speculative load hardening. diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td index 4a21321..81cbd38 100644 --- a/clang/include/clang/Basic/DiagnosticSemaKinds.td +++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td @@ -7575,6 +7575,8 @@ def err_typecheck_illegal_increment_decrement : Error< "cannot %select{decrement|increment}1 value of type %0">; def err_typecheck_expect_int : Error< "used type %0 where integer is required">; +def err_typecheck_expect_function_pointer + : Error<"used type %0 where function pointer is required">; def err_typecheck_expect_hlsl_resource : Error< "used type %0 where __hlsl_resource_t is required">; def err_typecheck_arithmetic_incomplete_or_sizeless_type : Error< @@ -13202,6 +13204,10 @@ def err_wasm_builtin_arg_must_match_table_element_type : Error < "%ordinal0 argument must match the element type of the WebAssembly table in the %ordinal1 argument">; def err_wasm_builtin_arg_must_be_integer_type : Error < "%ordinal0 argument must be an integer">; +def err_wasm_builtin_test_fp_sig_cannot_include_reference_type + : Error<"not supported for " + "function pointers with a reference type %select{return " + "value|parameter}0">; // OpenACC diagnostics. def warn_acc_routine_unimplemented @@ -13257,6 +13263,11 @@ def err_acc_not_a_var_ref def err_acc_not_a_var_ref_use_device_declare : Error<"OpenACC variable %select{in 'use_device' clause|on 'declare' " "construct}0 is not a valid variable name or array name">; +def ext_acc_array_section_use_device_declare + : Extension< + "sub-array as a variable %select{in 'use_device' clause|on " + "'declare' construct}0 is not a valid variable name or array name">, + InGroup<DiagGroup<"openacc-extension">>; def err_acc_not_a_var_ref_cache : Error<"OpenACC variable in 'cache' directive is not a valid sub-array or " "array element">; @@ -13318,8 +13329,9 @@ def err_acc_reduction_num_gangs_conflict "appear on a '%2' construct " "with a '%3' clause%select{ with more than 1 argument|}0">; def err_acc_reduction_type - : Error<"OpenACC 'reduction' variable must be of scalar type, sub-array, or a " - "composite of scalar types;%select{| sub-array base}1 type is %0">; + : Error<"OpenACC 'reduction' variable must be of scalar type, aggregate, " + "sub-array, or a composite of scalar types;%select{| sub-array " + "base}1 type is %0">; def err_acc_reduction_composite_type : Error<"OpenACC 'reduction' variable must be a composite of scalar types; " "%1 %select{is not a class or struct|is incomplete|is not an " diff --git a/clang/include/clang/CIR/Dialect/IR/CIRAttrs.td b/clang/include/clang/CIR/Dialect/IR/CIRAttrs.td index 29d8aea..9961544 100644 --- a/clang/include/clang/CIR/Dialect/IR/CIRAttrs.td +++ b/clang/include/clang/CIR/Dialect/IR/CIRAttrs.td @@ -147,6 +147,18 @@ def UndefAttr : CIR_TypedAttr<"Undef", "undef"> { } //===----------------------------------------------------------------------===// +// PoisonAttr +//===----------------------------------------------------------------------===// + +def CIR_PoisonAttr : CIR_TypedAttr<"Poison", "poison"> { + let summary = "Represent a typed poison constant"; + let description = [{ + The PoisonAttr represents a typed poison constant, corresponding to LLVM's + notion of poison. + }]; +} + +//===----------------------------------------------------------------------===// // IntegerAttr //===----------------------------------------------------------------------===// diff --git a/clang/include/clang/CIR/Dialect/IR/CIROps.td b/clang/include/clang/CIR/Dialect/IR/CIROps.td index 32bb900..e2ddbd1 100644 --- a/clang/include/clang/CIR/Dialect/IR/CIROps.td +++ b/clang/include/clang/CIR/Dialect/IR/CIROps.td @@ -2817,6 +2817,8 @@ class CIR_BitOpBase<string mnemonic, TypeConstraint operandTy> let assemblyFormat = [{ $input `:` type($result) attr-dict }]; + + let hasFolder = 1; } class CIR_BitZeroCountOpBase<string mnemonic, TypeConstraint operandTy> @@ -3024,6 +3026,8 @@ def CIR_RotateOp : CIR_Op<"rotate", [Pure, SameOperandsAndResultType]> { bool isRotateLeft() { return getRotateLeft(); } bool isRotateRight() { return !getRotateLeft(); } }]; + + let hasFolder = 1; } //===----------------------------------------------------------------------===// diff --git a/clang/include/clang/Driver/Options.td b/clang/include/clang/Driver/Options.td index fa24838..e2ab046 100644 --- a/clang/include/clang/Driver/Options.td +++ b/clang/include/clang/Driver/Options.td @@ -2320,21 +2320,21 @@ def fsymbol_partition_EQ : Joined<["-"], "fsymbol-partition=">, Group<f_Group>, defm atomic_remote_memory : BoolFOption<"atomic-remote-memory", LangOpts<"AtomicRemoteMemory">, DefaultFalse, - PosFlag<SetTrue, [], [ClangOption, CC1Option, FlangOption, FC1Option], "May have">, - NegFlag<SetFalse, [], [ClangOption, FlangOption], "Assume no">, - BothFlags<[], [ClangOption, FlangOption], " atomic operations on remote memory">>; + PosFlag<SetTrue, [], [ClangOption, CC1Option], "May have">, + NegFlag<SetFalse, [], [ClangOption], "Assume no">, + BothFlags<[], [ClangOption], " atomic operations on remote memory">>; defm atomic_fine_grained_memory : BoolFOption<"atomic-fine-grained-memory", LangOpts<"AtomicFineGrainedMemory">, DefaultFalse, - PosFlag<SetTrue, [], [ClangOption, CC1Option, FlangOption, FC1Option], "May have">, - NegFlag<SetFalse, [], [ClangOption, FlangOption], "Assume no">, - BothFlags<[], [ClangOption, FlangOption], " atomic operations on fine-grained memory">>; + PosFlag<SetTrue, [], [ClangOption, CC1Option], "May have">, + NegFlag<SetFalse, [], [ClangOption], "Assume no">, + BothFlags<[], [ClangOption], " atomic operations on fine-grained memory">>; defm atomic_ignore_denormal_mode : BoolFOption<"atomic-ignore-denormal-mode", LangOpts<"AtomicIgnoreDenormalMode">, DefaultFalse, - PosFlag<SetTrue, [], [ClangOption, CC1Option, FlangOption, FC1Option], "Allow">, - NegFlag<SetFalse, [], [ClangOption, FlangOption], "Disallow">, - BothFlags<[], [ClangOption, FlangOption], " atomic operations to ignore denormal mode">>; + PosFlag<SetTrue, [], [ClangOption, CC1Option], "Allow">, + NegFlag<SetFalse, [], [ClangOption], "Disallow">, + BothFlags<[], [ClangOption], " atomic operations to ignore denormal mode">>; defm memory_profile : OptInCC1FFlag<"memory-profile", "Enable", "Disable", " heap memory profiling">; def fmemory_profile_EQ : Joined<["-"], "fmemory-profile=">, @@ -2597,6 +2597,16 @@ def fsanitize_undefined_trap_on_error def fno_sanitize_undefined_trap_on_error : Flag<["-"], "fno-sanitize-undefined-trap-on-error">, Group<f_clang_Group>, Alias<fno_sanitize_trap_EQ>, AliasArgs<["undefined"]>; +defm sanitize_debug_trap_reasons + : BoolFOption< + "sanitize-debug-trap-reasons", + CodeGenOpts<"SanitizeDebugTrapReasons">, DefaultTrue, + PosFlag<SetTrue, [], [ClangOption, CC1Option], + "Annotate trap blocks in debug info with UBSan trap reasons">, + NegFlag<SetFalse, [], [ClangOption, CC1Option], + "Do not annotate trap blocks in debug info with UBSan trap " + "reasons">>; + defm sanitize_minimal_runtime : BoolOption<"f", "sanitize-minimal-runtime", CodeGenOpts<"SanitizeMinimalRuntime">, DefaultFalse, PosFlag<SetTrue>, @@ -5360,9 +5370,9 @@ defm amdgpu_precise_memory_op " precise memory mode (AMDGPU only)">; def munsafe_fp_atomics : Flag<["-"], "munsafe-fp-atomics">, - Visibility<[ClangOption, CC1Option, FlangOption, FC1Option]>, Alias<fatomic_ignore_denormal_mode>; + Visibility<[ClangOption, CC1Option]>, Alias<fatomic_ignore_denormal_mode>; def mno_unsafe_fp_atomics : Flag<["-"], "mno-unsafe-fp-atomics">, - Visibility<[ClangOption, FlangOption]>, Alias<fno_atomic_ignore_denormal_mode>; + Visibility<[ClangOption]>, Alias<fno_atomic_ignore_denormal_mode>; def faltivec : Flag<["-"], "faltivec">, Group<f_Group>; def fno_altivec : Flag<["-"], "fno-altivec">, Group<f_Group>; diff --git a/clang/include/clang/Format/Format.h b/clang/include/clang/Format/Format.h index a54ab19..31582a4 100644 --- a/clang/include/clang/Format/Format.h +++ b/clang/include/clang/Format/Format.h @@ -831,7 +831,7 @@ struct FormatStyle { /// Never merge functions into a single line. SFS_None, /// Only merge functions defined inside a class. Same as ``inline``, - /// except it does not implies ``empty``: i.e. top level empty functions + /// except it does not imply ``empty``: i.e. top level empty functions /// are not merged either. /// \code /// class Foo { diff --git a/clang/include/clang/Parse/ParseHLSLRootSignature.h b/clang/include/clang/Parse/ParseHLSLRootSignature.h index ad66a26..a49bdfd 100644 --- a/clang/include/clang/Parse/ParseHLSLRootSignature.h +++ b/clang/include/clang/Parse/ParseHLSLRootSignature.h @@ -30,7 +30,6 @@ namespace hlsl { class RootSignatureParser { public: RootSignatureParser(llvm::dxbc::RootSignatureVersion Version, - SmallVector<RootSignatureElement> &Elements, StringLiteral *Signature, Preprocessor &PP); /// Consumes tokens from the Lexer and constructs the in-memory @@ -40,6 +39,9 @@ public: /// Returns true if a parsing error is encountered. bool parse(); + /// Return all elements that have been parsed. + ArrayRef<RootSignatureElement> getElements() { return Elements; } + private: DiagnosticsEngine &getDiags() { return PP.getDiagnostics(); } @@ -226,7 +228,7 @@ private: private: llvm::dxbc::RootSignatureVersion Version; - SmallVector<RootSignatureElement> &Elements; + SmallVector<RootSignatureElement> Elements; StringLiteral *Signature; RootSignatureLexer Lexer; Preprocessor &PP; diff --git a/clang/include/clang/Sema/SemaWasm.h b/clang/include/clang/Sema/SemaWasm.h index 2123e07..8c0639f 100644 --- a/clang/include/clang/Sema/SemaWasm.h +++ b/clang/include/clang/Sema/SemaWasm.h @@ -37,6 +37,7 @@ public: bool BuiltinWasmTableGrow(CallExpr *TheCall); bool BuiltinWasmTableFill(CallExpr *TheCall); bool BuiltinWasmTableCopy(CallExpr *TheCall); + bool BuiltinWasmTestFunctionPointerSignature(CallExpr *TheCall); WebAssemblyImportNameAttr * mergeImportNameAttr(Decl *D, const WebAssemblyImportNameAttr &AL); diff --git a/clang/lib/AST/ASTContext.cpp b/clang/lib/AST/ASTContext.cpp index 6b6275f..16cf114 100644 --- a/clang/lib/AST/ASTContext.cpp +++ b/clang/lib/AST/ASTContext.cpp @@ -940,7 +940,6 @@ ASTContext::ASTContext(LangOptions &LOpts, SourceManager &SM, FunctionProtoTypes(this_(), FunctionProtoTypesLog2InitSize), DependentTypeOfExprTypes(this_()), DependentDecltypeTypes(this_()), DependentPackIndexingTypes(this_()), TemplateSpecializationTypes(this_()), - DependentTemplateSpecializationTypes(this_()), DependentBitIntTypes(this_()), SubstTemplateTemplateParmPacks(this_()), DeducedTemplates(this_()), ArrayParameterTypes(this_()), CanonTemplateTemplateParms(this_()), SourceMgr(SM), LangOpts(LOpts), @@ -5979,10 +5978,9 @@ QualType ASTContext::getDependentTemplateSpecializationType( llvm::FoldingSetNodeID ID; DependentTemplateSpecializationType::Profile(ID, *this, Keyword, Name, Args); - void *InsertPos = nullptr; - if (auto *T = DependentTemplateSpecializationTypes.FindNodeOrInsertPos( - ID, InsertPos)) - return QualType(T, 0); + if (auto const T_iter = DependentTemplateSpecializationTypes.find(ID); + T_iter != DependentTemplateSpecializationTypes.end()) + return QualType(T_iter->getSecond(), 0); NestedNameSpecifier *NNS = Name.getQualifier(); @@ -6001,11 +5999,6 @@ QualType ASTContext::getDependentTemplateSpecializationType( CanonKeyword, {CanonNNS, Name.getName(), /*HasTemplateKeyword=*/true}, CanonArgs, /*IsCanonical=*/true); - // Find the insert position again. - [[maybe_unused]] auto *Nothing = - DependentTemplateSpecializationTypes.FindNodeOrInsertPos(ID, - InsertPos); - assert(!Nothing && "canonical type broken"); } } else { assert(Keyword == getCanonicalElaboratedTypeKeyword(Keyword)); @@ -6021,8 +6014,13 @@ QualType ASTContext::getDependentTemplateSpecializationType( alignof(DependentTemplateSpecializationType)); auto *T = new (Mem) DependentTemplateSpecializationType(Keyword, Name, Args, Canon); +#ifndef NDEBUG + llvm::FoldingSetNodeID InsertedID; + T->Profile(InsertedID, *this); + assert(InsertedID == ID && "ID does not match"); +#endif Types.push_back(T); - DependentTemplateSpecializationTypes.InsertNode(T, InsertPos); + DependentTemplateSpecializationTypes.try_emplace(ID, T); return QualType(T, 0); } diff --git a/clang/lib/AST/ExprConstant.cpp b/clang/lib/AST/ExprConstant.cpp index 0d12161..9808298 100644 --- a/clang/lib/AST/ExprConstant.cpp +++ b/clang/lib/AST/ExprConstant.cpp @@ -14636,7 +14636,9 @@ EvaluateComparisonBinaryOperator(EvalInfo &Info, const BinaryOperator *E, if (!LHSDesignator.Invalid && !RHSDesignator.Invalid && IsRelational) { bool WasArrayIndex; unsigned Mismatch = FindDesignatorMismatch( - getType(LHSValue.Base), LHSDesignator, RHSDesignator, WasArrayIndex); + LHSValue.Base.isNull() ? QualType() + : getType(LHSValue.Base).getNonReferenceType(), + LHSDesignator, RHSDesignator, WasArrayIndex); // At the point where the designators diverge, the comparison has a // specified value if: // - we are comparing array indices @@ -14680,7 +14682,7 @@ EvaluateComparisonBinaryOperator(EvalInfo &Info, const BinaryOperator *E, // compare pointers within the object in question; otherwise, the result // depends on where the object is located in memory. if (!LHSValue.Base.isNull() && IsRelational) { - QualType BaseTy = getType(LHSValue.Base); + QualType BaseTy = getType(LHSValue.Base).getNonReferenceType(); if (BaseTy->isIncompleteType()) return Error(E); CharUnits Size = Info.Ctx.getTypeSizeInChars(BaseTy); diff --git a/clang/lib/AST/OSLog.cpp b/clang/lib/AST/OSLog.cpp index b777d4d..91f8410 100644 --- a/clang/lib/AST/OSLog.cpp +++ b/clang/lib/AST/OSLog.cpp @@ -1,4 +1,16 @@ -// TODO: header template +//===--- OSLog.cpp - OS log format string analysis ------------------------===// +// +// 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 implements analysis functions for OS log format strings and +/// buffer layout computation for __builtin_os_log_format and related builtins. +/// +//===----------------------------------------------------------------------===// #include "clang/AST/OSLog.h" #include "clang/AST/Attr.h" @@ -137,8 +149,8 @@ public: for (auto &Data : ArgsData) { if (!Data.MaskType.empty()) { CharUnits Size = CharUnits::fromQuantity(8); - Layout.Items.emplace_back(OSLogBufferItem::MaskKind, nullptr, - Size, 0, Data.MaskType); + Layout.Items.emplace_back(OSLogBufferItem::MaskKind, nullptr, Size, 0, + Data.MaskType); } if (Data.FieldWidth) { diff --git a/clang/lib/Basic/Targets/WebAssembly.cpp b/clang/lib/Basic/Targets/WebAssembly.cpp index af25d25..e362350e 100644 --- a/clang/lib/Basic/Targets/WebAssembly.cpp +++ b/clang/lib/Basic/Targets/WebAssembly.cpp @@ -64,6 +64,7 @@ bool WebAssemblyTargetInfo::hasFeature(StringRef Feature) const { .Case("mutable-globals", HasMutableGlobals) .Case("nontrapping-fptoint", HasNontrappingFPToInt) .Case("reference-types", HasReferenceTypes) + .Case("gc", HasGC) .Case("relaxed-simd", SIMDLevel >= RelaxedSIMD) .Case("sign-ext", HasSignExt) .Case("simd128", SIMDLevel >= SIMD128) @@ -106,6 +107,8 @@ void WebAssemblyTargetInfo::getTargetDefines(const LangOptions &Opts, Builder.defineMacro("__wasm_nontrapping_fptoint__"); if (HasReferenceTypes) Builder.defineMacro("__wasm_reference_types__"); + if (HasGC) + Builder.defineMacro("__wasm_gc__"); if (SIMDLevel >= RelaxedSIMD) Builder.defineMacro("__wasm_relaxed_simd__"); if (HasSignExt) @@ -307,6 +310,14 @@ bool WebAssemblyTargetInfo::handleTargetFeatures( HasReferenceTypes = false; continue; } + if (Feature == "+gc") { + HasGC = true; + continue; + } + if (Feature == "-gc") { + HasGC = false; + continue; + } if (Feature == "+relaxed-simd") { SIMDLevel = std::max(SIMDLevel, RelaxedSIMD); continue; @@ -353,6 +364,11 @@ bool WebAssemblyTargetInfo::handleTargetFeatures( return false; } + // gc implies reference-types + if (HasGC) { + HasReferenceTypes = true; + } + // bulk-memory-opt is a subset of bulk-memory. if (HasBulkMemory) { HasBulkMemoryOpt = true; diff --git a/clang/lib/Basic/Targets/WebAssembly.h b/clang/lib/Basic/Targets/WebAssembly.h index 57b366c..c47c8cc 100644 --- a/clang/lib/Basic/Targets/WebAssembly.h +++ b/clang/lib/Basic/Targets/WebAssembly.h @@ -69,6 +69,7 @@ class LLVM_LIBRARY_VISIBILITY WebAssemblyTargetInfo : public TargetInfo { bool HasMutableGlobals = false; bool HasNontrappingFPToInt = false; bool HasReferenceTypes = false; + bool HasGC = false; bool HasSignExt = false; bool HasTailCall = false; bool HasWideArithmetic = false; diff --git a/clang/lib/CIR/CodeGen/CIRGenExprAggregate.cpp b/clang/lib/CIR/CodeGen/CIRGenExprAggregate.cpp index 0d12c5c..51aab95 100644 --- a/clang/lib/CIR/CodeGen/CIRGenExprAggregate.cpp +++ b/clang/lib/CIR/CodeGen/CIRGenExprAggregate.cpp @@ -357,10 +357,97 @@ void AggExprEmitter::visitCXXParenListOrInitListExpr( emitArrayInit(dest.getAddress(), arrayTy, e->getType(), e, args, arrayFiller); return; + } else if (e->getType()->isVariableArrayType()) { + cgf.cgm.errorNYI(e->getSourceRange(), + "visitCXXParenListOrInitListExpr variable array type"); + return; + } + + if (e->getType()->isArrayType()) { + cgf.cgm.errorNYI(e->getSourceRange(), + "visitCXXParenListOrInitListExpr array type"); + return; + } + + assert(e->getType()->isRecordType() && "Only support structs/unions here!"); + + // Do struct initialization; this code just sets each individual member + // to the approprate value. This makes bitfield support automatic; + // the disadvantage is that the generated code is more difficult for + // the optimizer, especially with bitfields. + unsigned numInitElements = args.size(); + RecordDecl *record = e->getType()->castAs<RecordType>()->getDecl(); + + // We'll need to enter cleanup scopes in case any of the element + // initializers throws an exception. + assert(!cir::MissingFeatures::requiresCleanups()); + + unsigned curInitIndex = 0; + + // Emit initialization of base classes. + if (auto *cxxrd = dyn_cast<CXXRecordDecl>(record)) { + assert(numInitElements >= cxxrd->getNumBases() && + "missing initializer for base class"); + if (cxxrd->getNumBases() > 0) { + cgf.cgm.errorNYI(e->getSourceRange(), + "visitCXXParenListOrInitListExpr base class init"); + return; + } + } + + LValue destLV = cgf.makeAddrLValue(dest.getAddress(), e->getType()); + + if (record->isUnion()) { + cgf.cgm.errorNYI(e->getSourceRange(), + "visitCXXParenListOrInitListExpr union type"); + return; } - cgf.cgm.errorNYI( - "visitCXXParenListOrInitListExpr Record or VariableSizeArray type"); + // Here we iterate over the fields; this makes it simpler to both + // default-initialize fields and skip over unnamed fields. + for (const FieldDecl *field : record->fields()) { + // We're done once we hit the flexible array member. + if (field->getType()->isIncompleteArrayType()) + break; + + // Always skip anonymous bitfields. + if (field->isUnnamedBitField()) + continue; + + // We're done if we reach the end of the explicit initializers, we + // have a zeroed object, and the rest of the fields are + // zero-initializable. + if (curInitIndex == numInitElements && dest.isZeroed() && + cgf.getTypes().isZeroInitializable(e->getType())) + break; + LValue lv = + cgf.emitLValueForFieldInitialization(destLV, field, field->getName()); + // We never generate write-barriers for initialized fields. + assert(!cir::MissingFeatures::setNonGC()); + + if (curInitIndex < numInitElements) { + // Store the initializer into the field. + CIRGenFunction::SourceLocRAIIObject loc{ + cgf, cgf.getLoc(record->getSourceRange())}; + emitInitializationToLValue(args[curInitIndex++], lv); + } else { + // We're out of initializers; default-initialize to null + emitNullInitializationToLValue(cgf.getLoc(e->getSourceRange()), lv); + } + + // Push a destructor if necessary. + // FIXME: if we have an array of structures, all explicitly + // initialized, we can end up pushing a linear number of cleanups. + if (field->getType().isDestructedType()) { + cgf.cgm.errorNYI(e->getSourceRange(), + "visitCXXParenListOrInitListExpr destructor"); + return; + } + + // From classic codegen, maybe not useful for CIR: + // If the GEP didn't get used because of a dead zero init or something + // else, clean it up for -O0 builds and general tidiness. + } } // TODO(cir): This could be shared with classic codegen. diff --git a/clang/lib/CIR/CodeGen/CIRGenExprComplex.cpp b/clang/lib/CIR/CodeGen/CIRGenExprComplex.cpp index d52da0c..02685a3 100644 --- a/clang/lib/CIR/CodeGen/CIRGenExprComplex.cpp +++ b/clang/lib/CIR/CodeGen/CIRGenExprComplex.cpp @@ -60,7 +60,7 @@ public: mlir::Value VisitDeclRefExpr(DeclRefExpr *e); mlir::Value VisitGenericSelectionExpr(GenericSelectionExpr *e); mlir::Value VisitImplicitCastExpr(ImplicitCastExpr *e); - mlir::Value VisitInitListExpr(const InitListExpr *e); + mlir::Value VisitInitListExpr(InitListExpr *e); mlir::Value VisitCompoundLiteralExpr(CompoundLiteralExpr *e) { return emitLoadOfLValue(e); @@ -194,8 +194,12 @@ mlir::Value ComplexExprEmitter::emitCast(CastKind ck, Expr *op, } case CK_LValueToRValueBitCast: { - cgf.cgm.errorNYI("ComplexExprEmitter::emitCast CK_LValueToRValueBitCast"); - return {}; + LValue sourceLVal = cgf.emitLValue(op); + Address addr = sourceLVal.getAddress().withElementType( + builder, cgf.convertTypeForMem(destTy)); + LValue destLV = cgf.makeAddrLValue(addr, destTy); + assert(!cir::MissingFeatures::opTBAA()); + return emitLoadOfLValue(destLV, op->getExprLoc()); } case CK_BitCast: @@ -448,7 +452,7 @@ mlir::Value ComplexExprEmitter::VisitImplicitCastExpr(ImplicitCastExpr *e) { return emitCast(e->getCastKind(), e->getSubExpr(), e->getType()); } -mlir::Value ComplexExprEmitter::VisitInitListExpr(const InitListExpr *e) { +mlir::Value ComplexExprEmitter::VisitInitListExpr(InitListExpr *e) { mlir::Location loc = cgf.getLoc(e->getExprLoc()); if (e->getNumInits() == 2) { mlir::Value real = cgf.emitScalarExpr(e->getInit(0)); @@ -456,10 +460,8 @@ mlir::Value ComplexExprEmitter::VisitInitListExpr(const InitListExpr *e) { return builder.createComplexCreate(loc, real, imag); } - if (e->getNumInits() == 1) { - cgf.cgm.errorNYI("Create Complex with InitList with size 1"); - return {}; - } + if (e->getNumInits() == 1) + return Visit(e->getInit(0)); assert(e->getNumInits() == 0 && "Unexpected number of inits"); mlir::Type complexTy = cgf.convertType(e->getType()); diff --git a/clang/lib/CIR/Dialect/IR/CIRDialect.cpp b/clang/lib/CIR/Dialect/IR/CIRDialect.cpp index cd77166..2213c75 100644 --- a/clang/lib/CIR/Dialect/IR/CIRDialect.cpp +++ b/clang/lib/CIR/Dialect/IR/CIRDialect.cpp @@ -17,6 +17,7 @@ #include "mlir/Interfaces/ControlFlowInterfaces.h" #include "mlir/Interfaces/FunctionImplementation.h" +#include "mlir/Support/LLVM.h" #include "clang/CIR/Dialect/IR/CIROpsDialect.cpp.inc" #include "clang/CIR/Dialect/IR/CIROpsEnums.cpp.inc" @@ -338,7 +339,7 @@ static LogicalResult checkConstantTypes(mlir::Operation *op, mlir::Type opType, } if (mlir::isa<cir::ConstArrayAttr, cir::ConstVectorAttr, - cir::ConstComplexAttr>(attrType)) + cir::ConstComplexAttr, cir::PoisonAttr>(attrType)) return success(); assert(isa<TypedAttr>(attrType) && "What else could we be looking at here?"); @@ -628,6 +629,11 @@ static Value tryFoldCastChain(cir::CastOp op) { } OpFoldResult cir::CastOp::fold(FoldAdaptor adaptor) { + if (mlir::isa_and_present<cir::PoisonAttr>(adaptor.getSrc())) { + // Propagate poison value + return cir::PoisonAttr::get(getContext(), getType()); + } + if (getSrc().getType() == getType()) { switch (getKind()) { case cir::CastKind::integral: { @@ -1782,6 +1788,12 @@ static bool isBoolNot(cir::UnaryOp op) { // // and the argument of the first one (%0) will be used instead. OpFoldResult cir::UnaryOp::fold(FoldAdaptor adaptor) { + if (auto poison = + mlir::dyn_cast_if_present<cir::PoisonAttr>(adaptor.getInput())) { + // Propagate poison values + return poison; + } + if (isBoolNot(*this)) if (auto previous = dyn_cast_or_null<UnaryOp>(getInput().getDefiningOp())) if (isBoolNot(previous)) @@ -2231,6 +2243,134 @@ LogicalResult cir::ComplexImagPtrOp::verify() { } //===----------------------------------------------------------------------===// +// Bit manipulation operations +//===----------------------------------------------------------------------===// + +static OpFoldResult +foldUnaryBitOp(mlir::Attribute inputAttr, + llvm::function_ref<llvm::APInt(const llvm::APInt &)> func, + bool poisonZero = false) { + if (mlir::isa_and_present<cir::PoisonAttr>(inputAttr)) { + // Propagate poison value + return inputAttr; + } + + auto input = mlir::dyn_cast_if_present<IntAttr>(inputAttr); + if (!input) + return nullptr; + + llvm::APInt inputValue = input.getValue(); + if (poisonZero && inputValue.isZero()) + return cir::PoisonAttr::get(input.getType()); + + llvm::APInt resultValue = func(inputValue); + return IntAttr::get(input.getType(), resultValue); +} + +OpFoldResult BitClrsbOp::fold(FoldAdaptor adaptor) { + return foldUnaryBitOp(adaptor.getInput(), [](const llvm::APInt &inputValue) { + unsigned resultValue = + inputValue.getBitWidth() - inputValue.getSignificantBits(); + return llvm::APInt(inputValue.getBitWidth(), resultValue); + }); +} + +OpFoldResult BitClzOp::fold(FoldAdaptor adaptor) { + return foldUnaryBitOp( + adaptor.getInput(), + [](const llvm::APInt &inputValue) { + unsigned resultValue = inputValue.countLeadingZeros(); + return llvm::APInt(inputValue.getBitWidth(), resultValue); + }, + getPoisonZero()); +} + +OpFoldResult BitCtzOp::fold(FoldAdaptor adaptor) { + return foldUnaryBitOp( + adaptor.getInput(), + [](const llvm::APInt &inputValue) { + return llvm::APInt(inputValue.getBitWidth(), + inputValue.countTrailingZeros()); + }, + getPoisonZero()); +} + +OpFoldResult BitParityOp::fold(FoldAdaptor adaptor) { + return foldUnaryBitOp(adaptor.getInput(), [](const llvm::APInt &inputValue) { + return llvm::APInt(inputValue.getBitWidth(), inputValue.popcount() % 2); + }); +} + +OpFoldResult BitPopcountOp::fold(FoldAdaptor adaptor) { + return foldUnaryBitOp(adaptor.getInput(), [](const llvm::APInt &inputValue) { + return llvm::APInt(inputValue.getBitWidth(), inputValue.popcount()); + }); +} + +OpFoldResult BitReverseOp::fold(FoldAdaptor adaptor) { + return foldUnaryBitOp(adaptor.getInput(), [](const llvm::APInt &inputValue) { + return inputValue.reverseBits(); + }); +} + +OpFoldResult ByteSwapOp::fold(FoldAdaptor adaptor) { + return foldUnaryBitOp(adaptor.getInput(), [](const llvm::APInt &inputValue) { + return inputValue.byteSwap(); + }); +} + +OpFoldResult RotateOp::fold(FoldAdaptor adaptor) { + if (mlir::isa_and_present<cir::PoisonAttr>(adaptor.getInput()) || + mlir::isa_and_present<cir::PoisonAttr>(adaptor.getAmount())) { + // Propagate poison values + return cir::PoisonAttr::get(getType()); + } + + auto input = mlir::dyn_cast_if_present<IntAttr>(adaptor.getInput()); + auto amount = mlir::dyn_cast_if_present<IntAttr>(adaptor.getAmount()); + if (!input && !amount) + return nullptr; + + // We could fold cir.rotate even if one of its two operands is not a constant: + // - `cir.rotate left/right %0, 0` could be folded into just %0 even if %0 + // is not a constant. + // - `cir.rotate left/right 0/0b111...111, %0` could be folded into 0 or + // 0b111...111 even if %0 is not a constant. + + llvm::APInt inputValue; + if (input) { + inputValue = input.getValue(); + if (inputValue.isZero() || inputValue.isAllOnes()) { + // An input value of all 0s or all 1s will not change after rotation + return input; + } + } + + uint64_t amountValue; + if (amount) { + amountValue = amount.getValue().urem(getInput().getType().getWidth()); + if (amountValue == 0) { + // A shift amount of 0 will not change the input value + return getInput(); + } + } + + if (!input || !amount) + return nullptr; + + assert(inputValue.getBitWidth() == getInput().getType().getWidth() && + "input value must have the same bit width as the input type"); + + llvm::APInt resultValue; + if (isRotateLeft()) + resultValue = inputValue.rotl(amountValue); + else + resultValue = inputValue.rotr(amountValue); + + return IntAttr::get(input.getContext(), input.getType(), resultValue); +} + +//===----------------------------------------------------------------------===// // TableGen'd op method definitions //===----------------------------------------------------------------------===// diff --git a/clang/lib/CIR/Dialect/Transforms/CIRCanonicalize.cpp b/clang/lib/CIR/Dialect/Transforms/CIRCanonicalize.cpp index e505db5..2143f16 100644 --- a/clang/lib/CIR/Dialect/Transforms/CIRCanonicalize.cpp +++ b/clang/lib/CIR/Dialect/Transforms/CIRCanonicalize.cpp @@ -143,7 +143,8 @@ void CIRCanonicalizePass::runOnOperation() { if (isa<BrOp, BrCondOp, CastOp, ScopeOp, SwitchOp, SelectOp, UnaryOp, ComplexCreateOp, ComplexImagOp, ComplexRealOp, VecCmpOp, VecCreateOp, VecExtractOp, VecShuffleOp, VecShuffleDynamicOp, - VecTernaryOp>(op)) + VecTernaryOp, BitClrsbOp, BitClzOp, BitCtzOp, BitParityOp, + BitPopcountOp, BitReverseOp, ByteSwapOp, RotateOp>(op)) ops.push_back(op); }); diff --git a/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp b/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp index 3cd7de0..c27b889 100644 --- a/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp +++ b/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp @@ -1027,6 +1027,12 @@ mlir::LogicalResult CIRToLLVMConstantOpLowering::matchAndRewrite( mlir::ConversionPatternRewriter &rewriter) const { mlir::Attribute attr = op.getValue(); + if (mlir::isa<cir::PoisonAttr>(attr)) { + rewriter.replaceOpWithNewOp<mlir::LLVM::PoisonOp>( + op, getTypeConverter()->convertType(op.getType())); + return mlir::success(); + } + if (mlir::isa<mlir::IntegerType>(op.getType())) { // Verified cir.const operations cannot actually be of these types, but the // lowering pass may generate temporary cir.const operations with these diff --git a/clang/lib/CodeGen/BackendUtil.cpp b/clang/lib/CodeGen/BackendUtil.cpp index 1b72578..0b8b824 100644 --- a/clang/lib/CodeGen/BackendUtil.cpp +++ b/clang/lib/CodeGen/BackendUtil.cpp @@ -1027,12 +1027,6 @@ void EmitAssemblyHelper::RunOptimizationPipeline( MPM.addPass( createModuleToFunctionPassAdaptor(ObjCARCExpandPass())); }); - PB.registerPipelineEarlySimplificationEPCallback( - [](ModulePassManager &MPM, OptimizationLevel Level, - ThinOrFullLTOPhase) { - if (Level != OptimizationLevel::O0) - MPM.addPass(ObjCARCAPElimPass()); - }); PB.registerScalarOptimizerLateEPCallback( [](FunctionPassManager &FPM, OptimizationLevel Level) { if (Level != OptimizationLevel::O0) diff --git a/clang/lib/CodeGen/CGCall.cpp b/clang/lib/CodeGen/CGCall.cpp index 0bceece..d9bd443 100644 --- a/clang/lib/CodeGen/CGCall.cpp +++ b/clang/lib/CodeGen/CGCall.cpp @@ -2852,20 +2852,28 @@ void CodeGenModule::ConstructAttributeList(StringRef Name, if (AI.getInReg()) Attrs.addAttribute(llvm::Attribute::InReg); - // Depending on the ABI, this may be either a byval or a dead_on_return - // argument. - if (AI.getIndirectByVal()) { - Attrs.addByValAttr(getTypes().ConvertTypeForMem(ParamType)); - } else { - // Add dead_on_return when the object's lifetime ends in the callee. - // This includes trivially-destructible objects, as well as objects - // whose destruction / clean-up is carried out within the callee (e.g., - // Obj-C ARC-managed structs, MSVC callee-destroyed objects). - if (!ParamType.isDestructedType() || !ParamType->isRecordType() || - ParamType->castAs<RecordType>() - ->getDecl() - ->isParamDestroyedInCallee()) - Attrs.addAttribute(llvm::Attribute::DeadOnReturn); + // HLSL out and inout parameters must not be marked with ByVal or + // DeadOnReturn attributes because stores to these parameters by the + // callee are visible to the caller. + if (auto ParamABI = FI.getExtParameterInfo(ArgNo).getABI(); + ParamABI != ParameterABI::HLSLOut && + ParamABI != ParameterABI::HLSLInOut) { + + // Depending on the ABI, this may be either a byval or a dead_on_return + // argument. + if (AI.getIndirectByVal()) { + Attrs.addByValAttr(getTypes().ConvertTypeForMem(ParamType)); + } else { + // Add dead_on_return when the object's lifetime ends in the callee. + // This includes trivially-destructible objects, as well as objects + // whose destruction / clean-up is carried out within the callee + // (e.g., Obj-C ARC-managed structs, MSVC callee-destroyed objects). + if (!ParamType.isDestructedType() || !ParamType->isRecordType() || + ParamType->castAs<RecordType>() + ->getDecl() + ->isParamDestroyedInCallee()) + Attrs.addAttribute(llvm::Attribute::DeadOnReturn); + } } auto *Decl = ParamType->getAsRecordDecl(); diff --git a/clang/lib/CodeGen/CGDebugInfo.cpp b/clang/lib/CodeGen/CGDebugInfo.cpp index a371b67..77fc3a2 100644 --- a/clang/lib/CodeGen/CGDebugInfo.cpp +++ b/clang/lib/CodeGen/CGDebugInfo.cpp @@ -6435,7 +6435,7 @@ CodeGenFunction::LexicalScope::~LexicalScope() { static std::string SanitizerHandlerToCheckLabel(SanitizerHandler Handler) { std::string Label; switch (Handler) { -#define SANITIZER_CHECK(Enum, Name, Version) \ +#define SANITIZER_CHECK(Enum, Name, Version, Msg) \ case Enum: \ Label = "__ubsan_check_" #Name; \ break; diff --git a/clang/lib/CodeGen/CGExpr.cpp b/clang/lib/CodeGen/CGExpr.cpp index 85c7688..90aed79 100644 --- a/clang/lib/CodeGen/CGExpr.cpp +++ b/clang/lib/CodeGen/CGExpr.cpp @@ -85,6 +85,16 @@ enum VariableTypeDescriptorKind : uint16_t { // Miscellaneous Helper Methods //===--------------------------------------------------------------------===// +static llvm::StringRef GetUBSanTrapForHandler(SanitizerHandler ID) { + switch (ID) { +#define SANITIZER_CHECK(Enum, Name, Version, Msg) \ + case SanitizerHandler::Enum: \ + return Msg; + LIST_SANITIZER_CHECKS +#undef SANITIZER_CHECK + } +} + /// CreateTempAlloca - This creates a alloca and inserts it into the entry /// block. RawAddress @@ -3649,7 +3659,7 @@ struct SanitizerHandlerInfo { } const SanitizerHandlerInfo SanitizerHandlers[] = { -#define SANITIZER_CHECK(Enum, Name, Version) {#Name, Version}, +#define SANITIZER_CHECK(Enum, Name, Version, Msg) {#Name, Version}, LIST_SANITIZER_CHECKS #undef SANITIZER_CHECK }; @@ -3954,6 +3964,8 @@ void CodeGenFunction::EmitCfiCheckFail() { StartFunction(GlobalDecl(), CGM.getContext().VoidTy, F, FI, Args, SourceLocation()); + ApplyDebugLocation ADL = ApplyDebugLocation::CreateArtificial(*this); + // This function is not affected by NoSanitizeList. This function does // not have a source location, but "src:*" would still apply. Revert any // changes to SanOpts made in StartFunction. @@ -4051,6 +4063,15 @@ void CodeGenFunction::EmitTrapCheck(llvm::Value *Checked, llvm::BasicBlock *&TrapBB = TrapBBs[CheckHandlerID]; + llvm::DILocation *TrapLocation = Builder.getCurrentDebugLocation(); + llvm::StringRef TrapMessage = GetUBSanTrapForHandler(CheckHandlerID); + + if (getDebugInfo() && !TrapMessage.empty() && + CGM.getCodeGenOpts().SanitizeDebugTrapReasons && TrapLocation) { + TrapLocation = getDebugInfo()->CreateTrapFailureMessageFor( + TrapLocation, "Undefined Behavior Sanitizer", TrapMessage); + } + NoMerge = NoMerge || !CGM.getCodeGenOpts().OptimizationLevel || (CurCodeDecl && CurCodeDecl->hasAttr<OptimizeNoneAttr>()); @@ -4059,8 +4080,8 @@ void CodeGenFunction::EmitTrapCheck(llvm::Value *Checked, auto Call = TrapBB->begin(); assert(isa<llvm::CallInst>(Call) && "Expected call in trap BB"); - Call->applyMergedLocation(Call->getDebugLoc(), - Builder.getCurrentDebugLocation()); + Call->applyMergedLocation(Call->getDebugLoc(), TrapLocation); + Builder.CreateCondBr(Checked, Cont, TrapBB, MDHelper.createLikelyBranchWeights()); } else { @@ -4069,6 +4090,8 @@ void CodeGenFunction::EmitTrapCheck(llvm::Value *Checked, MDHelper.createLikelyBranchWeights()); EmitBlock(TrapBB); + ApplyDebugLocation applyTrapDI(*this, TrapLocation); + llvm::CallInst *TrapCall = Builder.CreateCall(CGM.getIntrinsic(llvm::Intrinsic::ubsantrap), llvm::ConstantInt::get(CGM.Int8Ty, CheckHandlerID)); diff --git a/clang/lib/CodeGen/SanitizerHandler.h b/clang/lib/CodeGen/SanitizerHandler.h index bb42e39..a66e7ab 100644 --- a/clang/lib/CodeGen/SanitizerHandler.h +++ b/clang/lib/CodeGen/SanitizerHandler.h @@ -14,35 +14,69 @@ #define LLVM_CLANG_LIB_CODEGEN_SANITIZER_HANDLER_H #define LIST_SANITIZER_CHECKS \ - SANITIZER_CHECK(AddOverflow, add_overflow, 0) \ - SANITIZER_CHECK(BuiltinUnreachable, builtin_unreachable, 0) \ - SANITIZER_CHECK(CFICheckFail, cfi_check_fail, 0) \ - SANITIZER_CHECK(DivremOverflow, divrem_overflow, 0) \ - SANITIZER_CHECK(DynamicTypeCacheMiss, dynamic_type_cache_miss, 0) \ - SANITIZER_CHECK(FloatCastOverflow, float_cast_overflow, 0) \ - SANITIZER_CHECK(FunctionTypeMismatch, function_type_mismatch, 0) \ - SANITIZER_CHECK(ImplicitConversion, implicit_conversion, 0) \ - SANITIZER_CHECK(InvalidBuiltin, invalid_builtin, 0) \ - SANITIZER_CHECK(InvalidObjCCast, invalid_objc_cast, 0) \ - SANITIZER_CHECK(LoadInvalidValue, load_invalid_value, 0) \ - SANITIZER_CHECK(MissingReturn, missing_return, 0) \ - SANITIZER_CHECK(MulOverflow, mul_overflow, 0) \ - SANITIZER_CHECK(NegateOverflow, negate_overflow, 0) \ - SANITIZER_CHECK(NullabilityArg, nullability_arg, 0) \ - SANITIZER_CHECK(NullabilityReturn, nullability_return, 1) \ - SANITIZER_CHECK(NonnullArg, nonnull_arg, 0) \ - SANITIZER_CHECK(NonnullReturn, nonnull_return, 1) \ - SANITIZER_CHECK(OutOfBounds, out_of_bounds, 0) \ - SANITIZER_CHECK(PointerOverflow, pointer_overflow, 0) \ - SANITIZER_CHECK(ShiftOutOfBounds, shift_out_of_bounds, 0) \ - SANITIZER_CHECK(SubOverflow, sub_overflow, 0) \ - SANITIZER_CHECK(TypeMismatch, type_mismatch, 1) \ - SANITIZER_CHECK(AlignmentAssumption, alignment_assumption, 0) \ - SANITIZER_CHECK(VLABoundNotPositive, vla_bound_not_positive, 0) \ - SANITIZER_CHECK(BoundsSafety, bounds_safety, 0) + SANITIZER_CHECK(AddOverflow, add_overflow, 0, "Integer addition overflowed") \ + SANITIZER_CHECK(BuiltinUnreachable, builtin_unreachable, 0, \ + "_builtin_unreachable(), execution reached an unreachable " \ + "program point") \ + SANITIZER_CHECK(CFICheckFail, cfi_check_fail, 0, \ + "Control flow integrity check failed") \ + SANITIZER_CHECK(DivremOverflow, divrem_overflow, 0, \ + "Integer divide or remainder overflowed") \ + SANITIZER_CHECK(DynamicTypeCacheMiss, dynamic_type_cache_miss, 0, \ + "Dynamic type cache miss, member call made on an object " \ + "whose dynamic type differs from the expected type") \ + SANITIZER_CHECK(FloatCastOverflow, float_cast_overflow, 0, \ + "Floating-point to integer conversion overflowed") \ + SANITIZER_CHECK(FunctionTypeMismatch, function_type_mismatch, 0, \ + "Function called with mismatched signature") \ + SANITIZER_CHECK(ImplicitConversion, implicit_conversion, 0, \ + "Implicit integer conversion overflowed or lost data") \ + SANITIZER_CHECK(InvalidBuiltin, invalid_builtin, 0, \ + "Invalid use of builtin function") \ + SANITIZER_CHECK(InvalidObjCCast, invalid_objc_cast, 0, \ + "Invalid Objective-C cast") \ + SANITIZER_CHECK(LoadInvalidValue, load_invalid_value, 0, \ + "Loaded an invalid or uninitialized value for the type") \ + SANITIZER_CHECK(MissingReturn, missing_return, 0, \ + "Execution reached the end of a value-returning function " \ + "without returning a value") \ + SANITIZER_CHECK(MulOverflow, mul_overflow, 0, \ + "Integer multiplication overflowed") \ + SANITIZER_CHECK(NegateOverflow, negate_overflow, 0, \ + "Integer negation overflowed") \ + SANITIZER_CHECK( \ + NullabilityArg, nullability_arg, 0, \ + "Passing null as an argument which is annotated with _Nonnull") \ + SANITIZER_CHECK(NullabilityReturn, nullability_return, 1, \ + "Returning null from a function with a return type " \ + "annotated with _Nonnull") \ + SANITIZER_CHECK(NonnullArg, nonnull_arg, 0, \ + "Passing null pointer as an argument which is declared to " \ + "never be null") \ + SANITIZER_CHECK(NonnullReturn, nonnull_return, 1, \ + "Returning null pointer from a function which is declared " \ + "to never return null") \ + SANITIZER_CHECK(OutOfBounds, out_of_bounds, 0, "Array index out of bounds") \ + SANITIZER_CHECK(PointerOverflow, pointer_overflow, 0, \ + "Pointer arithmetic overflowed bounds") \ + SANITIZER_CHECK(ShiftOutOfBounds, shift_out_of_bounds, 0, \ + "Shift exponent is too large for the type") \ + SANITIZER_CHECK(SubOverflow, sub_overflow, 0, \ + "Integer subtraction overflowed") \ + SANITIZER_CHECK(TypeMismatch, type_mismatch, 1, \ + "Type mismatch in operation") \ + SANITIZER_CHECK(AlignmentAssumption, alignment_assumption, 0, \ + "Alignment assumption violated") \ + SANITIZER_CHECK( \ + VLABoundNotPositive, vla_bound_not_positive, 0, \ + "Variable length array bound evaluates to non-positive value") \ + SANITIZER_CHECK(BoundsSafety, bounds_safety, 0, \ + "") // BoundsSafety Msg is empty because it is not considered + // part of UBSan; therefore, no trap reason is emitted for + // this case. enum SanitizerHandler { -#define SANITIZER_CHECK(Enum, Name, Version) Enum, +#define SANITIZER_CHECK(Enum, Name, Version, Msg) Enum, LIST_SANITIZER_CHECKS #undef SANITIZER_CHECK }; diff --git a/clang/lib/CodeGen/TargetBuiltins/AMDGPU.cpp b/clang/lib/CodeGen/TargetBuiltins/AMDGPU.cpp index e469a01..70f510a 100644 --- a/clang/lib/CodeGen/TargetBuiltins/AMDGPU.cpp +++ b/clang/lib/CodeGen/TargetBuiltins/AMDGPU.cpp @@ -633,6 +633,41 @@ Value *CodeGenFunction::EmitAMDGPUBuiltinExpr(unsigned BuiltinID, llvm::Function *F = CGM.getIntrinsic(IID, {LoadTy}); return Builder.CreateCall(F, {Addr}); } + case AMDGPU::BI__builtin_amdgcn_global_load_monitor_b32: + case AMDGPU::BI__builtin_amdgcn_global_load_monitor_b64: + case AMDGPU::BI__builtin_amdgcn_global_load_monitor_b128: + case AMDGPU::BI__builtin_amdgcn_flat_load_monitor_b32: + case AMDGPU::BI__builtin_amdgcn_flat_load_monitor_b64: + case AMDGPU::BI__builtin_amdgcn_flat_load_monitor_b128: { + + Intrinsic::ID IID; + switch (BuiltinID) { + case AMDGPU::BI__builtin_amdgcn_global_load_monitor_b32: + IID = Intrinsic::amdgcn_global_load_monitor_b32; + break; + case AMDGPU::BI__builtin_amdgcn_global_load_monitor_b64: + IID = Intrinsic::amdgcn_global_load_monitor_b64; + break; + case AMDGPU::BI__builtin_amdgcn_global_load_monitor_b128: + IID = Intrinsic::amdgcn_global_load_monitor_b128; + break; + case AMDGPU::BI__builtin_amdgcn_flat_load_monitor_b32: + IID = Intrinsic::amdgcn_flat_load_monitor_b32; + break; + case AMDGPU::BI__builtin_amdgcn_flat_load_monitor_b64: + IID = Intrinsic::amdgcn_flat_load_monitor_b64; + break; + case AMDGPU::BI__builtin_amdgcn_flat_load_monitor_b128: + IID = Intrinsic::amdgcn_flat_load_monitor_b128; + break; + } + + llvm::Type *LoadTy = ConvertType(E->getType()); + llvm::Value *Addr = EmitScalarExpr(E->getArg(0)); + llvm::Value *Val = EmitScalarExpr(E->getArg(1)); + llvm::Function *F = CGM.getIntrinsic(IID, {LoadTy}); + return Builder.CreateCall(F, {Addr, Val}); + } case AMDGPU::BI__builtin_amdgcn_load_to_lds: { // Should this have asan instrumentation? return emitBuiltinWithOneOverloadedType<5>(*this, E, diff --git a/clang/lib/CodeGen/TargetBuiltins/WebAssembly.cpp b/clang/lib/CodeGen/TargetBuiltins/WebAssembly.cpp index b7fd70e..33a8d8f 100644 --- a/clang/lib/CodeGen/TargetBuiltins/WebAssembly.cpp +++ b/clang/lib/CodeGen/TargetBuiltins/WebAssembly.cpp @@ -12,7 +12,10 @@ #include "CGBuiltin.h" #include "clang/Basic/TargetBuiltins.h" +#include "llvm/ADT/APInt.h" +#include "llvm/IR/Constants.h" #include "llvm/IR/IntrinsicsWebAssembly.h" +#include "llvm/Support/ErrorHandling.h" using namespace clang; using namespace CodeGen; @@ -218,6 +221,64 @@ Value *CodeGenFunction::EmitWebAssemblyBuiltinExpr(unsigned BuiltinID, Function *Callee = CGM.getIntrinsic(Intrinsic::wasm_ref_null_func); return Builder.CreateCall(Callee); } + case WebAssembly::BI__builtin_wasm_test_function_pointer_signature: { + Value *FuncRef = EmitScalarExpr(E->getArg(0)); + + // Get the function type from the argument's static type + QualType ArgType = E->getArg(0)->getType(); + const PointerType *PtrTy = ArgType->getAs<PointerType>(); + assert(PtrTy && "Sema should have ensured this is a function pointer"); + + const FunctionType *FuncTy = PtrTy->getPointeeType()->getAs<FunctionType>(); + assert(FuncTy && "Sema should have ensured this is a function pointer"); + + // In the llvm IR, we won't have access any more to the type of the function + // pointer so we need to insert this type information somehow. The + // @llvm.wasm.ref.test.func takes varargs arguments whose values are unused + // to indicate the type of the function to test for. See the test here: + // llvm/test/CodeGen/WebAssembly/ref-test-func.ll + // + // The format is: first we include the return types (since this is a C + // function pointer, there will be 0 or one of these) then a token type to + // indicate the boundary between return types and param types, then the + // param types. + + llvm::FunctionType *LLVMFuncTy = + cast<llvm::FunctionType>(ConvertType(QualType(FuncTy, 0))); + + unsigned NParams = LLVMFuncTy->getNumParams(); + std::vector<Value *> Args; + Args.reserve(NParams + 3); + // The only real argument is the FuncRef + Args.push_back(FuncRef); + + // Add the type information + auto addType = [this, &Args](llvm::Type *T) { + if (T->isVoidTy()) { + // Do nothing + } else if (T->isFloatingPointTy()) { + Args.push_back(ConstantFP::get(T, 0)); + } else if (T->isIntegerTy()) { + Args.push_back(ConstantInt::get(T, 0)); + } else if (T->isPointerTy()) { + Args.push_back(ConstantPointerNull::get(llvm::PointerType::get( + getLLVMContext(), T->getPointerAddressSpace()))); + } else { + // TODO: Handle reference types. For now, we reject them in Sema. + llvm_unreachable("Unhandled type"); + } + }; + + addType(LLVMFuncTy->getReturnType()); + // The token type indicates the boundary between return types and param + // types. + Args.push_back(PoisonValue::get(llvm::Type::getTokenTy(getLLVMContext()))); + for (unsigned i = 0; i < NParams; i++) { + addType(LLVMFuncTy->getParamType(i)); + } + Function *Callee = CGM.getIntrinsic(Intrinsic::wasm_ref_test_func); + return Builder.CreateCall(Callee, Args); + } case WebAssembly::BI__builtin_wasm_swizzle_i8x16: { Value *Src = EmitScalarExpr(E->getArg(0)); Value *Indices = EmitScalarExpr(E->getArg(1)); diff --git a/clang/lib/Driver/SanitizerArgs.cpp b/clang/lib/Driver/SanitizerArgs.cpp index 21e4cff..98793a5 100644 --- a/clang/lib/Driver/SanitizerArgs.cpp +++ b/clang/lib/Driver/SanitizerArgs.cpp @@ -1382,6 +1382,12 @@ void SanitizerArgs::addArgs(const ToolChain &TC, const llvm::opt::ArgList &Args, CmdArgs.push_back(Args.MakeArgString("-fsanitize-annotate-debug-info=" + toString(AnnotateDebugInfo))); + if (const Arg *A = + Args.getLastArg(options::OPT_fsanitize_debug_trap_reasons, + options::OPT_fno_sanitize_debug_trap_reasons)) { + CmdArgs.push_back(Args.MakeArgString(A->getAsString(Args))); + } + addSpecialCaseListOpt(Args, CmdArgs, "-fsanitize-ignorelist=", UserIgnorelistFiles); addSpecialCaseListOpt(Args, CmdArgs, diff --git a/clang/lib/Driver/ToolChains/Clang.cpp b/clang/lib/Driver/ToolChains/Clang.cpp index 7d0c142..9d882db 100644 --- a/clang/lib/Driver/ToolChains/Clang.cpp +++ b/clang/lib/Driver/ToolChains/Clang.cpp @@ -3881,17 +3881,17 @@ static bool RenderModulesOptions(Compilation &C, const Driver &D, const ArgList &Args, const InputInfo &Input, const InputInfo &Output, bool HaveStd20, ArgStringList &CmdArgs) { - bool IsCXX = types::isCXX(Input.getType()); - bool HaveStdCXXModules = IsCXX && HaveStd20; + const bool IsCXX = types::isCXX(Input.getType()); + const bool HaveStdCXXModules = IsCXX && HaveStd20; bool HaveModules = HaveStdCXXModules; // -fmodules enables the use of precompiled modules (off by default). // Users can pass -fno-cxx-modules to turn off modules support for // C++/Objective-C++ programs. + const bool AllowedInCXX = Args.hasFlag(options::OPT_fcxx_modules, + options::OPT_fno_cxx_modules, true); bool HaveClangModules = false; if (Args.hasFlag(options::OPT_fmodules, options::OPT_fno_modules, false)) { - bool AllowedInCXX = Args.hasFlag(options::OPT_fcxx_modules, - options::OPT_fno_cxx_modules, true); if (AllowedInCXX || !IsCXX) { CmdArgs.push_back("-fmodules"); HaveClangModules = true; @@ -3900,6 +3900,9 @@ static bool RenderModulesOptions(Compilation &C, const Driver &D, HaveModules |= HaveClangModules; + if (HaveModules && !AllowedInCXX) + CmdArgs.push_back("-fno-cxx-modules"); + // -fmodule-maps enables implicit reading of module map files. By default, // this is enabled if we are using Clang's flavor of precompiled modules. if (Args.hasFlag(options::OPT_fimplicit_module_maps, diff --git a/clang/lib/Format/Format.cpp b/clang/lib/Format/Format.cpp index 1cfa3d1..e6808f7 100644 --- a/clang/lib/Format/Format.cpp +++ b/clang/lib/Format/Format.cpp @@ -1754,7 +1754,6 @@ FormatStyle getGoogleStyle(FormatStyle::LanguageKind Language) { GoogleStyle.AttributeMacros.push_back("absl_nullable"); GoogleStyle.AttributeMacros.push_back("absl_nullability_unknown"); GoogleStyle.BreakTemplateDeclarations = FormatStyle::BTDS_Yes; - GoogleStyle.DerivePointerAlignment = true; GoogleStyle.IncludeStyle.IncludeBlocks = tooling::IncludeStyle::IBS_Regroup; GoogleStyle.IncludeStyle.IncludeCategories = {{"^<ext/.*\\.h>", 2, 0, false}, {"^<.*\\.h>", 1, 0, false}, @@ -1863,6 +1862,7 @@ FormatStyle getGoogleStyle(FormatStyle::LanguageKind Language) { } else if (Language == FormatStyle::LK_ObjC) { GoogleStyle.AlwaysBreakBeforeMultilineStrings = false; GoogleStyle.ColumnLimit = 100; + GoogleStyle.DerivePointerAlignment = true; // "Regroup" doesn't work well for ObjC yet (main header heuristic, // relationship between ObjC standard library headers and other heades, // #imports, etc.) diff --git a/clang/lib/Parse/ParseDeclCXX.cpp b/clang/lib/Parse/ParseDeclCXX.cpp index 31392d1d..bc8841c 100644 --- a/clang/lib/Parse/ParseDeclCXX.cpp +++ b/clang/lib/Parse/ParseDeclCXX.cpp @@ -4940,9 +4940,8 @@ void Parser::ParseHLSLRootSignatureAttributeArgs(ParsedAttributes &Attrs) { // signature string and construct the in-memory elements if (!Found) { // Invoke the root signature parser to construct the in-memory constructs - SmallVector<hlsl::RootSignatureElement> RootElements; - hlsl::RootSignatureParser Parser(getLangOpts().HLSLRootSigVer, RootElements, - Signature, PP); + hlsl::RootSignatureParser Parser(getLangOpts().HLSLRootSigVer, Signature, + PP); if (Parser.parse()) { T.consumeClose(); return; @@ -4950,7 +4949,7 @@ void Parser::ParseHLSLRootSignatureAttributeArgs(ParsedAttributes &Attrs) { // Construct the declaration. Actions.HLSL().ActOnFinishRootSignatureDecl(RootSignatureLoc, DeclIdent, - RootElements); + Parser.getElements()); } // Create the arg for the ParsedAttr diff --git a/clang/lib/Parse/ParseHLSLRootSignature.cpp b/clang/lib/Parse/ParseHLSLRootSignature.cpp index db9ed83..98dc458 100644 --- a/clang/lib/Parse/ParseHLSLRootSignature.cpp +++ b/clang/lib/Parse/ParseHLSLRootSignature.cpp @@ -27,11 +27,10 @@ static const TokenKind RootElementKeywords[] = { }; RootSignatureParser::RootSignatureParser( - llvm::dxbc::RootSignatureVersion Version, - SmallVector<RootSignatureElement> &Elements, StringLiteral *Signature, + llvm::dxbc::RootSignatureVersion Version, StringLiteral *Signature, Preprocessor &PP) - : Version(Version), Elements(Elements), Signature(Signature), - Lexer(Signature->getString()), PP(PP), CurToken(0) {} + : Version(Version), Signature(Signature), Lexer(Signature->getString()), + PP(PP), CurToken(0) {} bool RootSignatureParser::parse() { // Iterate as many RootSignatureElements as possible, until we hit the diff --git a/clang/lib/Sema/SemaOpenACC.cpp b/clang/lib/Sema/SemaOpenACC.cpp index 128a5db..8bfea62 100644 --- a/clang/lib/Sema/SemaOpenACC.cpp +++ b/clang/lib/Sema/SemaOpenACC.cpp @@ -699,11 +699,19 @@ ExprResult SemaOpenACC::ActOnVar(OpenACCDirectiveKind DK, OpenACCClauseKind CK, // OpenACC3.3 2.13: // A 'var' in a 'declare' directive must be a variable or array name. if ((CK == OpenACCClauseKind::UseDevice || - DK == OpenACCDirectiveKind::Declare) && - isa<ArraySectionExpr, ArraySubscriptExpr>(CurVarExpr)) { - Diag(VarExpr->getExprLoc(), diag::err_acc_not_a_var_ref_use_device_declare) - << (DK == OpenACCDirectiveKind::Declare); - return ExprError(); + DK == OpenACCDirectiveKind::Declare)) { + if (isa<ArraySubscriptExpr>(CurVarExpr)) { + Diag(VarExpr->getExprLoc(), + diag::err_acc_not_a_var_ref_use_device_declare) + << (DK == OpenACCDirectiveKind::Declare); + return ExprError(); + } + // As an extension, we allow 'array sections'/'sub-arrays' here, as that is + // effectively defining an array, and are in common use. + if (isa<ArraySectionExpr>(CurVarExpr)) + Diag(VarExpr->getExprLoc(), + diag::ext_acc_array_section_use_device_declare) + << (DK == OpenACCDirectiveKind::Declare); } // Sub-arrays/subscript-exprs are fine as long as the base is a diff --git a/clang/lib/Sema/SemaOpenACCClause.cpp b/clang/lib/Sema/SemaOpenACCClause.cpp index 3f90fe8..b54a012 100644 --- a/clang/lib/Sema/SemaOpenACCClause.cpp +++ b/clang/lib/Sema/SemaOpenACCClause.cpp @@ -1919,6 +1919,14 @@ ExprResult SemaOpenACC::CheckReductionVar(OpenACCDirectiveKind DirectiveKind, << EltTy << /*Sub array base type*/ 1; return ExprError(); } + } else if (VarExpr->getType()->isArrayType()) { + // Arrays are considered an 'aggregate variable' explicitly, so are OK, no + // additional checking required. + // + // Glossary: Aggregate variables – a variable of any non-scalar datatype, + // including array or composite variables. + // + // The next branch (record decl) checks for composite variables. } else if (auto *RD = VarExpr->getType()->getAsRecordDecl()) { if (!RD->isStruct() && !RD->isClass()) { Diag(VarExpr->getExprLoc(), diag::err_acc_reduction_composite_type) @@ -2246,7 +2254,13 @@ bool SemaOpenACC::CheckDeclareClause(SemaOpenACC::OpenACCParsedClause &Clause, continue; } } else { - const auto *DRE = cast<DeclRefExpr>(VarExpr); + + const Expr *VarExprTemp = VarExpr; + + while (const auto *ASE = dyn_cast<ArraySectionExpr>(VarExprTemp)) + VarExprTemp = ASE->getBase()->IgnoreParenImpCasts(); + + const auto *DRE = cast<DeclRefExpr>(VarExprTemp); if (const auto *Var = dyn_cast<VarDecl>(DRE->getDecl())) { CurDecl = Var->getCanonicalDecl(); diff --git a/clang/lib/Sema/SemaWasm.cpp b/clang/lib/Sema/SemaWasm.cpp index 6faea24..8998492 100644 --- a/clang/lib/Sema/SemaWasm.cpp +++ b/clang/lib/Sema/SemaWasm.cpp @@ -227,6 +227,53 @@ bool SemaWasm::BuiltinWasmTableCopy(CallExpr *TheCall) { return false; } +bool SemaWasm::BuiltinWasmTestFunctionPointerSignature(CallExpr *TheCall) { + if (SemaRef.checkArgCount(TheCall, 1)) + return true; + + Expr *FuncPtrArg = TheCall->getArg(0); + QualType ArgType = FuncPtrArg->getType(); + + // Check that the argument is a function pointer + const PointerType *PtrTy = ArgType->getAs<PointerType>(); + if (!PtrTy) { + return Diag(FuncPtrArg->getBeginLoc(), + diag::err_typecheck_expect_function_pointer) + << ArgType << FuncPtrArg->getSourceRange(); + } + + const FunctionProtoType *FuncTy = + PtrTy->getPointeeType()->getAs<FunctionProtoType>(); + if (!FuncTy) { + return Diag(FuncPtrArg->getBeginLoc(), + diag::err_typecheck_expect_function_pointer) + << ArgType << FuncPtrArg->getSourceRange(); + } + + // Check that the function pointer doesn't use reference types + if (FuncTy->getReturnType().isWebAssemblyReferenceType()) { + return Diag( + FuncPtrArg->getBeginLoc(), + diag::err_wasm_builtin_test_fp_sig_cannot_include_reference_type) + << 0 << FuncTy->getReturnType() << FuncPtrArg->getSourceRange(); + } + auto NParams = FuncTy->getNumParams(); + for (unsigned I = 0; I < NParams; I++) { + if (FuncTy->getParamType(I).isWebAssemblyReferenceType()) { + return Diag( + FuncPtrArg->getBeginLoc(), + diag:: + err_wasm_builtin_test_fp_sig_cannot_include_reference_type) + << 1 << FuncPtrArg->getSourceRange(); + } + } + + // Set return type to int (the result of the test) + TheCall->setType(getASTContext().IntTy); + + return false; +} + bool SemaWasm::CheckWebAssemblyBuiltinFunctionCall(const TargetInfo &TI, unsigned BuiltinID, CallExpr *TheCall) { @@ -249,6 +296,8 @@ bool SemaWasm::CheckWebAssemblyBuiltinFunctionCall(const TargetInfo &TI, return BuiltinWasmTableFill(TheCall); case WebAssembly::BI__builtin_wasm_table_copy: return BuiltinWasmTableCopy(TheCall); + case WebAssembly::BI__builtin_wasm_test_function_pointer_signature: + return BuiltinWasmTestFunctionPointerSignature(TheCall); } return false; diff --git a/clang/test/CIR/CodeGen/complex-cast.cpp b/clang/test/CIR/CodeGen/complex-cast.cpp index 94f47e4..0881057 100644 --- a/clang/test/CIR/CodeGen/complex-cast.cpp +++ b/clang/test/CIR/CodeGen/complex-cast.cpp @@ -326,3 +326,33 @@ void complex_to_complex_cast() { // OGCG: store i32 %[[REAL_INT_CAST]], ptr {{.*}}, align 4 // OGCG: store i32 %[[IMAG_INT_CAST]], ptr getelementptr inbounds nuw ({ i32, i32 }, ptr {{.*}}, i32 0, i32 1), align 4 +struct CX { + double real; + double imag; +}; + +void lvalue_to_rvalue_bitcast() { + CX a; + double _Complex b = __builtin_bit_cast(double _Complex, a); +} + + +// CIR-BEFORE: %{{.*}} = cir.cast(bitcast, %{{.*}} : !cir.ptr<!rec_CX>), !cir.ptr<!cir.complex<!cir.double>> + +// CIR-AFTER: %{{.*}} = cir.cast(bitcast, %{{.*}} : !cir.ptr<!rec_CX>), !cir.ptr<!cir.complex<!cir.double>> + +// LLVM: %[[PTR_ADDR:.*]] = alloca %struct.CX, i64 1, align 8 +// LLVM: %[[COMPLEX_ADDR:.*]] = alloca { double, double }, i64 1, align 8 +// LLVM: %[[PTR_TO_COMPLEX:.*]] = load { double, double }, ptr %[[PTR_ADDR]], align 8 +// LLVM: store { double, double } %[[PTR_TO_COMPLEX]], ptr %[[COMPLEX_ADDR]], align 8 + +// OGCG: %[[A_ADDR:.*]] = alloca %struct.CX, align 8 +// OGCG: %[[B_ADDR:.*]] = alloca { double, double }, align 8 +// OGCG: %[[A_REAL_PTR:.*]] = getelementptr inbounds nuw { double, double }, ptr %[[A_ADDR]], i32 0, i32 0 +// OGCG: %[[A_REAL:.*]] = load double, ptr %[[A_REAL_PTR]], align 8 +// OGCG: %[[A_IMAG_PTR:.*]] = getelementptr inbounds nuw { double, double }, ptr %[[A_ADDR]], i32 0, i32 1 +// OGCG: %[[A_IMAG:.*]] = load double, ptr %[[A_IMAG_PTR]], align 8 +// OGCG: %[[B_REAL_PTR:.*]] = getelementptr inbounds nuw { double, double }, ptr %[[B_ADDR]], i32 0, i32 0 +// OGCG: %[[B_IMAG_PTR:.*]] = getelementptr inbounds nuw { double, double }, ptr %[[B_ADDR]], i32 0, i32 1 +// OGCG: store double %[[A_REAL]], ptr %[[B_REAL_PTR]], align 8 +// OGCG: store double %[[A_IMAG]], ptr %[[B_IMAG_PTR]], align 8 diff --git a/clang/test/CIR/CodeGen/complex.cpp b/clang/test/CIR/CodeGen/complex.cpp index 0a7765f..bd7de9a 100644 --- a/clang/test/CIR/CodeGen/complex.cpp +++ b/clang/test/CIR/CodeGen/complex.cpp @@ -780,3 +780,22 @@ void foo29() { // OGCG: %[[INIT_IMAG_PTR:.*]] = getelementptr inbounds nuw { i32, i32 }, ptr %[[INIT]], i32 0, i32 1 // OGCG: store i32 0, ptr %[[INIT_REAL_PTR]], align 4 // OGCG: store i32 0, ptr %[[INIT_IMAG_PTR]], align 4 + +void foo30() { + float _Complex a = { 1.0f }; +} + +// CIR: %[[A_ADDR:.*]] = cir.alloca !cir.complex<!cir.float>, !cir.ptr<!cir.complex<!cir.float>>, ["a", init] +// CIR: %[[CONST_1F:.*]] = cir.const #cir.fp<1.000000e+00> : !cir.float +// CIR: %[[CONST_0F:.*]] = cir.const #cir.fp<0.000000e+00> : !cir.float +// CIR: %[[COMPLEX:.*]] = cir.complex.create %[[CONST_1F]], %[[CONST_0F]] : !cir.float -> !cir.complex<!cir.float> +// CIR: cir.store{{.*}} %[[COMPLEX]], %[[A_ADDR]] : !cir.complex<!cir.float>, !cir.ptr<!cir.complex<!cir.float>> + +// LLVM: %[[A_ADDR:.*]] = alloca { float, float }, i64 1, align 4 +// LLVM: store { float, float } { float 1.000000e+00, float 0.000000e+00 }, ptr %[[A_ADDR]], align 4 + +// OGCG: %[[A_ADDR:.*]] = alloca { float, float }, align 4 +// OGCG: %[[A_REAL_PTR:.*]] = getelementptr inbounds nuw { float, float }, ptr %[[A_ADDR]], i32 0, i32 0 +// OGCG: %[[A_IMAG_PTR:.*]] = getelementptr inbounds nuw { float, float }, ptr %[[A_ADDR]], i32 0, i32 1 +// OGCG: store float 1.000000e+00, ptr %[[A_REAL_PTR]], align 4 +// OGCG: store float 0.000000e+00, ptr %[[A_IMAG_PTR]], align 4 diff --git a/clang/test/CIR/CodeGen/struct-init.cpp b/clang/test/CIR/CodeGen/struct-init.cpp new file mode 100644 index 0000000..a47ef53 --- /dev/null +++ b/clang/test/CIR/CodeGen/struct-init.cpp @@ -0,0 +1,184 @@ +// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -fclangir -emit-cir %s -o %t.cir +// RUN: FileCheck --check-prefix=CIR --input-file=%t.cir %s +// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -fclangir -emit-llvm %s -o %t-cir.ll +// RUN: FileCheck --check-prefix=LLVM --input-file=%t-cir.ll %s +// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -emit-llvm %s -o %t.ll +// RUN: FileCheck --check-prefix=OGCG --input-file=%t.ll %s + +struct S { + int a, b, c; +}; + +void init() { + S s1 = {1, 2, 3}; + S s2 = {4, 5}; +} + +// CIR: cir.func{{.*}} @_Z4initv() +// CIR: %[[S1:.*]] = cir.alloca !rec_S, !cir.ptr<!rec_S>, ["s1", init] +// CIR: %[[S2:.*]] = cir.alloca !rec_S, !cir.ptr<!rec_S>, ["s2", init] +// CIR: %[[S1_A:.*]] = cir.get_member %[[S1]][0] {name = "a"} +// CIR: %[[ONE:.*]] = cir.const #cir.int<1> +// CIR: cir.store{{.*}} %[[ONE]], %[[S1_A]] +// CIR: %[[S1_B:.*]] = cir.get_member %[[S1]][1] {name = "b"} +// CIR: %[[TWO:.*]] = cir.const #cir.int<2> +// CIR: cir.store{{.*}} %[[TWO]], %[[S1_B]] +// CIR: %[[S1_C:.*]] = cir.get_member %[[S1]][2] {name = "c"} +// CIR: %[[THREE:.*]] = cir.const #cir.int<3> +// CIR: cir.store{{.*}} %[[THREE]], %[[S1_C]] +// CIR: %[[S2_A:.*]] = cir.get_member %[[S2]][0] {name = "a"} +// CIR: %[[FOUR:.*]] = cir.const #cir.int<4> +// CIR: cir.store{{.*}} %[[FOUR]], %[[S2_A]] +// CIR: %[[S2_B:.*]] = cir.get_member %[[S2]][1] {name = "b"} +// CIR: %[[FIVE:.*]] = cir.const #cir.int<5> +// CIR: cir.store{{.*}} %[[FIVE]], %[[S2_B]] +// CIR: %[[S2_C:.*]] = cir.get_member %[[S2]][2] {name = "c"} +// CIR: %[[ZERO:.*]] = cir.const #cir.int<0> +// CIR: cir.store{{.*}} %[[ZERO]], %[[S2_C]] +// CIR: cir.return + +// LLVM: define{{.*}} void @_Z4initv() +// LLVM: %[[S1:.*]] = alloca %struct.S +// LLVM: %[[S2:.*]] = alloca %struct.S +// LLVM: %[[S1_A:.*]] = getelementptr %struct.S, ptr %[[S1]], i32 0, i32 0 +// LLVM: store i32 1, ptr %[[S1_A]] +// LLVM: %[[S1_B:.*]] = getelementptr %struct.S, ptr %[[S1]], i32 0, i32 1 +// LLVM: store i32 2, ptr %[[S1_B]] +// LLVM: %[[S1_C:.*]] = getelementptr %struct.S, ptr %[[S1]], i32 0, i32 2 +// LLVM: store i32 3, ptr %[[S1_C]] +// LLVM: %[[S2_A:.*]] = getelementptr %struct.S, ptr %[[S2]], i32 0, i32 0 +// LLVM: store i32 4, ptr %[[S2_A]] +// LLVM: %[[S2_B:.*]] = getelementptr %struct.S, ptr %[[S2]], i32 0, i32 1 +// LLVM: store i32 5, ptr %[[S2_B]] +// LLVM: %[[S2_C:.*]] = getelementptr %struct.S, ptr %[[S2]], i32 0, i32 2 +// LLVM: store i32 0, ptr %[[S2_C]] + +// OGCG: @__const._Z4initv.s1 = private unnamed_addr constant %struct.S { i32 1, i32 2, i32 3 } +// OGCG: @__const._Z4initv.s2 = private unnamed_addr constant %struct.S { i32 4, i32 5, i32 0 } + +// OGCG: define{{.*}} void @_Z4initv() +// OGCG: %[[S1:.*]] = alloca %struct.S +// OGCG: %[[S2:.*]] = alloca %struct.S +// OGCG: call void @llvm.memcpy.p0.p0.i64(ptr{{.*}} %[[S1]], ptr{{.*}} @__const._Z4initv.s1, i64 12, i1 false) +// OGCG: call void @llvm.memcpy.p0.p0.i64(ptr{{.*}} %[[S2]], ptr{{.*}} @__const._Z4initv.s2, i64 12, i1 false) + +void init_var(int a, int b) { + S s = {a, b}; +} + +// CIR: cir.func{{.*}} @_Z8init_varii(%[[A_ARG:.*]]: !s32i {{.*}}, %[[B_ARG:.*]]: !s32i {{.*}}) +// CIR: %[[A_PTR:.*]] = cir.alloca !s32i, !cir.ptr<!s32i>, ["a", init] +// CIR: %[[B_PTR:.*]] = cir.alloca !s32i, !cir.ptr<!s32i>, ["b", init] +// CIR: %[[S:.*]] = cir.alloca !rec_S, !cir.ptr<!rec_S>, ["s", init] +// CIR: cir.store{{.*}} %[[A_ARG]], %[[A_PTR]] +// CIR: cir.store{{.*}} %[[B_ARG]], %[[B_PTR]] +// CIR: %[[S_A:.*]] = cir.get_member %[[S]][0] {name = "a"} +// CIR: %[[A:.*]] = cir.load{{.*}} %[[A_PTR]] +// CIR: cir.store{{.*}} %[[A]], %[[S_A]] +// CIR: %[[S_B:.*]] = cir.get_member %[[S]][1] {name = "b"} +// CIR: %[[B:.*]] = cir.load{{.*}} %[[B_PTR]] +// CIR: cir.store{{.*}} %[[B]], %[[S_B]] +// CIR: cir.return + +// LLVM: define{{.*}} void @_Z8init_varii(i32 %[[A_ARG:.*]], i32 %[[B_ARG:.*]]) +// LLVM: %[[A_PTR:.*]] = alloca i32 +// LLVM: %[[B_PTR:.*]] = alloca i32 +// LLVM: %[[S:.*]] = alloca %struct.S +// LLVM: store i32 %[[A_ARG]], ptr %[[A_PTR]] +// LLVM: store i32 %[[B_ARG]], ptr %[[B_PTR]] +// LLVM: %[[S_A:.*]] = getelementptr %struct.S, ptr %[[S]], i32 0, i32 0 +// LLVM: %[[A:.*]] = load i32, ptr %[[A_PTR]] +// LLVM: store i32 %[[A]], ptr %[[S_A]] +// LLVM: %[[S_B:.*]] = getelementptr %struct.S, ptr %[[S]], i32 0, i32 1 +// LLVM: %[[B:.*]] = load i32, ptr %[[B_PTR]] +// LLVM: store i32 %[[B]], ptr %[[S_B]] +// LLVM: ret void + +// OGCG: define{{.*}} void @_Z8init_varii(i32 {{.*}} %[[A_ARG:.*]], i32 {{.*}} %[[B_ARG:.*]]) +// OGCG: %[[A_PTR:.*]] = alloca i32 +// OGCG: %[[B_PTR:.*]] = alloca i32 +// OGCG: %[[S:.*]] = alloca %struct.S +// OGCG: store i32 %[[A_ARG]], ptr %[[A_PTR]] +// OGCG: store i32 %[[B_ARG]], ptr %[[B_PTR]] +// OGCG: %[[S_A:.*]] = getelementptr {{.*}} %struct.S, ptr %[[S]], i32 0, i32 0 +// OGCG: %[[A:.*]] = load i32, ptr %[[A_PTR]] +// OGCG: store i32 %[[A]], ptr %[[S_A]] +// OGCG: %[[S_B:.*]] = getelementptr {{.*}} %struct.S, ptr %[[S]], i32 0, i32 1 +// OGCG: %[[B:.*]] = load i32, ptr %[[B_PTR]] +// OGCG: store i32 %[[B]], ptr %[[S_B]] +// OGCG: %[[S_C:.*]] = getelementptr {{.*}} %struct.S, ptr %[[S]], i32 0, i32 2 +// OGCG: store i32 0, ptr %[[S_C]] +// OGCG: ret void + +void init_expr(int a, int b, int c) { + S s = {a + 1, b + 2, c + 3}; +} + +// CIR: cir.func{{.*}} @_Z9init_expriii(%[[A_ARG:.*]]: !s32i {{.*}}, %[[B_ARG:.*]]: !s32i {{.*}}, %[[C_ARG:.*]]: !s32i {{.*}}) +// CIR: %[[A_PTR:.*]] = cir.alloca !s32i, !cir.ptr<!s32i>, ["a", init] +// CIR: %[[B_PTR:.*]] = cir.alloca !s32i, !cir.ptr<!s32i>, ["b", init] +// CIR: %[[C_PTR:.*]] = cir.alloca !s32i, !cir.ptr<!s32i>, ["c", init] +// CIR: %[[S:.*]] = cir.alloca !rec_S, !cir.ptr<!rec_S>, ["s", init] +// CIR: cir.store{{.*}} %[[A_ARG]], %[[A_PTR]] +// CIR: cir.store{{.*}} %[[B_ARG]], %[[B_PTR]] +// CIR: cir.store{{.*}} %[[C_ARG]], %[[C_PTR]] +// CIR: %[[S_A:.*]] = cir.get_member %[[S]][0] {name = "a"} +// CIR: %[[A:.*]] = cir.load{{.*}} %[[A_PTR]] +// CIR: %[[ONE:.*]] = cir.const #cir.int<1> +// CIR: %[[A_PLUS_ONE:.*]] = cir.binop(add, %[[A]], %[[ONE]]) +// CIR: cir.store{{.*}} %[[A_PLUS_ONE]], %[[S_A]] +// CIR: %[[S_B:.*]] = cir.get_member %[[S]][1] {name = "b"} +// CIR: %[[B:.*]] = cir.load{{.*}} %[[B_PTR]] +// CIR: %[[TWO:.*]] = cir.const #cir.int<2> +// CIR: %[[B_PLUS_TWO:.*]] = cir.binop(add, %[[B]], %[[TWO]]) nsw : !s32i +// CIR: cir.store{{.*}} %[[B_PLUS_TWO]], %[[S_B]] +// CIR: %[[S_C:.*]] = cir.get_member %[[S]][2] {name = "c"} +// CIR: %[[C:.*]] = cir.load{{.*}} %[[C_PTR]] +// CIR: %[[THREE:.*]] = cir.const #cir.int<3> +// CIR: %[[C_PLUS_THREE:.*]] = cir.binop(add, %[[C]], %[[THREE]]) nsw : !s32i +// CIR: cir.store{{.*}} %[[C_PLUS_THREE]], %[[S_C]] +// CIR: cir.return + +// LLVM: define{{.*}} void @_Z9init_expriii(i32 %[[A_ARG:.*]], i32 %[[B_ARG:.*]], i32 %[[C_ARG:.*]]) +// LLVM: %[[A_PTR:.*]] = alloca i32 +// LLVM: %[[B_PTR:.*]] = alloca i32 +// LLVM: %[[C_PTR:.*]] = alloca i32 +// LLVM: %[[S:.*]] = alloca %struct.S +// LLVM: store i32 %[[A_ARG]], ptr %[[A_PTR]] +// LLVM: store i32 %[[B_ARG]], ptr %[[B_PTR]] +// LLVM: store i32 %[[C_ARG]], ptr %[[C_PTR]] +// LLVM: %[[S_A:.*]] = getelementptr %struct.S, ptr %[[S]], i32 0, i32 0 +// LLVM: %[[A:.*]] = load i32, ptr %[[A_PTR]] +// LLVM: %[[A_PLUS_ONE:.*]] = add nsw i32 %[[A]], 1 +// LLVM: store i32 %[[A_PLUS_ONE]], ptr %[[S_A]] +// LLVM: %[[S_B:.*]] = getelementptr %struct.S, ptr %[[S]], i32 0, i32 1 +// LLVM: %[[B:.*]] = load i32, ptr %[[B_PTR]] +// LLVM: %[[B_PLUS_TWO:.*]] = add nsw i32 %[[B]], 2 +// LLVM: store i32 %[[B_PLUS_TWO]], ptr %[[S_B]] +// LLVM: %[[S_C:.*]] = getelementptr %struct.S, ptr %[[S]], i32 0, i32 2 +// LLVM: %[[C:.*]] = load i32, ptr %[[C_PTR]] +// LLVM: %[[C_PLUS_THREE:.*]] = add nsw i32 %[[C]], 3 +// LLVM: store i32 %[[C_PLUS_THREE]], ptr %[[S_C]] +// LLVM: ret void + +// OGCG: define{{.*}} void @_Z9init_expriii(i32 {{.*}} %[[A_ARG:.*]], i32 {{.*}} %[[B_ARG:.*]], i32 {{.*}} %[[C_ARG:.*]]) +// OGCG: %[[A_PTR:.*]] = alloca i32 +// OGCG: %[[B_PTR:.*]] = alloca i32 +// OGCG: %[[C_PTR:.*]] = alloca i32 +// OGCG: %[[S:.*]] = alloca %struct.S +// OGCG: store i32 %[[A_ARG]], ptr %[[A_PTR]] +// OGCG: store i32 %[[B_ARG]], ptr %[[B_PTR]] +// OGCG: store i32 %[[C_ARG]], ptr %[[C_PTR]] +// OGCG: %[[S_A:.*]] = getelementptr {{.*}} %struct.S, ptr %[[S]], i32 0, i32 0 +// OGCG: %[[A:.*]] = load i32, ptr %[[A_PTR]] +// OGCG: %[[A_PLUS_ONE:.*]] = add nsw i32 %[[A]], 1 +// OGCG: store i32 %[[A_PLUS_ONE]], ptr %[[S_A]] +// OGCG: %[[S_B:.*]] = getelementptr {{.*}} %struct.S, ptr %[[S]], i32 0, i32 1 +// OGCG: %[[B:.*]] = load i32, ptr %[[B_PTR]] +// OGCG: %[[B_PLUS_TWO:.*]] = add nsw i32 %[[B]], 2 +// OGCG: store i32 %[[B_PLUS_TWO]], ptr %[[S_B]] +// OGCG: %[[S_C:.*]] = getelementptr {{.*}} %struct.S, ptr %[[S]], i32 0, i32 2 +// OGCG: %[[C:.*]] = load i32, ptr %[[C_PTR]] +// OGCG: %[[C_PLUS_THREE:.*]] = add nsw i32 %[[C]], 3 +// OGCG: store i32 %[[C_PLUS_THREE]], ptr %[[S_C]] +// OGCG: ret void diff --git a/clang/test/CIR/CodeGenOpenACC/host_data.c b/clang/test/CIR/CodeGenOpenACC/host_data.c index aeaf3d2f..fa06d2a 100644 --- a/clang/test/CIR/CodeGenOpenACC/host_data.c +++ b/clang/test/CIR/CodeGenOpenACC/host_data.c @@ -1,13 +1,15 @@ // RUN: %clang_cc1 -fopenacc -Wno-openacc-self-if-potential-conflict -emit-cir -fclangir %s -o - | FileCheck %s -void acc_host_data(int cond, int var1, int var2) { - // CHECK: cir.func{{.*}} @acc_host_data(%[[ARG_COND:.*]]: !s32i {{.*}}, %[[ARG_V1:.*]]: !s32i {{.*}}, %[[ARG_V2:.*]]: !s32i {{.*}}) { +void acc_host_data(int cond, int var1, int var2, int *arr) { + // CHECK: cir.func{{.*}} @acc_host_data(%[[ARG_COND:.*]]: !s32i {{.*}}, %[[ARG_V1:.*]]: !s32i {{.*}}, %[[ARG_V2:.*]]: !s32i {{.*}}, %[[ARG_ARR:.*]]: !cir.ptr<!s32i> {{.*}}) { // CHECK-NEXT: %[[COND:.*]] = cir.alloca !s32i, !cir.ptr<!s32i>, ["cond", init] // CHECK-NEXT: %[[V1:.*]] = cir.alloca !s32i, !cir.ptr<!s32i>, ["var1", init] // CHECK-NEXT: %[[V2:.*]] = cir.alloca !s32i, !cir.ptr<!s32i>, ["var2", init] + // CHECK-NEXT: %[[ARR:.*]] = cir.alloca !cir.ptr<!s32i>, !cir.ptr<!cir.ptr<!s32i>>, ["arr", init] // CHECK-NEXT: cir.store %[[ARG_COND]], %[[COND]] : !s32i, !cir.ptr<!s32i> // CHECK-NEXT: cir.store %[[ARG_V1]], %[[V1]] : !s32i, !cir.ptr<!s32i> // CHECK-NEXT: cir.store %[[ARG_V2]], %[[V2]] : !s32i, !cir.ptr<!s32i> + // CHECK-NEXT: cir.store %[[ARG_ARR]], %[[ARR]] : !cir.ptr<!s32i>, !cir.ptr<!cir.ptr<!s32i>> #pragma acc host_data use_device(var1) {} @@ -52,4 +54,18 @@ void acc_host_data(int cond, int var1, int var2) { // CHECK-NEXT: acc.host_data if(%[[COND_CAST]]) dataOperands(%[[USE_DEV1]], %[[USE_DEV2]] : !cir.ptr<!s32i>, !cir.ptr<!s32i>) { // CHECK-NEXT: acc.terminator // CHECK-NEXT: } attributes {ifPresent} + +#pragma acc host_data use_device(arr[0:var1]) + {} + // CHECK-NEXT: %[[ZERO:.*]] = cir.const #cir.int<0> + // CHECK-NEXT: %[[ZERO_CAST:.*]] = builtin.unrealized_conversion_cast %[[ZERO]] : !s32i to si32 + // CHECK-NEXT: %[[VAR1_LOAD:.*]] = cir.load{{.*}} %[[V1]] : !cir.ptr<!s32i>, !s32i + // CHECK-NEXT: %[[VAR1_CAST:.*]] = builtin.unrealized_conversion_cast %[[VAR1_LOAD]] : !s32i to si32 + // CHECK-NEXT: %[[CONST_ZERO:.*]] = arith.constant 0 + // CHECK-NEXT: %[[CONST_ONE:.*]] = arith.constant 1 + // CHECK-NEXT: %[[BOUNDS:.*]] = acc.bounds lowerbound(%[[ZERO_CAST]] : si32) extent(%[[VAR1_CAST]] : si32) stride(%[[CONST_ONE]] : i64) startIdx(%[[CONST_ZERO]] : i64) + // CHECK-NEXT: %[[USE_DEV1:.*]] = acc.use_device varPtr(%[[ARR]] : !cir.ptr<!cir.ptr<!s32i>>) bounds(%[[BOUNDS]]) -> !cir.ptr<!cir.ptr<!s32i>> {name = "arr[0:var1]"} + // CHECK-NEXT: acc.host_data dataOperands(%[[USE_DEV1]] : !cir.ptr<!cir.ptr<!s32i>>) + // CHECK-NEXT: acc.terminator + // CHECK-NEXT: } loc } diff --git a/clang/test/CIR/Lowering/poison.cir b/clang/test/CIR/Lowering/poison.cir new file mode 100644 index 0000000..6f8b792 --- /dev/null +++ b/clang/test/CIR/Lowering/poison.cir @@ -0,0 +1,14 @@ +// RUN: cir-translate -cir-to-llvmir --disable-cc-lowering -o %t.ll %s +// RUN: FileCheck -check-prefix=LLVM --input-file=%t.ll %s + +!s32i = !cir.int<s, 32> + +module { + cir.func @lower_poison() -> !s32i { + %0 = cir.const #cir.poison : !s32i + cir.return %0 : !s32i + } + // LLVM-LABEL: @lower_poison + // LLVM-NEXT: ret i32 poison + // LLVM-NEXT: } +} diff --git a/clang/test/CIR/Transforms/bit.cir b/clang/test/CIR/Transforms/bit.cir new file mode 100644 index 0000000..fc27adb --- /dev/null +++ b/clang/test/CIR/Transforms/bit.cir @@ -0,0 +1,211 @@ +// RUN: cir-opt -cir-canonicalize -cir-simplify -o %t.cir %s +// RUN: FileCheck --input-file=%t.cir %s + +!s32i = !cir.int<s, 32> +!u32i = !cir.int<u, 32> + +module { + cir.func @fold_clrsb() -> !s32i { + %0 = cir.const #cir.int<1> : !s32i + %1 = cir.clrsb %0 : !s32i + cir.return %1 : !s32i + } + // CHECK-LABEL: @fold_clrsb + // CHECK-NEXT: %[[R:.+]] = cir.const #cir.int<30> : !s32i + // CHECK-NEXT: cir.return %[[R]] : !s32i + // CHECK-NEXT: } + + cir.func @fold_clz() -> !u32i { + %0 = cir.const #cir.int<1> : !u32i + %1 = cir.clz %0 : !u32i + cir.return %1 : !u32i + } + // CHECK-LABEL: @fold_clz + // CHECK-NEXT: %[[R:.+]] = cir.const #cir.int<31> : !u32i + // CHECK-NEXT: cir.return %[[R]] : !u32i + // CHECK-NEXT: } + + cir.func @fold_clz_zero_poison() -> !u32i { + %0 = cir.const #cir.int<0> : !u32i + %1 = cir.clz %0 poison_zero : !u32i + cir.return %1 : !u32i + } + // CHECK-LABEL: @fold_clz_zero_poison + // CHECK-NEXT: %[[R:.+]] = cir.const #cir.poison : !u32i + // CHECK-NEXT: cir.return %[[R]] : !u32i + // CHECK-NEXT: } + + cir.func @fold_clz_zero_no_poison() -> !u32i { + %0 = cir.const #cir.int<0> : !u32i + %1 = cir.clz %0 : !u32i + cir.return %1 : !u32i + } + // CHECK-LABEL: @fold_clz_zero_no_poison + // CHECK-NEXT: %[[R:.+]] = cir.const #cir.int<32> : !u32i + // CHECK-NEXT: cir.return %[[R]] : !u32i + // CHECK-NEXT: } + + cir.func @fold_ctz() -> !u32i { + %0 = cir.const #cir.int<2> : !u32i + %1 = cir.ctz %0 : !u32i + cir.return %1 : !u32i + } + // CHECK-LABEL: @fold_ctz + // CHECK-NEXT: %[[R:.+]] = cir.const #cir.int<1> : !u32i + // CHECK-NEXT: cir.return %[[R]] : !u32i + // CHECK-NEXT: } + + cir.func @fold_ctz_zero_poison() -> !u32i { + %0 = cir.const #cir.int<0> : !u32i + %1 = cir.ctz %0 poison_zero : !u32i + cir.return %1 : !u32i + } + // CHECK-LABEL: @fold_ctz_zero_poison + // CHECK-NEXT: %[[R:.+]] = cir.const #cir.poison : !u32i + // CHECK-NEXT: cir.return %[[R]] : !u32i + // CHECK-NEXT: } + + cir.func @fold_ctz_zero_no_poison() -> !u32i { + %0 = cir.const #cir.int<0> : !u32i + %1 = cir.ctz %0 : !u32i + cir.return %1 : !u32i + } + // CHECK-LABEL: @fold_ctz_zero_no_poison + // CHECK-NEXT: %[[R:.+]] = cir.const #cir.int<32> : !u32i + // CHECK-NEXT: cir.return %[[R]] : !u32i + // CHECK-NEXT: } + + cir.func @fold_parity() -> !u32i { + // 0xdeadbeef is 0b1101_1110_1010_1101_1011_1110_1110_1111 + // 0xdeadbeef contains 24 ones + %0 = cir.const #cir.int<0xdeadbeef> : !u32i + %1 = cir.parity %0 : !u32i + cir.return %1 : !u32i + } + // CHECK-LABEL: @fold_parity + // CHECK-NEXT: %[[R:.+]] = cir.const #cir.int<0> : !u32i + // CHECK-NEXT: cir.return %[[R]] : !u32i + // CHECK-NEXT: } + + cir.func @fold_popcount() -> !u32i { + // 0xdeadbeef is 0b1101_1110_1010_1101_1011_1110_1110_1111 + // 0xdeadbeef contains 24 ones + %0 = cir.const #cir.int<0xdeadbeef> : !u32i + %1 = cir.popcount %0 : !u32i + cir.return %1 : !u32i + } + // CHECK-LABEL: @fold_popcount + // CHECK-NEXT: %[[R:.+]] = cir.const #cir.int<24> : !u32i + // CHECK-NEXT: cir.return %[[R]] : !u32i + // CHECK-NEXT: } + + cir.func @fold_bitreverse() -> !u32i { + // 0xdeadbeef is 0b1101_1110_1010_1101_1011_1110_1110_1111 + %0 = cir.const #cir.int<0xdeadbeef> : !u32i + %1 = cir.bitreverse %0 : !u32i + cir.return %1 : !u32i + } + // CHECK-LABEL: @fold_bitreverse + // 4152210811 is 0b1111_0111_0111_1101_1011_0101_0111_1011 + // CHECK-NEXT: %[[R:.+]] = cir.const #cir.int<4152210811> : !u32i + // CHECK-NEXT: cir.return %[[R]] : !u32i + // CHECK-NEXT: } + + cir.func @fold_byte_swap() -> !u32i { + %0 = cir.const #cir.int<0xdeadbeef> : !u32i + %1 = cir.byte_swap %0 : !u32i + cir.return %1 : !u32i + } + // CHECK-LABEL: @fold_byte_swap + // 4022250974 is 0xefbeadde + // CHECK-NEXT: %[[R:.+]] = cir.const #cir.int<4022250974> : !u32i + // CHECK-NEXT: cir.return %[[R]] : !u32i + // CHECK-NEXT: } + + cir.func @fold_input_poison() -> !s32i { + %0 = cir.const #cir.poison : !s32i + %1 = cir.clrsb %0 : !s32i + cir.return %1 : !s32i + } + // CHECK-LABEL: @fold_input_poison + // CHECK-NEXT: %[[P:.+]] = cir.const #cir.poison : !s32i + // CHECK-NEXT: cir.return %[[P]] : !s32i + // CHECK-NEXT: } + + cir.func @fold_rotate_input_all_zeros(%arg0 : !u32i) -> !u32i { + %0 = cir.const #cir.int<0> : !u32i + %1 = cir.rotate left %0, %arg0 : !u32i + cir.return %1 : !u32i + } + // CHECK-LABEL: @fold_rotate_input_all_zeros + // CHECK-NEXT: %[[R:.+]] = cir.const #cir.int<0> : !u32i + // CHECK-NEXT: cir.return %[[R]] : !u32i + // CHECK-NEXT: } + + cir.func @fold_rotate_input_all_ones(%arg0 : !u32i) -> !u32i { + // 4294967295 is 0b1111_1111_1111_1111_1111_1111_1111_1111 + %0 = cir.const #cir.int<4294967295> : !u32i + %1 = cir.rotate left %0, %arg0 : !u32i + cir.return %1 : !u32i + } + // CHECK-LABEL: @fold_rotate_input_all_ones + // CHECK-NEXT: %[[R:.+]] = cir.const #cir.int<4294967295> : !u32i + // CHECK-NEXT: cir.return %[[R]] : !u32i + // CHECK-NEXT: } + + cir.func @fold_rotate_zero_amount(%arg0 : !u32i) -> !u32i { + %0 = cir.const #cir.int<32> : !u32i + %1 = cir.rotate left %arg0, %0 : !u32i + cir.return %1 : !u32i + } + // CHECK-LABEL: @fold_rotate_zero_amount + // CHECK-SAME: (%[[R:.+]]: !u32i) + // CHECK-NEXT: cir.return %[[R]] : !u32i + // CHECK-NEXT: } + + cir.func @fold_rotate_left() -> !u32i { + // 0xdeadbeef is 0b1101_1110_1010_1101_1011_1110_1110_1111 + %0 = cir.const #cir.int<0xdeadbeef> : !u32i + %1 = cir.const #cir.int<8> : !u32i + %2 = cir.rotate left %0, %1 : !u32i + cir.return %2 : !u32i + } + // CHECK-LABEL: @fold_rotate_left + // 2914971614 is 0b1010_1101_1011_1110_1110_1111_1101_1110 + // CHECK-NEXT: %[[R:.+]] = cir.const #cir.int<2914971614> : !u32i + // CHECK-NEXT: cir.return %[[R]] : !u32i + // CHECK-NEXT: } + + cir.func @fold_rotate_right() -> !u32i { + // 0xdeadbeef is 0b1101_1110_1010_1101_1011_1110_1110_1111 + %0 = cir.const #cir.int<0xdeadbeef> : !u32i + %1 = cir.const #cir.int<8> : !u32i + %2 = cir.rotate right %0, %1 : !u32i + cir.return %2 : !u32i + } + // CHECK-LABEL: @fold_rotate_right + // 4260027374 is 0b1110_1111_1101_1110_1010_1101_1011_1110 + // CHECK-NEXT: %[[R:.+]] = cir.const #cir.int<4024348094> : !u32i + // CHECK-NEXT: cir.return %[[R]] : !u32i + // CHECK-NEXT: } + + cir.func @fold_rotate_input_poison(%arg0 : !u32i) -> !u32i { + %0 = cir.const #cir.poison : !u32i + %1 = cir.rotate left %0, %arg0 : !u32i + cir.return %1 : !u32i + } + // CHECK-LABEL: @fold_rotate_input_poison + // CHECK-NEXT: %[[P:.+]] = cir.const #cir.poison : !u32i + // CHECK-NEXT: cir.return %[[P]] : !u32i + // CHECK-NEXT: } + + cir.func @fold_rotate_amount_poison(%arg0 : !u32i) -> !u32i { + %0 = cir.const #cir.poison : !u32i + %1 = cir.rotate left %arg0, %0 : !u32i + cir.return %1 : !u32i + } + // CHECK-LABEL: @fold_rotate_amount_poison + // CHECK-NEXT: %[[P:.+]] = cir.const #cir.poison : !u32i + // CHECK-NEXT: cir.return %[[P]] : !u32i + // CHECK-NEXT: } +} diff --git a/clang/test/CIR/Transforms/canonicalize.cir b/clang/test/CIR/Transforms/canonicalize.cir index 7ba163e..5daff11 100644 --- a/clang/test/CIR/Transforms/canonicalize.cir +++ b/clang/test/CIR/Transforms/canonicalize.cir @@ -39,6 +39,16 @@ module { // CHECK: cir.func{{.*}} @unary_not(%arg0: !cir.bool) -> !cir.bool // CHECK-NEXT: cir.return %arg0 : !cir.bool + cir.func @unary_poison() -> !s32i { + %0 = cir.const #cir.poison : !s32i + %1 = cir.unary(inc, %0) : !s32i, !s32i + cir.return %1 : !s32i + } + // CHECK: @unary_poison + // CHECK-NEXT: %[[P:.+]] = cir.const #cir.poison : !s32i + // CHECK-NEXT: cir.return %[[P]] : !s32i + // CHECK-NEXT: } + cir.func @cast1(%arg0: !cir.bool) -> !cir.bool { %0 = cir.cast(bool_to_int, %arg0 : !cir.bool), !s32i %1 = cir.cast(int_to_bool, %0 : !s32i), !cir.bool @@ -70,4 +80,14 @@ module { // CHECK-NEXT: %[[CAST3:.*]] = cir.cast(integral, %[[CAST2]] : !s32i), !s64i // CHECK-NEXT: cir.return %[[CAST3]] : !s64i + cir.func @cast_poison() -> !s64i { + %0 = cir.const #cir.poison : !s32i + %1 = cir.cast(integral, %0 : !s32i), !s64i + cir.return %1 : !s64i + } + // CHECK: @cast_poison + // CHECK-NEXT: %[[P:.+]] = cir.const #cir.poison : !s64i + // CHECK-NEXT: cir.return %[[P]] : !s64i + // CHECK-NEXT: } + } diff --git a/clang/test/CodeGen/bounds-checking-debuginfo.c b/clang/test/CodeGen/bounds-checking-debuginfo.c index 74c0666..bd7aedd 100644 --- a/clang/test/CodeGen/bounds-checking-debuginfo.c +++ b/clang/test/CodeGen/bounds-checking-debuginfo.c @@ -25,13 +25,13 @@ void d(double*); // CHECK-TRAP-NEXT: [[TMP1:%.*]] = icmp ult i64 [[TMP0]], 10, !dbg [[DBG23]], !nosanitize [[META10]] // CHECK-TRAP-NEXT: br i1 [[TMP1]], label %[[CONT:.*]], label %[[TRAP:.*]], !dbg [[DBG23]], !prof [[PROF27:![0-9]+]], !nosanitize [[META10]] // CHECK-TRAP: [[TRAP]]: -// CHECK-TRAP-NEXT: call void @llvm.ubsantrap(i8 18) #[[ATTR3:[0-9]+]], !dbg [[DBG23]], !nosanitize [[META10]] -// CHECK-TRAP-NEXT: unreachable, !dbg [[DBG23]], !nosanitize [[META10]] +// CHECK-TRAP-NEXT: call void @llvm.ubsantrap(i8 18) #[[ATTR3:[0-9]+]], !dbg [[DBGTRAP:![0-9]+]], !nosanitize [[META10]] +// CHECK-TRAP-NEXT: unreachable, !dbg [[DBGTRAP]], !nosanitize [[META10]] // CHECK-TRAP: [[CONT]]: // CHECK-TRAP-NEXT: [[IDXPROM:%.*]] = sext i32 [[CALL]] to i64, !dbg [[DBG26:![0-9]+]] // CHECK-TRAP-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds [10 x double], ptr [[A]], i64 0, i64 [[IDXPROM]], !dbg [[DBG26]] // CHECK-TRAP-NEXT: [[TMP2:%.*]] = load double, ptr [[ARRAYIDX]], align 8, !dbg [[DBG26]] -// CHECK-TRAP-NEXT: ret double [[TMP2]], !dbg [[DBG28:![0-9]+]] +// CHECK-TRAP-NEXT: ret double [[TMP2]], !dbg [[DBG30:![0-9]+]] // // CHECK-NOTRAP-LABEL: define dso_local double @f1( // CHECK-NOTRAP-SAME: i32 noundef [[B:%.*]], i32 noundef [[I:%.*]]) #[[ATTR0:[0-9]+]] !dbg [[DBG4:![0-9]+]] { @@ -93,7 +93,9 @@ double f1(int b, int i) { // CHECK-TRAP: [[META25]] = !DISubroutineType(types: null) // CHECK-TRAP: [[DBG26]] = !DILocation(line: 66, column: 10, scope: [[DBG4]]) // CHECK-TRAP: [[PROF27]] = !{!"branch_weights", i32 1048575, i32 1} -// CHECK-TRAP: [[DBG28]] = !DILocation(line: 66, column: 3, scope: [[DBG4]]) +// CHECK-TRAP: [[DBGTRAP]] = !DILocation(line: 0, scope: [[TRAPMSG:![0-9]+]], inlinedAt: [[DBG23]]) +// CHECK-TRAP: [[TRAPMSG]] = distinct !DISubprogram(name: "__clang_trap_msg$Undefined Behavior Sanitizer$Array index out of bounds", scope: [[META5]], file: [[META5]], type: [[META25]], flags: DIFlagArtificial, spFlags: DISPFlagDefinition, unit: [[META0]]) +// CHECK-TRAP: [[DBG30]] = !DILocation(line: 66, column: 3, scope: [[DBG4]]) //. // CHECK-NOTRAP: [[META0:![0-9]+]] = distinct !DICompileUnit(language: DW_LANG_C11, file: [[META1:![0-9]+]], isOptimized: false, runtimeVersion: 0, emissionKind: FullDebug, splitDebugInlining: false, nameTableKind: None) // CHECK-NOTRAP: [[META1]] = !DIFile(filename: "<stdin>", directory: {{.*}}) diff --git a/clang/test/CodeGen/builtins-wasm.c b/clang/test/CodeGen/builtins-wasm.c index d8aff82..f201dfe 100644 --- a/clang/test/CodeGen/builtins-wasm.c +++ b/clang/test/CodeGen/builtins-wasm.c @@ -1,6 +1,6 @@ -// RUN: %clang_cc1 -triple wasm32-unknown-unknown -target-feature +reference-types -target-feature +simd128 -target-feature +relaxed-simd -target-feature +nontrapping-fptoint -target-feature +exception-handling -target-feature +bulk-memory -target-feature +atomics -target-feature +fp16 -flax-vector-conversions=none -O3 -emit-llvm -o - %s | FileCheck %s -check-prefixes WEBASSEMBLY,WEBASSEMBLY32 -// RUN: %clang_cc1 -triple wasm64-unknown-unknown -target-feature +reference-types -target-feature +simd128 -target-feature +relaxed-simd -target-feature +nontrapping-fptoint -target-feature +exception-handling -target-feature +bulk-memory -target-feature +atomics -target-feature +fp16 -flax-vector-conversions=none -O3 -emit-llvm -o - %s | FileCheck %s -check-prefixes WEBASSEMBLY,WEBASSEMBLY64 -// RUN: not %clang_cc1 -triple wasm64-unknown-unknown -target-feature +reference-types -target-feature +nontrapping-fptoint -target-feature +exception-handling -target-feature +bulk-memory -target-feature +atomics -flax-vector-conversions=none -O3 -emit-llvm -o - %s 2>&1 | FileCheck %s -check-prefixes MISSING-SIMD +// RUN: %clang_cc1 -triple wasm32-unknown-unknown -target-feature +reference-types -target-feature +simd128 -target-feature +relaxed-simd -target-feature +nontrapping-fptoint -target-feature +exception-handling -target-feature +bulk-memory -target-feature +atomics -target-feature +gc -target-feature +fp16 -flax-vector-conversions=none -O3 -emit-llvm -o - %s | FileCheck %s -check-prefixes WEBASSEMBLY,WEBASSEMBLY32 +// RUN: %clang_cc1 -triple wasm64-unknown-unknown -target-feature +reference-types -target-feature +simd128 -target-feature +relaxed-simd -target-feature +nontrapping-fptoint -target-feature +exception-handling -target-feature +bulk-memory -target-feature +atomics -target-feature +gc -target-feature +fp16 -flax-vector-conversions=none -O3 -emit-llvm -o - %s | FileCheck %s -check-prefixes WEBASSEMBLY,WEBASSEMBLY64 +// RUN: not %clang_cc1 -triple wasm64-unknown-unknown -target-feature +reference-types -target-feature +nontrapping-fptoint -target-feature +exception-handling -target-feature +bulk-memory -target-feature +atomics -target-feature +gc -flax-vector-conversions=none -O3 -emit-llvm -o - %s 2>&1 | FileCheck %s -check-prefixes MISSING-SIMD // SIMD convenience types typedef signed char i8x16 __attribute((vector_size(16))); @@ -751,3 +751,24 @@ void *tp (void) { return __builtin_thread_pointer (); // WEBASSEMBLY: call {{.*}} @llvm.thread.pointer.p0() } + +typedef void (*Fvoid)(void); +typedef float (*Ffloats)(float, double, int); +typedef void (*Fpointers)(Fvoid, Ffloats, void*, int*, int***, char[5]); + +void use(int); + +void test_function_pointer_signature_void(Fvoid func) { + // WEBASSEMBLY: %0 = tail call i32 (ptr, ...) @llvm.wasm.ref.test.func(ptr %func, token poison) + use(__builtin_wasm_test_function_pointer_signature(func)); +} + +void test_function_pointer_signature_floats(Ffloats func) { + // WEBASSEMBLY: tail call i32 (ptr, ...) @llvm.wasm.ref.test.func(ptr %func, float 0.000000e+00, token poison, float 0.000000e+00, double 0.000000e+00, i32 0) + use(__builtin_wasm_test_function_pointer_signature(func)); +} + +void test_function_pointer_signature_pointers(Fpointers func) { + // WEBASSEMBLY: %0 = tail call i32 (ptr, ...) @llvm.wasm.ref.test.func(ptr %func, token poison, ptr null, ptr null, ptr null, ptr null, ptr null, ptr null) + use(__builtin_wasm_test_function_pointer_signature(func)); +} diff --git a/clang/test/CodeGen/cfi-icall-generalize-debuginfo.c b/clang/test/CodeGen/cfi-icall-generalize-debuginfo.c index 304b605..0ffc2b9 100644 --- a/clang/test/CodeGen/cfi-icall-generalize-debuginfo.c +++ b/clang/test/CodeGen/cfi-icall-generalize-debuginfo.c @@ -30,11 +30,11 @@ int** f(const char *a, const char **b) { // UNGENERALIZED-NEXT: [[TMP0:%.*]] = tail call i1 @llvm.type.test(ptr [[FP]], metadata !"_ZTSFPPiPKcPS2_E"), !dbg [[DBG34:![0-9]+]], !nosanitize [[META38:![0-9]+]] // UNGENERALIZED-NEXT: br i1 [[TMP0]], label %[[CONT:.*]], label %[[TRAP:.*]], !dbg [[DBG34]], !prof [[PROF39:![0-9]+]], !nosanitize [[META38]] // UNGENERALIZED: [[TRAP]]: -// UNGENERALIZED-NEXT: tail call void @llvm.ubsantrap(i8 2) #[[ATTR4:[0-9]+]], !dbg [[DBG34]], !nosanitize [[META38]] -// UNGENERALIZED-NEXT: unreachable, !dbg [[DBG34]], !nosanitize [[META38]] +// UNGENERALIZED-NEXT: tail call void @llvm.ubsantrap(i8 2) #[[ATTR4:[0-9]+]], !dbg [[DBGTRAP:![0-9]+]], !nosanitize [[META38]] +// UNGENERALIZED-NEXT: unreachable, !dbg [[DBGTRAP]], !nosanitize [[META38]] // UNGENERALIZED: [[CONT]]: // UNGENERALIZED-NEXT: [[CALL:%.*]] = tail call ptr [[FP]](ptr noundef null, ptr noundef null) #[[ATTR5:[0-9]+]], !dbg [[DBG37:![0-9]+]] -// UNGENERALIZED-NEXT: ret void, !dbg [[DBG40:![0-9]+]] +// UNGENERALIZED-NEXT: ret void, !dbg [[DBG42:![0-9]+]] // // GENERALIZED-LABEL: define dso_local void @g( // GENERALIZED-SAME: ptr noundef [[FP:%.*]]) local_unnamed_addr #[[ATTR1:[0-9]+]] !dbg [[DBG25:![0-9]+]] !type [[META31:![0-9]+]] !type [[META32:![0-9]+]] { @@ -43,11 +43,11 @@ int** f(const char *a, const char **b) { // GENERALIZED-NEXT: [[TMP0:%.*]] = tail call i1 @llvm.type.test(ptr [[FP]], metadata !"_ZTSFPvPKvS_E.generalized"), !dbg [[DBG34:![0-9]+]], !nosanitize [[META38:![0-9]+]] // GENERALIZED-NEXT: br i1 [[TMP0]], label %[[CONT:.*]], label %[[TRAP:.*]], !dbg [[DBG34]], !prof [[PROF39:![0-9]+]], !nosanitize [[META38]] // GENERALIZED: [[TRAP]]: -// GENERALIZED-NEXT: tail call void @llvm.ubsantrap(i8 2) #[[ATTR4:[0-9]+]], !dbg [[DBG34]], !nosanitize [[META38]] -// GENERALIZED-NEXT: unreachable, !dbg [[DBG34]], !nosanitize [[META38]] +// GENERALIZED-NEXT: tail call void @llvm.ubsantrap(i8 2) #[[ATTR4:[0-9]+]], !dbg [[DBGTRAP:![0-9]+]], !nosanitize [[META38]] +// GENERALIZED-NEXT: unreachable, !dbg [[DBGTRAP]], !nosanitize [[META38]] // GENERALIZED: [[CONT]]: // GENERALIZED-NEXT: [[CALL:%.*]] = tail call ptr [[FP]](ptr noundef null, ptr noundef null) #[[ATTR5:[0-9]+]], !dbg [[DBG37:![0-9]+]] -// GENERALIZED-NEXT: ret void, !dbg [[DBG40:![0-9]+]] +// GENERALIZED-NEXT: ret void, !dbg [[DBG42:![0-9]+]] // void g(int** (*fp)(const char *, const char **)) { fp(0, 0); @@ -90,7 +90,9 @@ void g(int** (*fp)(const char *, const char **)) { // UNGENERALIZED: [[DBG37]] = !DILocation(line: 53, column: 3, scope: [[DBG25]]) // UNGENERALIZED: [[META38]] = !{} // UNGENERALIZED: [[PROF39]] = !{!"branch_weights", i32 1048575, i32 1} -// UNGENERALIZED: [[DBG40]] = !DILocation(line: 54, column: 1, scope: [[DBG25]]) +// UNGENERALIZED: [[DBGTRAP]] = !DILocation(line: 0, scope: [[TRAPMSG:![0-9]+]], inlinedAt: [[DBG34]]) +// UNGENERALIZED: [[TRAPMSG]] = distinct !DISubprogram(name: "__clang_trap_msg$Undefined Behavior Sanitizer$Control flow integrity check failed", scope: [[META11]], file: [[META11]], type: [[META36]], flags: DIFlagArtificial, spFlags: DISPFlagDefinition, unit: [[META0]]) +// UNGENERALIZED: [[DBG42]] = !DILocation(line: 54, column: 1, scope: [[DBG25]]) //. // GENERALIZED: [[META0:![0-9]+]] = distinct !DICompileUnit(language: DW_LANG_C11, file: [[META1:![0-9]+]], isOptimized: true, runtimeVersion: 0, emissionKind: FullDebug, retainedTypes: [[META2:![0-9]+]], splitDebugInlining: false, nameTableKind: None) // GENERALIZED: [[META1]] = !DIFile(filename: "{{.*}}<stdin>", directory: {{.*}}) @@ -128,5 +130,7 @@ void g(int** (*fp)(const char *, const char **)) { // GENERALIZED: [[DBG37]] = !DILocation(line: 53, column: 3, scope: [[DBG25]]) // GENERALIZED: [[META38]] = !{} // GENERALIZED: [[PROF39]] = !{!"branch_weights", i32 1048575, i32 1} -// GENERALIZED: [[DBG40]] = !DILocation(line: 54, column: 1, scope: [[DBG25]]) +// GENERALIZED: [[DBGTRAP]] = !DILocation(line: 0, scope: [[TRAPMSG:![0-9]+]], inlinedAt: [[DBG34]]) +// GENERALIZED: [[TRAPMSG]] = distinct !DISubprogram(name: "__clang_trap_msg$Undefined Behavior Sanitizer$Control flow integrity check failed", scope: [[META11]], file: [[META11]], type: [[META36]], flags: DIFlagArtificial, spFlags: DISPFlagDefinition, unit: [[META0]]) +// GENERALIZED: [[DBG42]] = !DILocation(line: 54, column: 1, scope: [[DBG25]]) //. diff --git a/clang/test/CodeGen/cfi-icall-normalize2-debuginfo.c b/clang/test/CodeGen/cfi-icall-normalize2-debuginfo.c index a2f6ee0c..258c3bf 100644 --- a/clang/test/CodeGen/cfi-icall-normalize2-debuginfo.c +++ b/clang/test/CodeGen/cfi-icall-normalize2-debuginfo.c @@ -15,50 +15,50 @@ // CHECK-NEXT: [[TMP0:%.*]] = tail call i1 @llvm.type.test(ptr [[FN]], metadata !"_ZTSFvu3i32E.normalized"), !dbg [[DBG21:![0-9]+]], !nosanitize [[META25:![0-9]+]] // CHECK-NEXT: br i1 [[TMP0]], label %[[CONT:.*]], label %[[TRAP:.*]], !dbg [[DBG21]], !prof [[PROF26:![0-9]+]], !nosanitize [[META25]] // CHECK: [[TRAP]]: -// CHECK-NEXT: tail call void @llvm.ubsantrap(i8 2) #[[ATTR3:[0-9]+]], !dbg [[DBG21]], !nosanitize [[META25]] -// CHECK-NEXT: unreachable, !dbg [[DBG21]], !nosanitize [[META25]] +// CHECK-NEXT: tail call void @llvm.ubsantrap(i8 2) #[[ATTR3:[0-9]+]], !dbg [[DBGTRAP:![0-9]+]], !nosanitize [[META25]] +// CHECK-NEXT: unreachable, !dbg [[DBGTRAP]], !nosanitize [[META25]] // CHECK: [[CONT]]: // CHECK-NEXT: tail call void [[FN]](i32 noundef [[ARG]]) #[[ATTR4:[0-9]+]], !dbg [[DBG24:![0-9]+]] -// CHECK-NEXT: ret void, !dbg [[DBG27:![0-9]+]] +// CHECK-NEXT: ret void, !dbg [[DBG29:![0-9]+]] // void foo(void (*fn)(int), int arg) { fn(arg); } // CHECK-LABEL: define dso_local void @bar( -// CHECK-SAME: ptr noundef [[FN:%.*]], i32 noundef [[ARG1:%.*]], i32 noundef [[ARG2:%.*]]) local_unnamed_addr #[[ATTR0]] !dbg [[DBG28:![0-9]+]] !type [[META38:![0-9]+]] !type [[META39:![0-9]+]] { +// CHECK-SAME: ptr noundef [[FN:%.*]], i32 noundef [[ARG1:%.*]], i32 noundef [[ARG2:%.*]]) local_unnamed_addr #[[ATTR0]] !dbg [[DBG30:![0-9]+]] !type [[META40:![0-9]+]] !type [[META41:![0-9]+]] { // CHECK-NEXT: [[ENTRY:.*:]] -// CHECK-NEXT: #dbg_value(ptr [[FN]], [[META35:![0-9]+]], !DIExpression(), [[META40:![0-9]+]]) -// CHECK-NEXT: #dbg_value(i32 [[ARG1]], [[META36:![0-9]+]], !DIExpression(), [[META40]]) -// CHECK-NEXT: #dbg_value(i32 [[ARG2]], [[META37:![0-9]+]], !DIExpression(), [[META40]]) -// CHECK-NEXT: [[TMP0:%.*]] = tail call i1 @llvm.type.test(ptr [[FN]], metadata !"_ZTSFvu3i32S_E.normalized"), !dbg [[DBG41:![0-9]+]], !nosanitize [[META25]] -// CHECK-NEXT: br i1 [[TMP0]], label %[[CONT:.*]], label %[[TRAP:.*]], !dbg [[DBG41]], !prof [[PROF26]], !nosanitize [[META25]] +// CHECK-NEXT: #dbg_value(ptr [[FN]], [[META37:![0-9]+]], !DIExpression(), [[META42:![0-9]+]]) +// CHECK-NEXT: #dbg_value(i32 [[ARG1]], [[META38:![0-9]+]], !DIExpression(), [[META42]]) +// CHECK-NEXT: #dbg_value(i32 [[ARG2]], [[META39:![0-9]+]], !DIExpression(), [[META42]]) +// CHECK-NEXT: [[TMP0:%.*]] = tail call i1 @llvm.type.test(ptr [[FN]], metadata !"_ZTSFvu3i32S_E.normalized"), !dbg [[DBG43:![0-9]+]], !nosanitize [[META25]] +// CHECK-NEXT: br i1 [[TMP0]], label %[[CONT:.*]], label %[[TRAP:.*]], !dbg [[DBG43]], !prof [[PROF26]], !nosanitize [[META25]] // CHECK: [[TRAP]]: -// CHECK-NEXT: tail call void @llvm.ubsantrap(i8 2) #[[ATTR3]], !dbg [[DBG41]], !nosanitize [[META25]] -// CHECK-NEXT: unreachable, !dbg [[DBG41]], !nosanitize [[META25]] +// CHECK-NEXT: tail call void @llvm.ubsantrap(i8 2) #[[ATTR3]], !dbg [[DBG45:![0-9]+]], !nosanitize [[META25]] +// CHECK-NEXT: unreachable, !dbg [[DBG45]], !nosanitize [[META25]] // CHECK: [[CONT]]: -// CHECK-NEXT: tail call void [[FN]](i32 noundef [[ARG1]], i32 noundef [[ARG2]]) #[[ATTR4]], !dbg [[DBG42:![0-9]+]] -// CHECK-NEXT: ret void, !dbg [[DBG43:![0-9]+]] +// CHECK-NEXT: tail call void [[FN]](i32 noundef [[ARG1]], i32 noundef [[ARG2]]) #[[ATTR4]], !dbg [[DBG44:![0-9]+]] +// CHECK-NEXT: ret void, !dbg [[DBG46:![0-9]+]] // void bar(void (*fn)(int, int), int arg1, int arg2) { fn(arg1, arg2); } // CHECK-LABEL: define dso_local void @baz( -// CHECK-SAME: ptr noundef [[FN:%.*]], i32 noundef [[ARG1:%.*]], i32 noundef [[ARG2:%.*]], i32 noundef [[ARG3:%.*]]) local_unnamed_addr #[[ATTR0]] !dbg [[DBG44:![0-9]+]] !type [[META55:![0-9]+]] !type [[META56:![0-9]+]] { +// CHECK-SAME: ptr noundef [[FN:%.*]], i32 noundef [[ARG1:%.*]], i32 noundef [[ARG2:%.*]], i32 noundef [[ARG3:%.*]]) local_unnamed_addr #[[ATTR0]] !dbg [[DBG47:![0-9]+]] !type [[META58:![0-9]+]] !type [[META59:![0-9]+]] { // CHECK-NEXT: [[ENTRY:.*:]] -// CHECK-NEXT: #dbg_value(ptr [[FN]], [[META51:![0-9]+]], !DIExpression(), [[META57:![0-9]+]]) -// CHECK-NEXT: #dbg_value(i32 [[ARG1]], [[META52:![0-9]+]], !DIExpression(), [[META57]]) -// CHECK-NEXT: #dbg_value(i32 [[ARG2]], [[META53:![0-9]+]], !DIExpression(), [[META57]]) -// CHECK-NEXT: #dbg_value(i32 [[ARG3]], [[META54:![0-9]+]], !DIExpression(), [[META57]]) -// CHECK-NEXT: [[TMP0:%.*]] = tail call i1 @llvm.type.test(ptr [[FN]], metadata !"_ZTSFvu3i32S_S_E.normalized"), !dbg [[DBG58:![0-9]+]], !nosanitize [[META25]] -// CHECK-NEXT: br i1 [[TMP0]], label %[[CONT:.*]], label %[[TRAP:.*]], !dbg [[DBG58]], !prof [[PROF26]], !nosanitize [[META25]] +// CHECK-NEXT: #dbg_value(ptr [[FN]], [[META54:![0-9]+]], !DIExpression(), [[META60:![0-9]+]]) +// CHECK-NEXT: #dbg_value(i32 [[ARG1]], [[META55:![0-9]+]], !DIExpression(), [[META60]]) +// CHECK-NEXT: #dbg_value(i32 [[ARG2]], [[META56:![0-9]+]], !DIExpression(), [[META60]]) +// CHECK-NEXT: #dbg_value(i32 [[ARG3]], [[META57:![0-9]+]], !DIExpression(), [[META60]]) +// CHECK-NEXT: [[TMP0:%.*]] = tail call i1 @llvm.type.test(ptr [[FN]], metadata !"_ZTSFvu3i32S_S_E.normalized"), !dbg [[DBG61:![0-9]+]], !nosanitize [[META25]] +// CHECK-NEXT: br i1 [[TMP0]], label %[[CONT:.*]], label %[[TRAP:.*]], !dbg [[DBG61]], !prof [[PROF26]], !nosanitize [[META25]] // CHECK: [[TRAP]]: -// CHECK-NEXT: tail call void @llvm.ubsantrap(i8 2) #[[ATTR3]], !dbg [[DBG58]], !nosanitize [[META25]] -// CHECK-NEXT: unreachable, !dbg [[DBG58]], !nosanitize [[META25]] +// CHECK-NEXT: tail call void @llvm.ubsantrap(i8 2) #[[ATTR3]], !dbg [[DBG63:![0-9]+]], !nosanitize [[META25]] +// CHECK-NEXT: unreachable, !dbg [[DBG63]], !nosanitize [[META25]] // CHECK: [[CONT]]: -// CHECK-NEXT: tail call void [[FN]](i32 noundef [[ARG1]], i32 noundef [[ARG2]], i32 noundef [[ARG3]]) #[[ATTR4]], !dbg [[DBG59:![0-9]+]] -// CHECK-NEXT: ret void, !dbg [[DBG60:![0-9]+]] +// CHECK-NEXT: tail call void [[FN]](i32 noundef [[ARG1]], i32 noundef [[ARG2]], i32 noundef [[ARG3]]) #[[ATTR4]], !dbg [[DBG62:![0-9]+]] +// CHECK-NEXT: ret void, !dbg [[DBG64:![0-9]+]] // void baz(void (*fn)(int, int, int), int arg1, int arg2, int arg3) { fn(arg1, arg2, arg3); @@ -87,38 +87,42 @@ void baz(void (*fn)(int, int, int), int arg1, int arg2, int arg3) { // CHECK: [[DBG24]] = !DILocation(line: 25, column: 5, scope: [[DBG7]]) // CHECK: [[META25]] = !{} // CHECK: [[PROF26]] = !{!"branch_weights", i32 1048575, i32 1} -// CHECK: [[DBG27]] = !DILocation(line: 26, column: 1, scope: [[DBG7]]) -// CHECK: [[DBG28]] = distinct !DISubprogram(name: "bar", scope: [[META8]], file: [[META8]], line: 43, type: [[META29:![0-9]+]], scopeLine: 43, flags: DIFlagPrototyped, spFlags: DISPFlagDefinition | DISPFlagOptimized, unit: [[META0]], retainedNodes: [[META34:![0-9]+]]) -// CHECK: [[META29]] = !DISubroutineType(types: [[META30:![0-9]+]]) -// CHECK: [[META30]] = !{null, [[META31:![0-9]+]], [[META14]], [[META14]]} -// CHECK: [[META31]] = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: [[META32:![0-9]+]], size: 64) -// CHECK: [[META32]] = !DISubroutineType(types: [[META33:![0-9]+]]) -// CHECK: [[META33]] = !{null, [[META14]], [[META14]]} -// CHECK: [[META34]] = !{[[META35]], [[META36]], [[META37]]} -// CHECK: [[META35]] = !DILocalVariable(name: "fn", arg: 1, scope: [[DBG28]], file: [[META8]], line: 43, type: [[META31]]) -// CHECK: [[META36]] = !DILocalVariable(name: "arg1", arg: 2, scope: [[DBG28]], file: [[META8]], line: 43, type: [[META14]]) -// CHECK: [[META37]] = !DILocalVariable(name: "arg2", arg: 3, scope: [[DBG28]], file: [[META8]], line: 43, type: [[META14]]) -// CHECK: [[META38]] = !{i64 0, !"_ZTSFvPFvu3i32S_ES_S_E.normalized"} -// CHECK: [[META39]] = !{i64 0, !"_ZTSFvPvu3i32S0_E.normalized.generalized"} -// CHECK: [[META40]] = !DILocation(line: 0, scope: [[DBG28]]) -// CHECK: [[DBG41]] = !DILocation(line: 0, scope: [[META22]], inlinedAt: [[DBG42]]) -// CHECK: [[DBG42]] = !DILocation(line: 44, column: 5, scope: [[DBG28]]) -// CHECK: [[DBG43]] = !DILocation(line: 45, column: 1, scope: [[DBG28]]) -// CHECK: [[DBG44]] = distinct !DISubprogram(name: "baz", scope: [[META8]], file: [[META8]], line: 63, type: [[META45:![0-9]+]], scopeLine: 63, flags: DIFlagPrototyped, spFlags: DISPFlagDefinition | DISPFlagOptimized, unit: [[META0]], retainedNodes: [[META50:![0-9]+]]) -// CHECK: [[META45]] = !DISubroutineType(types: [[META46:![0-9]+]]) -// CHECK: [[META46]] = !{null, [[META47:![0-9]+]], [[META14]], [[META14]], [[META14]]} -// CHECK: [[META47]] = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: [[META48:![0-9]+]], size: 64) +// CHECK: [[DBGTRAP]] = !DILocation(line: 0, scope: [[TRAPMSG:![0-9]+]], inlinedAt: [[DBG21]]) +// CHECK: [[TRAPMSG]] = distinct !DISubprogram(name: "__clang_trap_msg$Undefined Behavior Sanitizer$Control flow integrity check failed", scope: [[META8]], file: [[META8]], type: [[META23]], flags: DIFlagArtificial, spFlags: DISPFlagDefinition, unit: [[META0]]) +// CHECK: [[DBG29]] = !DILocation(line: 26, column: 1, scope: [[DBG7]]) +// CHECK: [[DBG30]] = distinct !DISubprogram(name: "bar", scope: [[META8]], file: [[META8]], line: 43, type: [[META31:![0-9]+]], scopeLine: 43, flags: DIFlagPrototyped, spFlags: DISPFlagDefinition | DISPFlagOptimized, unit: [[META0]], retainedNodes: [[META36:![0-9]+]]) +// CHECK: [[META31]] = !DISubroutineType(types: [[META32:![0-9]+]]) +// CHECK: [[META32]] = !{null, [[META33:![0-9]+]], [[META14]], [[META14]]} +// CHECK: [[META33]] = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: [[META34:![0-9]+]], size: 64) +// CHECK: [[META34]] = !DISubroutineType(types: [[META35:![0-9]+]]) +// CHECK: [[META35]] = !{null, [[META14]], [[META14]]} +// CHECK: [[META36]] = !{[[META37]], [[META38]], [[META39]]} +// CHECK: [[META37]] = !DILocalVariable(name: "fn", arg: 1, scope: [[DBG30]], file: [[META8]], line: 43, type: [[META33]]) +// CHECK: [[META38]] = !DILocalVariable(name: "arg1", arg: 2, scope: [[DBG30]], file: [[META8]], line: 43, type: [[META14]]) +// CHECK: [[META39]] = !DILocalVariable(name: "arg2", arg: 3, scope: [[DBG30]], file: [[META8]], line: 43, type: [[META14]]) +// CHECK: [[META40]] = !{i64 0, !"_ZTSFvPFvu3i32S_ES_S_E.normalized"} +// CHECK: [[META41]] = !{i64 0, !"_ZTSFvPvu3i32S0_E.normalized.generalized"} +// CHECK: [[META42]] = !DILocation(line: 0, scope: [[DBG30]]) +// CHECK: [[DBG43]] = !DILocation(line: 0, scope: [[META22]], inlinedAt: [[DBG44]]) +// CHECK: [[DBG44]] = !DILocation(line: 44, column: 5, scope: [[DBG30]]) +// CHECK: [[DBG45]] = !DILocation(line: 0, scope: [[TRAPMSG]], inlinedAt: [[DBG43]]) +// CHECK: [[DBG46]] = !DILocation(line: 45, column: 1, scope: [[DBG30]]) +// CHECK: [[DBG47]] = distinct !DISubprogram(name: "baz", scope: [[META8]], file: [[META8]], line: 63, type: [[META48:![0-9]+]], scopeLine: 63, flags: DIFlagPrototyped, spFlags: DISPFlagDefinition | DISPFlagOptimized, unit: [[META0]], retainedNodes: [[META53:![0-9]+]]) // CHECK: [[META48]] = !DISubroutineType(types: [[META49:![0-9]+]]) -// CHECK: [[META49]] = !{null, [[META14]], [[META14]], [[META14]]} -// CHECK: [[META50]] = !{[[META51]], [[META52]], [[META53]], [[META54]]} -// CHECK: [[META51]] = !DILocalVariable(name: "fn", arg: 1, scope: [[DBG44]], file: [[META8]], line: 63, type: [[META47]]) -// CHECK: [[META52]] = !DILocalVariable(name: "arg1", arg: 2, scope: [[DBG44]], file: [[META8]], line: 63, type: [[META14]]) -// CHECK: [[META53]] = !DILocalVariable(name: "arg2", arg: 3, scope: [[DBG44]], file: [[META8]], line: 63, type: [[META14]]) -// CHECK: [[META54]] = !DILocalVariable(name: "arg3", arg: 4, scope: [[DBG44]], file: [[META8]], line: 63, type: [[META14]]) -// CHECK: [[META55]] = !{i64 0, !"_ZTSFvPFvu3i32S_S_ES_S_S_E.normalized"} -// CHECK: [[META56]] = !{i64 0, !"_ZTSFvPvu3i32S0_S0_E.normalized.generalized"} -// CHECK: [[META57]] = !DILocation(line: 0, scope: [[DBG44]]) -// CHECK: [[DBG58]] = !DILocation(line: 0, scope: [[META22]], inlinedAt: [[DBG59]]) -// CHECK: [[DBG59]] = !DILocation(line: 64, column: 5, scope: [[DBG44]]) -// CHECK: [[DBG60]] = !DILocation(line: 65, column: 1, scope: [[DBG44]]) +// CHECK: [[META49]] = !{null, [[META50:![0-9]+]], [[META14]], [[META14]], [[META14]]} +// CHECK: [[META50]] = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: [[META51:![0-9]+]], size: 64) +// CHECK: [[META51]] = !DISubroutineType(types: [[META52:![0-9]+]]) +// CHECK: [[META52]] = !{null, [[META14]], [[META14]], [[META14]]} +// CHECK: [[META53]] = !{[[META54]], [[META55]], [[META56]], [[META57]]} +// CHECK: [[META54]] = !DILocalVariable(name: "fn", arg: 1, scope: [[DBG47]], file: [[META8]], line: 63, type: [[META50]]) +// CHECK: [[META55]] = !DILocalVariable(name: "arg1", arg: 2, scope: [[DBG47]], file: [[META8]], line: 63, type: [[META14]]) +// CHECK: [[META56]] = !DILocalVariable(name: "arg2", arg: 3, scope: [[DBG47]], file: [[META8]], line: 63, type: [[META14]]) +// CHECK: [[META57]] = !DILocalVariable(name: "arg3", arg: 4, scope: [[DBG47]], file: [[META8]], line: 63, type: [[META14]]) +// CHECK: [[META58]] = !{i64 0, !"_ZTSFvPFvu3i32S_S_ES_S_S_E.normalized"} +// CHECK: [[META59]] = !{i64 0, !"_ZTSFvPvu3i32S0_S0_E.normalized.generalized"} +// CHECK: [[META60]] = !DILocation(line: 0, scope: [[DBG47]]) +// CHECK: [[DBG61]] = !DILocation(line: 0, scope: [[META22]], inlinedAt: [[DBG62]]) +// CHECK: [[DBG62]] = !DILocation(line: 64, column: 5, scope: [[DBG47]]) +// CHECK: [[DBG63]] = !DILocation(line: 0, scope: [[TRAPMSG]], inlinedAt: [[DBG61]]) +// CHECK: [[DBG64]] = !DILocation(line: 65, column: 1, scope: [[DBG47]]) //. diff --git a/clang/test/CodeGen/ubsan-trap-debugloc.c b/clang/test/CodeGen/ubsan-trap-debugloc.c index 87cbfad..2f5258a 100644 --- a/clang/test/CodeGen/ubsan-trap-debugloc.c +++ b/clang/test/CodeGen/ubsan-trap-debugloc.c @@ -20,5 +20,8 @@ void bar(volatile int a) __attribute__((optnone)) { // CHECK: [[LOC]] = !DILocation(line: 0 // With optimisations disabled the traps are not merged and retain accurate debug locations -// CHECK: [[LOC2]] = !DILocation(line: 15, column: 9 -// CHECK: [[LOC3]] = !DILocation(line: 16, column: 9 + // CHECK-DAG: [[SRC2:![0-9]+]] = !DILocation(line: 15, column: 9, + // CHECK-DAG: [[SRC3:![0-9]+]] = !DILocation(line: 16, column: 9, + // CHECK-DAG: [[LOC2]] = !DILocation(line: 0, scope: [[SCOPE2:![0-9]+]], inlinedAt: [[SRC2]]) + // CHECK-DAG: [[LOC3]] = !DILocation(line: 0, scope: [[SCOPE3:![0-9]+]], inlinedAt: [[SRC3]]) + diff --git a/clang/test/CodeGen/ubsan-trap-reason-add-overflow.c b/clang/test/CodeGen/ubsan-trap-reason-add-overflow.c new file mode 100644 index 0000000..225778d --- /dev/null +++ b/clang/test/CodeGen/ubsan-trap-reason-add-overflow.c @@ -0,0 +1,9 @@ +// RUN: %clang_cc1 -triple arm64-apple-macosx14.0.0 -O0 -debug-info-kind=standalone -dwarf-version=5 \ +// RUN: -fsanitize=signed-integer-overflow -fsanitize-trap=signed-integer-overflow -emit-llvm %s -o - | FileCheck %s + +int add_overflow(int a, int b) { return a + b; } + +// CHECK-LABEL: @add_overflow +// CHECK: call void @llvm.ubsantrap(i8 0) {{.*}}!dbg [[LOC:![0-9]+]] +// CHECK: [[LOC]] = !DILocation(line: 0, scope: [[MSG:![0-9]+]], {{.+}}) +// CHECK: [[MSG]] = distinct !DISubprogram(name: "__clang_trap_msg$Undefined Behavior Sanitizer$Integer addition overflowed" diff --git a/clang/test/CodeGen/ubsan-trap-reason-alignment-assumption.c b/clang/test/CodeGen/ubsan-trap-reason-alignment-assumption.c new file mode 100644 index 0000000..3247ceb --- /dev/null +++ b/clang/test/CodeGen/ubsan-trap-reason-alignment-assumption.c @@ -0,0 +1,15 @@ +// RUN: %clang_cc1 -triple arm64-apple-macosx14.0.0 -O0 -debug-info-kind=standalone -dwarf-version=5 \ +// RUN: -fsanitize=alignment -fsanitize-trap=alignment -emit-llvm %s -o - | FileCheck %s + +#include <stdint.h> +int32_t *get_int(void) __attribute__((assume_aligned(16))); + +void retrieve_int(void) { + int *i = get_int(); + *i = 7; +} + +// CHECK-LABEL: @retrieve_int +// CHECK: call void @llvm.ubsantrap(i8 23) {{.*}}!dbg [[LOC:![0-9]+]] +// CHECK: [[LOC]] = !DILocation(line: 0, scope: [[MSG:![0-9]+]], {{.+}}) +// CHECK: [[MSG]] = distinct !DISubprogram(name: "__clang_trap_msg$Undefined Behavior Sanitizer$Alignment assumption violated" diff --git a/clang/test/CodeGen/ubsan-trap-reason-builtin-unreachable.c b/clang/test/CodeGen/ubsan-trap-reason-builtin-unreachable.c new file mode 100644 index 0000000..97bd690 --- /dev/null +++ b/clang/test/CodeGen/ubsan-trap-reason-builtin-unreachable.c @@ -0,0 +1,9 @@ +// RUN: %clang_cc1 -triple arm64-apple-macosx14.0.0 -O0 -debug-info-kind=standalone -dwarf-version=5 \ +// RUN: -fsanitize=unreachable -fsanitize-trap=unreachable -emit-llvm %s -o - | FileCheck %s + +int call_builtin_unreachable(void) { __builtin_unreachable(); } + +// CHECK-LABEL: @call_builtin_unreachable +// CHECK: call void @llvm.ubsantrap(i8 1) {{.*}}!dbg [[LOC:![0-9]+]] +// CHECK: [[LOC]] = !DILocation(line: 0, scope: [[MSG:![0-9]+]], {{.+}}) +// CHECK: [[MSG]] = distinct !DISubprogram(name: "__clang_trap_msg$Undefined Behavior Sanitizer$_builtin_unreachable(), execution reached an unreachable program point" diff --git a/clang/test/CodeGen/ubsan-trap-reason-cfi-check-fail.c b/clang/test/CodeGen/ubsan-trap-reason-cfi-check-fail.c new file mode 100644 index 0000000..9304f51 --- /dev/null +++ b/clang/test/CodeGen/ubsan-trap-reason-cfi-check-fail.c @@ -0,0 +1,25 @@ +// RUN: %clang_cc1 -triple arm64-apple-macosx14.0.0 -O0 -debug-info-kind=standalone -dwarf-version=5 \ +// RUN: -fsanitize=cfi-icall -fsanitize-trap=cfi-icall -emit-llvm %s -o - | FileCheck %s + +typedef int (*fp_t)(int); + +int good(int x) { return x + 1; } + +int bad(void) { return 0; } + +int cfi_trigger(int a) { + fp_t p = good; + int r1 = p(a); + + p = (fp_t)(void *)bad; + int r2 = p(a); + + return r1 + r2; +} + +// CHECK-LABEL: @good +// CHECK-LABEL: @bad +// CHECK-LABEL: @cfi_trigger +// CHECK: call void @llvm.ubsantrap(i8 2) {{.*}}!dbg [[LOC:![0-9]+]] +// CHECK: [[LOC]] = !DILocation(line: 0, scope: [[MSG:![0-9]+]], {{.+}}) +// CHECK: [[MSG]] = distinct !DISubprogram(name: "__clang_trap_msg$Undefined Behavior Sanitizer$Control flow integrity check failed" diff --git a/clang/test/CodeGen/ubsan-trap-reason-crash.cpp b/clang/test/CodeGen/ubsan-trap-reason-crash.cpp new file mode 100644 index 0000000..6add9bf --- /dev/null +++ b/clang/test/CodeGen/ubsan-trap-reason-crash.cpp @@ -0,0 +1,20 @@ +// FIXME: We should emit a trap message for this case too. +// But sometimes Clang will emit a ubsan trap into the prologue of a function, +// at which point the debug-info locations haven't been set up yet and +// can't hook up our artificial inline frame. [Issue #150707] + +// RUN: %clang_cc1 -triple arm64-apple-macosx14.0.0 -O0 -debug-info-kind=standalone -dwarf-version=5 \ +// RUN: -fsanitize=null -fsanitize-trap=null -emit-llvm %s -o - | FileCheck %s + +struct Foo { + void target() {} +} f; + +void caller() { + f.target(); +} + + +// CHECK-LABEL: @_Z6callerv +// CHECK: call void @llvm.ubsantrap(i8 22){{.*}}!nosanitize +// CHECK-NOT: __clang_trap_msg diff --git a/clang/test/CodeGen/ubsan-trap-reason-div-rem-overflow.c b/clang/test/CodeGen/ubsan-trap-reason-div-rem-overflow.c new file mode 100644 index 0000000..d0b21dd --- /dev/null +++ b/clang/test/CodeGen/ubsan-trap-reason-div-rem-overflow.c @@ -0,0 +1,9 @@ +// RUN: %clang_cc1 -triple arm64-apple-macosx14.0.0 -O0 -debug-info-kind=standalone -dwarf-version=5 \ +// RUN: -fsanitize=signed-integer-overflow -fsanitize-trap=signed-integer-overflow -emit-llvm %s -o - | FileCheck %s + +int div_rem_overflow(int a, int b) { return a / b; } + +// CHECK-LABEL: @div_rem_overflow +// CHECK: call void @llvm.ubsantrap(i8 3) {{.*}}!dbg [[LOC:![0-9]+]] +// CHECK: [[LOC]] = !DILocation(line: 0, scope: [[MSG:![0-9]+]], {{.+}}) +// CHECK: [[MSG]] = distinct !DISubprogram(name: "__clang_trap_msg$Undefined Behavior Sanitizer$Integer divide or remainder overflowed" diff --git a/clang/test/CodeGen/ubsan-trap-reason-dynamic-type-cache-miss.cpp b/clang/test/CodeGen/ubsan-trap-reason-dynamic-type-cache-miss.cpp new file mode 100644 index 0000000..f89fbdcf --- /dev/null +++ b/clang/test/CodeGen/ubsan-trap-reason-dynamic-type-cache-miss.cpp @@ -0,0 +1,26 @@ +// RUN: %clang_cc1 -triple arm64-apple-macosx14.0.0 -O0 -debug-info-kind=standalone -dwarf-version=5 \ +// RUN: -fsanitize=vptr -fsanitize-trap=vptr -emit-llvm %s -o - | FileCheck %s + +struct A { + virtual void foo(); +}; +struct B { + virtual void bar(); +}; + +void A::foo() {} +void B::bar() {} + +int dynamic_type_cache_miss() { + B b; + A &a = reinterpret_cast<A &>(b); + a.foo(); + return 0; +} + +// CHECK-LABEL: @_ZN1A3fooEv +// CHECK-LABEL: @_ZN1B3barEv +// CHECK-LABEL: @_Z23dynamic_type_cache_missv +// CHECK: call void @llvm.ubsantrap(i8 4) {{.*}}!dbg [[LOC:![0-9]+]] +// CHECK: [[LOC]] = !DILocation(line: 0, scope: [[MSG:![0-9]+]], {{.+}}) +// CHECK: [[MSG]] = distinct !DISubprogram(name: "__clang_trap_msg$Undefined Behavior Sanitizer$Dynamic type cache miss, member call made on an object whose dynamic type differs from the expected type" diff --git a/clang/test/CodeGen/ubsan-trap-reason-flag.c b/clang/test/CodeGen/ubsan-trap-reason-flag.c new file mode 100644 index 0000000..5cc16d1 --- /dev/null +++ b/clang/test/CodeGen/ubsan-trap-reason-flag.c @@ -0,0 +1,22 @@ +// RUN: %clang_cc1 -triple arm64-apple-macosx14.0.0 -O0 -debug-info-kind=standalone -dwarf-version=5 \ +// RUN: -fsanitize=signed-integer-overflow -fsanitize-trap=signed-integer-overflow -emit-llvm %s -o - \ +// RUN: | FileCheck %s --check-prefix=ANNOTATE + +// RUN: %clang_cc1 -triple arm64-apple-macosx14.0.0 -O0 -debug-info-kind=standalone -dwarf-version=5 \ +// RUN: -fsanitize=signed-integer-overflow -fsanitize-trap=signed-integer-overflow \ +// RUN: -fsanitize-debug-trap-reasons -emit-llvm %s -o - | FileCheck %s --check-prefix=ANNOTATE + +// RUN: %clang_cc1 -triple arm64-apple-macosx14.0.0 -O0 -debug-info-kind=standalone -dwarf-version=5 \ +// RUN: -fsanitize=signed-integer-overflow -fsanitize-trap=signed-integer-overflow \ +// RUN: -fno-sanitize-debug-trap-reasons -emit-llvm %s -o - | FileCheck %s --check-prefix=NO-ANNOTATE + +int add_overflow(int a, int b) { return a + b; } + +// ANNOTATE-LABEL: @add_overflow +// ANNOTATE: call void @llvm.ubsantrap(i8 0) {{.*}}!dbg [[LOC:![0-9]+]] +// ANNOTATE: [[LOC]] = !DILocation(line: 0, scope: [[MSG:![0-9]+]], {{.+}}) +// ANNOTATE: [[MSG]] = distinct !DISubprogram(name: "__clang_trap_msg$Undefined Behavior Sanitizer$Integer addition overflowed" + +// NO-ANNOTATE-LABEL: @add_overflow +// NO-ANNOTATE: call void @llvm.ubsantrap(i8 0) {{.*}}!dbg [[LOC:![0-9]+]] +// NO-ANNOTATE-NOT: __clang_trap_msg diff --git a/clang/test/CodeGen/ubsan-trap-reason-float-cast-overflow.c b/clang/test/CodeGen/ubsan-trap-reason-float-cast-overflow.c new file mode 100644 index 0000000..079a191e --- /dev/null +++ b/clang/test/CodeGen/ubsan-trap-reason-float-cast-overflow.c @@ -0,0 +1,9 @@ +// RUN: %clang_cc1 -triple arm64-apple-macosx14.0.0 -O0 -debug-info-kind=standalone -dwarf-version=5 \ +// RUN: -fsanitize=float-cast-overflow -fsanitize-trap=float-cast-overflow -emit-llvm %s -o - | FileCheck %s + +int float_cast_overflow(float x) { return (int)x; } + +// CHECK-LABEL: @float_cast_overflow +// CHECK: call void @llvm.ubsantrap(i8 5) {{.*}}!dbg [[LOC:![0-9]+]] +// CHECK: [[LOC]] = !DILocation(line: 0, scope: [[MSG:![0-9]+]], {{.+}}) +// CHECK: [[MSG]] = distinct !DISubprogram(name: "__clang_trap_msg$Undefined Behavior Sanitizer$Floating-point to integer conversion overflowed" diff --git a/clang/test/CodeGen/ubsan-trap-reason-function-type-mismatch.c b/clang/test/CodeGen/ubsan-trap-reason-function-type-mismatch.c new file mode 100644 index 0000000..1727f9c --- /dev/null +++ b/clang/test/CodeGen/ubsan-trap-reason-function-type-mismatch.c @@ -0,0 +1,18 @@ +// RUN: %clang_cc1 -triple arm64-apple-macosx14.0.0 -O0 -debug-info-kind=standalone -dwarf-version=5 \ +// RUN: -fsanitize=function -fsanitize-trap=function -emit-llvm %s -o - | FileCheck %s + +void target(void) {} + +int function_type_mismatch(void) { + int (*fp_int)(int); + + fp_int = (int (*)(int))(void *)target; + + return fp_int(42); +} + +// CHECK-LABEL: @target +// CHECK-LABEL: @function_type_mismatch +// CHECK: call void @llvm.ubsantrap(i8 6) {{.*}}!dbg [[LOC:![0-9]+]] +// CHECK: [[LOC]] = !DILocation(line: 0, scope: [[MSG:![0-9]+]], {{.+}}) +// CHECK: [[MSG]] = distinct !DISubprogram(name: "__clang_trap_msg$Undefined Behavior Sanitizer$Function called with mismatched signature" diff --git a/clang/test/CodeGen/ubsan-trap-reason-implicit-conversion.c b/clang/test/CodeGen/ubsan-trap-reason-implicit-conversion.c new file mode 100644 index 0000000..43c091d --- /dev/null +++ b/clang/test/CodeGen/ubsan-trap-reason-implicit-conversion.c @@ -0,0 +1,11 @@ +// RUN: %clang_cc1 -triple arm64-apple-macosx14.0.0 -O0 -debug-info-kind=standalone -dwarf-version=5 \ +// RUN: -fsanitize=implicit-unsigned-integer-truncation -fsanitize-trap=implicit-unsigned-integer-truncation -emit-llvm %s -o - | FileCheck %s + +unsigned long long big; + +unsigned implicit_conversion(void) { return big; } + +// CHECK-LABEL: @implicit_conversion +// CHECK: call void @llvm.ubsantrap(i8 7) {{.*}}!dbg [[LOC:![0-9]+]] +// CHECK: [[LOC]] = !DILocation(line: 0, scope: [[MSG:![0-9]+]], {{.+}}) +// CHECK: [[MSG]] = distinct !DISubprogram(name: "__clang_trap_msg$Undefined Behavior Sanitizer$Implicit integer conversion overflowed or lost data" diff --git a/clang/test/CodeGen/ubsan-trap-reason-invalid-builtin.c b/clang/test/CodeGen/ubsan-trap-reason-invalid-builtin.c new file mode 100644 index 0000000..56cf674 --- /dev/null +++ b/clang/test/CodeGen/ubsan-trap-reason-invalid-builtin.c @@ -0,0 +1,9 @@ +// RUN: %clang_cc1 -triple arm64-apple-macosx14.0.0 -O0 -debug-info-kind=standalone -dwarf-version=5 \ +// RUN: -fsanitize=builtin -fsanitize-trap=builtin -emit-llvm %s -o - | FileCheck %s + +unsigned invalid_builtin(unsigned x) { return __builtin_clz(x); } + +// CHECK-LABEL: @invalid_builtin +// CHECK: call void @llvm.ubsantrap(i8 8) {{.*}}!dbg [[LOC:![0-9]+]] +// CHECK: [[LOC]] = !DILocation(line: 0, scope: [[MSG:![0-9]+]], {{.+}}) +// CHECK: [[MSG]] = distinct !DISubprogram(name: "__clang_trap_msg$Undefined Behavior Sanitizer$Invalid use of builtin function" diff --git a/clang/test/CodeGen/ubsan-trap-reason-invalid-objc-cast.m b/clang/test/CodeGen/ubsan-trap-reason-invalid-objc-cast.m new file mode 100644 index 0000000..ed2d5ff --- /dev/null +++ b/clang/test/CodeGen/ubsan-trap-reason-invalid-objc-cast.m @@ -0,0 +1,32 @@ +// RUN: %clang_cc1 -triple arm64-apple-macosx14.0.0 -O0 -debug-info-kind=standalone -dwarf-version=5 \ +// RUN: -fsanitize=objc-cast -fsanitize-trap=objc-cast -emit-llvm %s -o - | FileCheck %s + +@interface NSFastEnumerationState +@end + +#define NSUInteger unsigned int + +@interface NSArray ++(NSArray*) arrayWithObjects: (id) first, ...; +- (NSUInteger) countByEnumeratingWithState:(NSFastEnumerationState *) state + objects:(id[]) buffer + count:(NSUInteger) len; +-(unsigned) count; +@end +@interface NSString +-(const char*) cString; +@end + +void receive_NSString(NSString*); + +void t0(void) { + NSArray *array = [NSArray arrayWithObjects: @"0", @"1", (void*)0]; + for (NSString *i in array) { + receive_NSString(i); + } +} + +// CHECK-LABEL: @t0 +// CHECK: call void @llvm.ubsantrap(i8 9) {{.*}}!dbg [[LOC:![0-9]+]] +// CHECK: [[LOC]] = !DILocation(line: 0, scope: [[MSG:![0-9]+]], {{.+}}) +// CHECK: [[MSG]] = distinct !DISubprogram(name: "__clang_trap_msg$Undefined Behavior Sanitizer$Invalid Objective-C cast" diff --git a/clang/test/CodeGen/ubsan-trap-reason-load-invalid-value.c b/clang/test/CodeGen/ubsan-trap-reason-load-invalid-value.c new file mode 100644 index 0000000..4aad832 --- /dev/null +++ b/clang/test/CodeGen/ubsan-trap-reason-load-invalid-value.c @@ -0,0 +1,13 @@ +// RUN: %clang_cc1 -triple arm64-apple-macosx14.0.0 -O0 -debug-info-kind=standalone -dwarf-version=5 \ +// RUN: -fsanitize=bool -fsanitize-trap=bool -emit-llvm %s -o - | FileCheck %s + +#include <stdbool.h> + +unsigned char bad_byte; + +bool load_invalid_value(void) { return *((bool *)&bad_byte); } + +// CHECK-LABEL: @load_invalid_value +// CHECK: call void @llvm.ubsantrap(i8 10) {{.*}}!dbg [[LOC:![0-9]+]] +// CHECK: [[LOC]] = !DILocation(line: 0, scope: [[MSG:![0-9]+]], {{.+}}) +// CHECK: [[MSG]] = distinct !DISubprogram(name: "__clang_trap_msg$Undefined Behavior Sanitizer$Loaded an invalid or uninitialized value for the type" diff --git a/clang/test/CodeGen/ubsan-trap-reason-missing-return.cpp b/clang/test/CodeGen/ubsan-trap-reason-missing-return.cpp new file mode 100644 index 0000000..2818d9d --- /dev/null +++ b/clang/test/CodeGen/ubsan-trap-reason-missing-return.cpp @@ -0,0 +1,12 @@ +// RUN: %clang_cc1 -triple arm64-apple-macosx14.0.0 -O0 -debug-info-kind=standalone -dwarf-version=5 \ +// RUN: -fsanitize=return -fsanitize-trap=return -emit-llvm %s -o - | FileCheck %s + +int missing_return(int x) { + if (x > 0) + return x; +} + +// CHECK-LABEL: @_Z14missing_return +// CHECK: call void @llvm.ubsantrap(i8 11) {{.*}}!dbg [[LOC:![0-9]+]] +// CHECK: [[LOC]] = !DILocation(line: 0, scope: [[MSG:![0-9]+]], {{.+}}) +// CHECK: [[MSG]] = distinct !DISubprogram(name: "__clang_trap_msg$Undefined Behavior Sanitizer$Execution reached the end of a value-returning function without returning a value" diff --git a/clang/test/CodeGen/ubsan-trap-reason-mul-overflow.c b/clang/test/CodeGen/ubsan-trap-reason-mul-overflow.c new file mode 100644 index 0000000..cf9a0b4 --- /dev/null +++ b/clang/test/CodeGen/ubsan-trap-reason-mul-overflow.c @@ -0,0 +1,9 @@ +// RUN: %clang_cc1 -triple arm64-apple-macosx14.0.0 -O0 -debug-info-kind=standalone -dwarf-version=5 \ +// RUN: -fsanitize=signed-integer-overflow -fsanitize-trap=signed-integer-overflow -emit-llvm %s -o - | FileCheck %s + +int mul_overflow(int a, int b) { return a * b; } + +// CHECK-LABEL: @mul_overflow +// CHECK: call void @llvm.ubsantrap(i8 12) {{.*}}!dbg [[LOC:![0-9]+]] +// CHECK: [[LOC]] = !DILocation(line: 0, scope: [[MSG:![0-9]+]], {{.+}}) +// CHECK: [[MSG]] = distinct !DISubprogram(name: "__clang_trap_msg$Undefined Behavior Sanitizer$Integer multiplication overflowed" diff --git a/clang/test/CodeGen/ubsan-trap-reason-negate-overflow.c b/clang/test/CodeGen/ubsan-trap-reason-negate-overflow.c new file mode 100644 index 0000000..5534679 --- /dev/null +++ b/clang/test/CodeGen/ubsan-trap-reason-negate-overflow.c @@ -0,0 +1,12 @@ +// RUN: %clang_cc1 -triple arm64-apple-macosx14.0.0 -O0 -debug-info-kind=standalone -dwarf-version=5 \ +// RUN: -fsanitize=signed-integer-overflow -fsanitize-trap=signed-integer-overflow -emit-llvm %s -o - | FileCheck %s + +int negate_overflow() { + int x; + return -x; +} + +// CHECK-LABEL: @negate_overflow +// CHECK: call void @llvm.ubsantrap(i8 13) {{.*}}!dbg [[LOC:![0-9]+]] +// CHECK: [[LOC]] = !DILocation(line: 0, scope: [[MSG:![0-9]+]], {{.+}}) +// CHECK: [[MSG]] = distinct !DISubprogram(name: "__clang_trap_msg$Undefined Behavior Sanitizer$Integer negation overflowed" diff --git a/clang/test/CodeGen/ubsan-trap-reason-nonnull-arg.c b/clang/test/CodeGen/ubsan-trap-reason-nonnull-arg.c new file mode 100644 index 0000000..1f0f450 --- /dev/null +++ b/clang/test/CodeGen/ubsan-trap-reason-nonnull-arg.c @@ -0,0 +1,12 @@ +// RUN: %clang_cc1 -triple arm64-apple-macosx14.0.0 -O0 -debug-info-kind=standalone -dwarf-version=5 \ +// RUN: -fsanitize=nonnull-attribute -fsanitize-trap=nonnull-attribute -emit-llvm %s -o - | FileCheck %s + +__attribute__((nonnull)) void nonnull_arg(int *p) { (void)p; } + +void trigger_nonnull_arg() { nonnull_arg(0); } + +// CHECK-LABEL: @nonnull_arg +// CHECK-LABEL: @trigger_nonnull_arg +// CHECK: call void @llvm.ubsantrap(i8 16) {{.*}}!dbg [[LOC:![0-9]+]] +// CHECK: [[LOC]] = !DILocation(line: 0, scope: [[MSG:![0-9]+]], {{.+}}) +// CHECK: [[MSG]] = distinct !DISubprogram(name: "__clang_trap_msg$Undefined Behavior Sanitizer$Passing null pointer as an argument which is declared to never be null" diff --git a/clang/test/CodeGen/ubsan-trap-reason-nonnull-return.c b/clang/test/CodeGen/ubsan-trap-reason-nonnull-return.c new file mode 100644 index 0000000..1197b4d --- /dev/null +++ b/clang/test/CodeGen/ubsan-trap-reason-nonnull-return.c @@ -0,0 +1,14 @@ +// RUN: %clang_cc1 -triple arm64-apple-macosx14.0.0 -O0 -debug-info-kind=standalone -dwarf-version=5 \ +// RUN: -fsanitize=returns-nonnull-attribute -fsanitize-trap=returns-nonnull-attribute -emit-llvm %s -o - | FileCheck %s + +__attribute__((returns_nonnull)) int *must_return_nonnull(int bad) { + if (bad) + return 0; + static int x = 1; + return &x; +} + +// CHECK-LABEL: @must_return_nonnull +// CHECK: call void @llvm.ubsantrap(i8 17) {{.*}}!dbg [[LOC:![0-9]+]] +// CHECK: [[LOC]] = !DILocation(line: 0, scope: [[MSG:![0-9]+]], {{.+}}) +// CHECK: [[MSG]] = distinct !DISubprogram(name: "__clang_trap_msg$Undefined Behavior Sanitizer$Returning null pointer from a function which is declared to never return null" diff --git a/clang/test/CodeGen/ubsan-trap-reason-nullability-arg.c b/clang/test/CodeGen/ubsan-trap-reason-nullability-arg.c new file mode 100644 index 0000000..2bc71de --- /dev/null +++ b/clang/test/CodeGen/ubsan-trap-reason-nullability-arg.c @@ -0,0 +1,14 @@ +// RUN: %clang_cc1 -triple arm64-apple-macosx14.0.0 -O0 -debug-info-kind=standalone -dwarf-version=5 \ +// RUN: -fsanitize=nullability-arg -fsanitize-trap=nullability-arg -emit-llvm %s -o - | FileCheck %s + +#include <stddef.h> + +int nullability_arg(int *_Nonnull p) { return *p; } + +int trigger_nullability_arg(void) { return nullability_arg(NULL); } + +// CHECK-LABEL: @nullability_arg +// CHECK-LABEL: @trigger_nullability_arg +// CHECK: call void @llvm.ubsantrap(i8 14) {{.*}}!dbg [[LOC:![0-9]+]] +// CHECK: [[LOC]] = !DILocation(line: 0, scope: [[MSG:![0-9]+]], {{.+}}) +// CHECK: [[MSG]] = distinct !DISubprogram(name: "__clang_trap_msg$Undefined Behavior Sanitizer$Passing null as an argument which is annotated with _Nonnull" diff --git a/clang/test/CodeGen/ubsan-trap-reason-nullability-return.c b/clang/test/CodeGen/ubsan-trap-reason-nullability-return.c new file mode 100644 index 0000000..3d64c5a --- /dev/null +++ b/clang/test/CodeGen/ubsan-trap-reason-nullability-return.c @@ -0,0 +1,18 @@ +// RUN: %clang_cc1 -triple arm64-apple-macosx14.0.0 -O0 -debug-info-kind=standalone -dwarf-version=5 \ +// RUN: -fsanitize=nullability-return -fsanitize-trap=nullability-return -emit-llvm %s -o - | FileCheck %s + +#include <stdbool.h> +#include <stddef.h> + +int *_Nonnull nullability_return(bool fail) { + if (fail) + return NULL; + + static int x = 0; + return &x; +} + +// CHECK-LABEL: @nullability_return +// CHECK: call void @llvm.ubsantrap(i8 15) {{.*}}!dbg [[LOC:![0-9]+]] +// CHECK: [[LOC]] = !DILocation(line: 0, scope: [[MSG:![0-9]+]], {{.+}}) +// CHECK: [[MSG]] = distinct !DISubprogram(name: "__clang_trap_msg$Undefined Behavior Sanitizer$Returning null from a function with a return type annotated with _Nonnull" diff --git a/clang/test/CodeGen/ubsan-trap-reason-out-of-bounds.c b/clang/test/CodeGen/ubsan-trap-reason-out-of-bounds.c new file mode 100644 index 0000000..979886d --- /dev/null +++ b/clang/test/CodeGen/ubsan-trap-reason-out-of-bounds.c @@ -0,0 +1,12 @@ +// RUN: %clang_cc1 -triple arm64-apple-macosx14.0.0 -O0 -debug-info-kind=standalone -dwarf-version=5 \ +// RUN: -fsanitize=array-bounds -fsanitize-trap=array-bounds -emit-llvm %s -o - | FileCheck %s + +int out_of_bounds() { + int a[1] = {0}; + return a[1]; +} + +// CHECK-LABEL: @out_of_bounds +// CHECK: call void @llvm.ubsantrap(i8 18) {{.*}}!dbg [[LOC:![0-9]+]] +// CHECK: [[LOC]] = !DILocation(line: 0, scope: [[MSG:![0-9]+]], {{.+}}) +// CHECK: [[MSG]] = distinct !DISubprogram(name: "__clang_trap_msg$Undefined Behavior Sanitizer$Array index out of bounds" diff --git a/clang/test/CodeGen/ubsan-trap-reason-pointer-overflow.c b/clang/test/CodeGen/ubsan-trap-reason-pointer-overflow.c new file mode 100644 index 0000000..41cb487 --- /dev/null +++ b/clang/test/CodeGen/ubsan-trap-reason-pointer-overflow.c @@ -0,0 +1,16 @@ +// RUN: %clang_cc1 -triple arm64-apple-macosx14.0.0 -O0 -debug-info-kind=standalone -dwarf-version=5 \ +// RUN: -fsanitize=pointer-overflow -fsanitize-trap=pointer-overflow -emit-llvm %s -o - | FileCheck %s + +#include <stddef.h> +#include <stdint.h> + +int *pointer_overflow(void) { + int buf[4]; + volatile size_t n = (SIZE_MAX / sizeof(int)) - 1; + return buf + n; +} + +// CHECK-LABEL: @pointer_overflow +// CHECK: call void @llvm.ubsantrap(i8 19) {{.*}}!dbg [[LOC:![0-9]+]] +// CHECK: [[LOC]] = !DILocation(line: 0, scope: [[MSG:![0-9]+]], {{.+}}) +// CHECK: [[MSG]] = distinct !DISubprogram(name: "__clang_trap_msg$Undefined Behavior Sanitizer$Pointer arithmetic overflowed bounds" diff --git a/clang/test/CodeGen/ubsan-trap-reason-shift-out-of-bounds.c b/clang/test/CodeGen/ubsan-trap-reason-shift-out-of-bounds.c new file mode 100644 index 0000000..1a7465d --- /dev/null +++ b/clang/test/CodeGen/ubsan-trap-reason-shift-out-of-bounds.c @@ -0,0 +1,12 @@ +// RUN: %clang_cc1 -triple arm64-apple-macosx14.0.0 -O0 -debug-info-kind=standalone -dwarf-version=5 \ +// RUN: -fsanitize=shift-base -fsanitize-trap=shift-base -emit-llvm %s -o - | FileCheck %s + +int shift_out_of_bounds(void) { + int sh = 32; + return 1 << sh; +} + +// CHECK-LABEL: @shift_out_of_bounds +// CHECK: call void @llvm.ubsantrap(i8 20) {{.*}}!dbg [[LOC:![0-9]+]] +// CHECK: [[LOC]] = !DILocation(line: 0, scope: [[MSG:![0-9]+]], {{.+}}) +// CHECK: [[MSG]] = distinct !DISubprogram(name: "__clang_trap_msg$Undefined Behavior Sanitizer$Shift exponent is too large for the type" diff --git a/clang/test/CodeGen/ubsan-trap-reason-sub-overflow.c b/clang/test/CodeGen/ubsan-trap-reason-sub-overflow.c new file mode 100644 index 0000000..62aa7fc --- /dev/null +++ b/clang/test/CodeGen/ubsan-trap-reason-sub-overflow.c @@ -0,0 +1,9 @@ +// RUN: %clang_cc1 -triple arm64-apple-macosx14.0.0 -O0 -debug-info-kind=standalone -dwarf-version=5 \ +// RUN: -fsanitize=signed-integer-overflow -fsanitize-trap=signed-integer-overflow -emit-llvm %s -o - | FileCheck %s + +int sub_overflow(int a, int b) { return a - b; } + +// CHECK-LABEL: @sub_overflow +// CHECK: call void @llvm.ubsantrap(i8 21) {{.*}}!dbg [[LOC:![0-9]+]] +// CHECK: [[LOC]] = !DILocation(line: 0, scope: [[MSG:![0-9]+]], {{.+}}) +// CHECK: [[MSG]] = distinct !DISubprogram(name: "__clang_trap_msg$Undefined Behavior Sanitizer$Integer subtraction overflowed" diff --git a/clang/test/CodeGen/ubsan-trap-reason-type-mismatch.c b/clang/test/CodeGen/ubsan-trap-reason-type-mismatch.c new file mode 100644 index 0000000..802ec91 --- /dev/null +++ b/clang/test/CodeGen/ubsan-trap-reason-type-mismatch.c @@ -0,0 +1,9 @@ +// RUN: %clang_cc1 -triple arm64-apple-macosx14.0.0 -O0 -debug-info-kind=standalone -dwarf-version=5 \ +// RUN: -fsanitize=alignment -fsanitize-trap=alignment -emit-llvm %s -o - | FileCheck %s + +int type_mismatch(int *p) { return *p; } + +// CHECK-LABEL: @type_mismatch +// CHECK: call void @llvm.ubsantrap(i8 22) {{.*}}!dbg [[LOC:![0-9]+]] +// CHECK: [[LOC]] = !DILocation(line: 0, scope: [[MSG:![0-9]+]], {{.+}}) +// CHECK: [[MSG]] = distinct !DISubprogram(name: "__clang_trap_msg$Undefined Behavior Sanitizer$Type mismatch in operation" diff --git a/clang/test/CodeGen/ubsan-trap-reason-vla-bound-not-positive.c b/clang/test/CodeGen/ubsan-trap-reason-vla-bound-not-positive.c new file mode 100644 index 0000000..ad9c408 --- /dev/null +++ b/clang/test/CodeGen/ubsan-trap-reason-vla-bound-not-positive.c @@ -0,0 +1,14 @@ +// RUN: %clang_cc1 -triple arm64-apple-macosx14.0.0 -O0 -debug-info-kind=standalone -dwarf-version=5 \ +// RUN: -fsanitize=vla-bound -fsanitize-trap=vla-bound -emit-llvm %s -o - | FileCheck %s + +int n = 0; + +int vla_bound_not_positive(void) { + int a[n]; + return sizeof a; +} + +// CHECK-LABEL: @vla_bound_not_positive +// CHECK: call void @llvm.ubsantrap(i8 24) {{.*}}!dbg [[LOC:![0-9]+]] +// CHECK: [[LOC]] = !DILocation(line: 0, scope: [[MSG:![0-9]+]], {{.+}}) +// CHECK: [[MSG]] = distinct !DISubprogram(name: "__clang_trap_msg$Undefined Behavior Sanitizer$Variable length array bound evaluates to non-positive value" diff --git a/clang/test/CodeGenHLSL/BasicFeatures/ArrayOutputArguments.hlsl b/clang/test/CodeGenHLSL/BasicFeatures/ArrayOutputArguments.hlsl index bccfaf5..4571649 100644 --- a/clang/test/CodeGenHLSL/BasicFeatures/ArrayOutputArguments.hlsl +++ b/clang/test/CodeGenHLSL/BasicFeatures/ArrayOutputArguments.hlsl @@ -11,7 +11,7 @@ void increment(inout int Arr[2]) { // CHECK-NEXT: [[Tmp:%.*]] = alloca [2 x i32], align 4 // CHECK-NEXT: call void @llvm.memcpy.p0.p0.i32(ptr align 4 [[A]], ptr align 4 @{{.*}}, i32 8, i1 false) // CHECK-NEXT: call void @llvm.memcpy.p0.p0.i32(ptr align 4 [[Tmp]], ptr align 4 [[A]], i32 8, i1 false) -// CHECK-NEXT: call void @{{.*}}increment{{.*}}(ptr noalias noundef byval([2 x i32]) align 4 [[Tmp]]) +// CHECK-NEXT: call void @{{.*}}increment{{.*}}(ptr noalias noundef align 4 [[Tmp]]) // CHECK-NEXT: call void @llvm.memcpy.p0.p0.i32(ptr align 4 [[A]], ptr align 4 [[Tmp]], i32 8, i1 false) // CHECK-NEXT: [[Idx:%.*]] = getelementptr inbounds [2 x i32], ptr [[A]], i32 0, i32 0 // CHECK-NEXT: [[B:%.*]] = load i32, ptr [[Idx]], align 4 @@ -32,7 +32,7 @@ void fn2(out int Arr[2]) { // CHECK: [[A:%.*]] = alloca [2 x i32], align 4 // CHECK-NEXT: [[Tmp:%.*]] = alloca [2 x i32], align 4 // CHECK-NEXT: call void @llvm.memcpy.p0.p0.i32(ptr align 4 [[A]], ptr align 4 @{{.*}}, i32 8, i1 false) -// CHECK-NEXT: call void @{{.*}}fn2{{.*}}(ptr noalias noundef byval([2 x i32]) align 4 [[Tmp]]) +// CHECK-NEXT: call void @{{.*}}fn2{{.*}}(ptr noalias noundef align 4 [[Tmp]]) // CHECK-NEXT: call void @llvm.memcpy.p0.p0.i32(ptr align 4 [[A]], ptr align 4 [[Tmp]], i32 8, i1 false) // CHECK-NEXT: [[Idx:%.*]] = getelementptr inbounds [2 x i32], ptr [[A]], i32 0, i32 0 // CHECK-NEXT: [[B:%.*]] = load i32, ptr [[Idx]], align 4 @@ -56,7 +56,7 @@ void nestedCall(inout int Arr[2], uint index) { // CHECK-NEXT: [[Tmp:%.*]] = alloca [2 x i32], align 4 // CHECK-NEXT: call void @llvm.memcpy.p0.p0.i32(ptr align 4 [[A]], ptr align 4 @{{.*}}, i32 8, i1 false) // CHECK-NEXT: call void @llvm.memcpy.p0.p0.i32(ptr align 4 [[Tmp]], ptr align 4 [[A]], i32 8, i1 false) -// CHECK-NEXT: call void @{{.*}}nestedCall{{.*}}(ptr noalias noundef byval([2 x i32]) align 4 [[Tmp]], i32 noundef 0) +// CHECK-NEXT: call void @{{.*}}nestedCall{{.*}}(ptr noalias noundef align 4 [[Tmp]], i32 noundef 0) // CHECK-NEXT: call void @llvm.memcpy.p0.p0.i32(ptr align 4 [[A]], ptr align 4 [[Tmp]], i32 8, i1 false) // CHECK-NEXT: [[Idx:%.*]] = getelementptr inbounds [2 x i32], ptr [[A]], i32 0, i32 1 // CHECK-NEXT: [[B:%.*]] = load i32, ptr [[Idx]], align 4 @@ -70,7 +70,7 @@ export int arrayCall3() { // CHECK-LABEL: outerCall // CHECK: [[Tmp:%.*]] = alloca [2 x i32], align 4 // CHECK-NEXT: call void @llvm.memcpy.p0.p0.i32(ptr align 4 [[Tmp]], ptr align 4 %{{.*}}, i32 8, i1 false) -// CHECK-NEXT: call void {{.*}}increment{{.*}}(ptr noalias noundef byval([2 x i32]) align 4 [[Tmp]]) +// CHECK-NEXT: call void {{.*}}increment{{.*}}(ptr noalias noundef align 4 [[Tmp]]) // CHECK-NEXT: call void @llvm.memcpy.p0.p0.i32(ptr align 4 {{.*}}, ptr align 4 [[Tmp]], i32 8, i1 false) // CHECK-NEXT: ret void void outerCall(inout int Arr[2]) { @@ -82,7 +82,7 @@ void outerCall(inout int Arr[2]) { // CHECK-NEXT: [[Tmp:%.*]] = alloca [2 x i32], align 4 // CHECK-NEXT: call void @llvm.memcpy.p0.p0.i32(ptr align 4 [[A]], ptr align 4 @{{.*}}, i32 8, i1 false) // CHECK-NEXT: call void @llvm.memcpy.p0.p0.i32(ptr align 4 [[Tmp]], ptr align 4 [[A]], i32 8, i1 false) -// CHECK-NEXT: call void @{{.*}}outerCall{{.*}}(ptr noalias noundef byval([2 x i32]) align 4 [[Tmp]]) +// CHECK-NEXT: call void @{{.*}}outerCall{{.*}}(ptr noalias noundef align 4 [[Tmp]]) // CHECK-NEXT: call void @llvm.memcpy.p0.p0.i32(ptr align 4 [[A]], ptr align 4 [[Tmp]], i32 8, i1 false) // CHECK-NEXT: [[Idx:%.*]] = getelementptr inbounds [2 x i32], ptr [[A]], i32 0, i32 0 // CHECK-NEXT: [[B:%.*]] = load i32, ptr [[Idx]], align 4 @@ -110,7 +110,7 @@ void outerCall2(inout int Arr[2]) { // CHECK-NEXT: [[Tmp:%.*]] = alloca [2 x i32], align 4 // CHECK-NEXT: call void @llvm.memcpy.p0.p0.i32(ptr align 4 [[A]], ptr align 4 @{{.*}}, i32 8, i1 false) // CHECK-NEXT: call void @llvm.memcpy.p0.p0.i32(ptr align 4 [[Tmp]], ptr align 4 [[A]], i32 8, i1 false) -// CHECK-NEXT: call void @{{.*}}outerCall2{{.*}}(ptr noalias noundef byval([2 x i32]) align 4 [[Tmp]]) +// CHECK-NEXT: call void @{{.*}}outerCall2{{.*}}(ptr noalias noundef align 4 [[Tmp]]) // CHECK-NEXT: call void @llvm.memcpy.p0.p0.i32(ptr align 4 [[A]], ptr align 4 [[Tmp]], i32 8, i1 false) // CHECK-NEXT: [[Idx:%.*]] = getelementptr inbounds [2 x i32], ptr [[A]], i32 0, i32 0 // CHECK-NEXT: [[B:%.*]] = load i32, ptr [[Idx]], align 4 diff --git a/clang/test/CodeGenOpenCL/builtins-amdgcn-gfx1250-load-monitor.cl b/clang/test/CodeGenOpenCL/builtins-amdgcn-gfx1250-load-monitor.cl new file mode 100644 index 0000000..f2552d4 --- /dev/null +++ b/clang/test/CodeGenOpenCL/builtins-amdgcn-gfx1250-load-monitor.cl @@ -0,0 +1,66 @@ +// NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py +// REQUIRES: amdgpu-registered-target +// RUN: %clang_cc1 -cl-std=CL2.0 -triple amdgcn-unknown-unknown -target-cpu gfx1250 -emit-llvm -o - %s | FileCheck %s --check-prefix=CHECK-GFX1250 + +typedef int v2i __attribute__((ext_vector_type(2))); +typedef int v4i __attribute__((ext_vector_type(4))); + +// CHECK-GFX1250-LABEL: @test_amdgcn_global_load_monitor_b32( +// CHECK-GFX1250-NEXT: entry: +// CHECK-GFX1250-NEXT: [[TMP0:%.*]] = tail call i32 @llvm.amdgcn.global.load.monitor.b32.i32(ptr addrspace(1) [[INPTR:%.*]], i32 1) +// CHECK-GFX1250-NEXT: ret i32 [[TMP0]] +// +int test_amdgcn_global_load_monitor_b32(global int* inptr) +{ + return __builtin_amdgcn_global_load_monitor_b32(inptr, 1); +} + +// CHECK-GFX1250-LABEL: @test_amdgcn_global_load_monitor_b64( +// CHECK-GFX1250-NEXT: entry: +// CHECK-GFX1250-NEXT: [[TMP0:%.*]] = tail call <2 x i32> @llvm.amdgcn.global.load.monitor.b64.v2i32(ptr addrspace(1) [[INPTR:%.*]], i32 10) +// CHECK-GFX1250-NEXT: ret <2 x i32> [[TMP0]] +// +v2i test_amdgcn_global_load_monitor_b64(global v2i* inptr) +{ + return __builtin_amdgcn_global_load_monitor_b64(inptr, 10); +} + +// CHECK-GFX1250-LABEL: @test_amdgcn_global_load_monitor_b128( +// CHECK-GFX1250-NEXT: entry: +// CHECK-GFX1250-NEXT: [[TMP0:%.*]] = tail call <4 x i32> @llvm.amdgcn.global.load.monitor.b128.v4i32(ptr addrspace(1) [[INPTR:%.*]], i32 22) +// CHECK-GFX1250-NEXT: ret <4 x i32> [[TMP0]] +// +v4i test_amdgcn_global_load_monitor_b128(global v4i* inptr) +{ + return __builtin_amdgcn_global_load_monitor_b128(inptr, 22); +} + +// CHECK-GFX1250-LABEL: @test_amdgcn_flat_load_monitor_b32( +// CHECK-GFX1250-NEXT: entry: +// CHECK-GFX1250-NEXT: [[TMP0:%.*]] = tail call i32 @llvm.amdgcn.flat.load.monitor.b32.i32(ptr [[INPTR:%.*]], i32 27) +// CHECK-GFX1250-NEXT: ret i32 [[TMP0]] +// +int test_amdgcn_flat_load_monitor_b32(int* inptr) +{ + return __builtin_amdgcn_flat_load_monitor_b32(inptr, 27); +} + +// CHECK-GFX1250-LABEL: @test_amdgcn_flat_load_monitor_b64( +// CHECK-GFX1250-NEXT: entry: +// CHECK-GFX1250-NEXT: [[TMP0:%.*]] = tail call <2 x i32> @llvm.amdgcn.flat.load.monitor.b64.v2i32(ptr [[INPTR:%.*]], i32 1) +// CHECK-GFX1250-NEXT: ret <2 x i32> [[TMP0]] +// +v2i test_amdgcn_flat_load_monitor_b64(v2i* inptr) +{ + return __builtin_amdgcn_flat_load_monitor_b64(inptr, 1); +} + +// CHECK-GFX1250-LABEL: @test_amdgcn_flat_load_monitor_b128( +// CHECK-GFX1250-NEXT: entry: +// CHECK-GFX1250-NEXT: [[TMP0:%.*]] = tail call <4 x i32> @llvm.amdgcn.flat.load.monitor.b128.v4i32(ptr [[INPTR:%.*]], i32 0) +// CHECK-GFX1250-NEXT: ret <4 x i32> [[TMP0]] +// +v4i test_amdgcn_flat_load_monitor_b128(v4i* inptr) +{ + return __builtin_amdgcn_flat_load_monitor_b128(inptr, 0); +} diff --git a/clang/test/Driver/modules.mm b/clang/test/Driver/modules.mm index d1536c7..f0b0669 100644 --- a/clang/test/Driver/modules.mm +++ b/clang/test/Driver/modules.mm @@ -3,6 +3,9 @@ // RUN: %clang -fmodules -fno-cxx-modules -### %s 2>&1 | FileCheck -check-prefix=CHECK-NO-MODULES %s // CHECK-NO-MODULES-NOT: -fmodules +// RUN: %clang -std=c++20 -fno-cxx-modules -### %s 2>&1 | FileCheck -check-prefix=CHECK-NO-CPP-20-MODULES %s +// CHECK-NO-CPP-20-MODULES: -fno-cxx-modules + // RUN: %clang -fmodules -### %s 2>&1 | FileCheck -check-prefix=CHECK-HAS-MODULES %s // RUN: %clang -fmodules -fno-cxx-modules -fcxx-modules -### %s 2>&1 | FileCheck -check-prefix=CHECK-HAS-MODULES %s // CHECK-HAS-MODULES: -fmodules diff --git a/clang/test/Parser/dep_template_spec_type.cpp b/clang/test/Parser/dep_template_spec_type.cpp new file mode 100644 index 0000000..65544bb --- /dev/null +++ b/clang/test/Parser/dep_template_spec_type.cpp @@ -0,0 +1,16 @@ +// RUN: seq 100 | xargs -Ifoo %clang_cc1 -fsyntax-only -verify %s +// expected-no-diagnostics +// This is a regression test for a non-deterministic stack-overflow. + +template <typename C, typename S1, int rbits> +typename C::A Bar(const S1& x, const C& c = C()) { + using T = typename C::A; + T result; + + using PreC = typename C::template boop<T::p + rbits>; + using ExactC = typename C::template bap<PreC::p + 2>; + + using D = typename ExactC::A; + + return result; +} diff --git a/clang/test/Sema/builtins-wasm.c b/clang/test/Sema/builtins-wasm.c index 31e5291..a3486b1 100644 --- a/clang/test/Sema/builtins-wasm.c +++ b/clang/test/Sema/builtins-wasm.c @@ -54,3 +54,27 @@ void test_table_copy(int dst_idx, int src_idx, int nelem) { __builtin_wasm_table_copy(table, table, dst_idx, src_idx, table); // expected-error {{5th argument must be an integer}} __builtin_wasm_table_copy(table, table, dst_idx, src_idx, nelem); } + +typedef void (*F1)(void); +typedef int (*F2)(int); +typedef int (*F3)(__externref_t); +typedef __externref_t (*F4)(int); + +void test_function_pointer_signature() { + // Test argument count validation + (void)__builtin_wasm_test_function_pointer_signature(); // expected-error {{too few arguments to function call, expected 1, have 0}} + (void)__builtin_wasm_test_function_pointer_signature((F1)0, (F2)0); // expected-error {{too many arguments to function call, expected 1, have 2}} + + // // Test argument type validation - should require function pointer + (void)__builtin_wasm_test_function_pointer_signature((void*)0); // expected-error {{used type 'void *' where function pointer is required}} + (void)__builtin_wasm_test_function_pointer_signature((int)0); // expected-error {{used type 'int' where function pointer is required}} + (void)__builtin_wasm_test_function_pointer_signature((F3)0); // expected-error {{not supported for function pointers with a reference type parameter}} + (void)__builtin_wasm_test_function_pointer_signature((F4)0); // expected-error {{not supported for function pointers with a reference type return value}} + + // // Test valid usage + int res = __builtin_wasm_test_function_pointer_signature((F1)0); + res = __builtin_wasm_test_function_pointer_signature((F2)0); + + // Test return type + _Static_assert(EXPR_HAS_TYPE(__builtin_wasm_test_function_pointer_signature((F1)0), int), ""); +} diff --git a/clang/test/SemaCXX/constant-expression-p2280r4.cpp b/clang/test/SemaCXX/constant-expression-p2280r4.cpp index 16f5f82..312a778 100644 --- a/clang/test/SemaCXX/constant-expression-p2280r4.cpp +++ b/clang/test/SemaCXX/constant-expression-p2280r4.cpp @@ -383,3 +383,17 @@ namespace enable_if_2 { } } } + +namespace GH150015 { + extern int (& c)[8]; // interpreter-note {{declared here}} + constexpr int x = c <= c+8; // interpreter-error {{constexpr variable 'x' must be initialized by a constant expression}} \ + // interpreter-note {{initializer of 'c' is unknown}} + + struct X {}; + struct Y {}; + struct Z : X, Y {}; + extern Z &z; // interpreter-note{{declared here}} + constexpr int bases = (void*)(X*)&z <= (Y*)&z; // expected-error {{constexpr variable 'bases' must be initialized by a constant expression}} \ + // nointerpreter-note {{comparison of addresses of subobjects of different base classes has unspecified value}} \ + // interpreter-note {{initializer of 'z' is unknown}} +} diff --git a/clang/test/SemaOpenACC/compute-construct-reduction-clause.c b/clang/test/SemaOpenACC/compute-construct-reduction-clause.c index 6a77f07..995b6d3 100644 --- a/clang/test/SemaOpenACC/compute-construct-reduction-clause.c +++ b/clang/test/SemaOpenACC/compute-construct-reduction-clause.c @@ -68,7 +68,6 @@ void uses(unsigned Parm) { #pragma acc parallel reduction(&: ChC) while (1); - // expected-error@+1{{OpenACC 'reduction' variable must be of scalar type, sub-array, or a composite of scalar types; type is 'int[5]'}} #pragma acc parallel reduction(&: Array) while (1); @@ -76,7 +75,7 @@ void uses(unsigned Parm) { while (1); struct CompositeHasComposite ChCArray[5]; - // expected-error@+1{{OpenACC 'reduction' variable must be of scalar type, sub-array, or a composite of scalar types; sub-array base type is 'struct CompositeHasComposite'}} + // expected-error@+1{{OpenACC 'reduction' variable must be of scalar type, aggregate, sub-array, or a composite of scalar types; sub-array base type is 'struct CompositeHasComposite'}} #pragma acc parallel reduction(&: CoS, Array[I], ChCArray[0:I]) while (1); diff --git a/clang/test/SemaOpenACC/compute-construct-reduction-clause.cpp b/clang/test/SemaOpenACC/compute-construct-reduction-clause.cpp index 3e972b0..b40268c 100644 --- a/clang/test/SemaOpenACC/compute-construct-reduction-clause.cpp +++ b/clang/test/SemaOpenACC/compute-construct-reduction-clause.cpp @@ -70,7 +70,6 @@ void uses(unsigned Parm) { // expected-note@#COS_FIELD{{invalid field is here}} #pragma acc parallel reduction(&: ChC) while (1); - // expected-error@+1{{OpenACC 'reduction' variable must be of scalar type, sub-array, or a composite of scalar types; type is 'int[5]'}} #pragma acc parallel reduction(&: Array) while (1); @@ -140,10 +139,8 @@ void TemplUses(T Parm, U CoS, V ChC) { // expected-note@#COS_FIELD{{invalid field is here}} #pragma acc parallel reduction(&: ChC) while (1); - // expected-error@+1{{OpenACC 'reduction' variable must be of scalar type, sub-array, or a composite of scalar types; type is 'int[5]'}} #pragma acc parallel reduction(&: Array) while (1); - // expected-error@+1{{OpenACC 'reduction' variable must be of scalar type, sub-array, or a composite of scalar types; type is 'int[5]'}} #pragma acc parallel reduction(&: NonDepArray) while (1); diff --git a/clang/test/SemaOpenACC/data-construct-use_device-clause.c b/clang/test/SemaOpenACC/data-construct-use_device-clause.c index 9239757..65eaf4e 100644 --- a/clang/test/SemaOpenACC/data-construct-use_device-clause.c +++ b/clang/test/SemaOpenACC/data-construct-use_device-clause.c @@ -1,4 +1,4 @@ -// RUN: %clang_cc1 %s -fopenacc -verify +// RUN: %clang_cc1 %s -fopenacc -verify -Wopenacc-extension typedef struct IsComplete { struct S { int A; } CompositeMember; @@ -23,7 +23,7 @@ void uses(int IntParam, short *PointerParam, float ArrayParam[5], Complete Compo #pragma acc host_data use_device(LocalComposite.ScalarMember, LocalComposite.ScalarMember) ; - // expected-error@+1{{OpenACC variable in 'use_device' clause is not a valid variable name or array name}} + // expected-warning@+1{{sub-array as a variable in 'use_device' clause is not a valid variable name or array name}} #pragma acc host_data use_device(LocalArray[2:1]) // expected-error@+1{{OpenACC variable in 'use_device' clause is not a valid variable name or array name}} @@ -35,12 +35,12 @@ void uses(int IntParam, short *PointerParam, float ArrayParam[5], Complete Compo ; // expected-error@+2{{OpenACC sub-array length is unspecified and cannot be inferred because the subscripted value is not an array}} - // expected-error@+1{{OpenACC variable in 'use_device' clause is not a valid variable name or array name}} + // expected-warning@+1{{sub-array as a variable in 'use_device' clause is not a valid variable name or array name}} #pragma acc host_data use_device(PointerParam[2:]) ; // expected-error@+2{{OpenACC sub-array specified range [2:5] would be out of the range of the subscripted array size of 5}} - // expected-error@+1{{OpenACC variable in 'use_device' clause is not a valid variable name or array name}} + // expected-warning@+1{{sub-array as a variable in 'use_device' clause is not a valid variable name or array name}} #pragma acc host_data use_device(ArrayParam[2:5]) ; diff --git a/clang/test/SemaOpenACC/data-construct.cpp b/clang/test/SemaOpenACC/data-construct.cpp index 394ebb0..da7b80a 100644 --- a/clang/test/SemaOpenACC/data-construct.cpp +++ b/clang/test/SemaOpenACC/data-construct.cpp @@ -1,4 +1,4 @@ -// RUN: %clang_cc1 %s -fopenacc -verify -Wno-empty-body -Wno-unused-value +// RUN: %clang_cc1 %s -fopenacc -verify -Wno-empty-body -Wno-unused-value -Wopenacc-extension void HasStmt() { { @@ -185,7 +185,7 @@ void HostDataRules() { #pragma acc host_data use_device(Array) ; - // expected-error@+1{{OpenACC variable in 'use_device' clause is not a valid variable name or array name}} + // expected-warning@+1{{sub-array as a variable in 'use_device' clause is not a valid variable name or array name}} #pragma acc host_data use_device(Array[1:1]) ; diff --git a/clang/test/SemaOpenACC/declare-construct.cpp b/clang/test/SemaOpenACC/declare-construct.cpp index 6f21aed..6828ecd 100644 --- a/clang/test/SemaOpenACC/declare-construct.cpp +++ b/clang/test/SemaOpenACC/declare-construct.cpp @@ -1,7 +1,8 @@ -// RUN: %clang_cc1 %s -fopenacc -verify +// RUN: %clang_cc1 %s -fopenacc -verify -Wopenacc-extension int *Global; int GlobalArray[5]; +int GlobalArray2[5]; // expected-error@+1{{no valid clauses specified in OpenACC 'declare' directive}} #pragma acc declare namespace NS { @@ -265,8 +266,8 @@ void use() { // expected-error@+1{{OpenACC variable on 'declare' construct is not a valid variable name or array name}} #pragma acc declare create(GlobalArray[0]) -// expected-error@+1{{OpenACC variable on 'declare' construct is not a valid variable name or array name}} -#pragma acc declare create(GlobalArray[0: 1]) +// expected-warning@+1{{sub-array as a variable on 'declare' construct is not a valid variable name or array name}} +#pragma acc declare create(GlobalArray[0: 1]) // #GLOBALARRAYREF struct S { int I; }; // expected-error@+1{{OpenACC variable on 'declare' construct is not a valid variable name or array name}} @@ -288,8 +289,12 @@ void ExternVar() { #pragma acc declare copy(I) copyin(I2), copyout(I3), create(I4), present(I5), deviceptr(I6), device_resident(I7), link(I8) } +// expected-error@+2{{variable referenced in 'link' clause of OpenACC 'declare' directive was already referenced}} +// expected-note@#GLOBALARRAYREF{{previous reference is here}} +#pragma acc declare link(GlobalArray) + // Link can only have global, namespace, or extern vars. -#pragma acc declare link(Global, GlobalArray) +#pragma acc declare link(Global, GlobalArray2) struct Struct2 { static const int StaticMem = 5; diff --git a/clang/test/SemaOpenACC/loop-construct-reduction-clause.cpp b/clang/test/SemaOpenACC/loop-construct-reduction-clause.cpp index bbcfffb..00bcd74 100644 --- a/clang/test/SemaOpenACC/loop-construct-reduction-clause.cpp +++ b/clang/test/SemaOpenACC/loop-construct-reduction-clause.cpp @@ -36,7 +36,6 @@ void uses() { #pragma acc serial { - // expected-error@+1{{OpenACC 'reduction' variable must be of scalar type, sub-array, or a composite of scalar types; type is 'int[5]'}} #pragma acc loop reduction(+:Array) for(int i = 0; i < 5; ++i){} } @@ -172,7 +171,6 @@ void templ_uses() { #pragma acc serial { - // expected-error@+1{{OpenACC 'reduction' variable must be of scalar type, sub-array, or a composite of scalar types; type is 'int[5]'}} #pragma acc loop reduction(+:Array) for(int i = 0; i < 5; ++i){} } diff --git a/clang/test/SemaOpenCL/builtins-amdgcn-error-gfx1250-param.cl b/clang/test/SemaOpenCL/builtins-amdgcn-error-gfx1250-param.cl index 12a0f3c..3247380 100644 --- a/clang/test/SemaOpenCL/builtins-amdgcn-error-gfx1250-param.cl +++ b/clang/test/SemaOpenCL/builtins-amdgcn-error-gfx1250-param.cl @@ -1,6 +1,7 @@ // REQUIRES: amdgpu-registered-target // RUN: %clang_cc1 -cl-std=CL2.0 -triple amdgcn-- -target-cpu gfx1250 -verify -S -o - %s +typedef int v2i __attribute__((ext_vector_type(2))); typedef int v4i __attribute__((ext_vector_type(4))); typedef int v8i __attribute__((ext_vector_type(8))); @@ -28,6 +29,17 @@ void test__builtin_amdgcn_cvt_f16_bf8(int a, int b) { __builtin_amdgcn_cvt_f16_bf8(a, b); // expected-error {{'__builtin_amdgcn_cvt_f16_bf8' must be a constant integer}} } +void test_amdgcn_load_monitor(global int* b32gaddr, global v2i* b64gaddr, global v4i* b128gaddr, int *b32faddr, v2i* b64faddr, v4i *b128faddr, + global int* b32out, global v2i* b64out, global v4i* b128out, int cpol) +{ + *b32out = __builtin_amdgcn_global_load_monitor_b32(b32gaddr, cpol); // expected-error {{'__builtin_amdgcn_global_load_monitor_b32' must be a constant integer}} + *b64out = __builtin_amdgcn_global_load_monitor_b64(b64gaddr, cpol); // expected-error {{'__builtin_amdgcn_global_load_monitor_b64' must be a constant integer}} + *b128out = __builtin_amdgcn_global_load_monitor_b128(b128gaddr, cpol); // expected-error {{'__builtin_amdgcn_global_load_monitor_b128' must be a constant integer}} + *b32out = __builtin_amdgcn_flat_load_monitor_b32(b32faddr, cpol); // expected-error {{'__builtin_amdgcn_flat_load_monitor_b32' must be a constant integer}} + *b64out = __builtin_amdgcn_flat_load_monitor_b64(b64faddr, cpol); // expected-error {{'__builtin_amdgcn_flat_load_monitor_b64' must be a constant integer}} + *b128out = __builtin_amdgcn_flat_load_monitor_b128(b128faddr, cpol); // expected-error {{'__builtin_amdgcn_flat_load_monitor_b128' must be a constant integer}} +} + void test_amdgcn_tensor_load_store(v4i sg0, v8i sg1, v4i sg2, v4i sg3, int cpol) { __builtin_amdgcn_tensor_load_to_lds(sg0, sg1, sg2, sg3, cpol); // expected-error {{'__builtin_amdgcn_tensor_load_to_lds' must be a constant integer}} diff --git a/clang/unittests/Format/FormatTest.cpp b/clang/unittests/Format/FormatTest.cpp index c20d099..553d980 100644 --- a/clang/unittests/Format/FormatTest.cpp +++ b/clang/unittests/Format/FormatTest.cpp @@ -8593,10 +8593,10 @@ TEST_F(FormatTest, BreaksFunctionDeclarations) { "operator<<(const SomeLooooooooooooooooooooooooogType &other);"); verifyGoogleFormat( "SomeLoooooooooooooooooooooooooooooogType operator>>(\n" - " const SomeLooooooooogType &a, const SomeLooooooooogType &b);"); + " const SomeLooooooooogType& a, const SomeLooooooooogType& b);"); verifyGoogleFormat( "SomeLoooooooooooooooooooooooooooooogType operator<<(\n" - " const SomeLooooooooogType &a, const SomeLooooooooogType &b);"); + " const SomeLooooooooogType& a, const SomeLooooooooogType& b);"); verifyFormat("void aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa(\n" " int aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa = 1);"); @@ -8605,7 +8605,7 @@ TEST_F(FormatTest, BreaksFunctionDeclarations) { verifyGoogleFormat( "typename aaaaaaaaaa<aaaaaa>::aaaaaaaaaaa\n" "aaaaaaaaaa<aaaaaa>::aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa(\n" - " bool *aaaaaaaaaaaaaaaaaa, bool *aa) {}"); + " bool* aaaaaaaaaaaaaaaaaa, bool* aa) {}"); verifyGoogleFormat("template <typename T>\n" "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\n" "aaaaaaaaaaaaaaaaaaaaaaa<T>::aaaaaaaaaaaaa(\n" @@ -12915,27 +12915,31 @@ TEST_F(FormatTest, UnderstandsEllipsis) { } TEST_F(FormatTest, AdaptivelyFormatsPointersAndReferences) { + auto Style = getGoogleStyle(); + EXPECT_FALSE(Style.DerivePointerAlignment); + Style.DerivePointerAlignment = true; + verifyFormat("int *a;\n" "int *a;\n" "int *a;", "int *a;\n" "int* a;\n" "int *a;", - getGoogleStyle()); + Style); verifyFormat("int* a;\n" "int* a;\n" "int* a;", "int* a;\n" "int* a;\n" "int *a;", - getGoogleStyle()); + Style); verifyFormat("int *a;\n" "int *a;\n" "int *a;", "int *a;\n" "int * a;\n" "int * a;", - getGoogleStyle()); + Style); verifyFormat("auto x = [] {\n" " int *a;\n" " int *a;\n" @@ -12944,7 +12948,7 @@ TEST_F(FormatTest, AdaptivelyFormatsPointersAndReferences) { "auto x=[]{int *a;\n" "int * a;\n" "int * a;};", - getGoogleStyle()); + Style); } TEST_F(FormatTest, UnderstandsRvalueReferences) { @@ -13080,7 +13084,7 @@ TEST_F(FormatTest, FormatsCasts) { verifyFormat("virtual void foo(char &) const;"); verifyFormat("virtual void foo(int *a, char *) const;"); verifyFormat("int a = sizeof(int *) + b;"); - verifyGoogleFormat("int a = alignof(int *) + b;"); + verifyGoogleFormat("int a = alignof(int*) + b;"); verifyFormat("bool b = f(g<int>) && c;"); verifyFormat("typedef void (*f)(int i) func;"); verifyFormat("void operator++(int) noexcept;"); @@ -25449,7 +25453,7 @@ TEST_F(FormatTest, AtomicQualifier) { verifyFormat("struct foo {\n" " int a1;\n" " _Atomic(a) a2;\n" - " _Atomic(_Atomic(int) *const) a3;\n" + " _Atomic(_Atomic(int)* const) a3;\n" "};", Google); verifyFormat("_Atomic(uint64_t) a;"); diff --git a/clang/unittests/Parse/ParseHLSLRootSignatureTest.cpp b/clang/unittests/Parse/ParseHLSLRootSignatureTest.cpp index 4b24800..4d08f8d 100644 --- a/clang/unittests/Parse/ParseHLSLRootSignatureTest.cpp +++ b/clang/unittests/Parse/ParseHLSLRootSignatureTest.cpp @@ -136,15 +136,13 @@ TEST_F(ParseHLSLRootSignatureTest, ValidParseEmptyTest) { TrivialModuleLoader ModLoader; auto PP = createPP(Source, ModLoader); - SmallVector<RootSignatureElement> Elements; - hlsl::RootSignatureParser Parser(RootSignatureVersion::V1_1, Elements, - Signature, *PP); + hlsl::RootSignatureParser Parser(RootSignatureVersion::V1_1, Signature, *PP); // Test no diagnostics produced Consumer->setNoDiag(); ASSERT_FALSE(Parser.parse()); - ASSERT_EQ((int)Elements.size(), 0); + ASSERT_EQ((int)Parser.getElements().size(), 0); ASSERT_TRUE(Consumer->isSatisfied()); } @@ -172,15 +170,14 @@ TEST_F(ParseHLSLRootSignatureTest, ValidParseDTClausesTest) { TrivialModuleLoader ModLoader; auto PP = createPP(Source, ModLoader); - SmallVector<RootSignatureElement> Elements; - hlsl::RootSignatureParser Parser(RootSignatureVersion::V1_1, Elements, - Signature, *PP); + hlsl::RootSignatureParser Parser(RootSignatureVersion::V1_1, Signature, *PP); // Test no diagnostics produced Consumer->setNoDiag(); ASSERT_FALSE(Parser.parse()); + auto Elements = Parser.getElements(); // First Descriptor Table with 4 elements RootElement Elem = Elements[0].getElement(); ASSERT_TRUE(std::holds_alternative<DescriptorTableClause>(Elem)); @@ -277,15 +274,14 @@ TEST_F(ParseHLSLRootSignatureTest, ValidParseStaticSamplerTest) { TrivialModuleLoader ModLoader; auto PP = createPP(Source, ModLoader); - SmallVector<RootSignatureElement> Elements; - hlsl::RootSignatureParser Parser(RootSignatureVersion::V1_1, Elements, - Signature, *PP); + hlsl::RootSignatureParser Parser(RootSignatureVersion::V1_1, Signature, *PP); // Test no diagnostics produced Consumer->setNoDiag(); ASSERT_FALSE(Parser.parse()); + auto Elements = Parser.getElements(); ASSERT_EQ(Elements.size(), 2u); // Check default values are as expected @@ -364,15 +360,14 @@ TEST_F(ParseHLSLRootSignatureTest, ValidParseFloatsTest) { TrivialModuleLoader ModLoader; auto PP = createPP(Source, ModLoader); - SmallVector<RootSignatureElement> Elements; - hlsl::RootSignatureParser Parser(RootSignatureVersion::V1_1, Elements, - Signature, *PP); + hlsl::RootSignatureParser Parser(RootSignatureVersion::V1_1, Signature, *PP); // Test no diagnostics produced Consumer->setNoDiag(); ASSERT_FALSE(Parser.parse()); + auto Elements = Parser.getElements(); RootElement Elem = Elements[0].getElement(); ASSERT_TRUE(std::holds_alternative<StaticSampler>(Elem)); ASSERT_FLOAT_EQ(std::get<StaticSampler>(Elem).MipLODBias, 0.f); @@ -441,15 +436,14 @@ TEST_F(ParseHLSLRootSignatureTest, ValidSamplerFlagsTest) { TrivialModuleLoader ModLoader; auto PP = createPP(Source, ModLoader); - SmallVector<RootSignatureElement> Elements; - hlsl::RootSignatureParser Parser(RootSignatureVersion::V1_1, Elements, - Signature, *PP); + hlsl::RootSignatureParser Parser(RootSignatureVersion::V1_1, Signature, *PP); // Test no diagnostics produced Consumer->setNoDiag(); ASSERT_FALSE(Parser.parse()); + auto Elements = Parser.getElements(); RootElement Elem = Elements[0].getElement(); ASSERT_TRUE(std::holds_alternative<DescriptorTableClause>(Elem)); ASSERT_EQ(std::get<DescriptorTableClause>(Elem).Type, ClauseType::Sampler); @@ -474,15 +468,14 @@ TEST_F(ParseHLSLRootSignatureTest, ValidParseRootConsantsTest) { TrivialModuleLoader ModLoader; auto PP = createPP(Source, ModLoader); - SmallVector<RootSignatureElement> Elements; - hlsl::RootSignatureParser Parser(RootSignatureVersion::V1_1, Elements, - Signature, *PP); + hlsl::RootSignatureParser Parser(RootSignatureVersion::V1_1, Signature, *PP); // Test no diagnostics produced Consumer->setNoDiag(); ASSERT_FALSE(Parser.parse()); + auto Elements = Parser.getElements(); ASSERT_EQ(Elements.size(), 2u); RootElement Elem = Elements[0].getElement(); @@ -533,15 +526,14 @@ TEST_F(ParseHLSLRootSignatureTest, ValidParseRootFlagsTest) { TrivialModuleLoader ModLoader; auto PP = createPP(Source, ModLoader); - SmallVector<RootSignatureElement> Elements; - hlsl::RootSignatureParser Parser(RootSignatureVersion::V1_1, Elements, - Signature, *PP); + hlsl::RootSignatureParser Parser(RootSignatureVersion::V1_1, Signature, *PP); // Test no diagnostics produced Consumer->setNoDiag(); ASSERT_FALSE(Parser.parse()); + auto Elements = Parser.getElements(); ASSERT_EQ(Elements.size(), 3u); RootElement Elem = Elements[0].getElement(); @@ -588,15 +580,14 @@ TEST_F(ParseHLSLRootSignatureTest, ValidParseRootDescriptorsTest) { TrivialModuleLoader ModLoader; auto PP = createPP(Source, ModLoader); - SmallVector<RootSignatureElement> Elements; - hlsl::RootSignatureParser Parser(RootSignatureVersion::V1_1, Elements, - Signature, *PP); + hlsl::RootSignatureParser Parser(RootSignatureVersion::V1_1, Signature, *PP); // Test no diagnostics produced Consumer->setNoDiag(); ASSERT_FALSE(Parser.parse()); + auto Elements = Parser.getElements(); ASSERT_EQ(Elements.size(), 4u); RootElement Elem = Elements[0].getElement(); @@ -664,9 +655,7 @@ TEST_F(ParseHLSLRootSignatureTest, ValidTrailingCommaTest) { TrivialModuleLoader ModLoader; auto PP = createPP(Source, ModLoader); - SmallVector<RootSignatureElement> Elements; - hlsl::RootSignatureParser Parser(RootSignatureVersion::V1_1, Elements, - Signature, *PP); + hlsl::RootSignatureParser Parser(RootSignatureVersion::V1_1, Signature, *PP); // Test no diagnostics produced Consumer->setNoDiag(); @@ -697,15 +686,14 @@ TEST_F(ParseHLSLRootSignatureTest, ValidVersion10Test) { TrivialModuleLoader ModLoader; auto PP = createPP(Source, ModLoader); - SmallVector<RootSignatureElement> Elements; - hlsl::RootSignatureParser Parser(RootSignatureVersion::V1_0, Elements, - Signature, *PP); + hlsl::RootSignatureParser Parser(RootSignatureVersion::V1_0, Signature, *PP); // Test no diagnostics produced Consumer->setNoDiag(); ASSERT_FALSE(Parser.parse()); + auto Elements = Parser.getElements(); auto DefRootDescriptorFlag = llvm::dxbc::RootDescriptorFlags::DataVolatile; RootElement Elem = Elements[0].getElement(); ASSERT_TRUE(std::holds_alternative<RootDescriptor>(Elem)); @@ -770,15 +758,14 @@ TEST_F(ParseHLSLRootSignatureTest, ValidVersion11Test) { TrivialModuleLoader ModLoader; auto PP = createPP(Source, ModLoader); - SmallVector<RootSignatureElement> Elements; - hlsl::RootSignatureParser Parser(RootSignatureVersion::V1_1, Elements, - Signature, *PP); + hlsl::RootSignatureParser Parser(RootSignatureVersion::V1_1, Signature, *PP); // Test no diagnostics produced Consumer->setNoDiag(); ASSERT_FALSE(Parser.parse()); + auto Elements = Parser.getElements(); RootElement Elem = Elements[0].getElement(); ASSERT_TRUE(std::holds_alternative<RootDescriptor>(Elem)); ASSERT_EQ(std::get<RootDescriptor>(Elem).Type, DescriptorType::CBuffer); @@ -838,9 +825,7 @@ TEST_F(ParseHLSLRootSignatureTest, InvalidParseUnexpectedTokenTest) { TrivialModuleLoader ModLoader; auto PP = createPP(Source, ModLoader); - SmallVector<RootSignatureElement> Elements; - hlsl::RootSignatureParser Parser(RootSignatureVersion::V1_1, Elements, - Signature, *PP); + hlsl::RootSignatureParser Parser(RootSignatureVersion::V1_1, Signature, *PP); // Test correct diagnostic produced Consumer->setExpected(diag::err_expected_either); @@ -860,9 +845,7 @@ TEST_F(ParseHLSLRootSignatureTest, InvalidParseInvalidTokenTest) { TrivialModuleLoader ModLoader; auto PP = createPP(Source, ModLoader); - SmallVector<RootSignatureElement> Elements; - hlsl::RootSignatureParser Parser(RootSignatureVersion::V1_1, Elements, - Signature, *PP); + hlsl::RootSignatureParser Parser(RootSignatureVersion::V1_1, Signature, *PP); // Test correct diagnostic produced - invalid token Consumer->setExpected(diag::err_hlsl_invalid_token); @@ -882,9 +865,7 @@ TEST_F(ParseHLSLRootSignatureTest, InvalidParseUnexpectedEndOfStreamTest) { TrivialModuleLoader ModLoader; auto PP = createPP(Source, ModLoader); - SmallVector<RootSignatureElement> Elements; - hlsl::RootSignatureParser Parser(RootSignatureVersion::V1_1, Elements, - Signature, *PP); + hlsl::RootSignatureParser Parser(RootSignatureVersion::V1_1, Signature, *PP); // Test correct diagnostic produced - expected '(' after DescriptorTable Consumer->setExpected(diag::err_expected_after); @@ -909,9 +890,7 @@ TEST_F(ParseHLSLRootSignatureTest, InvalidMissingDTParameterTest) { TrivialModuleLoader ModLoader; auto PP = createPP(Source, ModLoader); - SmallVector<RootSignatureElement> Elements; - hlsl::RootSignatureParser Parser(RootSignatureVersion::V1_1, Elements, - Signature, *PP); + hlsl::RootSignatureParser Parser(RootSignatureVersion::V1_1, Signature, *PP); // Test correct diagnostic produced Consumer->setExpected(diag::err_hlsl_rootsig_missing_param); @@ -933,9 +912,7 @@ TEST_F(ParseHLSLRootSignatureTest, InvalidMissingRDParameterTest) { TrivialModuleLoader ModLoader; auto PP = createPP(Source, ModLoader); - SmallVector<RootSignatureElement> Elements; - hlsl::RootSignatureParser Parser(RootSignatureVersion::V1_1, Elements, - Signature, *PP); + hlsl::RootSignatureParser Parser(RootSignatureVersion::V1_1, Signature, *PP); // Test correct diagnostic produced Consumer->setExpected(diag::err_hlsl_rootsig_missing_param); @@ -957,9 +934,7 @@ TEST_F(ParseHLSLRootSignatureTest, InvalidMissingRCParameterTest) { TrivialModuleLoader ModLoader; auto PP = createPP(Source, ModLoader); - SmallVector<RootSignatureElement> Elements; - hlsl::RootSignatureParser Parser(RootSignatureVersion::V1_1, Elements, - Signature, *PP); + hlsl::RootSignatureParser Parser(RootSignatureVersion::V1_1, Signature, *PP); // Test correct diagnostic produced Consumer->setExpected(diag::err_hlsl_rootsig_missing_param); @@ -983,9 +958,7 @@ TEST_F(ParseHLSLRootSignatureTest, InvalidRepeatedMandatoryDTParameterTest) { TrivialModuleLoader ModLoader; auto PP = createPP(Source, ModLoader); - SmallVector<RootSignatureElement> Elements; - hlsl::RootSignatureParser Parser(RootSignatureVersion::V1_1, Elements, - Signature, *PP); + hlsl::RootSignatureParser Parser(RootSignatureVersion::V1_1, Signature, *PP); // Test correct diagnostic produced Consumer->setExpected(diag::err_hlsl_rootsig_repeat_param); @@ -1007,9 +980,7 @@ TEST_F(ParseHLSLRootSignatureTest, InvalidRepeatedMandatoryRCParameterTest) { TrivialModuleLoader ModLoader; auto PP = createPP(Source, ModLoader); - SmallVector<RootSignatureElement> Elements; - hlsl::RootSignatureParser Parser(RootSignatureVersion::V1_1, Elements, - Signature, *PP); + hlsl::RootSignatureParser Parser(RootSignatureVersion::V1_1, Signature, *PP); // Test correct diagnostic produced Consumer->setExpected(diag::err_hlsl_rootsig_repeat_param); @@ -1033,9 +1004,7 @@ TEST_F(ParseHLSLRootSignatureTest, InvalidRepeatedOptionalDTParameterTest) { TrivialModuleLoader ModLoader; auto PP = createPP(Source, ModLoader); - SmallVector<RootSignatureElement> Elements; - hlsl::RootSignatureParser Parser(RootSignatureVersion::V1_1, Elements, - Signature, *PP); + hlsl::RootSignatureParser Parser(RootSignatureVersion::V1_1, Signature, *PP); // Test correct diagnostic produced Consumer->setExpected(diag::err_hlsl_rootsig_repeat_param); @@ -1061,9 +1030,7 @@ TEST_F(ParseHLSLRootSignatureTest, InvalidRepeatedOptionalRCParameterTest) { TrivialModuleLoader ModLoader; auto PP = createPP(Source, ModLoader); - SmallVector<RootSignatureElement> Elements; - hlsl::RootSignatureParser Parser(RootSignatureVersion::V1_1, Elements, - Signature, *PP); + hlsl::RootSignatureParser Parser(RootSignatureVersion::V1_1, Signature, *PP); // Test correct diagnostic produced Consumer->setExpected(diag::err_hlsl_rootsig_repeat_param); @@ -1086,9 +1053,7 @@ TEST_F(ParseHLSLRootSignatureTest, InvalidLexOverflowedNumberTest) { TrivialModuleLoader ModLoader; auto PP = createPP(Source, ModLoader); - SmallVector<RootSignatureElement> Elements; - hlsl::RootSignatureParser Parser(RootSignatureVersion::V1_1, Elements, - Signature, *PP); + hlsl::RootSignatureParser Parser(RootSignatureVersion::V1_1, Signature, *PP); // Test correct diagnostic produced Consumer->setExpected(diag::err_hlsl_number_literal_overflow); @@ -1110,9 +1075,7 @@ TEST_F(ParseHLSLRootSignatureTest, InvalidParseOverflowedNegativeNumberTest) { TrivialModuleLoader ModLoader; auto PP = createPP(Source, ModLoader); - SmallVector<RootSignatureElement> Elements; - hlsl::RootSignatureParser Parser(RootSignatureVersion::V1_1, Elements, - Signature, *PP); + hlsl::RootSignatureParser Parser(RootSignatureVersion::V1_1, Signature, *PP); // Test correct diagnostic produced Consumer->setExpected(diag::err_hlsl_number_literal_overflow); @@ -1133,9 +1096,7 @@ TEST_F(ParseHLSLRootSignatureTest, InvalidLexOverflowedFloatTest) { TrivialModuleLoader ModLoader; auto PP = createPP(Source, ModLoader); - SmallVector<RootSignatureElement> Elements; - hlsl::RootSignatureParser Parser(RootSignatureVersion::V1_1, Elements, - Signature, *PP); + hlsl::RootSignatureParser Parser(RootSignatureVersion::V1_1, Signature, *PP); // Test correct diagnostic produced Consumer->setExpected(diag::err_hlsl_number_literal_overflow); @@ -1156,9 +1117,7 @@ TEST_F(ParseHLSLRootSignatureTest, InvalidLexNegOverflowedFloatTest) { TrivialModuleLoader ModLoader; auto PP = createPP(Source, ModLoader); - SmallVector<RootSignatureElement> Elements; - hlsl::RootSignatureParser Parser(RootSignatureVersion::V1_1, Elements, - Signature, *PP); + hlsl::RootSignatureParser Parser(RootSignatureVersion::V1_1, Signature, *PP); // Test correct diagnostic produced Consumer->setExpected(diag::err_hlsl_number_literal_overflow); @@ -1179,9 +1138,7 @@ TEST_F(ParseHLSLRootSignatureTest, InvalidLexOverflowedDoubleTest) { TrivialModuleLoader ModLoader; auto PP = createPP(Source, ModLoader); - SmallVector<RootSignatureElement> Elements; - hlsl::RootSignatureParser Parser(RootSignatureVersion::V1_1, Elements, - Signature, *PP); + hlsl::RootSignatureParser Parser(RootSignatureVersion::V1_1, Signature, *PP); // Test correct diagnostic produced Consumer->setExpected(diag::err_hlsl_number_literal_overflow); @@ -1202,9 +1159,7 @@ TEST_F(ParseHLSLRootSignatureTest, InvalidLexUnderflowFloatTest) { TrivialModuleLoader ModLoader; auto PP = createPP(Source, ModLoader); - SmallVector<RootSignatureElement> Elements; - hlsl::RootSignatureParser Parser(RootSignatureVersion::V1_1, Elements, - Signature, *PP); + hlsl::RootSignatureParser Parser(RootSignatureVersion::V1_1, Signature, *PP); // Test correct diagnostic produced Consumer->setExpected(diag::err_hlsl_number_literal_underflow); @@ -1228,9 +1183,7 @@ TEST_F(ParseHLSLRootSignatureTest, InvalidNonZeroFlagsTest) { TrivialModuleLoader ModLoader; auto PP = createPP(Source, ModLoader); - SmallVector<RootSignatureElement> Elements; - hlsl::RootSignatureParser Parser(RootSignatureVersion::V1_1, Elements, - Signature, *PP); + hlsl::RootSignatureParser Parser(RootSignatureVersion::V1_1, Signature, *PP); // Test correct diagnostic produced Consumer->setExpected(diag::err_hlsl_rootsig_non_zero_flag); @@ -1253,9 +1206,7 @@ TEST_F(ParseHLSLRootSignatureTest, InvalidRootElementMissingCommaTest) { TrivialModuleLoader ModLoader; auto PP = createPP(Source, ModLoader); - SmallVector<RootSignatureElement> Elements; - hlsl::RootSignatureParser Parser(RootSignatureVersion::V1_1, Elements, - Signature, *PP); + hlsl::RootSignatureParser Parser(RootSignatureVersion::V1_1, Signature, *PP); // Test correct diagnostic produced Consumer->setExpected(diag::err_expected_either); @@ -1280,9 +1231,7 @@ TEST_F(ParseHLSLRootSignatureTest, InvalidDescriptorTableMissingCommaTest) { TrivialModuleLoader ModLoader; auto PP = createPP(Source, ModLoader); - SmallVector<RootSignatureElement> Elements; - hlsl::RootSignatureParser Parser(RootSignatureVersion::V1_1, Elements, - Signature, *PP); + hlsl::RootSignatureParser Parser(RootSignatureVersion::V1_1, Signature, *PP); // Test correct diagnostic produced Consumer->setExpected(diag::err_expected_either); @@ -1307,9 +1256,7 @@ TEST_F(ParseHLSLRootSignatureTest, InvalidRootConstantParamsCommaTest) { TrivialModuleLoader ModLoader; auto PP = createPP(Source, ModLoader); - SmallVector<RootSignatureElement> Elements; - hlsl::RootSignatureParser Parser(RootSignatureVersion::V1_1, Elements, - Signature, *PP); + hlsl::RootSignatureParser Parser(RootSignatureVersion::V1_1, Signature, *PP); // Test correct diagnostic produced Consumer->setExpected(diag::err_expected_either); @@ -1334,9 +1281,7 @@ TEST_F(ParseHLSLRootSignatureTest, InvalidRootDescriptorParamsCommaTest) { TrivialModuleLoader ModLoader; auto PP = createPP(Source, ModLoader); - SmallVector<RootSignatureElement> Elements; - hlsl::RootSignatureParser Parser(RootSignatureVersion::V1_1, Elements, - Signature, *PP); + hlsl::RootSignatureParser Parser(RootSignatureVersion::V1_1, Signature, *PP); // Test correct diagnostic produced Consumer->setExpected(diag::err_expected_either); @@ -1363,9 +1308,7 @@ TEST_F(ParseHLSLRootSignatureTest, InvalidDescriptorClauseParamsCommaTest) { TrivialModuleLoader ModLoader; auto PP = createPP(Source, ModLoader); - SmallVector<RootSignatureElement> Elements; - hlsl::RootSignatureParser Parser(RootSignatureVersion::V1_1, Elements, - Signature, *PP); + hlsl::RootSignatureParser Parser(RootSignatureVersion::V1_1, Signature, *PP); // Test correct diagnostic produced Consumer->setExpected(diag::err_expected_either); @@ -1390,9 +1333,7 @@ TEST_F(ParseHLSLRootSignatureTest, InvalidStaticSamplerCommaTest) { TrivialModuleLoader ModLoader; auto PP = createPP(Source, ModLoader); - SmallVector<RootSignatureElement> Elements; - hlsl::RootSignatureParser Parser(RootSignatureVersion::V1_1, Elements, - Signature, *PP); + hlsl::RootSignatureParser Parser(RootSignatureVersion::V1_1, Signature, *PP); // Test correct diagnostic produced Consumer->setExpected(diag::err_expected_either); @@ -1414,9 +1355,7 @@ TEST_F(ParseHLSLRootSignatureTest, InvalidRootDescriptorParamTest) { TrivialModuleLoader ModLoader; auto PP = createPP(Source, ModLoader); - SmallVector<RootSignatureElement> Elements; - hlsl::RootSignatureParser Parser(RootSignatureVersion::V1_1, Elements, - Signature, *PP); + hlsl::RootSignatureParser Parser(RootSignatureVersion::V1_1, Signature, *PP); // Test correct diagnostic produced Consumer->setExpected(diag::err_hlsl_invalid_token); @@ -1441,9 +1380,7 @@ TEST_F(ParseHLSLRootSignatureTest, InvalidDescriptorTableParamTest) { TrivialModuleLoader ModLoader; auto PP = createPP(Source, ModLoader); - SmallVector<RootSignatureElement> Elements; - hlsl::RootSignatureParser Parser(RootSignatureVersion::V1_1, Elements, - Signature, *PP); + hlsl::RootSignatureParser Parser(RootSignatureVersion::V1_1, Signature, *PP); // Test correct diagnostic produced Consumer->setExpected(diag::err_hlsl_invalid_token); @@ -1467,9 +1404,7 @@ TEST_F(ParseHLSLRootSignatureTest, InvalidDescriptorTableClauseParamTest) { TrivialModuleLoader ModLoader; auto PP = createPP(Source, ModLoader); - SmallVector<RootSignatureElement> Elements; - hlsl::RootSignatureParser Parser(RootSignatureVersion::V1_1, Elements, - Signature, *PP); + hlsl::RootSignatureParser Parser(RootSignatureVersion::V1_1, Signature, *PP); // Test correct diagnostic produced Consumer->setExpected(diag::err_hlsl_invalid_token); @@ -1496,9 +1431,7 @@ TEST_F(ParseHLSLRootSignatureTest, InvalidStaticSamplerParamTest) { TrivialModuleLoader ModLoader; auto PP = createPP(Source, ModLoader); - SmallVector<RootSignatureElement> Elements; - hlsl::RootSignatureParser Parser(RootSignatureVersion::V1_1, Elements, - Signature, *PP); + hlsl::RootSignatureParser Parser(RootSignatureVersion::V1_1, Signature, *PP); // Test correct diagnostic produced Consumer->setExpected(diag::err_hlsl_invalid_token); @@ -1523,9 +1456,7 @@ TEST_F(ParseHLSLRootSignatureTest, InvalidVisibilityValueTest) { TrivialModuleLoader ModLoader; auto PP = createPP(Source, ModLoader); - SmallVector<RootSignatureElement> Elements; - hlsl::RootSignatureParser Parser(RootSignatureVersion::V1_1, Elements, - Signature, *PP); + hlsl::RootSignatureParser Parser(RootSignatureVersion::V1_1, Signature, *PP); // Test correct diagnostic produced Consumer->setExpected(diag::err_hlsl_invalid_token); @@ -1549,9 +1480,7 @@ TEST_F(ParseHLSLRootSignatureTest, InvalidRegisterValueTest) { TrivialModuleLoader ModLoader; auto PP = createPP(Source, ModLoader); - SmallVector<RootSignatureElement> Elements; - hlsl::RootSignatureParser Parser(RootSignatureVersion::V1_1, Elements, - Signature, *PP); + hlsl::RootSignatureParser Parser(RootSignatureVersion::V1_1, Signature, *PP); // Test correct diagnostic produced Consumer->setExpected(diag::err_hlsl_invalid_token); @@ -1576,9 +1505,7 @@ TEST_F(ParseHLSLRootSignatureTest, InvalidFilterValueTest) { TrivialModuleLoader ModLoader; auto PP = createPP(Source, ModLoader); - SmallVector<RootSignatureElement> Elements; - hlsl::RootSignatureParser Parser(RootSignatureVersion::V1_1, Elements, - Signature, *PP); + hlsl::RootSignatureParser Parser(RootSignatureVersion::V1_1, Signature, *PP); // Test correct diagnostic produced Consumer->setExpected(diag::err_hlsl_invalid_token); @@ -1603,9 +1530,7 @@ TEST_F(ParseHLSLRootSignatureTest, InvalidTextureAddressModeValueTest) { TrivialModuleLoader ModLoader; auto PP = createPP(Source, ModLoader); - SmallVector<RootSignatureElement> Elements; - hlsl::RootSignatureParser Parser(RootSignatureVersion::V1_1, Elements, - Signature, *PP); + hlsl::RootSignatureParser Parser(RootSignatureVersion::V1_1, Signature, *PP); // Test correct diagnostic produced Consumer->setExpected(diag::err_hlsl_invalid_token); @@ -1630,9 +1555,7 @@ TEST_F(ParseHLSLRootSignatureTest, InvalidComparisonFuncValueTest) { TrivialModuleLoader ModLoader; auto PP = createPP(Source, ModLoader); - SmallVector<RootSignatureElement> Elements; - hlsl::RootSignatureParser Parser(RootSignatureVersion::V1_1, Elements, - Signature, *PP); + hlsl::RootSignatureParser Parser(RootSignatureVersion::V1_1, Signature, *PP); // Test correct diagnostic produced Consumer->setExpected(diag::err_hlsl_invalid_token); @@ -1657,9 +1580,7 @@ TEST_F(ParseHLSLRootSignatureTest, InvalidStaticBorderColorValueTest) { TrivialModuleLoader ModLoader; auto PP = createPP(Source, ModLoader); - SmallVector<RootSignatureElement> Elements; - hlsl::RootSignatureParser Parser(RootSignatureVersion::V1_1, Elements, - Signature, *PP); + hlsl::RootSignatureParser Parser(RootSignatureVersion::V1_1, Signature, *PP); // Test correct diagnostic produced Consumer->setExpected(diag::err_hlsl_invalid_token); @@ -1681,9 +1602,7 @@ TEST_F(ParseHLSLRootSignatureTest, InvalidRootFlagsValueTest) { TrivialModuleLoader ModLoader; auto PP = createPP(Source, ModLoader); - SmallVector<RootSignatureElement> Elements; - hlsl::RootSignatureParser Parser(RootSignatureVersion::V1_1, Elements, - Signature, *PP); + hlsl::RootSignatureParser Parser(RootSignatureVersion::V1_1, Signature, *PP); // Test correct diagnostic produced Consumer->setExpected(diag::err_hlsl_invalid_token); @@ -1705,9 +1624,7 @@ TEST_F(ParseHLSLRootSignatureTest, InvalidRootDescriptorFlagsValueTest) { TrivialModuleLoader ModLoader; auto PP = createPP(Source, ModLoader); - SmallVector<RootSignatureElement> Elements; - hlsl::RootSignatureParser Parser(RootSignatureVersion::V1_1, Elements, - Signature, *PP); + hlsl::RootSignatureParser Parser(RootSignatureVersion::V1_1, Signature, *PP); // Test correct diagnostic produced Consumer->setExpected(diag::err_hlsl_invalid_token); @@ -1733,9 +1650,7 @@ TEST_F(ParseHLSLRootSignatureTest, InvalidDescriptorRangeFlagsValueTest) { TrivialModuleLoader ModLoader; auto PP = createPP(Source, ModLoader); - SmallVector<RootSignatureElement> Elements; - hlsl::RootSignatureParser Parser(RootSignatureVersion::V1_1, Elements, - Signature, *PP); + hlsl::RootSignatureParser Parser(RootSignatureVersion::V1_1, Signature, *PP); // Test correct diagnostic produced Consumer->setExpected(diag::err_hlsl_invalid_token); |