Vendor import of clang trunk r300422:
https://llvm.org/svn/llvm-project/cfe/trunk@300422
This commit is contained in:
parent
7789b5ee78
commit
d6b76b4ff7
@ -82,6 +82,7 @@ if( CMAKE_SOURCE_DIR STREQUAL CMAKE_CURRENT_SOURCE_DIR )
|
||||
set(LLVM_SHLIB_OUTPUT_INTDIR ${LLVM_LIBRARY_OUTPUT_INTDIR})
|
||||
endif()
|
||||
|
||||
option(LLVM_ENABLE_WARNINGS "Enable compiler warnings." ON)
|
||||
option(LLVM_INSTALL_TOOLCHAIN_ONLY
|
||||
"Only include toolchain files in the 'install' target." OFF)
|
||||
|
||||
@ -185,6 +186,8 @@ if (LIBXML2_FOUND)
|
||||
set(CLANG_HAVE_LIBXML 1)
|
||||
endif()
|
||||
|
||||
find_package(Z3 4.5)
|
||||
|
||||
include(CheckIncludeFile)
|
||||
check_include_file(sys/resource.h CLANG_HAVE_RLIMITS)
|
||||
|
||||
@ -329,10 +332,6 @@ if (APPLE)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
configure_file(
|
||||
${CLANG_SOURCE_DIR}/include/clang/Config/config.h.cmake
|
||||
${CLANG_BINARY_DIR}/include/clang/Config/config.h)
|
||||
|
||||
include(CMakeParseArguments)
|
||||
include(AddClang)
|
||||
|
||||
@ -368,21 +367,21 @@ option(CLANG_BUILD_TOOLS
|
||||
"Build the Clang tools. If OFF, just generate build targets." ON)
|
||||
|
||||
option(CLANG_ENABLE_ARCMT "Build ARCMT." ON)
|
||||
if (CLANG_ENABLE_ARCMT)
|
||||
set(ENABLE_CLANG_ARCMT "1")
|
||||
else()
|
||||
set(ENABLE_CLANG_ARCMT "0")
|
||||
endif()
|
||||
|
||||
option(CLANG_ENABLE_STATIC_ANALYZER "Build static analyzer." ON)
|
||||
if (CLANG_ENABLE_STATIC_ANALYZER)
|
||||
set(ENABLE_CLANG_STATIC_ANALYZER "1")
|
||||
else()
|
||||
set(ENABLE_CLANG_STATIC_ANALYZER "0")
|
||||
|
||||
option(CLANG_ANALYZER_BUILD_Z3
|
||||
"Build the static analyzer with the Z3 constraint manager." OFF)
|
||||
|
||||
if(NOT CLANG_ENABLE_STATIC_ANALYZER AND (CLANG_ENABLE_ARCMT OR CLANG_ANALYZER_BUILD_Z3))
|
||||
message(FATAL_ERROR "Cannot disable static analyzer while enabling ARCMT or Z3")
|
||||
endif()
|
||||
|
||||
if (NOT CLANG_ENABLE_STATIC_ANALYZER AND CLANG_ENABLE_ARCMT)
|
||||
message(FATAL_ERROR "Cannot disable static analyzer while enabling ARCMT")
|
||||
if(CLANG_ANALYZER_BUILD_Z3)
|
||||
if(Z3_FOUND)
|
||||
set(CLANG_ANALYZER_WITH_Z3 1)
|
||||
else()
|
||||
message(FATAL_ERROR "Cannot find Z3 header file or shared library")
|
||||
endif()
|
||||
endif()
|
||||
|
||||
if(CLANG_ENABLE_ARCMT)
|
||||
@ -419,11 +418,6 @@ add_subdirectory(tools)
|
||||
add_subdirectory(runtime)
|
||||
|
||||
option(CLANG_BUILD_EXAMPLES "Build CLANG example programs by default." OFF)
|
||||
if (CLANG_BUILD_EXAMPLES)
|
||||
set(ENABLE_CLANG_EXAMPLES "1")
|
||||
else()
|
||||
set(ENABLE_CLANG_EXAMPLES "0")
|
||||
endif()
|
||||
add_subdirectory(examples)
|
||||
|
||||
if(APPLE)
|
||||
@ -519,6 +513,10 @@ if (CLANG_ENABLE_BOOTSTRAP)
|
||||
set(STAMP_DIR ${CMAKE_CURRENT_BINARY_DIR}/${NEXT_CLANG_STAGE}-stamps/)
|
||||
set(BINARY_DIR ${CMAKE_CURRENT_BINARY_DIR}/${NEXT_CLANG_STAGE}-bins/)
|
||||
|
||||
if(BOOTSTRAP_LLVM_ENABLE_LLD)
|
||||
add_dependencies(clang-bootstrap-deps lld)
|
||||
endif()
|
||||
|
||||
# If the next stage is LTO we need to depend on LTO and possibly lld or LLVMgold
|
||||
if(BOOTSTRAP_LLVM_ENABLE_LTO OR LLVM_ENABLE_LTO AND NOT LLVM_BUILD_INSTRUMENTED)
|
||||
if(APPLE)
|
||||
@ -535,9 +533,7 @@ if (CLANG_ENABLE_BOOTSTRAP)
|
||||
-DDYLD_LIBRARY_PATH=${LLVM_LIBRARY_OUTPUT_INTDIR})
|
||||
elseif(NOT WIN32)
|
||||
add_dependencies(clang-bootstrap-deps llvm-ar llvm-ranlib)
|
||||
if(BOOTSTRAP_LLVM_ENABLE_LLD)
|
||||
add_dependencies(clang-bootstrap-deps lld)
|
||||
elseif(LLVM_BINUTILS_INCDIR)
|
||||
if(NOT BOOTSTRAP_LLVM_ENABLE_LLD AND LLVM_BINUTILS_INCDIR)
|
||||
add_dependencies(clang-bootstrap-deps LLVMgold)
|
||||
endif()
|
||||
set(LTO_AR -DCMAKE_AR=${LLVM_RUNTIME_OUTPUT_INTDIR}/llvm-ar)
|
||||
@ -700,3 +696,7 @@ endif()
|
||||
if (LLVM_ADD_NATIVE_VISUALIZERS_TO_SOLUTION)
|
||||
add_subdirectory(utils/ClangVisualizers)
|
||||
endif()
|
||||
|
||||
configure_file(
|
||||
${CLANG_SOURCE_DIR}/include/clang/Config/config.h.cmake
|
||||
${CLANG_BINARY_DIR}/include/clang/Config/config.h)
|
||||
|
@ -1887,6 +1887,7 @@ def __repr__(self):
|
||||
TypeKind.OBJCCLASS = TypeKind(28)
|
||||
TypeKind.OBJCSEL = TypeKind(29)
|
||||
TypeKind.FLOAT128 = TypeKind(30)
|
||||
TypeKind.HALF = TypeKind(31)
|
||||
TypeKind.COMPLEX = TypeKind(100)
|
||||
TypeKind.POINTER = TypeKind(101)
|
||||
TypeKind.BLOCKPOINTER = TypeKind(102)
|
||||
|
6
cmake/caches/Apple-stage2-ThinLTO.cmake
Normal file
6
cmake/caches/Apple-stage2-ThinLTO.cmake
Normal file
@ -0,0 +1,6 @@
|
||||
# This file sets up a CMakeCache for Apple-style stage2 ThinLTO bootstrap. It is
|
||||
# specified by the stage1 build.
|
||||
|
||||
|
||||
set(LLVM_ENABLE_LTO THIN CACHE BOOL "")
|
||||
include(${CMAKE_CURRENT_LIST_DIR}/Apple-stage2.cmake)
|
66
cmake/caches/Fuchsia-stage2.cmake
Normal file
66
cmake/caches/Fuchsia-stage2.cmake
Normal file
@ -0,0 +1,66 @@
|
||||
# This file sets up a CMakeCache for the second stage of a Fuchsia toolchain
|
||||
# build.
|
||||
|
||||
set(LLVM_TARGETS_TO_BUILD X86;AArch64 CACHE STRING "")
|
||||
|
||||
set(PACKAGE_VENDOR Fuchsia CACHE STRING "")
|
||||
|
||||
set(LLVM_INCLUDE_EXAMPLES OFF CACHE BOOL "")
|
||||
set(LLVM_INCLUDE_DOCS OFF CACHE BOOL "")
|
||||
set(LLVM_TOOL_CLANG_TOOLS_EXTRA_BUILD OFF CACHE BOOL "")
|
||||
set(LLVM_ENABLE_ZLIB ON CACHE BOOL "")
|
||||
set(LLVM_ENABLE_BACKTRACES OFF CACHE BOOL "")
|
||||
set(LLVM_EXTERNALIZE_DEBUGINFO ON CACHE BOOL "")
|
||||
set(CLANG_PLUGIN_SUPPORT OFF CACHE BOOL "")
|
||||
|
||||
set(LLVM_ENABLE_LTO ON CACHE BOOL "")
|
||||
if(NOT APPLE)
|
||||
set(LLVM_ENABLE_LLD ON CACHE BOOL "")
|
||||
set(CLANG_DEFAULT_LINKER lld CACHE STRING "")
|
||||
endif()
|
||||
|
||||
if(APPLE)
|
||||
set(LLDB_CODESIGN_IDENTITY "" CACHE STRING "")
|
||||
endif()
|
||||
|
||||
set(CMAKE_BUILD_TYPE RelWithDebInfo CACHE STRING "")
|
||||
set(CMAKE_C_FLAGS_RELWITHDEBINFO "-O2 -gline-tables-only -DNDEBUG" CACHE STRING "")
|
||||
set(CMAKE_CXX_FLAGS_RELWITHDEBINFO "-O2 -gline-tables-only -DNDEBUG" CACHE STRING "")
|
||||
|
||||
set(LLVM_BUILTIN_TARGETS "x86_64-fuchsia-none;aarch64-fuchsia-none" CACHE STRING "")
|
||||
set(BUILTINS_x86_64-fuchsia-none_CMAKE_SYSROOT ${FUCHSIA_SYSROOT} CACHE STRING "")
|
||||
set(BUILTINS_x86_64-fuchsia-none_CMAKE_SYSTEM_NAME Fuchsia CACHE STRING "")
|
||||
set(BUILTINS_aarch64-fuchsia-none_CMAKE_SYSROOT ${FUCHSIA_SYSROOT} CACHE STRING "")
|
||||
set(BUILTINS_aarch64-fuchsia-none_CMAKE_SYSTEM_NAME Fuchsia CACHE STRING "")
|
||||
|
||||
# Setup toolchain.
|
||||
set(LLVM_INSTALL_TOOLCHAIN_ONLY ON CACHE BOOL "")
|
||||
set(LLVM_TOOLCHAIN_TOOLS
|
||||
llvm-ar
|
||||
llvm-cov
|
||||
llvm-cxxfilt
|
||||
llvm-dwarfdump
|
||||
llvm-dsymutil
|
||||
llvm-lib
|
||||
llvm-nm
|
||||
llvm-objdump
|
||||
llvm-profdata
|
||||
llvm-ranlib
|
||||
llvm-readobj
|
||||
llvm-size
|
||||
llvm-symbolizer
|
||||
CACHE STRING "")
|
||||
|
||||
set(LLVM_DISTRIBUTION_COMPONENTS
|
||||
clang
|
||||
lld
|
||||
lldb
|
||||
liblldb
|
||||
LTO
|
||||
clang-format
|
||||
clang-headers
|
||||
builtins-x86_64-fuchsia-none
|
||||
builtins-aarch64-fuchsia-none
|
||||
runtimes
|
||||
${LLVM_TOOLCHAIN_TOOLS}
|
||||
CACHE STRING "")
|
50
cmake/caches/Fuchsia.cmake
Normal file
50
cmake/caches/Fuchsia.cmake
Normal file
@ -0,0 +1,50 @@
|
||||
# This file sets up a CMakeCache for a Fuchsia toolchain build.
|
||||
|
||||
set(LLVM_TARGETS_TO_BUILD Native CACHE STRING "")
|
||||
|
||||
set(PACKAGE_VENDOR Fuchsia CACHE STRING "")
|
||||
|
||||
set(LLVM_INCLUDE_EXAMPLES OFF CACHE BOOL "")
|
||||
set(LLVM_INCLUDE_TESTS OFF CACHE BOOL "")
|
||||
set(LLVM_INCLUDE_DOCS OFF CACHE BOOL "")
|
||||
set(CLANG_INCLUDE_TESTS OFF CACHE BOOL "")
|
||||
set(LLVM_ENABLE_ZLIB OFF CACHE BOOL "")
|
||||
set(LLVM_ENABLE_BACKTRACES OFF CACHE BOOL "")
|
||||
set(CLANG_PLUGIN_SUPPORT OFF CACHE BOOL "")
|
||||
|
||||
set(CMAKE_BUILD_TYPE Release CACHE STRING "")
|
||||
|
||||
set(BOOTSTRAP_LLVM_ENABLE_LTO ON CACHE BOOL "")
|
||||
if(NOT APPLE)
|
||||
set(BOOTSTRAP_LLVM_ENABLE_LLD ON CACHE BOOL "")
|
||||
endif()
|
||||
|
||||
if(APPLE)
|
||||
set(COMPILER_RT_ENABLE_IOS OFF CACHE BOOL "")
|
||||
set(COMPILER_RT_ENABLE_TVOS OFF CACHE BOOL "")
|
||||
set(COMPILER_RT_ENABLE_WATCHOS OFF CACHE BOOL "")
|
||||
endif()
|
||||
|
||||
set(CLANG_BOOTSTRAP_TARGETS
|
||||
check-all
|
||||
check-llvm
|
||||
check-clang
|
||||
llvm-config
|
||||
test-suite
|
||||
test-depends
|
||||
llvm-test-depends
|
||||
clang-test-depends
|
||||
distribution
|
||||
install-distribution
|
||||
clang CACHE STRING "")
|
||||
|
||||
if(FUCHSIA_SYSROOT)
|
||||
set(EXTRA_ARGS -DFUCHSIA_SYSROOT=${FUCHSIA_SYSROOT})
|
||||
endif()
|
||||
|
||||
# Setup the bootstrap build.
|
||||
set(CLANG_ENABLE_BOOTSTRAP ON CACHE BOOL "")
|
||||
set(CLANG_BOOTSTRAP_CMAKE_ARGS
|
||||
${EXTRA_ARGS}
|
||||
-C ${CMAKE_CURRENT_LIST_DIR}/Fuchsia-stage2.cmake
|
||||
CACHE STRING "")
|
@ -4,17 +4,27 @@
|
||||
set(CLANG_INSTALL_PACKAGE_DIR lib${LLVM_LIBDIR_SUFFIX}/cmake/clang)
|
||||
set(clang_cmake_builddir "${CMAKE_BINARY_DIR}/${CLANG_INSTALL_PACKAGE_DIR}")
|
||||
|
||||
# Keep this in sync with llvm/cmake/CMakeLists.txt!
|
||||
set(LLVM_INSTALL_PACKAGE_DIR lib${LLVM_LIBDIR_SUFFIX}/cmake/llvm)
|
||||
set(llvm_cmake_builddir "${LLVM_BINARY_DIR}/${LLVM_INSTALL_PACKAGE_DIR}")
|
||||
|
||||
get_property(CLANG_EXPORTS GLOBAL PROPERTY CLANG_EXPORTS)
|
||||
export(TARGETS ${CLANG_EXPORTS} FILE ${clang_cmake_builddir}/ClangTargets.cmake)
|
||||
|
||||
# Generate ClangConfig.cmake for the build tree.
|
||||
set(CLANG_CONFIG_CMAKE_DIR "${clang_cmake_builddir}")
|
||||
set(CLANG_CONFIG_LLVM_CMAKE_DIR "${llvm_cmake_builddir}")
|
||||
set(CLANG_CONFIG_EXPORTS_FILE "${clang_cmake_builddir}/ClangTargets.cmake")
|
||||
set(CLANG_CONFIG_INCLUDE_DIRS
|
||||
"${CLANG_SOURCE_DIR}/include"
|
||||
"${CLANG_BINARY_DIR}/include"
|
||||
)
|
||||
configure_file(
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/ClangConfig.cmake.in
|
||||
${clang_cmake_builddir}/ClangConfig.cmake
|
||||
@ONLY)
|
||||
set(CLANG_CONFIG_CMAKE_DIR)
|
||||
set(CLANG_CONFIG_LLVM_CMAKE_DIR)
|
||||
set(CLANG_CONFIG_EXPORTS_FILE)
|
||||
|
||||
# Generate ClangConfig.cmake for the install tree.
|
||||
@ -29,7 +39,11 @@ foreach(p ${_count})
|
||||
get_filename_component(CLANG_INSTALL_PREFIX \"\${CLANG_INSTALL_PREFIX}\" PATH)")
|
||||
endforeach(p)
|
||||
set(CLANG_CONFIG_CMAKE_DIR "\${CLANG_INSTALL_PREFIX}/${CLANG_INSTALL_PACKAGE_DIR}")
|
||||
set(CLANG_CONFIG_LLVM_CMAKE_DIR "\${CLANG_INSTALL_PREFIX}/${LLVM_INSTALL_PACKAGE_DIR}")
|
||||
set(CLANG_CONFIG_EXPORTS_FILE "\${CLANG_CMAKE_DIR}/ClangTargets.cmake")
|
||||
set(CLANG_CONFIG_INCLUDE_DIRS
|
||||
"\${CLANG_INSTALL_PREFIX}/include"
|
||||
)
|
||||
configure_file(
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/ClangConfig.cmake.in
|
||||
${CMAKE_CURRENT_BINARY_DIR}/CMakeFiles/ClangConfig.cmake
|
||||
|
@ -1,11 +1,13 @@
|
||||
# This file allows users to call find_package(Clang) and pick up our targets.
|
||||
|
||||
find_package(LLVM REQUIRED CONFIG)
|
||||
|
||||
@CLANG_CONFIG_CODE@
|
||||
|
||||
find_package(LLVM REQUIRED CONFIG
|
||||
HINTS "@CLANG_CONFIG_LLVM_CMAKE_DIR@")
|
||||
|
||||
set(CLANG_EXPORTED_TARGETS "@CLANG_EXPORTS@")
|
||||
set(CLANG_CMAKE_DIR "@CLANG_CONFIG_CMAKE_DIR@")
|
||||
set(CLANG_INCLUDE_DIRS "@CLANG_CONFIG_INCLUDE_DIRS@")
|
||||
|
||||
# Provide all our library targets to users.
|
||||
include("@CLANG_CONFIG_EXPORTS_FILE@")
|
||||
|
28
cmake/modules/FindZ3.cmake
Normal file
28
cmake/modules/FindZ3.cmake
Normal file
@ -0,0 +1,28 @@
|
||||
find_path(Z3_INCLUDE_DIR NAMES z3.h
|
||||
PATH_SUFFIXES libz3 z3
|
||||
)
|
||||
|
||||
find_library(Z3_LIBRARIES NAMES z3 libz3
|
||||
)
|
||||
|
||||
find_program(Z3_EXECUTABLE z3)
|
||||
|
||||
if(Z3_INCLUDE_DIR AND Z3_EXECUTABLE)
|
||||
execute_process (COMMAND ${Z3_EXECUTABLE} -version
|
||||
OUTPUT_VARIABLE libz3_version_str
|
||||
ERROR_QUIET
|
||||
OUTPUT_STRIP_TRAILING_WHITESPACE)
|
||||
|
||||
string(REGEX REPLACE "^Z3 version ([0-9.]+)" "\\1"
|
||||
Z3_VERSION_STRING "${libz3_version_str}")
|
||||
unset(libz3_version_str)
|
||||
endif()
|
||||
|
||||
# handle the QUIETLY and REQUIRED arguments and set Z3_FOUND to TRUE if
|
||||
# all listed variables are TRUE
|
||||
include(FindPackageHandleStandardArgs)
|
||||
FIND_PACKAGE_HANDLE_STANDARD_ARGS(Z3
|
||||
REQUIRED_VARS Z3_LIBRARIES Z3_INCLUDE_DIR
|
||||
VERSION_VAR Z3_VERSION_STRING)
|
||||
|
||||
mark_as_advanced(Z3_INCLUDE_DIR Z3_LIBRARIES)
|
File diff suppressed because it is too large
Load Diff
2591
docs/ClangCommandLineReference.rst
Normal file
2591
docs/ClangCommandLineReference.rst
Normal file
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@ -498,12 +498,100 @@ In non-PIE executables the address of an external function (taken from
|
||||
the main executable) is the address of that function’s PLT record in
|
||||
the main executable. This would break the CFI checks.
|
||||
|
||||
Backward-edge CFI for return statements (RCFI)
|
||||
==============================================
|
||||
|
||||
This section is a proposal. As of March 2017 it is not implemented.
|
||||
|
||||
Backward-edge control flow (`RET` instructions) can be hijacked
|
||||
via overwriting the return address (`RA`) on stack.
|
||||
Various mitigation techniques (e.g. `SafeStack`_, `RFG`_, `Intel CET`_)
|
||||
try to detect or prevent `RA` corruption on stack.
|
||||
|
||||
RCFI enforces the expected control flow in several different ways described below.
|
||||
RCFI heavily relies on LTO.
|
||||
|
||||
Leaf Functions
|
||||
--------------
|
||||
If `f()` is a leaf function (i.e. it has no calls
|
||||
except maybe no-return calls) it can be called using a special calling convention
|
||||
that stores `RA` in a dedicated register `R` before the `CALL` instruction.
|
||||
`f()` does not spill `R` and does not use the `RET` instruction,
|
||||
instead it uses the value in `R` to `JMP` to `RA`.
|
||||
|
||||
This flavour of CFI is *precise*, i.e. the function is guaranteed to return
|
||||
to the point exactly following the call.
|
||||
|
||||
An alternative approach is to
|
||||
copy `RA` from stack to `R` in the first instruction of `f()`,
|
||||
then `JMP` to `R`.
|
||||
This approach is simpler to implement (does not require changing the caller)
|
||||
but weaker (there is a small window when `RA` is actually stored on stack).
|
||||
|
||||
|
||||
Functions called once
|
||||
---------------------
|
||||
Suppose `f()` is called in just one place in the program
|
||||
(assuming we can verify this in LTO mode).
|
||||
In this case we can replace the `RET` instruction with a `JMP` instruction
|
||||
with the immediate constant for `RA`.
|
||||
This will *precisely* enforce the return control flow no matter what is stored on stack.
|
||||
|
||||
Another variant is to compare `RA` on stack with the known constant and abort
|
||||
if they don't match; then `JMP` to the known constant address.
|
||||
|
||||
Functions called in a small number of call sites
|
||||
------------------------------------------------
|
||||
We may extend the above approach to cases where `f()`
|
||||
is called more than once (but still a small number of times).
|
||||
With LTO we know all possible values of `RA` and we check them
|
||||
one-by-one (or using binary search) against the value on stack.
|
||||
If the match is found, we `JMP` to the known constant address, otherwise abort.
|
||||
|
||||
This protection is *near-precise*, i.e. it guarantees that the control flow will
|
||||
be transferred to one of the valid return addresses for this function,
|
||||
but not necessary to the point of the most recent `CALL`.
|
||||
|
||||
General case
|
||||
------------
|
||||
For functions called multiple times a *return jump table* is constructed
|
||||
in the same manner as jump tables for indirect function calls (see above).
|
||||
The correct jump table entry (or it's index) is passed by `CALL` to `f()`
|
||||
(as an extra argument) and then spilled to stack.
|
||||
The `RET` instruction is replaced with a load of the jump table entry,
|
||||
jump table range check, and `JMP` to the jump table entry.
|
||||
|
||||
This protection is also *near-precise*.
|
||||
|
||||
Returns from functions called indirectly
|
||||
----------------------------------------
|
||||
|
||||
If a function is called indirectly, the return jump table is constructed for the
|
||||
equivalence class of functions instead of a single function.
|
||||
|
||||
Cross-DSO calls
|
||||
---------------
|
||||
Consider two instrumented DSOs, `A` and `B`. `A` defines `f()` and `B` calls it.
|
||||
|
||||
This case will be handled similarly to the cross-DSO scheme using the slow path callback.
|
||||
|
||||
Non-goals
|
||||
---------
|
||||
|
||||
RCFI does not protect `RET` instructions:
|
||||
* in non-instrumented DSOs,
|
||||
* in instrumented DSOs for functions that are called from non-instrumented DSOs,
|
||||
* embedded into other instructions (e.g. `0f4fc3 cmovg %ebx,%eax`).
|
||||
|
||||
.. _SafeStack: https://clang.llvm.org/docs/SafeStack.html
|
||||
.. _RFG: http://xlab.tencent.com/en/2016/11/02/return-flow-guard
|
||||
.. _Intel CET: https://software.intel.com/en-us/blogs/2016/06/09/intel-release-new-technology-specifications-protect-rop-attacks
|
||||
|
||||
Hardware support
|
||||
================
|
||||
|
||||
We believe that the above design can be efficiently implemented in hardware.
|
||||
A single new instruction added to an ISA would allow to perform the CFI check
|
||||
A single new instruction added to an ISA would allow to perform the forward-edge CFI check
|
||||
with fewer bytes per check (smaller code size overhead) and potentially more
|
||||
efficiently. The current software-only instrumentation requires at least
|
||||
32-bytes per check (on x86_64).
|
||||
@ -540,7 +628,7 @@ The bit vector lookup is probably too complex for a hardware implementation.
|
||||
Jump(kFailedCheckTarget);
|
||||
}
|
||||
|
||||
An alternative and more compact enconding would not use `kFailedCheckTarget`,
|
||||
An alternative and more compact encoding would not use `kFailedCheckTarget`,
|
||||
and will trap on check failure instead.
|
||||
This will allow us to fit the instruction into **8-9 bytes**.
|
||||
The cross-DSO checks will be performed by a trap handler and
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -85,3 +85,16 @@ List of projects and tools
|
||||
errors, fixit hints). See also `<http://l.rw.rw/clang_plugin>`_ for
|
||||
step-by-step instructions."
|
||||
|
||||
`<https://phabricator.kde.org/source/clazy>`_
|
||||
"clazy is a compiler plugin which allows clang to understand Qt semantics.
|
||||
You get more than 50 Qt related compiler warnings, ranging from unneeded
|
||||
memory allocations to misusage of API, including fix-its for automatic
|
||||
refactoring."
|
||||
|
||||
`<https://gerrit.libreoffice.org/gitweb?p=core.git;a=blob_plain;f=compilerplugins/README;hb=HEAD>`_
|
||||
"LibreOffice uses a Clang plugin infrastructure to check during the build
|
||||
various things, some more, some less specific to the LibreOffice source code.
|
||||
There are currently around 50 such checkers, from flagging C-style casts and
|
||||
uses of reserved identifiers to ensuring that code adheres to lifecycle
|
||||
protocols for certain LibreOffice-specific classes. They may serve as
|
||||
examples for writing RecursiveASTVisitor-based plugins."
|
||||
|
@ -10,15 +10,16 @@ using link-time optimization; in the case where LTO is not being used, the
|
||||
linkage unit's LTO unit is empty. Each linkage unit has only a single LTO unit.
|
||||
|
||||
The LTO visibility of a class is used by the compiler to determine which
|
||||
classes the virtual function call optimization and control flow integrity
|
||||
features apply to. These features use whole-program information, so they
|
||||
require the entire class hierarchy to be visible in order to work correctly.
|
||||
classes the whole-program devirtualization (``-fwhole-program-vtables``) and
|
||||
control flow integrity (``-fsanitize=cfi-vcall``) features apply to. These
|
||||
features use whole-program information, so they require the entire class
|
||||
hierarchy to be visible in order to work correctly.
|
||||
|
||||
If any translation unit in the program uses either of the virtual function
|
||||
call optimization or control flow integrity features, it is effectively an
|
||||
ODR violation to define a class with hidden LTO visibility in multiple linkage
|
||||
If any translation unit in the program uses either of the whole-program
|
||||
devirtualization or control flow integrity features, it is effectively an ODR
|
||||
violation to define a class with hidden LTO visibility in multiple linkage
|
||||
units. A class with public LTO visibility may be defined in multiple linkage
|
||||
units, but the tradeoff is that the virtual function call optimization and
|
||||
units, but the tradeoff is that the whole-program devirtualization and
|
||||
control flow integrity features can only be applied to classes with hidden LTO
|
||||
visibility. A class's LTO visibility is treated as an ODR-relevant property
|
||||
of its definition, so it must be consistent between translation units.
|
||||
|
@ -356,7 +356,7 @@ is:
|
||||
|
||||
Query for this feature with ``__has_extension(attribute_ext_vector_type)``.
|
||||
|
||||
Giving ``-faltivec`` option to clang enables support for AltiVec vector syntax
|
||||
Giving ``-maltivec`` option to clang enables support for AltiVec vector syntax
|
||||
and functions. For example:
|
||||
|
||||
.. code-block:: c++
|
||||
@ -993,6 +993,7 @@ The following type trait primitives are supported by Clang:
|
||||
* ``__has_trivial_destructor`` (GNU, Microsoft)
|
||||
* ``__has_virtual_destructor`` (GNU, Microsoft)
|
||||
* ``__is_abstract`` (GNU, Microsoft)
|
||||
* ``__is_aggregate`` (GNU, Microsoft)
|
||||
* ``__is_base_of`` (GNU, Microsoft)
|
||||
* ``__is_class`` (GNU, Microsoft)
|
||||
* ``__is_convertible_to`` (Microsoft)
|
||||
@ -1780,7 +1781,7 @@ String builtins
|
||||
---------------
|
||||
|
||||
Clang provides constant expression evaluation support for builtins forms of
|
||||
the following functions from the C standard library ``<strings.h>`` header:
|
||||
the following functions from the C standard library ``<string.h>`` header:
|
||||
|
||||
* ``memchr``
|
||||
* ``memcmp``
|
||||
@ -2312,3 +2313,36 @@ For example, the hint ``vectorize_width(4)`` is ignored if the loop is not
|
||||
proven safe to vectorize. To identify and diagnose optimization issues use
|
||||
`-Rpass`, `-Rpass-missed`, and `-Rpass-analysis` command line options. See the
|
||||
user guide for details.
|
||||
|
||||
Extensions to specify floating-point flags
|
||||
====================================================
|
||||
|
||||
The ``#pragma clang fp`` pragma allows floating-point options to be specified
|
||||
for a section of the source code. This pragma can only appear at file scope or
|
||||
at the start of a compound statement (excluding comments). When using within a
|
||||
compound statement, the pragma is active within the scope of the compound
|
||||
statement.
|
||||
|
||||
Currently, only FP contraction can be controlled with the pragma. ``#pragma
|
||||
clang fp contract`` specifies whether the compiler should contract a multiply
|
||||
and an addition (or subtraction) into a fused FMA operation when supported by
|
||||
the target.
|
||||
|
||||
The pragma can take three values: ``on``, ``fast`` and ``off``. The ``on``
|
||||
option is identical to using ``#pragma STDC FP_CONTRACT(ON)`` and it allows
|
||||
fusion as specified the language standard. The ``fast`` option allows fusiong
|
||||
in cases when the language standard does not make this possible (e.g. across
|
||||
statements in C)
|
||||
|
||||
.. code-block:: c++
|
||||
|
||||
for(...) {
|
||||
#pragma clang fp contract(fast)
|
||||
a = b[i] * c[i];
|
||||
d[i] += a;
|
||||
}
|
||||
|
||||
|
||||
The pragma can also be used with ``off`` which turns FP contraction off for a
|
||||
section of the code. This can be useful when fast contraction is otherwise
|
||||
enabled for the translation unit with the ``-ffp-contract=fast`` flag.
|
||||
|
@ -337,6 +337,15 @@ nonTypeTemplateParmDecl()
|
||||
</pre></td></tr>
|
||||
|
||||
|
||||
<tr><td>Matcher<<a href="http://clang.llvm.org/doxygen/classclang_1_1Decl.html">Decl</a>></td><td class="name" onclick="toggle('objcCategoryDecl0')"><a name="objcCategoryDecl0Anchor">objcCategoryDecl</a></td><td>Matcher<<a href="http://clang.llvm.org/doxygen/classclang_1_1ObjCCategoryDecl.html">ObjCCategoryDecl</a>>...</td></tr>
|
||||
<tr><td colspan="4" class="doc" id="objcCategoryDecl0"><pre>Matches Objective-C category declarations.
|
||||
|
||||
Example matches Foo (Additions)
|
||||
@interface Foo (Additions)
|
||||
@end
|
||||
</pre></td></tr>
|
||||
|
||||
|
||||
<tr><td>Matcher<<a href="http://clang.llvm.org/doxygen/classclang_1_1Decl.html">Decl</a>></td><td class="name" onclick="toggle('objcInterfaceDecl0')"><a name="objcInterfaceDecl0Anchor">objcInterfaceDecl</a></td><td>Matcher<<a href="http://clang.llvm.org/doxygen/classclang_1_1ObjCInterfaceDecl.html">ObjCInterfaceDecl</a>>...</td></tr>
|
||||
<tr><td colspan="4" class="doc" id="objcInterfaceDecl0"><pre>Matches Objective-C interface declarations.
|
||||
|
||||
@ -346,6 +355,50 @@ Example matches Foo
|
||||
</pre></td></tr>
|
||||
|
||||
|
||||
<tr><td>Matcher<<a href="http://clang.llvm.org/doxygen/classclang_1_1Decl.html">Decl</a>></td><td class="name" onclick="toggle('objcIvarDecl0')"><a name="objcIvarDecl0Anchor">objcIvarDecl</a></td><td>Matcher<<a href="http://clang.llvm.org/doxygen/classclang_1_1ObjCIvarDecl.html">ObjCIvarDecl</a>>...</td></tr>
|
||||
<tr><td colspan="4" class="doc" id="objcIvarDecl0"><pre>Matches Objective-C instance variable declarations.
|
||||
|
||||
Example matches _enabled
|
||||
@implementation Foo {
|
||||
BOOL _enabled;
|
||||
}
|
||||
@end
|
||||
</pre></td></tr>
|
||||
|
||||
|
||||
<tr><td>Matcher<<a href="http://clang.llvm.org/doxygen/classclang_1_1Decl.html">Decl</a>></td><td class="name" onclick="toggle('objcMethodDecl0')"><a name="objcMethodDecl0Anchor">objcMethodDecl</a></td><td>Matcher<<a href="http://clang.llvm.org/doxygen/classclang_1_1ObjCMethodDecl.html">ObjCMethodDecl</a>>...</td></tr>
|
||||
<tr><td colspan="4" class="doc" id="objcMethodDecl0"><pre>Matches Objective-C method declarations.
|
||||
|
||||
Example matches both declaration and definition of -[Foo method]
|
||||
@interface Foo
|
||||
- (void)method;
|
||||
@end
|
||||
|
||||
@implementation Foo
|
||||
- (void)method {}
|
||||
@end
|
||||
</pre></td></tr>
|
||||
|
||||
|
||||
<tr><td>Matcher<<a href="http://clang.llvm.org/doxygen/classclang_1_1Decl.html">Decl</a>></td><td class="name" onclick="toggle('objcPropertyDecl0')"><a name="objcPropertyDecl0Anchor">objcPropertyDecl</a></td><td>Matcher<<a href="http://clang.llvm.org/doxygen/classclang_1_1ObjCPropertyDecl.html">ObjCPropertyDecl</a>>...</td></tr>
|
||||
<tr><td colspan="4" class="doc" id="objcPropertyDecl0"><pre>Matches Objective-C property declarations.
|
||||
|
||||
Example matches enabled
|
||||
@interface Foo
|
||||
@property BOOL enabled;
|
||||
@end
|
||||
</pre></td></tr>
|
||||
|
||||
|
||||
<tr><td>Matcher<<a href="http://clang.llvm.org/doxygen/classclang_1_1Decl.html">Decl</a>></td><td class="name" onclick="toggle('objcProtocolDecl0')"><a name="objcProtocolDecl0Anchor">objcProtocolDecl</a></td><td>Matcher<<a href="http://clang.llvm.org/doxygen/classclang_1_1ObjCProtocolDecl.html">ObjCProtocolDecl</a>>...</td></tr>
|
||||
<tr><td colspan="4" class="doc" id="objcProtocolDecl0"><pre>Matches Objective-C protocol declarations.
|
||||
|
||||
Example matches FooDelegate
|
||||
@protocol FooDelegate
|
||||
@end
|
||||
</pre></td></tr>
|
||||
|
||||
|
||||
<tr><td>Matcher<<a href="http://clang.llvm.org/doxygen/classclang_1_1Decl.html">Decl</a>></td><td class="name" onclick="toggle('parmVarDecl0')"><a name="parmVarDecl0Anchor">parmVarDecl</a></td><td>Matcher<<a href="http://clang.llvm.org/doxygen/classclang_1_1ParmVarDecl.html">ParmVarDecl</a>>...</td></tr>
|
||||
<tr><td colspan="4" class="doc" id="parmVarDecl0"><pre>Matches parameter variable declarations.
|
||||
|
||||
@ -416,6 +469,15 @@ typeAliasDecl()
|
||||
</pre></td></tr>
|
||||
|
||||
|
||||
<tr><td>Matcher<<a href="http://clang.llvm.org/doxygen/classclang_1_1Decl.html">Decl</a>></td><td class="name" onclick="toggle('typeAliasTemplateDecl0')"><a name="typeAliasTemplateDecl0Anchor">typeAliasTemplateDecl</a></td><td>Matcher<<a href="http://clang.llvm.org/doxygen/classclang_1_1TypeAliasTemplateDecl.html">TypeAliasTemplateDecl</a>>...</td></tr>
|
||||
<tr><td colspan="4" class="doc" id="typeAliasTemplateDecl0"><pre>Matches type alias template declarations.
|
||||
|
||||
typeAliasTemplateDecl() matches
|
||||
template <typename T>
|
||||
using Y = X<T>;
|
||||
</pre></td></tr>
|
||||
|
||||
|
||||
<tr><td>Matcher<<a href="http://clang.llvm.org/doxygen/classclang_1_1Decl.html">Decl</a>></td><td class="name" onclick="toggle('typedefDecl0')"><a name="typedefDecl0Anchor">typedefDecl</a></td><td>Matcher<<a href="http://clang.llvm.org/doxygen/classclang_1_1TypedefDecl.html">TypedefDecl</a>>...</td></tr>
|
||||
<tr><td colspan="4" class="doc" id="typedefDecl0"><pre>Matches typedef declarations.
|
||||
|
||||
@ -5419,7 +5481,7 @@ alignof.
|
||||
|
||||
|
||||
<tr><td>Matcher<<a href="http://clang.llvm.org/doxygen/classclang_1_1Stmt.html">Stmt</a>></td><td class="name" onclick="toggle('forFunction0')"><a name="forFunction0Anchor">forFunction</a></td><td>Matcher<<a href="http://clang.llvm.org/doxygen/classclang_1_1FunctionDecl.html">FunctionDecl</a>> InnerMatcher</td></tr>
|
||||
<tr><td colspan="4" class="doc" id="forFunction0"><pre>Matches declaration of the function the statemenet belongs to
|
||||
<tr><td colspan="4" class="doc" id="forFunction0"><pre>Matches declaration of the function the statement belongs to
|
||||
|
||||
Given:
|
||||
F& operator=(const F& o) {
|
||||
|
@ -360,6 +360,7 @@ The ``framework`` qualifier specifies that this module corresponds to a Darwin-s
|
||||
Name.framework/
|
||||
Modules/module.modulemap Module map for the framework
|
||||
Headers/ Subdirectory containing framework headers
|
||||
PrivateHeaders/ Subdirectory containing framework private headers
|
||||
Frameworks/ Subdirectory containing embedded frameworks
|
||||
Resources/ Subdirectory containing additional resources
|
||||
Name Symbolic link to the shared library for the framework
|
||||
@ -842,6 +843,16 @@ would be available when ``Foo_Private.h`` is available, making it
|
||||
easier to split a library's public and private APIs along header
|
||||
boundaries.
|
||||
|
||||
When writing a private module as part of a *framework*, it's recommended that:
|
||||
|
||||
* Headers for this module are present in the ``PrivateHeaders``
|
||||
framework subdirectory.
|
||||
* The private module is defined as a *submodule* of the public framework (if
|
||||
there's one), similar to how ``Foo.Private`` is defined in the example above.
|
||||
* The ``explicit`` keyword should be used to guarantee that its content will
|
||||
only be available when the submodule itself is explicitly named (through a
|
||||
``@import`` for example).
|
||||
|
||||
Modularizing a Platform
|
||||
=======================
|
||||
To get any benefit out of modules, one needs to introduce module maps for software libraries starting at the bottom of the stack. This typically means introducing a module map covering the operating system's headers and the C standard library headers (in ``/usr/include``, for a Unix system).
|
||||
|
@ -1,6 +1,6 @@
|
||||
=========================
|
||||
Clang 4.0.0 Release Notes
|
||||
=========================
|
||||
=======================================
|
||||
Clang 5.0.0 (In-Progress) Release Notes
|
||||
=======================================
|
||||
|
||||
.. contents::
|
||||
:local:
|
||||
@ -8,11 +8,17 @@ Clang 4.0.0 Release Notes
|
||||
|
||||
Written by the `LLVM Team <http://llvm.org/>`_
|
||||
|
||||
.. warning::
|
||||
|
||||
These are in-progress notes for the upcoming Clang 5 release.
|
||||
Release notes for previous releases can be found on
|
||||
`the Download Page <http://releases.llvm.org/download.html>`_.
|
||||
|
||||
Introduction
|
||||
============
|
||||
|
||||
This document contains the release notes for the Clang C/C++/Objective-C/OpenCL
|
||||
frontend, part of the LLVM Compiler Infrastructure, release 4.0.0. Here we
|
||||
This document contains the release notes for the Clang C/C++/Objective-C
|
||||
frontend, part of the LLVM Compiler Infrastructure, release 5.0.0. Here we
|
||||
describe the status of Clang in some detail, including major
|
||||
improvements from the previous release and new feature work. For the
|
||||
general LLVM release notes, see `the LLVM
|
||||
@ -25,7 +31,12 @@ the latest release, please check out the main please see the `Clang Web
|
||||
Site <http://clang.llvm.org>`_ or the `LLVM Web
|
||||
Site <http://llvm.org>`_.
|
||||
|
||||
What's New in Clang 4.0.0?
|
||||
Note that if you are reading this file from a Subversion checkout or the
|
||||
main Clang web page, this document applies to the *next* release, not
|
||||
the current one. To see the release notes for a specific release, please
|
||||
see the `releases page <http://llvm.org/releases/>`_.
|
||||
|
||||
What's New in Clang 5.0.0?
|
||||
==========================
|
||||
|
||||
Some of the major new features and improvements to Clang are listed
|
||||
@ -36,147 +47,165 @@ sections with improvements to Clang's support for those languages.
|
||||
Major New Features
|
||||
------------------
|
||||
|
||||
- The `diagnose_if <AttributeReference.html#diagnose-if>`_ attribute has been
|
||||
added to clang. This attribute allows
|
||||
clang to emit a warning or error if a function call meets one or more
|
||||
user-specified conditions.
|
||||
- ...
|
||||
|
||||
- Enhanced devirtualization with
|
||||
`-fstrict-vtable-pointers <UsersManual.html#cmdoption-fstrict-vtable-pointers>`_.
|
||||
Clang devirtualizes across different basic blocks, like loops:
|
||||
Improvements to Clang's diagnostics
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
.. code-block:: c++
|
||||
|
||||
struct A {
|
||||
virtual void foo();
|
||||
};
|
||||
void indirect(A &a, int n) {
|
||||
for (int i = 0 ; i < n; i++)
|
||||
a.foo();
|
||||
}
|
||||
void test(int n) {
|
||||
A a;
|
||||
indirect(a, n);
|
||||
}
|
||||
|
||||
|
||||
Improvements to ThinLTO (-flto=thin)
|
||||
------------------------------------
|
||||
- Integration with profile data (PGO). When available, profile data enables
|
||||
more accurate function importing decisions, as well as cross-module indirect
|
||||
call promotion.
|
||||
- Significant build-time and binary-size improvements when compiling with debug
|
||||
info (``-g``).
|
||||
- -Wunused-lambda-capture warns when a variable explicitly captured
|
||||
by a lambda is not used in the body of the lambda.
|
||||
|
||||
New Compiler Flags
|
||||
------------------
|
||||
|
||||
- The option ``-Og`` has been added to optimize the debugging experience.
|
||||
For now, this option is exactly the same as ``-O1``. However, in the future,
|
||||
some other optimizations might be enabled or disabled.
|
||||
The option ....
|
||||
|
||||
- The option ``-MJ`` has been added to simplify adding JSON compilation
|
||||
database output into existing build systems.
|
||||
New Pragmas in Clang
|
||||
-----------------------
|
||||
|
||||
Clang now supports the ...
|
||||
|
||||
|
||||
Attribute Changes in Clang
|
||||
--------------------------
|
||||
|
||||
- ...
|
||||
|
||||
Windows Support
|
||||
---------------
|
||||
|
||||
Clang's support for building native Windows programs ...
|
||||
|
||||
|
||||
C Language Changes in Clang
|
||||
---------------------------
|
||||
|
||||
- ...
|
||||
|
||||
...
|
||||
|
||||
C11 Feature Support
|
||||
^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
...
|
||||
|
||||
C++ Language Changes in Clang
|
||||
-----------------------------
|
||||
|
||||
...
|
||||
|
||||
C++1z Feature Support
|
||||
^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
...
|
||||
|
||||
Objective-C Language Changes in Clang
|
||||
-------------------------------------
|
||||
|
||||
...
|
||||
|
||||
OpenCL C Language Changes in Clang
|
||||
----------------------------------
|
||||
|
||||
**The following bugs in the OpenCL header have been fixed:**
|
||||
...
|
||||
|
||||
* Added missing ``overloadable`` and ``convergent`` attributes.
|
||||
* Removed some erroneous extra ``native_*`` functions.
|
||||
OpenMP Support in Clang
|
||||
----------------------------------
|
||||
|
||||
**The following bugs in the generation of metadata have been fixed:**
|
||||
...
|
||||
|
||||
* Corrected the SPIR version depending on the OpenCL version.
|
||||
* Source level address spaces are taken from the SPIR specification.
|
||||
* Image types now contain no access qualifier.
|
||||
Internal API Changes
|
||||
--------------------
|
||||
|
||||
**The following bugs in the AMD target have been fixed:**
|
||||
These are major API changes that have happened since the 4.0.0 release of
|
||||
Clang. If upgrading an external codebase that uses Clang as a library,
|
||||
this section should help get you past the largest hurdles of upgrading.
|
||||
|
||||
* Corrected the bitwidth of ``size_t`` and NULL pointer value with respect to
|
||||
address spaces.
|
||||
* Added ``cl_khr_subgroups``, ``cl_amd_media_ops`` and ``cl_amd_media_ops2``
|
||||
extensions.
|
||||
* Added ``cl-denorms-are-zero`` support.
|
||||
* Changed address spaces for image objects to be ``constant``.
|
||||
* Added little-endian.
|
||||
- ...
|
||||
|
||||
**The following bugs in OpenCL 2.0 have been fixed:**
|
||||
AST Matchers
|
||||
------------
|
||||
|
||||
* Fixed pipe builtin function return type, added extra argument to generated
|
||||
IR intrinsics to propagate size and alignment information of the pipe packed
|
||||
type.
|
||||
* Improved pipe type to accommodate access qualifiers.
|
||||
* Added correct address space to the ObjC block generation and ``enqueue_kernel``
|
||||
prototype.
|
||||
* Improved handling of integer parameters of ``enqueue_kernel`` prototype. We
|
||||
now allow ``size_t`` instead of ``int`` for specifying block parameter sizes.
|
||||
* Allow using NULL (aka ``CLK_NULL_QUEUE``) with ``queue_t``.
|
||||
...
|
||||
|
||||
|
||||
**Improved the following diagnostics:**
|
||||
clang-format
|
||||
------------
|
||||
|
||||
* Disallow address spaces other than ``global`` for kernel pointer parameters.
|
||||
* Correct the use of half type argument and pointer assignment with
|
||||
dereferencing.
|
||||
* Disallow variadic arguments in functions and blocks.
|
||||
* Allow partial initializer for array and struct.
|
||||
* Option **BreakBeforeInheritanceComma** added to break before ``:`` and ``,`` in case of
|
||||
multiple inheritance in a class declaration. Enabled by default in the Mozilla coding style.
|
||||
|
||||
**Some changes to OpenCL extensions have been made:**
|
||||
+---------------------+----------------------------------------+
|
||||
| true | false |
|
||||
+=====================+========================================+
|
||||
| .. code-block:: c++ | .. code-block:: c++ |
|
||||
| | |
|
||||
| class MyClass | class MyClass : public X, public Y { |
|
||||
| : public X | }; |
|
||||
| , public Y { | |
|
||||
| }; | |
|
||||
+---------------------+----------------------------------------+
|
||||
|
||||
* Added ``cl_khr_mipmap_image``.
|
||||
* Added ``-cl-ext`` flag to allow overwriting supported extensions otherwise
|
||||
set by the target compiled for (Example: ``-cl-ext=-all,+cl_khr_fp16``).
|
||||
* New types and functions can now be flexibly added to extensions using the
|
||||
following pragmas instead of modifying the Clang source code:
|
||||
* Align block comment decorations.
|
||||
|
||||
.. code-block:: c
|
||||
+----------------------+---------------------+
|
||||
| Before | After |
|
||||
+======================+=====================+
|
||||
| .. code-block:: c++ | .. code-block:: c++ |
|
||||
| | |
|
||||
| /* line 1 | /* line 1 |
|
||||
| * line 2 | * line 2 |
|
||||
| */ | */ |
|
||||
+----------------------+---------------------+
|
||||
|
||||
#pragma OPENCL EXTENSION the_new_extension_name : begin
|
||||
// declare types and functions associated with the extension here
|
||||
#pragma OPENCL EXTENSION the_new_extension_name : end
|
||||
* The :doc:`ClangFormatStyleOptions` documentation provides detailed examples for most options.
|
||||
|
||||
* Namespace end comments are now added or updated automatically.
|
||||
|
||||
**Miscellaneous changes:**
|
||||
+---------------------+---------------------+
|
||||
| Before | After |
|
||||
+=====================+=====================+
|
||||
| .. code-block:: c++ | .. code-block:: c++ |
|
||||
| | |
|
||||
| namespace A { | namespace A { |
|
||||
| int i; | int i; |
|
||||
| int j; | int j; |
|
||||
| } | } |
|
||||
+---------------------+---------------------+
|
||||
|
||||
* Fix ``__builtin_astype`` to cast between different address space objects.
|
||||
* Allow using ``opencl_unroll_hint`` with earlier OpenCL versions than 2.0.
|
||||
* Improved handling of floating point literal to default to single precision if
|
||||
fp64 extension is not enabled.
|
||||
* Refactor ``sampler_t`` implementation to simplify initializer representation
|
||||
which is now handled as a compiler builtin function with an integer value
|
||||
passed into it.
|
||||
* Change fake address space map to use the SPIR convention.
|
||||
* Added `the OpenCL manual <UsersManual.html#opencl-features>`_ to Clang
|
||||
documentation.
|
||||
* Comment reflow support added. Overly long comment lines will now be reflown with the rest of
|
||||
the paragraph instead of just broken. Option **ReflowComments** added and enabled by default.
|
||||
|
||||
libclang
|
||||
--------
|
||||
|
||||
...
|
||||
|
||||
|
||||
Static Analyzer
|
||||
---------------
|
||||
|
||||
With the option ``--show-description``, scan-build's list of defects will also
|
||||
show the description of the defects.
|
||||
...
|
||||
|
||||
The analyzer now provides better support of code that uses gtest.
|
||||
Core Analysis Improvements
|
||||
==========================
|
||||
|
||||
Several new checks were added:
|
||||
- ...
|
||||
|
||||
- The analyzer warns when virtual calls are made from constructors or
|
||||
destructors. This check is off by default but can be enabled by passing the
|
||||
following command to scan-build: ``-enable-checker optin.cplusplus.VirtualCall``.
|
||||
- The analyzer checks for synthesized copy properties of mutable types in
|
||||
Objective C, such as ``NSMutableArray``. Calling the setter for these properties
|
||||
will store an immutable copy of the value.
|
||||
- The analyzer checks for calls to ``dispatch_once()`` that use an Objective-C
|
||||
instance variable as the predicate. Using an instance variable as a predicate
|
||||
may result in the passed-in block being executed multiple times or not at all.
|
||||
These calls should be rewritten either to use a lock or to store the predicate
|
||||
in a global or static variable.
|
||||
- The analyzer checks for unintended comparisons of ``NSNumber``, ``CFNumberRef``, and
|
||||
other Cocoa number objects to scalar values.
|
||||
New Issues Found
|
||||
================
|
||||
|
||||
- ...
|
||||
|
||||
Python Binding Changes
|
||||
----------------------
|
||||
|
||||
The following methods have been added:
|
||||
|
||||
- ...
|
||||
|
||||
Significant Known Problems
|
||||
==========================
|
||||
|
||||
Additional Information
|
||||
======================
|
||||
|
@ -227,7 +227,8 @@ easily used for bitset-based corpus distillation.
|
||||
Caller-callee coverage
|
||||
======================
|
||||
|
||||
(Experimental!)
|
||||
**Deprecated, don't use**
|
||||
|
||||
Every indirect function call is instrumented with a run-time function call that
|
||||
captures caller and callee. At the shutdown time the process dumps a separate
|
||||
file called ``caller-callee.PID.sancov`` which contains caller/callee pairs as
|
||||
@ -253,6 +254,8 @@ Current limitations:
|
||||
Coverage counters
|
||||
=================
|
||||
|
||||
**Deprecated, don't use**
|
||||
|
||||
This experimental feature is inspired by
|
||||
`AFL <http://lcamtuf.coredump.cx/afl/technical_details.txt>`__'s coverage
|
||||
instrumentation. With additional compile-time and run-time flags you can get
|
||||
@ -296,6 +299,9 @@ These counters may also be used for in-process coverage-guided fuzzers. See
|
||||
|
||||
Tracing basic blocks
|
||||
====================
|
||||
|
||||
**Deprecated, don't use**
|
||||
|
||||
Experimental support for basic block (or edge) tracing.
|
||||
With ``-fsanitize-coverage=trace-bb`` the compiler will insert
|
||||
``__sanitizer_cov_trace_basic_block(s32 *id)`` before every function, basic block, or edge
|
||||
@ -319,6 +325,9 @@ Basic block tracing is currently supported only for single-threaded applications
|
||||
|
||||
Tracing PCs
|
||||
===========
|
||||
|
||||
**Deprecated, don't use**
|
||||
|
||||
*Experimental* feature similar to tracing basic blocks, but with a different API.
|
||||
With ``-fsanitize-coverage=trace-pc`` the compiler will insert
|
||||
``__sanitizer_cov_trace_pc()`` on every edge.
|
||||
@ -331,16 +340,13 @@ and can be used with `AFL <http://lcamtuf.coredump.cx/afl>`__.
|
||||
|
||||
Tracing PCs with guards
|
||||
=======================
|
||||
Another *experimental* feature that tries to combine the functionality of `trace-pc`,
|
||||
`8bit-counters` and boolean coverage.
|
||||
|
||||
With ``-fsanitize-coverage=trace-pc-guard`` the compiler will insert the following code
|
||||
on every edge:
|
||||
|
||||
.. code-block:: none
|
||||
|
||||
if (guard_variable)
|
||||
__sanitizer_cov_trace_pc_guard(&guard_variable)
|
||||
__sanitizer_cov_trace_pc_guard(&guard_variable)
|
||||
|
||||
Every edge will have its own `guard_variable` (uint32_t).
|
||||
|
||||
@ -349,10 +355,11 @@ The compler will also insert a module constructor that will call
|
||||
.. code-block:: c++
|
||||
|
||||
// The guards are [start, stop).
|
||||
// This function may be called multiple times with the same values of start/stop.
|
||||
// This function will be called at least once per DSO and may be called
|
||||
// more than once with the same values of start/stop.
|
||||
__sanitizer_cov_trace_pc_guard_init(uint32_t *start, uint32_t *stop);
|
||||
|
||||
Similarly to `trace-pc,indirect-calls`, with `trace-pc-guards,indirect-calls`
|
||||
With `trace-pc-guards,indirect-calls`
|
||||
``__sanitizer_cov_trace_pc_indirect(void *callee)`` will be inserted on every indirect call.
|
||||
|
||||
The functions `__sanitizer_cov_trace_pc_*` should be defined by the user.
|
||||
@ -367,10 +374,10 @@ Example:
|
||||
#include <sanitizer/coverage_interface.h>
|
||||
|
||||
// This callback is inserted by the compiler as a module constructor
|
||||
// into every compilation unit. 'start' and 'stop' correspond to the
|
||||
// into every DSO. 'start' and 'stop' correspond to the
|
||||
// beginning and end of the section with the guards for the entire
|
||||
// binary (executable or DSO) and so it will be called multiple times
|
||||
// with the same parameters.
|
||||
// binary (executable or DSO). The callback will be called at least
|
||||
// once per DSO and may be called multiple times with the same parameters.
|
||||
extern "C" void __sanitizer_cov_trace_pc_guard_init(uint32_t *start,
|
||||
uint32_t *stop) {
|
||||
static uint64_t N; // Counter for the guards.
|
||||
|
@ -18,6 +18,7 @@ Clang ships two other code coverage implementations:
|
||||
various sanitizers. It can provide up to edge-level coverage.
|
||||
|
||||
* gcov - A GCC-compatible coverage implementation which operates on DebugInfo.
|
||||
This is enabled by ``-ftest-coverage`` or ``--coverage``.
|
||||
|
||||
From this point onwards "code coverage" will refer to the source-based kind.
|
||||
|
||||
@ -256,6 +257,8 @@ without using static initializers, do this manually:
|
||||
otherwise. Calling this function multiple times appends profile data to an
|
||||
existing on-disk raw profile.
|
||||
|
||||
In C++ files, declare these as ``extern "C"``.
|
||||
|
||||
Collecting coverage reports for the llvm project
|
||||
================================================
|
||||
|
||||
|
@ -50,9 +50,9 @@ instead of ``clang++`` if you're compiling/linking C code.
|
||||
You can enable only a subset of :ref:`checks <ubsan-checks>` offered by UBSan,
|
||||
and define the desired behavior for each kind of check:
|
||||
|
||||
* print a verbose error report and continue execution (default);
|
||||
* print a verbose error report and exit the program;
|
||||
* execute a trap instruction (doesn't require UBSan run-time support).
|
||||
* ``-fsanitize=...``: print a verbose error report and continue execution (default);
|
||||
* ``-fno-sanitize-recover=...``: print a verbose error report and exit the program;
|
||||
* ``-fsanitize-trap=...``: execute a trap instruction (doesn't require UBSan run-time support).
|
||||
|
||||
For example if you compile/link your program as:
|
||||
|
||||
@ -92,6 +92,12 @@ Available checks are:
|
||||
parameter which is declared to never be null.
|
||||
- ``-fsanitize=null``: Use of a null pointer or creation of a null
|
||||
reference.
|
||||
- ``-fsanitize=nullability-arg``: Passing null as a function parameter
|
||||
which is annotated with ``_Nonnull``.
|
||||
- ``-fsanitize=nullability-assign``: Assigning null to an lvalue which
|
||||
is annotated with ``_Nonnull``.
|
||||
- ``-fsanitize=nullability-return``: Returning null from a function with
|
||||
a return type annotated with ``_Nonnull``.
|
||||
- ``-fsanitize=object-size``: An attempt to potentially use bytes which
|
||||
the optimizer can determine are not part of the object being accessed.
|
||||
This will also detect some types of undefined behavior that may not
|
||||
@ -117,7 +123,9 @@ Available checks are:
|
||||
- ``-fsanitize=unreachable``: If control flow reaches
|
||||
``__builtin_unreachable``.
|
||||
- ``-fsanitize=unsigned-integer-overflow``: Unsigned integer
|
||||
overflows.
|
||||
overflows. Note that unlike signed integer overflow, unsigned integer
|
||||
is not undefined behavior. However, while it has well-defined semantics,
|
||||
it is often unintentional, so UBSan offers to catch it.
|
||||
- ``-fsanitize=vla-bound``: A variable-length array whose bound
|
||||
does not evaluate to a positive value.
|
||||
- ``-fsanitize=vptr``: Use of an object whose vptr indicates that
|
||||
@ -128,11 +136,15 @@ Available checks are:
|
||||
|
||||
You can also use the following check groups:
|
||||
- ``-fsanitize=undefined``: All of the checks listed above other than
|
||||
``unsigned-integer-overflow``.
|
||||
``unsigned-integer-overflow`` and the ``nullability-*`` checks.
|
||||
- ``-fsanitize=undefined-trap``: Deprecated alias of
|
||||
``-fsanitize=undefined``.
|
||||
- ``-fsanitize=integer``: Checks for undefined or suspicious integer
|
||||
behavior (e.g. unsigned integer overflow).
|
||||
- ``-fsanitize=nullability``: Enables ``nullability-arg``,
|
||||
``nullability-assign``, and ``nullability-return``. While violating
|
||||
nullability does not have undefined behavior, it is often unintentional,
|
||||
so UBSan offers to catch it.
|
||||
|
||||
Stack traces and report symbolization
|
||||
=====================================
|
||||
@ -145,6 +157,8 @@ will need to:
|
||||
``UBSAN_OPTIONS=print_stacktrace=1``.
|
||||
#. Make sure ``llvm-symbolizer`` binary is in ``PATH``.
|
||||
|
||||
Stacktrace printing for UBSan issues is currently not supported on Darwin.
|
||||
|
||||
Issue Suppression
|
||||
=================
|
||||
|
||||
|
@ -562,6 +562,16 @@ control the crash diagnostics.
|
||||
The -fno-crash-diagnostics flag can be helpful for speeding the process
|
||||
of generating a delta reduced test case.
|
||||
|
||||
Clang is also capable of generating preprocessed source file(s) and associated
|
||||
run script(s) even without a crash. This is specially useful when trying to
|
||||
generate a reproducer for warnings or errors while using modules.
|
||||
|
||||
.. option:: -gen-reproducer
|
||||
|
||||
Generates preprocessed source files, a reproducer script and if relevant, a
|
||||
cache containing: built module pcm's and all headers needed to rebuilt the
|
||||
same modules.
|
||||
|
||||
.. _rpass:
|
||||
|
||||
Options to Emit Optimization Reports
|
||||
@ -757,6 +767,7 @@ existed.
|
||||
#if foo
|
||||
#endif foo // warning: extra tokens at end of #endif directive
|
||||
|
||||
#pragma clang diagnostic push
|
||||
#pragma clang diagnostic ignored "-Wextra-tokens"
|
||||
|
||||
#if foo
|
||||
@ -1695,6 +1706,22 @@ below. If multiple flags are present, the last one is used.
|
||||
|
||||
Generate complete debug info.
|
||||
|
||||
Controlling Macro Debug Info Generation
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
Debug info for C preprocessor macros increases the size of debug information in
|
||||
the binary. Macro debug info generated by Clang can be controlled by the flags
|
||||
listed below.
|
||||
|
||||
.. option:: -fdebug-macro
|
||||
|
||||
Generate debug info for preprocessor macros. This flag is discarded when
|
||||
**-g0** is enabled.
|
||||
|
||||
.. option:: -fno-debug-macro
|
||||
|
||||
Do not generate debug info for preprocessor macros (default).
|
||||
|
||||
Controlling Debugger "Tuning"
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
@ -1862,7 +1889,7 @@ missing from this list, please send an e-mail to cfe-dev. This list
|
||||
currently excludes C++; see :ref:`C++ Language Features <cxx>`. Also, this
|
||||
list does not include bugs in mostly-implemented features; please see
|
||||
the `bug
|
||||
tracker <http://llvm.org/bugs/buglist.cgi?quicksearch=product%3Aclang+component%3A-New%2BBugs%2CAST%2CBasic%2CDriver%2CHeaders%2CLLVM%2BCodeGen%2Cparser%2Cpreprocessor%2CSemantic%2BAnalyzer>`_
|
||||
tracker <https://bugs.llvm.org/buglist.cgi?quicksearch=product%3Aclang+component%3A-New%2BBugs%2CAST%2CBasic%2CDriver%2CHeaders%2CLLVM%2BCodeGen%2Cparser%2Cpreprocessor%2CSemantic%2BAnalyzer>`_
|
||||
for known existing bugs (FIXME: Is there a section for bug-reporting
|
||||
guidelines somewhere?).
|
||||
|
||||
@ -2273,7 +2300,7 @@ An example is the subgroup operations such as `intel_sub_group_shuffle
|
||||
|
||||
// Define custom my_sub_group_shuffle(data, c)
|
||||
// that makes use of intel_sub_group_shuffle
|
||||
r1 = …
|
||||
r1 = ...
|
||||
if (r0) r1 = computeA();
|
||||
// Shuffle data from r1 into r3
|
||||
// of threads id r2.
|
||||
@ -2284,7 +2311,7 @@ with non-SPMD semantics this is optimized to the following equivalent code:
|
||||
|
||||
.. code-block:: c
|
||||
|
||||
r1 = …
|
||||
r1 = ...
|
||||
if (!r0)
|
||||
// Incorrect functionality! The data in r1
|
||||
// have not been computed by all threads yet.
|
||||
@ -2499,7 +2526,7 @@ official `MinGW-w64 website <http://mingw-w64.sourceforge.net>`_.
|
||||
Clang expects the GCC executable "gcc.exe" compiled for
|
||||
``i686-w64-mingw32`` (or ``x86_64-w64-mingw32``) to be present on PATH.
|
||||
|
||||
`Some tests might fail <http://llvm.org/bugs/show_bug.cgi?id=9072>`_ on
|
||||
`Some tests might fail <https://bugs.llvm.org/show_bug.cgi?id=9072>`_ on
|
||||
``x86_64-w64-mingw32``.
|
||||
|
||||
.. _clang-cl:
|
||||
@ -2542,7 +2569,7 @@ options are spelled with a leading ``/``, they will be mistaken for a filename:
|
||||
|
||||
clang-cl.exe: error: no such file or directory: '/foobar'
|
||||
|
||||
Please `file a bug <http://llvm.org/bugs/enter_bug.cgi?product=clang&component=Driver>`_
|
||||
Please `file a bug <https://bugs.llvm.org/enter_bug.cgi?product=clang&component=Driver>`_
|
||||
for any valid cl.exe flags that clang-cl does not understand.
|
||||
|
||||
Execute ``clang-cl /?`` to see a list of supported options:
|
||||
|
@ -178,15 +178,21 @@ ExprInspection checks
|
||||
This function explains the value of its argument in a human-readable manner
|
||||
in the warning message. You can make as many overrides of its prototype
|
||||
in the test code as necessary to explain various integral, pointer,
|
||||
or even record-type values.
|
||||
or even record-type values. To simplify usage in C code (where overloading
|
||||
the function declaration is not allowed), you may append an arbitrary suffix
|
||||
to the function name, without affecting functionality.
|
||||
|
||||
Example usage::
|
||||
|
||||
void clang_analyzer_explain(int);
|
||||
void clang_analyzer_explain(void *);
|
||||
|
||||
// Useful in C code
|
||||
void clang_analyzer_explain_int(int);
|
||||
|
||||
void foo(int param, void *ptr) {
|
||||
clang_analyzer_explain(param); // expected-warning{{argument 'param'}}
|
||||
clang_analyzer_explain_int(param); // expected-warning{{argument 'param'}}
|
||||
if (!ptr)
|
||||
clang_analyzer_explain(ptr); // expected-warning{{memory address '0'}}
|
||||
}
|
||||
|
@ -48,10 +48,10 @@
|
||||
# |version| and |release|, also used in various other places throughout the
|
||||
# built documents.
|
||||
#
|
||||
# The short X.Y version.
|
||||
version = '4.0'
|
||||
# The short version.
|
||||
version = '5'
|
||||
# The full version, including alpha/beta/rc tags.
|
||||
release = '4.0'
|
||||
release = '5'
|
||||
|
||||
# The language for content autogenerated by Sphinx. Refer to documentation
|
||||
# for a list of supported languages.
|
||||
|
@ -48,10 +48,10 @@
|
||||
# |version| and |release|, also used in various other places throughout the
|
||||
# built documents.
|
||||
#
|
||||
# The short X.Y version.
|
||||
version = '4'
|
||||
# The short version.
|
||||
version = '5'
|
||||
# The full version, including alpha/beta/rc tags.
|
||||
release = '4'
|
||||
release = '5'
|
||||
|
||||
# The language for content autogenerated by Sphinx. Refer to documentation
|
||||
# for a list of supported languages.
|
||||
|
@ -1885,7 +1885,7 @@ ENABLE_PREPROCESSING = YES
|
||||
# The default value is: NO.
|
||||
# This tag requires that the tag ENABLE_PREPROCESSING is set to YES.
|
||||
|
||||
MACRO_EXPANSION = NO
|
||||
MACRO_EXPANSION = YES
|
||||
|
||||
# If the EXPAND_ONLY_PREDEF and MACRO_EXPANSION tags are both set to YES then
|
||||
# the macro expansion is limited to the macros specified with the PREDEFINED and
|
||||
@ -1893,7 +1893,7 @@ MACRO_EXPANSION = NO
|
||||
# The default value is: NO.
|
||||
# This tag requires that the tag ENABLE_PREPROCESSING is set to YES.
|
||||
|
||||
EXPAND_ONLY_PREDEF = NO
|
||||
EXPAND_ONLY_PREDEF = YES
|
||||
|
||||
# If the SEARCH_INCLUDES tag is set to YES the includes files in the
|
||||
# INCLUDE_PATH will be searched if a #include is found.
|
||||
@ -1925,7 +1925,7 @@ INCLUDE_FILE_PATTERNS =
|
||||
# recursively expanded use the := operator instead of the = operator.
|
||||
# This tag requires that the tag ENABLE_PREPROCESSING is set to YES.
|
||||
|
||||
PREDEFINED =
|
||||
PREDEFINED = LLVM_ALIGNAS(x)=
|
||||
|
||||
# If the MACRO_EXPANSION and EXPAND_ONLY_PREDEF tags are set to YES then this
|
||||
# tag can be used to specify a list of macro names that should be expanded. The
|
||||
|
@ -19,6 +19,7 @@ Using Clang as a Compiler
|
||||
UsersManual
|
||||
Toolchain
|
||||
LanguageExtensions
|
||||
ClangCommandLineReference
|
||||
AttributeReference
|
||||
DiagnosticsReference
|
||||
CrossCompilation
|
||||
|
@ -19,7 +19,6 @@ def substitute(text, tag, contents):
|
||||
return re.sub(pattern, '%s', text, flags=re.S) % replacement
|
||||
|
||||
def doxygen2rst(text):
|
||||
text = re.sub(r'([^/\*])\*', r'\1\\*', text)
|
||||
text = re.sub(r'<tt>\s*(.*?)\s*<\/tt>', r'``\1``', text)
|
||||
text = re.sub(r'\\c ([^ ,;\.]+)', r'``\1``', text)
|
||||
text = re.sub(r'\\\w+ ', '', text)
|
||||
@ -65,7 +64,7 @@ def __init__(self, name, comment):
|
||||
self.comment = comment.strip()
|
||||
|
||||
def __str__(self):
|
||||
return '* ``%s`` %s' % (self.name, doxygen2rst(self.comment))
|
||||
return '\n* ``%s`` %s' % (self.name, doxygen2rst(self.comment))
|
||||
|
||||
class Enum:
|
||||
def __init__(self, name, comment):
|
||||
|
@ -3,6 +3,7 @@ set(LLVM_LINK_COMPONENTS
|
||||
ExecutionEngine
|
||||
MC
|
||||
MCJIT
|
||||
Option
|
||||
Support
|
||||
native
|
||||
)
|
||||
|
@ -478,8 +478,8 @@ CINDEX_LINKAGE void clang_getExpansionLocation(CXSourceLocation location,
|
||||
unsigned *offset);
|
||||
|
||||
/**
|
||||
* \brief Retrieve the file, line, column, and offset represented by
|
||||
* the given source location, as specified in a # line directive.
|
||||
* \brief Retrieve the file, line and column represented by the given source
|
||||
* location, as specified in a # line directive.
|
||||
*
|
||||
* Example: given the following source code in a file somefile.c
|
||||
*
|
||||
@ -3011,8 +3011,9 @@ enum CXTypeKind {
|
||||
CXType_ObjCClass = 28,
|
||||
CXType_ObjCSel = 29,
|
||||
CXType_Float128 = 30,
|
||||
CXType_Half = 31,
|
||||
CXType_FirstBuiltin = CXType_Void,
|
||||
CXType_LastBuiltin = CXType_ObjCSel,
|
||||
CXType_LastBuiltin = CXType_Half,
|
||||
|
||||
CXType_Complex = 100,
|
||||
CXType_Pointer = 101,
|
||||
@ -3435,6 +3436,16 @@ CINDEX_LINKAGE long long clang_getArraySize(CXType T);
|
||||
*/
|
||||
CINDEX_LINKAGE CXType clang_Type_getNamedType(CXType T);
|
||||
|
||||
/**
|
||||
* \brief Determine if a typedef is 'transparent' tag.
|
||||
*
|
||||
* A typedef is considered 'transparent' if it shares a name and spelling
|
||||
* location with its underlying tag type, as is the case with the NS_ENUM macro.
|
||||
*
|
||||
* \returns non-zero if transparent and zero otherwise.
|
||||
*/
|
||||
CINDEX_LINKAGE unsigned clang_Type_isTransparentTagTypedef(CXType T);
|
||||
|
||||
/**
|
||||
* \brief List the possible error codes for \c clang_Type_getSizeOf,
|
||||
* \c clang_Type_getAlignOf, \c clang_Type_getOffsetOf and
|
||||
@ -4023,8 +4034,8 @@ CINDEX_LINKAGE unsigned clang_Cursor_getObjCDeclQualifiers(CXCursor C);
|
||||
|
||||
/**
|
||||
* \brief Given a cursor that represents an Objective-C method or property
|
||||
* declaration, return non-zero if the declaration was affected by "@optional".
|
||||
* Returns zero if the cursor is not such a declaration or it is "@required".
|
||||
* declaration, return non-zero if the declaration was affected by "\@optional".
|
||||
* Returns zero if the cursor is not such a declaration or it is "\@required".
|
||||
*/
|
||||
CINDEX_LINKAGE unsigned clang_Cursor_isObjCOptional(CXCursor C);
|
||||
|
||||
@ -4700,7 +4711,7 @@ enum CXCompletionChunkKind {
|
||||
*/
|
||||
CXCompletionChunk_HorizontalSpace,
|
||||
/**
|
||||
* Vertical space ('\n'), after which it is generally a good idea to
|
||||
* Vertical space ('\\n'), after which it is generally a good idea to
|
||||
* perform indentation.
|
||||
*/
|
||||
CXCompletionChunk_VerticalSpace
|
||||
|
@ -39,6 +39,7 @@
|
||||
#include "clang/Basic/SanitizerBlacklist.h"
|
||||
#include "clang/Basic/SourceLocation.h"
|
||||
#include "clang/Basic/Specifiers.h"
|
||||
#include "clang/Basic/XRayLists.h"
|
||||
#include "llvm/ADT/APSInt.h"
|
||||
#include "llvm/ADT/ArrayRef.h"
|
||||
#include "llvm/ADT/DenseMap.h"
|
||||
@ -66,6 +67,7 @@
|
||||
#include <memory>
|
||||
#include <new>
|
||||
#include <string>
|
||||
#include <type_traits>
|
||||
#include <utility>
|
||||
#include <vector>
|
||||
|
||||
@ -167,18 +169,20 @@ class ASTContext : public RefCountedBase<ASTContext> {
|
||||
mutable llvm::FoldingSet<DependentUnaryTransformType>
|
||||
DependentUnaryTransformTypes;
|
||||
mutable llvm::FoldingSet<AutoType> AutoTypes;
|
||||
mutable llvm::FoldingSet<DeducedTemplateSpecializationType>
|
||||
DeducedTemplateSpecializationTypes;
|
||||
mutable llvm::FoldingSet<AtomicType> AtomicTypes;
|
||||
llvm::FoldingSet<AttributedType> AttributedTypes;
|
||||
mutable llvm::FoldingSet<PipeType> PipeTypes;
|
||||
|
||||
mutable llvm::FoldingSet<QualifiedTemplateName> QualifiedTemplateNames;
|
||||
mutable llvm::FoldingSet<DependentTemplateName> DependentTemplateNames;
|
||||
mutable llvm::FoldingSet<SubstTemplateTemplateParmStorage>
|
||||
mutable llvm::FoldingSet<SubstTemplateTemplateParmStorage>
|
||||
SubstTemplateTemplateParms;
|
||||
mutable llvm::ContextualFoldingSet<SubstTemplateTemplateParmPackStorage,
|
||||
ASTContext&>
|
||||
ASTContext&>
|
||||
SubstTemplateTemplateParmPacks;
|
||||
|
||||
|
||||
/// \brief The set of nested name specifiers.
|
||||
///
|
||||
/// This set is managed by the NestedNameSpecifier class.
|
||||
@ -200,17 +204,17 @@ class ASTContext : public RefCountedBase<ASTContext> {
|
||||
|
||||
/// \brief A cache mapping from CXXRecordDecls to key functions.
|
||||
llvm::DenseMap<const CXXRecordDecl*, LazyDeclPtr> KeyFunctions;
|
||||
|
||||
|
||||
/// \brief Mapping from ObjCContainers to their ObjCImplementations.
|
||||
llvm::DenseMap<ObjCContainerDecl*, ObjCImplDecl*> ObjCImpls;
|
||||
|
||||
|
||||
/// \brief Mapping from ObjCMethod to its duplicate declaration in the same
|
||||
/// interface.
|
||||
llvm::DenseMap<const ObjCMethodDecl*,const ObjCMethodDecl*> ObjCMethodRedecls;
|
||||
|
||||
/// \brief Mapping from __block VarDecls to their copy initialization expr.
|
||||
llvm::DenseMap<const VarDecl*, Expr*> BlockVarCopyInits;
|
||||
|
||||
|
||||
/// \brief Mapping from class scope functions specialization to their
|
||||
/// template patterns.
|
||||
llvm::DenseMap<const FunctionDecl*, FunctionDecl*>
|
||||
@ -226,21 +230,21 @@ class ASTContext : public RefCountedBase<ASTContext> {
|
||||
/// is used in canonical template names.
|
||||
class CanonicalTemplateTemplateParm : public llvm::FoldingSetNode {
|
||||
TemplateTemplateParmDecl *Parm;
|
||||
|
||||
|
||||
public:
|
||||
CanonicalTemplateTemplateParm(TemplateTemplateParmDecl *Parm)
|
||||
CanonicalTemplateTemplateParm(TemplateTemplateParmDecl *Parm)
|
||||
: Parm(Parm) { }
|
||||
|
||||
|
||||
TemplateTemplateParmDecl *getParam() const { return Parm; }
|
||||
|
||||
|
||||
void Profile(llvm::FoldingSetNodeID &ID) { Profile(ID, Parm); }
|
||||
|
||||
static void Profile(llvm::FoldingSetNodeID &ID,
|
||||
|
||||
static void Profile(llvm::FoldingSetNodeID &ID,
|
||||
TemplateTemplateParmDecl *Parm);
|
||||
};
|
||||
mutable llvm::FoldingSet<CanonicalTemplateTemplateParm>
|
||||
CanonTemplateTemplateParms;
|
||||
|
||||
|
||||
TemplateTemplateParmDecl *
|
||||
getCanonicalTemplateTemplateParmDecl(TemplateTemplateParmDecl *TTP) const;
|
||||
|
||||
@ -259,7 +263,7 @@ class ASTContext : public RefCountedBase<ASTContext> {
|
||||
|
||||
/// \brief The typedef for the predefined \c id type.
|
||||
mutable TypedefDecl *ObjCIdDecl;
|
||||
|
||||
|
||||
/// \brief The typedef for the predefined \c SEL type.
|
||||
mutable TypedefDecl *ObjCSelDecl;
|
||||
|
||||
@ -268,7 +272,7 @@ class ASTContext : public RefCountedBase<ASTContext> {
|
||||
|
||||
/// \brief The typedef for the predefined \c Protocol class in Objective-C.
|
||||
mutable ObjCInterfaceDecl *ObjCProtocolClassDecl;
|
||||
|
||||
|
||||
/// \brief The typedef for the predefined 'BOOL' type.
|
||||
mutable TypedefDecl *BOOLDecl;
|
||||
|
||||
@ -298,12 +302,12 @@ class ASTContext : public RefCountedBase<ASTContext> {
|
||||
mutable TypedefDecl *CFConstantStringTypeDecl;
|
||||
|
||||
mutable QualType ObjCSuperType;
|
||||
|
||||
|
||||
QualType ObjCNSStringType;
|
||||
|
||||
/// \brief The typedef declaration for the Objective-C "instancetype" type.
|
||||
TypedefDecl *ObjCInstanceTypeDecl;
|
||||
|
||||
|
||||
/// \brief The type for the C FILE type.
|
||||
TypeDecl *FILEDecl;
|
||||
|
||||
@ -451,11 +455,11 @@ class ASTContext : public RefCountedBase<ASTContext> {
|
||||
/// \brief Mapping that stores parameterIndex values for ParmVarDecls when
|
||||
/// that value exceeds the bitfield size of ParmVarDeclBits.ParameterIndex.
|
||||
typedef llvm::DenseMap<const VarDecl *, unsigned> ParameterIndexTable;
|
||||
ParameterIndexTable ParamIndices;
|
||||
|
||||
ParameterIndexTable ParamIndices;
|
||||
|
||||
ImportDecl *FirstLocalImport;
|
||||
ImportDecl *LastLocalImport;
|
||||
|
||||
|
||||
TranslationUnitDecl *TUDecl;
|
||||
mutable ExternCContextDecl *ExternCContext;
|
||||
mutable BuiltinTemplateDecl *MakeIntegerSeqDecl;
|
||||
@ -472,6 +476,10 @@ class ASTContext : public RefCountedBase<ASTContext> {
|
||||
/// entities should not be instrumented.
|
||||
std::unique_ptr<SanitizerBlacklist> SanitizerBL;
|
||||
|
||||
/// \brief Function filtering mechanism to determine whether a given function
|
||||
/// should be imbued with the XRay "always" or "never" attributes.
|
||||
std::unique_ptr<XRayFunctionFilter> XRayFilter;
|
||||
|
||||
/// \brief The allocator used to create AST objects.
|
||||
///
|
||||
/// AST objects are never destructed; rather, all memory associated with the
|
||||
@ -488,7 +496,7 @@ class ASTContext : public RefCountedBase<ASTContext> {
|
||||
/// \brief The logical -> physical address space map.
|
||||
const LangAS::Map *AddrSpaceMap;
|
||||
|
||||
/// \brief Address space map mangling must be used with language specific
|
||||
/// \brief Address space map mangling must be used with language specific
|
||||
/// address spaces (e.g. OpenCL/CUDA)
|
||||
bool AddrSpaceMapMangling;
|
||||
|
||||
@ -500,7 +508,7 @@ class ASTContext : public RefCountedBase<ASTContext> {
|
||||
const TargetInfo *Target;
|
||||
const TargetInfo *AuxTarget;
|
||||
clang::PrintingPolicy PrintingPolicy;
|
||||
|
||||
|
||||
public:
|
||||
IdentifierTable &Idents;
|
||||
SelectorTable &Selectors;
|
||||
@ -604,7 +612,7 @@ class ASTContext : public RefCountedBase<ASTContext> {
|
||||
void setPrintingPolicy(const clang::PrintingPolicy &Policy) {
|
||||
PrintingPolicy = Policy;
|
||||
}
|
||||
|
||||
|
||||
SourceManager& getSourceManager() { return SourceMgr; }
|
||||
const SourceManager& getSourceManager() const { return SourceMgr; }
|
||||
|
||||
@ -619,7 +627,7 @@ class ASTContext : public RefCountedBase<ASTContext> {
|
||||
return static_cast<T *>(Allocate(Num * sizeof(T), alignof(T)));
|
||||
}
|
||||
void Deallocate(void *Ptr) const { }
|
||||
|
||||
|
||||
/// Return the total amount of physical memory allocated for representing
|
||||
/// AST nodes and type information.
|
||||
size_t getASTAllocatedMemory() const {
|
||||
@ -627,7 +635,7 @@ class ASTContext : public RefCountedBase<ASTContext> {
|
||||
}
|
||||
/// Return the total memory used for various side tables.
|
||||
size_t getSideTableAllocatedMemory() const;
|
||||
|
||||
|
||||
PartialDiagnostic::StorageAllocator &getDiagAllocator() {
|
||||
return DiagAllocator;
|
||||
}
|
||||
@ -647,13 +655,17 @@ class ASTContext : public RefCountedBase<ASTContext> {
|
||||
QualType getRealTypeForBitwidth(unsigned DestWidth) const;
|
||||
|
||||
bool AtomicUsesUnsupportedLibcall(const AtomicExpr *E) const;
|
||||
|
||||
|
||||
const LangOptions& getLangOpts() const { return LangOpts; }
|
||||
|
||||
const SanitizerBlacklist &getSanitizerBlacklist() const {
|
||||
return *SanitizerBL;
|
||||
}
|
||||
|
||||
const XRayFunctionFilter &getXRayFilter() const {
|
||||
return *XRayFilter;
|
||||
}
|
||||
|
||||
DiagnosticsEngine &getDiagnostics() const;
|
||||
|
||||
FullSourceLoc getFullLoc(SourceLocation Loc) const {
|
||||
@ -862,7 +874,7 @@ class ASTContext : public RefCountedBase<ASTContext> {
|
||||
FieldDecl *getInstantiatedFromUnnamedFieldDecl(FieldDecl *Field);
|
||||
|
||||
void setInstantiatedFromUnnamedFieldDecl(FieldDecl *Inst, FieldDecl *Tmpl);
|
||||
|
||||
|
||||
// Access to the set of methods overridden by the given C++ method.
|
||||
typedef CXXMethodVector::const_iterator overridden_cxx_method_iterator;
|
||||
overridden_cxx_method_iterator
|
||||
@ -878,7 +890,7 @@ class ASTContext : public RefCountedBase<ASTContext> {
|
||||
|
||||
/// \brief Note that the given C++ \p Method overrides the given \p
|
||||
/// Overridden method.
|
||||
void addOverriddenMethod(const CXXMethodDecl *Method,
|
||||
void addOverriddenMethod(const CXXMethodDecl *Method,
|
||||
const CXXMethodDecl *Overridden);
|
||||
|
||||
/// \brief Return C++ or ObjC overridden methods for the given \p Method.
|
||||
@ -891,7 +903,7 @@ class ASTContext : public RefCountedBase<ASTContext> {
|
||||
void getOverriddenMethods(
|
||||
const NamedDecl *Method,
|
||||
SmallVectorImpl<const NamedDecl *> &Overridden) const;
|
||||
|
||||
|
||||
/// \brief Notify the AST context that a new import declaration has been
|
||||
/// parsed or implicitly created within this translation unit.
|
||||
void addedLocalImportDecl(ImportDecl *Import);
|
||||
@ -899,7 +911,7 @@ class ASTContext : public RefCountedBase<ASTContext> {
|
||||
static ImportDecl *getNextLocalImport(ImportDecl *Import) {
|
||||
return Import->NextLocalImport;
|
||||
}
|
||||
|
||||
|
||||
typedef llvm::iterator_range<import_iterator> import_range;
|
||||
import_range local_imports() const {
|
||||
return import_range(import_iterator(FirstLocalImport), import_iterator());
|
||||
@ -973,7 +985,7 @@ class ASTContext : public RefCountedBase<ASTContext> {
|
||||
CanQualType SingletonId;
|
||||
#include "clang/Basic/OpenCLImageTypes.def"
|
||||
CanQualType OCLSamplerTy, OCLEventTy, OCLClkEventTy;
|
||||
CanQualType OCLQueueTy, OCLNDRangeTy, OCLReserveIDTy;
|
||||
CanQualType OCLQueueTy, OCLReserveIDTy;
|
||||
CanQualType OMPArraySectionTy;
|
||||
|
||||
// Types for deductions in C++0x [stmt.ranged]'s desugaring. Built on demand.
|
||||
@ -1179,15 +1191,15 @@ class ASTContext : public RefCountedBase<ASTContext> {
|
||||
|
||||
/// Returns true iff we need copy/dispose helpers for the given type.
|
||||
bool BlockRequiresCopying(QualType Ty, const VarDecl *D);
|
||||
|
||||
|
||||
|
||||
|
||||
/// Returns true, if given type has a known lifetime. HasByrefExtendedLayout is set
|
||||
/// to false in this case. If HasByrefExtendedLayout returns true, byref variable
|
||||
/// has extended lifetime.
|
||||
/// has extended lifetime.
|
||||
bool getByrefLifetime(QualType Ty,
|
||||
Qualifiers::ObjCLifetime &Lifetime,
|
||||
bool &HasByrefExtendedLayout) const;
|
||||
|
||||
|
||||
/// \brief Return the uniqued reference to the type for an lvalue reference
|
||||
/// to the specified type.
|
||||
QualType getLValueReferenceType(QualType T, bool SpelledAsLValue = true)
|
||||
@ -1231,7 +1243,7 @@ class ASTContext : public RefCountedBase<ASTContext> {
|
||||
QualType getConstantArrayType(QualType EltTy, const llvm::APInt &ArySize,
|
||||
ArrayType::ArraySizeModifier ASM,
|
||||
unsigned IndexTypeQuals) const;
|
||||
|
||||
|
||||
/// \brief Returns a vla type where known sizes are replaced with [*].
|
||||
QualType getVariableArrayDecayedType(QualType Ty) const;
|
||||
|
||||
@ -1355,6 +1367,8 @@ class ASTContext : public RefCountedBase<ASTContext> {
|
||||
ElaboratedTypeKeyword Keyword, NestedNameSpecifier *NNS,
|
||||
const IdentifierInfo *Name, ArrayRef<TemplateArgument> Args) const;
|
||||
|
||||
TemplateArgument getInjectedTemplateArg(NamedDecl *ParamDecl);
|
||||
|
||||
/// Get a template argument list with one argument per template parameter
|
||||
/// in a template parameter list, such as for the injected class name of
|
||||
/// a class template.
|
||||
@ -1380,7 +1394,7 @@ class ASTContext : public RefCountedBase<ASTContext> {
|
||||
QualType getObjCTypeParamType(const ObjCTypeParamDecl *Decl,
|
||||
ArrayRef<ObjCProtocolDecl *> protocols,
|
||||
QualType Canonical = QualType()) const;
|
||||
|
||||
|
||||
bool ObjCObjectAdoptsQTypeProtocols(QualType QT, ObjCInterfaceDecl *Decl);
|
||||
/// QIdProtocolsAdoptObjCObjectProtocols - Checks that protocols in
|
||||
/// QT's qualified-id protocol list adopt all protocols in IDecl's list
|
||||
@ -1412,6 +1426,11 @@ class ASTContext : public RefCountedBase<ASTContext> {
|
||||
/// \brief C++11 deduction pattern for 'auto &&' type.
|
||||
QualType getAutoRRefDeductType() const;
|
||||
|
||||
/// \brief C++1z deduced class template specialization type.
|
||||
QualType getDeducedTemplateSpecializationType(TemplateName Template,
|
||||
QualType DeducedType,
|
||||
bool IsDependent) const;
|
||||
|
||||
/// \brief Return the unique reference to the type for the specified TagDecl
|
||||
/// (struct/union/class/enum) decl.
|
||||
QualType getTagDeclType(const TagDecl *Decl) const;
|
||||
@ -1471,11 +1490,11 @@ class ASTContext : public RefCountedBase<ASTContext> {
|
||||
|
||||
/// \brief Return the C structure type used to represent constant CFStrings.
|
||||
QualType getCFConstantStringType() const;
|
||||
|
||||
|
||||
/// \brief Returns the C struct type for objc_super
|
||||
QualType getObjCSuperType() const;
|
||||
void setObjCSuperType(QualType ST) { ObjCSuperType = ST; }
|
||||
|
||||
|
||||
/// Get the structure type used to representation CFStrings, or NULL
|
||||
/// if it hasn't yet been built.
|
||||
QualType getRawCFConstantStringType() const {
|
||||
@ -1496,11 +1515,11 @@ class ASTContext : public RefCountedBase<ASTContext> {
|
||||
QualType getObjCNSStringType() const {
|
||||
return ObjCNSStringType;
|
||||
}
|
||||
|
||||
|
||||
void setObjCNSStringType(QualType T) {
|
||||
ObjCNSStringType = T;
|
||||
}
|
||||
|
||||
|
||||
/// \brief Retrieve the type that \c id has been defined to, which may be
|
||||
/// different from the built-in \c id if \c id has been typedef'd.
|
||||
QualType getObjCIdRedefinitionType() const {
|
||||
@ -1508,7 +1527,7 @@ class ASTContext : public RefCountedBase<ASTContext> {
|
||||
return getObjCIdType();
|
||||
return ObjCIdRedefinitionType;
|
||||
}
|
||||
|
||||
|
||||
/// \brief Set the user-written type that redefines \c id.
|
||||
void setObjCIdRedefinitionType(QualType RedefType) {
|
||||
ObjCIdRedefinitionType = RedefType;
|
||||
@ -1521,7 +1540,7 @@ class ASTContext : public RefCountedBase<ASTContext> {
|
||||
return getObjCClassType();
|
||||
return ObjCClassRedefinitionType;
|
||||
}
|
||||
|
||||
|
||||
/// \brief Set the user-written type that redefines 'SEL'.
|
||||
void setObjCClassRedefinitionType(QualType RedefType) {
|
||||
ObjCClassRedefinitionType = RedefType;
|
||||
@ -1534,7 +1553,7 @@ class ASTContext : public RefCountedBase<ASTContext> {
|
||||
return getObjCSelType();
|
||||
return ObjCSelRedefinitionType;
|
||||
}
|
||||
|
||||
|
||||
/// \brief Set the user-written type that redefines 'SEL'.
|
||||
void setObjCSelRedefinitionType(QualType RedefType) {
|
||||
ObjCSelRedefinitionType = RedefType;
|
||||
@ -1586,7 +1605,7 @@ class ASTContext : public RefCountedBase<ASTContext> {
|
||||
/// \brief Retrieve the typedef declaration corresponding to the Objective-C
|
||||
/// "instancetype" type.
|
||||
TypedefDecl *getObjCInstanceTypeDecl();
|
||||
|
||||
|
||||
/// \brief Set the type for the C FILE type.
|
||||
void setFILEDecl(TypeDecl *FILEDecl) { this->FILEDecl = FILEDecl; }
|
||||
|
||||
@ -1671,7 +1690,7 @@ class ASTContext : public RefCountedBase<ASTContext> {
|
||||
|
||||
/// \brief Return the encoded type for this block declaration.
|
||||
std::string getObjCEncodingForBlock(const BlockExpr *blockExpr) const;
|
||||
|
||||
|
||||
/// getObjCEncodingForPropertyDecl - Return the encoded type for
|
||||
/// this method declaration. If non-NULL, Container must be either
|
||||
/// an ObjCCategoryImplDecl or ObjCImplementationDecl; it should
|
||||
@ -1681,7 +1700,7 @@ class ASTContext : public RefCountedBase<ASTContext> {
|
||||
|
||||
bool ProtocolCompatibleWithProtocol(ObjCProtocolDecl *lProto,
|
||||
ObjCProtocolDecl *rProto) const;
|
||||
|
||||
|
||||
ObjCPropertyImplDecl *getObjCPropertyImplDeclForPropertyDecl(
|
||||
const ObjCPropertyDecl *PD,
|
||||
const Decl *Container) const;
|
||||
@ -1693,7 +1712,7 @@ class ASTContext : public RefCountedBase<ASTContext> {
|
||||
/// \brief Retrieve the typedef corresponding to the predefined \c id type
|
||||
/// in Objective-C.
|
||||
TypedefDecl *getObjCIdDecl() const;
|
||||
|
||||
|
||||
/// \brief Represents the Objective-CC \c id type.
|
||||
///
|
||||
/// This is set up lazily, by Sema. \c id is always a (typedef for a)
|
||||
@ -1705,26 +1724,26 @@ class ASTContext : public RefCountedBase<ASTContext> {
|
||||
/// \brief Retrieve the typedef corresponding to the predefined 'SEL' type
|
||||
/// in Objective-C.
|
||||
TypedefDecl *getObjCSelDecl() const;
|
||||
|
||||
|
||||
/// \brief Retrieve the type that corresponds to the predefined Objective-C
|
||||
/// 'SEL' type.
|
||||
QualType getObjCSelType() const {
|
||||
QualType getObjCSelType() const {
|
||||
return getTypeDeclType(getObjCSelDecl());
|
||||
}
|
||||
|
||||
/// \brief Retrieve the typedef declaration corresponding to the predefined
|
||||
/// Objective-C 'Class' type.
|
||||
TypedefDecl *getObjCClassDecl() const;
|
||||
|
||||
|
||||
/// \brief Represents the Objective-C \c Class type.
|
||||
///
|
||||
/// This is set up lazily, by Sema. \c Class is always a (typedef for a)
|
||||
/// pointer type, a pointer to a struct.
|
||||
QualType getObjCClassType() const {
|
||||
QualType getObjCClassType() const {
|
||||
return getTypeDeclType(getObjCClassDecl());
|
||||
}
|
||||
|
||||
/// \brief Retrieve the Objective-C class declaration corresponding to
|
||||
/// \brief Retrieve the Objective-C class declaration corresponding to
|
||||
/// the predefined \c Protocol class.
|
||||
ObjCInterfaceDecl *getObjCProtocolDecl() const;
|
||||
|
||||
@ -1742,12 +1761,12 @@ class ASTContext : public RefCountedBase<ASTContext> {
|
||||
QualType getBOOLType() const {
|
||||
return getTypeDeclType(getBOOLDecl());
|
||||
}
|
||||
|
||||
|
||||
/// \brief Retrieve the type of the Objective-C \c Protocol class.
|
||||
QualType getObjCProtoType() const {
|
||||
return getObjCInterfaceType(getObjCProtocolDecl());
|
||||
}
|
||||
|
||||
|
||||
/// \brief Retrieve the C type declaration corresponding to the predefined
|
||||
/// \c __builtin_va_list type.
|
||||
TypedefDecl *getBuiltinVaListDecl() const;
|
||||
@ -1810,7 +1829,7 @@ class ASTContext : public RefCountedBase<ASTContext> {
|
||||
qs.addObjCLifetime(lifetime);
|
||||
return getQualifiedType(type, qs);
|
||||
}
|
||||
|
||||
|
||||
/// getUnqualifiedObjCPointerType - Returns version of
|
||||
/// Objective-C pointer type with lifetime qualifier removed.
|
||||
QualType getUnqualifiedObjCPointerType(QualType type) const {
|
||||
@ -1821,7 +1840,7 @@ class ASTContext : public RefCountedBase<ASTContext> {
|
||||
Qs.removeObjCLifetime();
|
||||
return getQualifiedType(type.getUnqualifiedType(), Qs);
|
||||
}
|
||||
|
||||
|
||||
DeclarationNameInfo getNameForTemplate(TemplateName Name,
|
||||
SourceLocation NameLoc) const;
|
||||
|
||||
@ -1840,7 +1859,7 @@ class ASTContext : public RefCountedBase<ASTContext> {
|
||||
TemplateName replacement) const;
|
||||
TemplateName getSubstTemplateTemplateParmPack(TemplateTemplateParmDecl *Param,
|
||||
const TemplateArgument &ArgPack) const;
|
||||
|
||||
|
||||
enum GetBuiltinTypeError {
|
||||
GE_None, ///< No error
|
||||
GE_Missing_stdio, ///< Missing a type from <stdio.h>
|
||||
@ -1905,7 +1924,7 @@ class ASTContext : public RefCountedBase<ASTContext> {
|
||||
uint64_t getCharWidth() const {
|
||||
return getTypeSize(CharTy);
|
||||
}
|
||||
|
||||
|
||||
/// \brief Convert a size in bits to a size in characters.
|
||||
CharUnits toCharUnitsFromBits(int64_t BitSize) const;
|
||||
|
||||
@ -1927,11 +1946,11 @@ class ASTContext : public RefCountedBase<ASTContext> {
|
||||
/// example, from alignment attributes).
|
||||
unsigned getTypeAlignIfKnown(QualType T) const;
|
||||
|
||||
/// \brief Return the ABI-specified alignment of a (complete) type \p T, in
|
||||
/// \brief Return the ABI-specified alignment of a (complete) type \p T, in
|
||||
/// characters.
|
||||
CharUnits getTypeAlignInChars(QualType T) const;
|
||||
CharUnits getTypeAlignInChars(const Type *T) const;
|
||||
|
||||
|
||||
// getTypeInfoDataSizeInChars - Return the size of a type, in chars. If the
|
||||
// type is a record, its data size is returned.
|
||||
std::pair<CharUnits, CharUnits> getTypeInfoDataSizeInChars(QualType T) const;
|
||||
@ -2036,10 +2055,10 @@ class ASTContext : public RefCountedBase<ASTContext> {
|
||||
VTableContextBase *getVTableContext();
|
||||
|
||||
MangleContext *createMangleContext();
|
||||
|
||||
|
||||
void DeepCollectObjCIvars(const ObjCInterfaceDecl *OI, bool leafClass,
|
||||
SmallVectorImpl<const ObjCIvarDecl*> &Ivars) const;
|
||||
|
||||
|
||||
unsigned CountNonClassIvars(const ObjCInterfaceDecl *OI) const;
|
||||
void CollectInheritedProtocols(const Decl *CDecl,
|
||||
llvm::SmallPtrSet<ObjCProtocolDecl*, 8> &Protocols);
|
||||
@ -2115,7 +2134,7 @@ class ASTContext : public RefCountedBase<ASTContext> {
|
||||
*SubTnullability == NullabilityKind::Unspecified ||
|
||||
*SuperTnullability == NullabilityKind::Unspecified)
|
||||
return true;
|
||||
|
||||
|
||||
if (IsParam) {
|
||||
// Ok for the superclass method parameter to be "nonnull" and the subclass
|
||||
// method parameter to be "nullable"
|
||||
@ -2134,9 +2153,9 @@ class ASTContext : public RefCountedBase<ASTContext> {
|
||||
|
||||
bool ObjCMethodsAreEqual(const ObjCMethodDecl *MethodDecl,
|
||||
const ObjCMethodDecl *MethodImp);
|
||||
|
||||
|
||||
bool UnwrapSimilarPointerTypes(QualType &T1, QualType &T2);
|
||||
|
||||
|
||||
/// \brief Retrieves the "canonical" nested name specifier for a
|
||||
/// given nested name specifier.
|
||||
///
|
||||
@ -2190,7 +2209,7 @@ class ASTContext : public RefCountedBase<ASTContext> {
|
||||
/// \brief Determine whether the given template names refer to the same
|
||||
/// template.
|
||||
bool hasSameTemplateName(TemplateName X, TemplateName Y);
|
||||
|
||||
|
||||
/// \brief Retrieve the "canonical" template argument.
|
||||
///
|
||||
/// The canonical template argument is the simplest template argument
|
||||
@ -2217,7 +2236,7 @@ class ASTContext : public RefCountedBase<ASTContext> {
|
||||
const {
|
||||
return dyn_cast_or_null<DependentSizedArrayType>(getAsArrayType(T));
|
||||
}
|
||||
|
||||
|
||||
/// \brief Return the innermost element type of an array type.
|
||||
///
|
||||
/// For example, will return "int" for int[m][n]
|
||||
@ -2236,14 +2255,14 @@ class ASTContext : public RefCountedBase<ASTContext> {
|
||||
/// parameter type used by semantic analysis (C99 6.7.5.3p[7,8],
|
||||
/// C++ [dcl.fct]p3). The adjusted parameter type is returned.
|
||||
QualType getAdjustedParameterType(QualType T) const;
|
||||
|
||||
|
||||
/// \brief Retrieve the parameter type as adjusted for use in the signature
|
||||
/// of a function, decaying array and function types and removing top-level
|
||||
/// cv-qualifiers.
|
||||
QualType getSignatureParameterType(QualType T) const;
|
||||
|
||||
|
||||
QualType getExceptionObjectType(QualType T) const;
|
||||
|
||||
|
||||
/// \brief Return the properly qualified result of decaying the specified
|
||||
/// array type to a pointer.
|
||||
///
|
||||
@ -2269,7 +2288,7 @@ class ASTContext : public RefCountedBase<ASTContext> {
|
||||
/// promotion occurs.
|
||||
QualType isPromotableBitField(Expr *E) const;
|
||||
|
||||
/// \brief Return the highest ranked integer type, see C99 6.3.1.8p1.
|
||||
/// \brief Return the highest ranked integer type, see C99 6.3.1.8p1.
|
||||
///
|
||||
/// If \p LHS > \p RHS, returns 1. If \p LHS == \p RHS, returns 0. If
|
||||
/// \p LHS < \p RHS, return -1.
|
||||
@ -2298,12 +2317,7 @@ class ASTContext : public RefCountedBase<ASTContext> {
|
||||
return getTargetAddressSpace(Q.getAddressSpace());
|
||||
}
|
||||
|
||||
unsigned getTargetAddressSpace(unsigned AS) const {
|
||||
if (AS < LangAS::Offset || AS >= LangAS::Offset + LangAS::Count)
|
||||
return AS;
|
||||
else
|
||||
return (*AddrSpaceMap)[AS - LangAS::Offset];
|
||||
}
|
||||
unsigned getTargetAddressSpace(unsigned AS) const;
|
||||
|
||||
/// Get target-dependent integer value for null pointer which is used for
|
||||
/// constant folding.
|
||||
@ -2311,8 +2325,7 @@ class ASTContext : public RefCountedBase<ASTContext> {
|
||||
|
||||
bool addressSpaceMapManglingFor(unsigned AS) const {
|
||||
return AddrSpaceMapMangling ||
|
||||
AS < LangAS::Offset ||
|
||||
AS >= LangAS::Offset + LangAS::Count;
|
||||
AS >= LangAS::Count;
|
||||
}
|
||||
|
||||
private:
|
||||
@ -2325,11 +2338,11 @@ class ASTContext : public RefCountedBase<ASTContext> {
|
||||
//===--------------------------------------------------------------------===//
|
||||
|
||||
/// Compatibility predicates used to check assignment expressions.
|
||||
bool typesAreCompatible(QualType T1, QualType T2,
|
||||
bool typesAreCompatible(QualType T1, QualType T2,
|
||||
bool CompareUnqualified = false); // C99 6.2.7p1
|
||||
|
||||
bool propertyTypesAreCompatible(QualType, QualType);
|
||||
bool typesAreBlockPointerCompatible(QualType, QualType);
|
||||
bool propertyTypesAreCompatible(QualType, QualType);
|
||||
bool typesAreBlockPointerCompatible(QualType, QualType);
|
||||
|
||||
bool isObjCIdType(QualType T) const {
|
||||
return T == getObjCIdType();
|
||||
@ -2344,7 +2357,7 @@ class ASTContext : public RefCountedBase<ASTContext> {
|
||||
bool ForCompare);
|
||||
|
||||
bool ObjCQualifiedClassTypesAreCompatible(QualType LHS, QualType RHS);
|
||||
|
||||
|
||||
// Check the safety of assignment from LHS to RHS
|
||||
bool canAssignObjCInterfaces(const ObjCObjectPointerType *LHSOPT,
|
||||
const ObjCObjectPointerType *RHSOPT);
|
||||
@ -2370,9 +2383,9 @@ class ASTContext : public RefCountedBase<ASTContext> {
|
||||
QualType mergeTransparentUnionType(QualType, QualType,
|
||||
bool OfBlockPointer=false,
|
||||
bool Unqualified = false);
|
||||
|
||||
|
||||
QualType mergeObjCGCQualifiers(QualType, QualType);
|
||||
|
||||
|
||||
bool doFunctionTypesMatchOnExtParameterInfos(
|
||||
const FunctionProtoType *FromFunctionType,
|
||||
const FunctionProtoType *ToFunctionType);
|
||||
@ -2442,7 +2455,7 @@ class ASTContext : public RefCountedBase<ASTContext> {
|
||||
/// an Objective-C method/property/ivar etc. that is part of an interface,
|
||||
/// otherwise returns null.
|
||||
const ObjCInterfaceDecl *getObjContainingInterface(const NamedDecl *ND) const;
|
||||
|
||||
|
||||
/// \brief Set the copy inialization expression of a block var decl.
|
||||
void setBlockVarCopyInits(VarDecl*VD, Expr* Init);
|
||||
/// \brief Get the copy initialization expression of the VarDecl \p VD, or
|
||||
@ -2466,10 +2479,10 @@ class ASTContext : public RefCountedBase<ASTContext> {
|
||||
/// initialized to a given location, which defaults to the empty
|
||||
/// location.
|
||||
TypeSourceInfo *
|
||||
getTrivialTypeSourceInfo(QualType T,
|
||||
getTrivialTypeSourceInfo(QualType T,
|
||||
SourceLocation Loc = SourceLocation()) const;
|
||||
|
||||
/// \brief Add a deallocation callback that will be invoked when the
|
||||
/// \brief Add a deallocation callback that will be invoked when the
|
||||
/// ASTContext is destroyed.
|
||||
///
|
||||
/// \param Callback A callback function that will be invoked on destruction.
|
||||
@ -2478,6 +2491,16 @@ class ASTContext : public RefCountedBase<ASTContext> {
|
||||
/// when it is called.
|
||||
void AddDeallocation(void (*Callback)(void*), void *Data);
|
||||
|
||||
/// If T isn't trivially destructible, calls AddDeallocation to register it
|
||||
/// for destruction.
|
||||
template <typename T>
|
||||
void addDestruction(T *Ptr) {
|
||||
if (!std::is_trivially_destructible<T>::value) {
|
||||
auto DestroyPtr = [](void *V) { static_cast<T *>(V)->~T(); };
|
||||
AddDeallocation(DestroyPtr, Ptr);
|
||||
}
|
||||
}
|
||||
|
||||
GVALinkage GetGVALinkageForFunction(const FunctionDecl *FD) const;
|
||||
GVALinkage GetGVALinkageForVariable(const VarDecl *VD);
|
||||
|
||||
@ -2534,15 +2557,15 @@ class ASTContext : public RefCountedBase<ASTContext> {
|
||||
|
||||
/// \brief The number of implicitly-declared default constructors.
|
||||
static unsigned NumImplicitDefaultConstructors;
|
||||
|
||||
/// \brief The number of implicitly-declared default constructors for
|
||||
|
||||
/// \brief The number of implicitly-declared default constructors for
|
||||
/// which declarations were built.
|
||||
static unsigned NumImplicitDefaultConstructorsDeclared;
|
||||
|
||||
/// \brief The number of implicitly-declared copy constructors.
|
||||
static unsigned NumImplicitCopyConstructors;
|
||||
|
||||
/// \brief The number of implicitly-declared copy constructors for
|
||||
|
||||
/// \brief The number of implicitly-declared copy constructors for
|
||||
/// which declarations were built.
|
||||
static unsigned NumImplicitCopyConstructorsDeclared;
|
||||
|
||||
@ -2555,25 +2578,25 @@ class ASTContext : public RefCountedBase<ASTContext> {
|
||||
|
||||
/// \brief The number of implicitly-declared copy assignment operators.
|
||||
static unsigned NumImplicitCopyAssignmentOperators;
|
||||
|
||||
/// \brief The number of implicitly-declared copy assignment operators for
|
||||
|
||||
/// \brief The number of implicitly-declared copy assignment operators for
|
||||
/// which declarations were built.
|
||||
static unsigned NumImplicitCopyAssignmentOperatorsDeclared;
|
||||
|
||||
/// \brief The number of implicitly-declared move assignment operators.
|
||||
static unsigned NumImplicitMoveAssignmentOperators;
|
||||
|
||||
/// \brief The number of implicitly-declared move assignment operators for
|
||||
|
||||
/// \brief The number of implicitly-declared move assignment operators for
|
||||
/// which declarations were built.
|
||||
static unsigned NumImplicitMoveAssignmentOperatorsDeclared;
|
||||
|
||||
/// \brief The number of implicitly-declared destructors.
|
||||
static unsigned NumImplicitDestructors;
|
||||
|
||||
/// \brief The number of implicitly-declared destructors for which
|
||||
|
||||
/// \brief The number of implicitly-declared destructors for which
|
||||
/// declarations were built.
|
||||
static unsigned NumImplicitDestructorsDeclared;
|
||||
|
||||
|
||||
public:
|
||||
/// \brief Initialize built-in types.
|
||||
///
|
||||
|
@ -22,6 +22,7 @@
|
||||
#include "llvm/ADT/PointerIntPair.h"
|
||||
#include "llvm/Support/type_traits.h"
|
||||
#include <algorithm>
|
||||
#include <cstddef>
|
||||
#include <cstring>
|
||||
#include <memory>
|
||||
|
||||
|
@ -169,9 +169,6 @@ BUILTIN_TYPE(OCLClkEvent, OCLClkEventTy)
|
||||
// OpenCL queue_t.
|
||||
BUILTIN_TYPE(OCLQueue, OCLQueueTy)
|
||||
|
||||
// OpenCL ndrange_t.
|
||||
BUILTIN_TYPE(OCLNDRange, OCLNDRangeTy)
|
||||
|
||||
// OpenCL reserve_id_t.
|
||||
BUILTIN_TYPE(OCLReserveID, OCLReserveIDTy)
|
||||
|
||||
|
@ -838,7 +838,7 @@ class VarDecl : public DeclaratorDecl, public Redeclarable<VarDecl> {
|
||||
|
||||
/// Describes the kind of default argument for this parameter. By default
|
||||
/// this is none. If this is normal, then the default argument is stored in
|
||||
/// the \c VarDecl initalizer expression unless we were unble to parse
|
||||
/// the \c VarDecl initializer expression unless we were unable to parse
|
||||
/// (even an invalid) expression for the default argument.
|
||||
unsigned DefaultArgKind : 2;
|
||||
|
||||
@ -1605,9 +1605,14 @@ class FunctionDecl : public DeclaratorDecl, public DeclContext,
|
||||
|
||||
// FIXME: This can be packed into the bitfields in DeclContext.
|
||||
// NOTE: VC++ packs bitfields poorly if the types differ.
|
||||
unsigned SClass : 2;
|
||||
unsigned SClass : 3;
|
||||
unsigned IsInline : 1;
|
||||
unsigned IsInlineSpecified : 1;
|
||||
protected:
|
||||
// This is shared by CXXConstructorDecl, CXXConversionDecl, and
|
||||
// CXXDeductionGuideDecl.
|
||||
unsigned IsExplicitSpecified : 1;
|
||||
private:
|
||||
unsigned IsVirtualAsWritten : 1;
|
||||
unsigned IsPure : 1;
|
||||
unsigned HasInheritedPrototype : 1;
|
||||
@ -1708,8 +1713,9 @@ class FunctionDecl : public DeclaratorDecl, public DeclContext,
|
||||
StartLoc),
|
||||
DeclContext(DK), redeclarable_base(C), ParamInfo(nullptr), Body(),
|
||||
SClass(S), IsInline(isInlineSpecified),
|
||||
IsInlineSpecified(isInlineSpecified), IsVirtualAsWritten(false),
|
||||
IsPure(false), HasInheritedPrototype(false), HasWrittenPrototype(true),
|
||||
IsInlineSpecified(isInlineSpecified), IsExplicitSpecified(false),
|
||||
IsVirtualAsWritten(false), IsPure(false),
|
||||
HasInheritedPrototype(false), HasWrittenPrototype(true),
|
||||
IsDeleted(false), IsTrivial(false), IsDefaulted(false),
|
||||
IsExplicitlyDefaulted(false), HasImplicitReturnZero(false),
|
||||
IsLateTemplateParsed(false), IsConstexpr(isConstexprSpecified),
|
||||
@ -2635,12 +2641,17 @@ class TypedefNameDecl : public TypeDecl, public Redeclarable<TypedefNameDecl> {
|
||||
typedef std::pair<TypeSourceInfo*, QualType> ModedTInfo;
|
||||
llvm::PointerUnion<TypeSourceInfo*, ModedTInfo*> MaybeModedTInfo;
|
||||
|
||||
// FIXME: This can be packed into the bitfields in Decl.
|
||||
/// If 0, we have not computed IsTransparentTag.
|
||||
/// Otherwise, IsTransparentTag is (CacheIsTransparentTag >> 1).
|
||||
mutable unsigned CacheIsTransparentTag : 2;
|
||||
|
||||
protected:
|
||||
TypedefNameDecl(Kind DK, ASTContext &C, DeclContext *DC,
|
||||
SourceLocation StartLoc, SourceLocation IdLoc,
|
||||
IdentifierInfo *Id, TypeSourceInfo *TInfo)
|
||||
: TypeDecl(DK, DC, IdLoc, Id, StartLoc), redeclarable_base(C),
|
||||
MaybeModedTInfo(TInfo) {}
|
||||
MaybeModedTInfo(TInfo), CacheIsTransparentTag(0) {}
|
||||
|
||||
typedef Redeclarable<TypedefNameDecl> redeclarable_base;
|
||||
TypedefNameDecl *getNextRedeclarationImpl() override {
|
||||
@ -2693,11 +2704,22 @@ class TypedefNameDecl : public TypeDecl, public Redeclarable<TypedefNameDecl> {
|
||||
/// this typedef declaration.
|
||||
TagDecl *getAnonDeclWithTypedefName(bool AnyRedecl = false) const;
|
||||
|
||||
/// Determines if this typedef shares a name and spelling location with its
|
||||
/// underlying tag type, as is the case with the NS_ENUM macro.
|
||||
bool isTransparentTag() const {
|
||||
if (CacheIsTransparentTag)
|
||||
return CacheIsTransparentTag & 0x2;
|
||||
return isTransparentTagSlow();
|
||||
}
|
||||
|
||||
// Implement isa/cast/dyncast/etc.
|
||||
static bool classof(const Decl *D) { return classofKind(D->getKind()); }
|
||||
static bool classofKind(Kind K) {
|
||||
return K >= firstTypedefName && K <= lastTypedefName;
|
||||
}
|
||||
|
||||
private:
|
||||
bool isTransparentTagSlow() const;
|
||||
};
|
||||
|
||||
/// TypedefDecl - Represents the declaration of a typedef-name via the 'typedef'
|
||||
@ -3229,6 +3251,18 @@ class EnumDecl : public TagDecl {
|
||||
return isCompleteDefinition() || isFixed();
|
||||
}
|
||||
|
||||
/// Returns true if this enum is either annotated with
|
||||
/// enum_extensibility(closed) or isn't annotated with enum_extensibility.
|
||||
bool isClosed() const;
|
||||
|
||||
/// Returns true if this enum is annotated with flag_enum and isn't annotated
|
||||
/// with enum_extensibility(open).
|
||||
bool isClosedFlag() const;
|
||||
|
||||
/// Returns true if this enum is annotated with neither flag_enum nor
|
||||
/// enum_extensibility(open).
|
||||
bool isClosedNonFlag() const;
|
||||
|
||||
/// \brief Retrieve the enum definition from which this enumeration could
|
||||
/// be instantiated, if it is an instantiation (rather than a non-template).
|
||||
EnumDecl *getTemplateInstantiationPattern() const;
|
||||
|
@ -654,20 +654,19 @@ class LLVM_ALIGNAS(/*alignof(uint64_t)*/ 8) Decl {
|
||||
/// a precompiled header or module) rather than having been parsed.
|
||||
bool isFromASTFile() const { return FromASTFile; }
|
||||
|
||||
/// \brief Retrieve the global declaration ID associated with this
|
||||
/// declaration, which specifies where in the
|
||||
unsigned getGlobalID() const {
|
||||
/// \brief Retrieve the global declaration ID associated with this
|
||||
/// declaration, which specifies where this Decl was loaded from.
|
||||
unsigned getGlobalID() const {
|
||||
if (isFromASTFile())
|
||||
return *((const unsigned*)this - 1);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/// \brief Retrieve the global ID of the module that owns this particular
|
||||
/// declaration.
|
||||
unsigned getOwningModuleID() const {
|
||||
if (isFromASTFile())
|
||||
return *((const unsigned*)this - 2);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -1030,7 +1029,7 @@ class LLVM_ALIGNAS(/*alignof(uint64_t)*/ 8) Decl {
|
||||
void dump() const;
|
||||
// Same as dump(), but forces color printing.
|
||||
void dumpColor() const;
|
||||
void dump(raw_ostream &Out) const;
|
||||
void dump(raw_ostream &Out, bool Deserialize = false) const;
|
||||
|
||||
/// \brief Looks through the Decl's underlying type to extract a FunctionType
|
||||
/// when possible. Will return null if the type underlying the Decl does not
|
||||
@ -1811,7 +1810,8 @@ class DeclContext {
|
||||
|
||||
void dumpDeclContext() const;
|
||||
void dumpLookups() const;
|
||||
void dumpLookups(llvm::raw_ostream &OS, bool DumpDecls = false) const;
|
||||
void dumpLookups(llvm::raw_ostream &OS, bool DumpDecls = false,
|
||||
bool Deserialize = false) const;
|
||||
|
||||
private:
|
||||
void reconcileExternalVisibleStorage() const;
|
||||
|
@ -203,6 +203,11 @@ class CXXBaseSpecifier {
|
||||
SourceLocation getLocStart() const LLVM_READONLY { return Range.getBegin(); }
|
||||
SourceLocation getLocEnd() const LLVM_READONLY { return Range.getEnd(); }
|
||||
|
||||
/// \brief Get the location at which the base class type was written.
|
||||
SourceLocation getBaseTypeLoc() const LLVM_READONLY {
|
||||
return BaseTypeInfo->getTypeLoc().getLocStart();
|
||||
}
|
||||
|
||||
/// \brief Determines whether the base class is a virtual base class (or not).
|
||||
bool isVirtual() const { return Virtual; }
|
||||
|
||||
@ -436,9 +441,10 @@ class CXXRecordDecl : public RecordDecl {
|
||||
/// either by the user or implicitly.
|
||||
unsigned DeclaredSpecialMembers : 6;
|
||||
|
||||
/// \brief Whether an implicit copy constructor would have a const-qualified
|
||||
/// parameter.
|
||||
unsigned ImplicitCopyConstructorHasConstParam : 1;
|
||||
/// \brief Whether an implicit copy constructor could have a const-qualified
|
||||
/// parameter, for initializing virtual bases and for other subobjects.
|
||||
unsigned ImplicitCopyConstructorCanHaveConstParamForVBase : 1;
|
||||
unsigned ImplicitCopyConstructorCanHaveConstParamForNonVBase : 1;
|
||||
|
||||
/// \brief Whether an implicit copy assignment operator would have a
|
||||
/// const-qualified parameter.
|
||||
@ -458,6 +464,11 @@ class CXXRecordDecl : public RecordDecl {
|
||||
/// \brief Whether we are currently parsing base specifiers.
|
||||
unsigned IsParsingBaseSpecifiers : 1;
|
||||
|
||||
unsigned HasODRHash : 1;
|
||||
|
||||
/// \brief A hash of parts of the class to help in ODR checking.
|
||||
unsigned ODRHash;
|
||||
|
||||
/// \brief The number of base class specifiers in Bases.
|
||||
unsigned NumBases;
|
||||
|
||||
@ -703,6 +714,8 @@ class CXXRecordDecl : public RecordDecl {
|
||||
return data().IsParsingBaseSpecifiers;
|
||||
}
|
||||
|
||||
unsigned getODRHash() const;
|
||||
|
||||
/// \brief Sets the base classes of this struct or class.
|
||||
void setBases(CXXBaseSpecifier const * const *Bases, unsigned NumBases);
|
||||
|
||||
@ -871,7 +884,9 @@ class CXXRecordDecl : public RecordDecl {
|
||||
/// \brief Determine whether an implicit copy constructor for this type
|
||||
/// would have a parameter with a const-qualified reference type.
|
||||
bool implicitCopyConstructorHasConstParam() const {
|
||||
return data().ImplicitCopyConstructorHasConstParam;
|
||||
return data().ImplicitCopyConstructorCanHaveConstParamForNonVBase &&
|
||||
(isAbstract() ||
|
||||
data().ImplicitCopyConstructorCanHaveConstParamForVBase);
|
||||
}
|
||||
|
||||
/// \brief Determine whether this class has a copy constructor with
|
||||
@ -1738,6 +1753,58 @@ class CXXRecordDecl : public RecordDecl {
|
||||
friend class ASTWriter;
|
||||
};
|
||||
|
||||
/// \brief Represents a C++ deduction guide declaration.
|
||||
///
|
||||
/// \code
|
||||
/// template<typename T> struct A { A(); A(T); };
|
||||
/// A() -> A<int>;
|
||||
/// \endcode
|
||||
///
|
||||
/// In this example, there will be an explicit deduction guide from the
|
||||
/// second line, and implicit deduction guide templates synthesized from
|
||||
/// the constructors of \c A.
|
||||
class CXXDeductionGuideDecl : public FunctionDecl {
|
||||
void anchor() override;
|
||||
private:
|
||||
CXXDeductionGuideDecl(ASTContext &C, DeclContext *DC, SourceLocation StartLoc,
|
||||
bool IsExplicit, const DeclarationNameInfo &NameInfo,
|
||||
QualType T, TypeSourceInfo *TInfo,
|
||||
SourceLocation EndLocation)
|
||||
: FunctionDecl(CXXDeductionGuide, C, DC, StartLoc, NameInfo, T, TInfo,
|
||||
SC_None, false, false) {
|
||||
if (EndLocation.isValid())
|
||||
setRangeEnd(EndLocation);
|
||||
IsExplicitSpecified = IsExplicit;
|
||||
}
|
||||
|
||||
public:
|
||||
static CXXDeductionGuideDecl *Create(ASTContext &C, DeclContext *DC,
|
||||
SourceLocation StartLoc, bool IsExplicit,
|
||||
const DeclarationNameInfo &NameInfo,
|
||||
QualType T, TypeSourceInfo *TInfo,
|
||||
SourceLocation EndLocation);
|
||||
|
||||
static CXXDeductionGuideDecl *CreateDeserialized(ASTContext &C, unsigned ID);
|
||||
|
||||
/// Whether this deduction guide is explicit.
|
||||
bool isExplicit() const { return IsExplicitSpecified; }
|
||||
|
||||
/// Whether this deduction guide was declared with the 'explicit' specifier.
|
||||
bool isExplicitSpecified() const { return IsExplicitSpecified; }
|
||||
|
||||
/// Get the template for which this guide performs deduction.
|
||||
TemplateDecl *getDeducedTemplate() const {
|
||||
return getDeclName().getCXXDeductionGuideTemplate();
|
||||
}
|
||||
|
||||
// Implement isa/cast/dyncast/etc.
|
||||
static bool classof(const Decl *D) { return classofKind(D->getKind()); }
|
||||
static bool classofKind(Kind K) { return K == CXXDeductionGuide; }
|
||||
|
||||
friend class ASTDeclReader;
|
||||
friend class ASTDeclWriter;
|
||||
};
|
||||
|
||||
/// \brief Represents a static or instance method of a struct/union/class.
|
||||
///
|
||||
/// In the terminology of the C++ Standard, these are the (static and
|
||||
@ -2161,13 +2228,9 @@ class CXXConstructorDecl final
|
||||
/// \{
|
||||
/// \brief The arguments used to initialize the base or member.
|
||||
LazyCXXCtorInitializersPtr CtorInitializers;
|
||||
unsigned NumCtorInitializers : 30;
|
||||
unsigned NumCtorInitializers : 31;
|
||||
/// \}
|
||||
|
||||
/// \brief Whether this constructor declaration has the \c explicit keyword
|
||||
/// specified.
|
||||
unsigned IsExplicitSpecified : 1;
|
||||
|
||||
/// \brief Whether this constructor declaration is an implicitly-declared
|
||||
/// inheriting constructor.
|
||||
unsigned IsInheritingConstructor : 1;
|
||||
@ -2181,11 +2244,11 @@ class CXXConstructorDecl final
|
||||
: CXXMethodDecl(CXXConstructor, C, RD, StartLoc, NameInfo, T, TInfo,
|
||||
SC_None, isInline, isConstexpr, SourceLocation()),
|
||||
CtorInitializers(nullptr), NumCtorInitializers(0),
|
||||
IsExplicitSpecified(isExplicitSpecified),
|
||||
IsInheritingConstructor((bool)Inherited) {
|
||||
setImplicit(isImplicitlyDeclared);
|
||||
if (Inherited)
|
||||
*getTrailingObjects<InheritedConstructor>() = Inherited;
|
||||
IsExplicitSpecified = isExplicitSpecified;
|
||||
}
|
||||
|
||||
public:
|
||||
@ -2198,15 +2261,6 @@ class CXXConstructorDecl final
|
||||
bool isConstexpr,
|
||||
InheritedConstructor Inherited = InheritedConstructor());
|
||||
|
||||
/// \brief Determine whether this constructor declaration has the
|
||||
/// \c explicit keyword specified.
|
||||
bool isExplicitSpecified() const { return IsExplicitSpecified; }
|
||||
|
||||
/// \brief Determine whether this constructor was marked "explicit" or not.
|
||||
bool isExplicit() const {
|
||||
return cast<CXXConstructorDecl>(getFirstDecl())->isExplicitSpecified();
|
||||
}
|
||||
|
||||
/// \brief Iterates through the member/base initializer list.
|
||||
typedef CXXCtorInitializer **init_iterator;
|
||||
|
||||
@ -2270,6 +2324,14 @@ class CXXConstructorDecl final
|
||||
CtorInitializers = Initializers;
|
||||
}
|
||||
|
||||
/// Whether this function is marked as explicit explicitly.
|
||||
bool isExplicitSpecified() const { return IsExplicitSpecified; }
|
||||
|
||||
/// Whether this function is explicit.
|
||||
bool isExplicit() const {
|
||||
return getCanonicalDecl()->isExplicitSpecified();
|
||||
}
|
||||
|
||||
/// \brief Determine whether this constructor is a delegating constructor.
|
||||
bool isDelegatingConstructor() const {
|
||||
return (getNumCtorInitializers() == 1) &&
|
||||
@ -2405,7 +2467,14 @@ class CXXDestructorDecl : public CXXMethodDecl {
|
||||
|
||||
void setOperatorDelete(FunctionDecl *OD);
|
||||
const FunctionDecl *getOperatorDelete() const {
|
||||
return cast<CXXDestructorDecl>(getFirstDecl())->OperatorDelete;
|
||||
return getCanonicalDecl()->OperatorDelete;
|
||||
}
|
||||
|
||||
CXXDestructorDecl *getCanonicalDecl() override {
|
||||
return cast<CXXDestructorDecl>(FunctionDecl::getCanonicalDecl());
|
||||
}
|
||||
const CXXDestructorDecl *getCanonicalDecl() const {
|
||||
return const_cast<CXXDestructorDecl*>(this)->getCanonicalDecl();
|
||||
}
|
||||
|
||||
// Implement isa/cast/dyncast/etc.
|
||||
@ -2428,19 +2497,16 @@ class CXXDestructorDecl : public CXXMethodDecl {
|
||||
/// \endcode
|
||||
class CXXConversionDecl : public CXXMethodDecl {
|
||||
void anchor() override;
|
||||
/// Whether this conversion function declaration is marked
|
||||
/// "explicit", meaning that it can only be applied when the user
|
||||
/// explicitly wrote a cast. This is a C++11 feature.
|
||||
bool IsExplicitSpecified : 1;
|
||||
|
||||
CXXConversionDecl(ASTContext &C, CXXRecordDecl *RD, SourceLocation StartLoc,
|
||||
const DeclarationNameInfo &NameInfo,
|
||||
QualType T, TypeSourceInfo *TInfo,
|
||||
bool isInline, bool isExplicitSpecified,
|
||||
bool isConstexpr, SourceLocation EndLocation)
|
||||
: CXXMethodDecl(CXXConversion, C, RD, StartLoc, NameInfo, T, TInfo,
|
||||
SC_None, isInline, isConstexpr, EndLocation),
|
||||
IsExplicitSpecified(isExplicitSpecified) { }
|
||||
const DeclarationNameInfo &NameInfo, QualType T,
|
||||
TypeSourceInfo *TInfo, bool isInline,
|
||||
bool isExplicitSpecified, bool isConstexpr,
|
||||
SourceLocation EndLocation)
|
||||
: CXXMethodDecl(CXXConversion, C, RD, StartLoc, NameInfo, T, TInfo,
|
||||
SC_None, isInline, isConstexpr, EndLocation) {
|
||||
IsExplicitSpecified = isExplicitSpecified;
|
||||
}
|
||||
|
||||
public:
|
||||
static CXXConversionDecl *Create(ASTContext &C, CXXRecordDecl *RD,
|
||||
@ -2452,17 +2518,12 @@ class CXXConversionDecl : public CXXMethodDecl {
|
||||
SourceLocation EndLocation);
|
||||
static CXXConversionDecl *CreateDeserialized(ASTContext &C, unsigned ID);
|
||||
|
||||
/// Whether this conversion function declaration is marked
|
||||
/// "explicit", meaning that it can only be used for direct initialization
|
||||
/// (including explitly written casts). This is a C++11 feature.
|
||||
/// Whether this function is marked as explicit explicitly.
|
||||
bool isExplicitSpecified() const { return IsExplicitSpecified; }
|
||||
|
||||
/// \brief Whether this is an explicit conversion operator (C++11 and later).
|
||||
///
|
||||
/// Explicit conversion operators are only considered for direct
|
||||
/// initialization, e.g., when the user has explicitly written a cast.
|
||||
/// Whether this function is explicit.
|
||||
bool isExplicit() const {
|
||||
return cast<CXXConversionDecl>(getFirstDecl())->isExplicitSpecified();
|
||||
return getCanonicalDecl()->isExplicitSpecified();
|
||||
}
|
||||
|
||||
/// \brief Returns the type that this conversion function is converting to.
|
||||
@ -2474,6 +2535,13 @@ class CXXConversionDecl : public CXXMethodDecl {
|
||||
/// a lambda closure type to a block pointer.
|
||||
bool isLambdaToBlockPointerConversion() const;
|
||||
|
||||
CXXConversionDecl *getCanonicalDecl() override {
|
||||
return cast<CXXConversionDecl>(FunctionDecl::getCanonicalDecl());
|
||||
}
|
||||
const CXXConversionDecl *getCanonicalDecl() const {
|
||||
return const_cast<CXXConversionDecl*>(this)->getCanonicalDecl();
|
||||
}
|
||||
|
||||
// Implement isa/cast/dyncast/etc.
|
||||
static bool classof(const Decl *D) { return classofKind(D->getKind()); }
|
||||
static bool classofKind(Kind K) { return K == CXXConversion; }
|
||||
|
@ -131,7 +131,7 @@ struct StoredDeclsList {
|
||||
} else {
|
||||
DeclsTy &Vec = *getAsVector();
|
||||
Vec.erase(std::remove_if(Vec.begin(), Vec.end(),
|
||||
std::mem_fun(&Decl::isFromASTFile)),
|
||||
[](Decl *D) { return D->isFromASTFile(); }),
|
||||
Vec.end());
|
||||
// Don't have any external decls any more.
|
||||
Data = DeclsAndHasExternalTy(&Vec, false);
|
||||
|
@ -381,15 +381,17 @@ class ObjCMethodDecl : public NamedDecl, public DeclContext {
|
||||
ArrayRef<SourceLocation> SelLocs = llvm::None);
|
||||
|
||||
// Iterator access to parameter types.
|
||||
typedef std::const_mem_fun_t<QualType, ParmVarDecl> deref_fun;
|
||||
typedef llvm::mapped_iterator<param_const_iterator, deref_fun>
|
||||
param_type_iterator;
|
||||
struct GetTypeFn {
|
||||
QualType operator()(const ParmVarDecl *PD) const { return PD->getType(); }
|
||||
};
|
||||
typedef llvm::mapped_iterator<param_const_iterator, GetTypeFn>
|
||||
param_type_iterator;
|
||||
|
||||
param_type_iterator param_type_begin() const {
|
||||
return llvm::map_iterator(param_begin(), deref_fun(&ParmVarDecl::getType));
|
||||
return llvm::map_iterator(param_begin(), GetTypeFn());
|
||||
}
|
||||
param_type_iterator param_type_end() const {
|
||||
return llvm::map_iterator(param_end(), deref_fun(&ParmVarDecl::getType));
|
||||
return llvm::map_iterator(param_end(), GetTypeFn());
|
||||
}
|
||||
|
||||
/// createImplicitParams - Used to lazily create the self and cmd
|
||||
@ -743,6 +745,8 @@ class ObjCPropertyDecl : public NamedDecl {
|
||||
|
||||
Selector GetterName; // getter name of NULL if no getter
|
||||
Selector SetterName; // setter name of NULL if no setter
|
||||
SourceLocation GetterNameLoc; // location of the getter attribute's value
|
||||
SourceLocation SetterNameLoc; // location of the setter attribute's value
|
||||
|
||||
ObjCMethodDecl *GetterMethodDecl; // Declaration of getter instance method
|
||||
ObjCMethodDecl *SetterMethodDecl; // Declaration of setter instance method
|
||||
@ -855,10 +859,18 @@ class ObjCPropertyDecl : public NamedDecl {
|
||||
}
|
||||
|
||||
Selector getGetterName() const { return GetterName; }
|
||||
void setGetterName(Selector Sel) { GetterName = Sel; }
|
||||
SourceLocation getGetterNameLoc() const { return GetterNameLoc; }
|
||||
void setGetterName(Selector Sel, SourceLocation Loc = SourceLocation()) {
|
||||
GetterName = Sel;
|
||||
GetterNameLoc = Loc;
|
||||
}
|
||||
|
||||
Selector getSetterName() const { return SetterName; }
|
||||
void setSetterName(Selector Sel) { SetterName = Sel; }
|
||||
SourceLocation getSetterNameLoc() const { return SetterNameLoc; }
|
||||
void setSetterName(Selector Sel, SourceLocation Loc = SourceLocation()) {
|
||||
SetterName = Sel;
|
||||
SetterNameLoc = Loc;
|
||||
}
|
||||
|
||||
ObjCMethodDecl *getGetterMethodDecl() const { return GetterMethodDecl; }
|
||||
void setGetterMethodDecl(ObjCMethodDecl *gDecl) { GetterMethodDecl = gDecl; }
|
||||
@ -2320,11 +2332,9 @@ class ObjCImplDecl : public ObjCContainerDecl {
|
||||
protected:
|
||||
ObjCImplDecl(Kind DK, DeclContext *DC,
|
||||
ObjCInterfaceDecl *classInterface,
|
||||
IdentifierInfo *Id,
|
||||
SourceLocation nameLoc, SourceLocation atStartLoc)
|
||||
: ObjCContainerDecl(DK, DC,
|
||||
classInterface? classInterface->getIdentifier()
|
||||
: nullptr,
|
||||
nameLoc, atStartLoc),
|
||||
: ObjCContainerDecl(DK, DC, Id, nameLoc, atStartLoc),
|
||||
ClassInterface(classInterface) {}
|
||||
|
||||
public:
|
||||
@ -2386,9 +2396,6 @@ class ObjCImplDecl : public ObjCContainerDecl {
|
||||
class ObjCCategoryImplDecl : public ObjCImplDecl {
|
||||
void anchor() override;
|
||||
|
||||
// Category name
|
||||
IdentifierInfo *Id;
|
||||
|
||||
// Category name location
|
||||
SourceLocation CategoryNameLoc;
|
||||
|
||||
@ -2396,8 +2403,9 @@ class ObjCCategoryImplDecl : public ObjCImplDecl {
|
||||
ObjCInterfaceDecl *classInterface,
|
||||
SourceLocation nameLoc, SourceLocation atStartLoc,
|
||||
SourceLocation CategoryNameLoc)
|
||||
: ObjCImplDecl(ObjCCategoryImpl, DC, classInterface, nameLoc, atStartLoc),
|
||||
Id(Id), CategoryNameLoc(CategoryNameLoc) {}
|
||||
: ObjCImplDecl(ObjCCategoryImpl, DC, classInterface, Id,
|
||||
nameLoc, atStartLoc),
|
||||
CategoryNameLoc(CategoryNameLoc) {}
|
||||
public:
|
||||
static ObjCCategoryImplDecl *Create(ASTContext &C, DeclContext *DC,
|
||||
IdentifierInfo *Id,
|
||||
@ -2407,37 +2415,10 @@ class ObjCCategoryImplDecl : public ObjCImplDecl {
|
||||
SourceLocation CategoryNameLoc);
|
||||
static ObjCCategoryImplDecl *CreateDeserialized(ASTContext &C, unsigned ID);
|
||||
|
||||
/// getIdentifier - Get the identifier that names the category
|
||||
/// interface associated with this implementation.
|
||||
/// FIXME: This is a bad API, we are hiding NamedDecl::getIdentifier()
|
||||
/// with a different meaning. For example:
|
||||
/// ((NamedDecl *)SomeCategoryImplDecl)->getIdentifier()
|
||||
/// returns the class interface name, whereas
|
||||
/// ((ObjCCategoryImplDecl *)SomeCategoryImplDecl)->getIdentifier()
|
||||
/// returns the category name.
|
||||
IdentifierInfo *getIdentifier() const {
|
||||
return Id;
|
||||
}
|
||||
void setIdentifier(IdentifierInfo *II) { Id = II; }
|
||||
|
||||
ObjCCategoryDecl *getCategoryDecl() const;
|
||||
|
||||
SourceLocation getCategoryNameLoc() const { return CategoryNameLoc; }
|
||||
|
||||
/// getName - Get the name of identifier for the class interface associated
|
||||
/// with this implementation as a StringRef.
|
||||
//
|
||||
// FIXME: This is a bad API, we are hiding NamedDecl::getName with a different
|
||||
// meaning.
|
||||
StringRef getName() const { return Id ? Id->getName() : StringRef(); }
|
||||
|
||||
/// @brief Get the name of the class associated with this interface.
|
||||
//
|
||||
// FIXME: Deprecated, move clients to getName().
|
||||
std::string getNameAsString() const {
|
||||
return getName();
|
||||
}
|
||||
|
||||
static bool classof(const Decl *D) { return classofKind(D->getKind()); }
|
||||
static bool classofKind(Kind K) { return K == ObjCCategoryImpl;}
|
||||
|
||||
@ -2493,7 +2474,10 @@ class ObjCImplementationDecl : public ObjCImplDecl {
|
||||
SourceLocation superLoc = SourceLocation(),
|
||||
SourceLocation IvarLBraceLoc=SourceLocation(),
|
||||
SourceLocation IvarRBraceLoc=SourceLocation())
|
||||
: ObjCImplDecl(ObjCImplementation, DC, classInterface, nameLoc, atStartLoc),
|
||||
: ObjCImplDecl(ObjCImplementation, DC, classInterface,
|
||||
classInterface ? classInterface->getIdentifier()
|
||||
: nullptr,
|
||||
nameLoc, atStartLoc),
|
||||
SuperClass(superDecl), SuperLoc(superLoc), IvarLBraceLoc(IvarLBraceLoc),
|
||||
IvarRBraceLoc(IvarRBraceLoc),
|
||||
IvarInitializers(nullptr), NumIvarInitializers(0),
|
||||
|
@ -344,6 +344,32 @@ class DefaultArgStorage {
|
||||
// Kinds of Templates
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
/// \brief Stores the template parameter list and associated constraints for
|
||||
/// \c TemplateDecl objects that track associated constraints.
|
||||
class ConstrainedTemplateDeclInfo {
|
||||
friend TemplateDecl;
|
||||
|
||||
public:
|
||||
ConstrainedTemplateDeclInfo() : TemplateParams(), AssociatedConstraints() {}
|
||||
|
||||
TemplateParameterList *getTemplateParameters() const {
|
||||
return TemplateParams;
|
||||
}
|
||||
|
||||
Expr *getAssociatedConstraints() const { return AssociatedConstraints; }
|
||||
|
||||
protected:
|
||||
void setTemplateParameters(TemplateParameterList *TParams) {
|
||||
TemplateParams = TParams;
|
||||
}
|
||||
|
||||
void setAssociatedConstraints(Expr *AC) { AssociatedConstraints = AC; }
|
||||
|
||||
TemplateParameterList *TemplateParams;
|
||||
Expr *AssociatedConstraints;
|
||||
};
|
||||
|
||||
|
||||
/// \brief The base class of all kinds of template declarations (e.g.,
|
||||
/// class, function, etc.).
|
||||
///
|
||||
@ -352,33 +378,53 @@ class DefaultArgStorage {
|
||||
class TemplateDecl : public NamedDecl {
|
||||
void anchor() override;
|
||||
protected:
|
||||
// This is probably never used.
|
||||
TemplateDecl(Kind DK, DeclContext *DC, SourceLocation L, DeclarationName Name)
|
||||
: NamedDecl(DK, DC, L, Name), TemplatedDecl(nullptr, false),
|
||||
TemplateParams(nullptr) {}
|
||||
|
||||
// Construct a template decl with the given name and parameters.
|
||||
// Used when there is not templated element (tt-params).
|
||||
TemplateDecl(Kind DK, DeclContext *DC, SourceLocation L, DeclarationName Name,
|
||||
// Used when there is no templated element (e.g., for tt-params).
|
||||
TemplateDecl(ConstrainedTemplateDeclInfo *CTDI, Kind DK, DeclContext *DC,
|
||||
SourceLocation L, DeclarationName Name,
|
||||
TemplateParameterList *Params)
|
||||
: NamedDecl(DK, DC, L, Name), TemplatedDecl(nullptr, false),
|
||||
TemplateParams(Params) {}
|
||||
TemplateParams(CTDI) {
|
||||
this->setTemplateParameters(Params);
|
||||
}
|
||||
|
||||
TemplateDecl(Kind DK, DeclContext *DC, SourceLocation L, DeclarationName Name,
|
||||
TemplateParameterList *Params)
|
||||
: TemplateDecl(nullptr, DK, DC, L, Name, Params) {}
|
||||
|
||||
// Construct a template decl with name, parameters, and templated element.
|
||||
TemplateDecl(Kind DK, DeclContext *DC, SourceLocation L, DeclarationName Name,
|
||||
TemplateDecl(ConstrainedTemplateDeclInfo *CTDI, Kind DK, DeclContext *DC,
|
||||
SourceLocation L, DeclarationName Name,
|
||||
TemplateParameterList *Params, NamedDecl *Decl)
|
||||
: NamedDecl(DK, DC, L, Name), TemplatedDecl(Decl, false),
|
||||
TemplateParams(Params) {}
|
||||
TemplateParams(CTDI) {
|
||||
this->setTemplateParameters(Params);
|
||||
}
|
||||
|
||||
TemplateDecl(Kind DK, DeclContext *DC, SourceLocation L, DeclarationName Name,
|
||||
TemplateParameterList *Params, NamedDecl *Decl)
|
||||
: TemplateDecl(nullptr, DK, DC, L, Name, Params, Decl) {}
|
||||
|
||||
public:
|
||||
/// Get the list of template parameters
|
||||
TemplateParameterList *getTemplateParameters() const {
|
||||
return TemplateParams;
|
||||
const auto *const CTDI =
|
||||
TemplateParams.dyn_cast<ConstrainedTemplateDeclInfo *>();
|
||||
return CTDI ? CTDI->getTemplateParameters()
|
||||
: TemplateParams.get<TemplateParameterList *>();
|
||||
}
|
||||
|
||||
/// Get the constraint-expression from the associated requires-clause (if any)
|
||||
const Expr *getRequiresClause() const {
|
||||
return TemplateParams ? TemplateParams->getRequiresClause() : nullptr;
|
||||
const TemplateParameterList *const TP = getTemplateParameters();
|
||||
return TP ? TP->getRequiresClause() : nullptr;
|
||||
}
|
||||
|
||||
Expr *getAssociatedConstraints() const {
|
||||
const TemplateDecl *const C = cast<TemplateDecl>(getCanonicalDecl());
|
||||
const auto *const CTDI =
|
||||
C->TemplateParams.dyn_cast<ConstrainedTemplateDeclInfo *>();
|
||||
return CTDI ? CTDI->getAssociatedConstraints() : nullptr;
|
||||
}
|
||||
|
||||
/// Get the underlying, templated declaration.
|
||||
@ -391,7 +437,7 @@ class TemplateDecl : public NamedDecl {
|
||||
}
|
||||
|
||||
SourceRange getSourceRange() const override LLVM_READONLY {
|
||||
return SourceRange(TemplateParams->getTemplateLoc(),
|
||||
return SourceRange(getTemplateParameters()->getTemplateLoc(),
|
||||
TemplatedDecl.getPointer()->getSourceRange().getEnd());
|
||||
}
|
||||
|
||||
@ -407,7 +453,29 @@ class TemplateDecl : public NamedDecl {
|
||||
/// (function or variable) is a concept.
|
||||
llvm::PointerIntPair<NamedDecl *, 1, bool> TemplatedDecl;
|
||||
|
||||
TemplateParameterList* TemplateParams;
|
||||
/// \brief The template parameter list and optional requires-clause
|
||||
/// associated with this declaration; alternatively, a
|
||||
/// \c ConstrainedTemplateDeclInfo if the associated constraints of the
|
||||
/// template are being tracked by this particular declaration.
|
||||
llvm::PointerUnion<TemplateParameterList *,
|
||||
ConstrainedTemplateDeclInfo *>
|
||||
TemplateParams;
|
||||
|
||||
void setTemplateParameters(TemplateParameterList *TParams) {
|
||||
if (auto *const CTDI =
|
||||
TemplateParams.dyn_cast<ConstrainedTemplateDeclInfo *>()) {
|
||||
CTDI->setTemplateParameters(TParams);
|
||||
} else {
|
||||
TemplateParams = TParams;
|
||||
}
|
||||
}
|
||||
|
||||
void setAssociatedConstraints(Expr *AC) {
|
||||
assert(isCanonicalDecl() &&
|
||||
"Attaching associated constraints to non-canonical Decl");
|
||||
TemplateParams.get<ConstrainedTemplateDeclInfo *>()
|
||||
->setAssociatedConstraints(AC);
|
||||
}
|
||||
|
||||
public:
|
||||
/// \brief Initialize the underlying templated declaration and
|
||||
@ -737,11 +805,17 @@ class RedeclarableTemplateDecl : public TemplateDecl,
|
||||
virtual CommonBase *newCommon(ASTContext &C) const = 0;
|
||||
|
||||
// Construct a template decl with name, parameters, and templated element.
|
||||
RedeclarableTemplateDecl(ConstrainedTemplateDeclInfo *CTDI, Kind DK,
|
||||
ASTContext &C, DeclContext *DC, SourceLocation L,
|
||||
DeclarationName Name, TemplateParameterList *Params,
|
||||
NamedDecl *Decl)
|
||||
: TemplateDecl(CTDI, DK, DC, L, Name, Params, Decl), redeclarable_base(C),
|
||||
Common() {}
|
||||
|
||||
RedeclarableTemplateDecl(Kind DK, ASTContext &C, DeclContext *DC,
|
||||
SourceLocation L, DeclarationName Name,
|
||||
TemplateParameterList *Params, NamedDecl *Decl)
|
||||
: TemplateDecl(DK, DC, L, Name, Params, Decl), redeclarable_base(C),
|
||||
Common() {}
|
||||
: RedeclarableTemplateDecl(nullptr, DK, C, DC, L, Name, Params, Decl) {}
|
||||
|
||||
public:
|
||||
template <class decl_type> friend class RedeclarableTemplate;
|
||||
@ -863,8 +937,6 @@ SpecEntryTraits<FunctionTemplateSpecializationInfo> {
|
||||
|
||||
/// Declaration of a template function.
|
||||
class FunctionTemplateDecl : public RedeclarableTemplateDecl {
|
||||
static void DeallocateCommon(void *Ptr);
|
||||
|
||||
protected:
|
||||
/// \brief Data that is common to all of the declarations of a given
|
||||
/// function template.
|
||||
@ -1407,7 +1479,9 @@ class TemplateTemplateParmDecl final
|
||||
unsigned NumExpansions);
|
||||
|
||||
using TemplateParmPosition::getDepth;
|
||||
using TemplateParmPosition::setDepth;
|
||||
using TemplateParmPosition::getPosition;
|
||||
using TemplateParmPosition::setPosition;
|
||||
using TemplateParmPosition::getIndex;
|
||||
|
||||
/// \brief Whether this template template parameter is a template
|
||||
@ -1960,8 +2034,6 @@ class ClassTemplatePartialSpecializationDecl
|
||||
|
||||
/// Declaration of a class template.
|
||||
class ClassTemplateDecl : public RedeclarableTemplateDecl {
|
||||
static void DeallocateCommon(void *Ptr);
|
||||
|
||||
protected:
|
||||
/// \brief Data that is common to all of the declarations of a given
|
||||
/// class template.
|
||||
@ -1997,10 +2069,16 @@ class ClassTemplateDecl : public RedeclarableTemplateDecl {
|
||||
llvm::FoldingSetVector<ClassTemplatePartialSpecializationDecl> &
|
||||
getPartialSpecializations();
|
||||
|
||||
ClassTemplateDecl(ConstrainedTemplateDeclInfo *CTDI, ASTContext &C,
|
||||
DeclContext *DC, SourceLocation L, DeclarationName Name,
|
||||
TemplateParameterList *Params, NamedDecl *Decl)
|
||||
: RedeclarableTemplateDecl(CTDI, ClassTemplate, C, DC, L, Name, Params,
|
||||
Decl) {}
|
||||
|
||||
ClassTemplateDecl(ASTContext &C, DeclContext *DC, SourceLocation L,
|
||||
DeclarationName Name, TemplateParameterList *Params,
|
||||
NamedDecl *Decl)
|
||||
: RedeclarableTemplateDecl(ClassTemplate, C, DC, L, Name, Params, Decl) {}
|
||||
: ClassTemplateDecl(nullptr, C, DC, L, Name, Params, Decl) {}
|
||||
|
||||
CommonBase *newCommon(ASTContext &C) const override;
|
||||
|
||||
@ -2023,12 +2101,14 @@ class ClassTemplateDecl : public RedeclarableTemplateDecl {
|
||||
return getTemplatedDecl()->isThisDeclarationADefinition();
|
||||
}
|
||||
|
||||
// FIXME: remove default argument for AssociatedConstraints
|
||||
/// \brief Create a class template node.
|
||||
static ClassTemplateDecl *Create(ASTContext &C, DeclContext *DC,
|
||||
SourceLocation L,
|
||||
DeclarationName Name,
|
||||
TemplateParameterList *Params,
|
||||
NamedDecl *Decl);
|
||||
NamedDecl *Decl,
|
||||
Expr *AssociatedConstraints = nullptr);
|
||||
|
||||
/// \brief Create an empty class template node.
|
||||
static ClassTemplateDecl *CreateDeserialized(ASTContext &C, unsigned ID);
|
||||
@ -2247,8 +2327,6 @@ class FriendTemplateDecl : public Decl {
|
||||
/// template \<typename T> using V = std::map<T*, int, MyCompare<T>>;
|
||||
/// \endcode
|
||||
class TypeAliasTemplateDecl : public RedeclarableTemplateDecl {
|
||||
static void DeallocateCommon(void *Ptr);
|
||||
|
||||
protected:
|
||||
typedef CommonBase Common;
|
||||
|
||||
@ -2773,8 +2851,6 @@ class VarTemplatePartialSpecializationDecl
|
||||
|
||||
/// Declaration of a variable template.
|
||||
class VarTemplateDecl : public RedeclarableTemplateDecl {
|
||||
static void DeallocateCommon(void *Ptr);
|
||||
|
||||
protected:
|
||||
/// \brief Data that is common to all of the declarations of a given
|
||||
/// variable template.
|
||||
@ -2946,6 +3022,16 @@ inline NamedDecl *getAsNamedDecl(TemplateParameter P) {
|
||||
return P.get<TemplateTemplateParmDecl*>();
|
||||
}
|
||||
|
||||
inline TemplateDecl *getAsTypeTemplateDecl(Decl *D) {
|
||||
auto *TD = dyn_cast<TemplateDecl>(D);
|
||||
return TD && (isa<ClassTemplateDecl>(TD) ||
|
||||
isa<ClassTemplatePartialSpecializationDecl>(TD) ||
|
||||
isa<TypeAliasTemplateDecl>(TD) ||
|
||||
isa<TemplateTemplateParmDecl>(TD))
|
||||
? TD
|
||||
: nullptr;
|
||||
}
|
||||
|
||||
} /* end of namespace clang */
|
||||
|
||||
#endif
|
||||
|
@ -23,6 +23,7 @@ namespace llvm {
|
||||
|
||||
namespace clang {
|
||||
class ASTContext;
|
||||
class CXXDeductionGuideNameExtra;
|
||||
class CXXLiteralOperatorIdName;
|
||||
class CXXOperatorIdName;
|
||||
class CXXSpecialName;
|
||||
@ -32,6 +33,7 @@ namespace clang {
|
||||
enum OverloadedOperatorKind : int;
|
||||
struct PrintingPolicy;
|
||||
class QualType;
|
||||
class TemplateDecl;
|
||||
class Type;
|
||||
class TypeSourceInfo;
|
||||
class UsingDirectiveDecl;
|
||||
@ -56,6 +58,7 @@ class DeclarationName {
|
||||
CXXConstructorName,
|
||||
CXXDestructorName,
|
||||
CXXConversionFunctionName,
|
||||
CXXDeductionGuideName,
|
||||
CXXOperatorName,
|
||||
CXXLiteralOperatorName,
|
||||
CXXUsingDirective
|
||||
@ -118,42 +121,36 @@ class DeclarationName {
|
||||
CXXSpecialName *getAsCXXSpecialName() const {
|
||||
NameKind Kind = getNameKind();
|
||||
if (Kind >= CXXConstructorName && Kind <= CXXConversionFunctionName)
|
||||
return reinterpret_cast<CXXSpecialName *>(Ptr & ~PtrMask);
|
||||
return reinterpret_cast<CXXSpecialName *>(getExtra());
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
/// If the stored pointer is actually a CXXDeductionGuideNameExtra, returns a
|
||||
/// pointer to it. Otherwise, returns a NULL pointer.
|
||||
CXXDeductionGuideNameExtra *getAsCXXDeductionGuideNameExtra() const {
|
||||
if (getNameKind() == CXXDeductionGuideName)
|
||||
return reinterpret_cast<CXXDeductionGuideNameExtra *>(getExtra());
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
/// getAsCXXOperatorIdName
|
||||
CXXOperatorIdName *getAsCXXOperatorIdName() const {
|
||||
if (getNameKind() == CXXOperatorName)
|
||||
return reinterpret_cast<CXXOperatorIdName *>(Ptr & ~PtrMask);
|
||||
return reinterpret_cast<CXXOperatorIdName *>(getExtra());
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
CXXLiteralOperatorIdName *getAsCXXLiteralOperatorIdName() const {
|
||||
if (getNameKind() == CXXLiteralOperatorName)
|
||||
return reinterpret_cast<CXXLiteralOperatorIdName *>(Ptr & ~PtrMask);
|
||||
return reinterpret_cast<CXXLiteralOperatorIdName *>(getExtra());
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
// Construct a declaration name from the name of a C++ constructor,
|
||||
// destructor, or conversion function.
|
||||
DeclarationName(CXXSpecialName *Name)
|
||||
DeclarationName(DeclarationNameExtra *Name)
|
||||
: Ptr(reinterpret_cast<uintptr_t>(Name)) {
|
||||
assert((Ptr & PtrMask) == 0 && "Improperly aligned CXXSpecialName");
|
||||
Ptr |= StoredDeclarationNameExtra;
|
||||
}
|
||||
|
||||
// Construct a declaration name from the name of a C++ overloaded
|
||||
// operator.
|
||||
DeclarationName(CXXOperatorIdName *Name)
|
||||
: Ptr(reinterpret_cast<uintptr_t>(Name)) {
|
||||
assert((Ptr & PtrMask) == 0 && "Improperly aligned CXXOperatorId");
|
||||
Ptr |= StoredDeclarationNameExtra;
|
||||
}
|
||||
|
||||
DeclarationName(CXXLiteralOperatorIdName *Name)
|
||||
: Ptr(reinterpret_cast<uintptr_t>(Name)) {
|
||||
assert((Ptr & PtrMask) == 0 && "Improperly aligned CXXLiteralOperatorId");
|
||||
assert((Ptr & PtrMask) == 0 && "Improperly aligned DeclarationNameExtra");
|
||||
Ptr |= StoredDeclarationNameExtra;
|
||||
}
|
||||
|
||||
@ -252,6 +249,10 @@ class DeclarationName {
|
||||
/// type associated with that name.
|
||||
QualType getCXXNameType() const;
|
||||
|
||||
/// If this name is the name of a C++ deduction guide, return the
|
||||
/// template associated with that name.
|
||||
TemplateDecl *getCXXDeductionGuideTemplate() const;
|
||||
|
||||
/// getCXXOverloadedOperator - If this name is the name of an
|
||||
/// overloadable operator in C++ (e.g., @c operator+), retrieve the
|
||||
/// kind of overloaded operator.
|
||||
@ -346,6 +347,7 @@ class DeclarationNameTable {
|
||||
void *CXXSpecialNamesImpl; // Actually a FoldingSet<CXXSpecialName> *
|
||||
CXXOperatorIdName *CXXOperatorNames; // Operator names
|
||||
void *CXXLiteralOperatorNames; // Actually a CXXOperatorIdName*
|
||||
void *CXXDeductionGuideNames; // FoldingSet<CXXDeductionGuideNameExtra> *
|
||||
|
||||
DeclarationNameTable(const DeclarationNameTable&) = delete;
|
||||
void operator=(const DeclarationNameTable&) = delete;
|
||||
@ -368,6 +370,9 @@ class DeclarationNameTable {
|
||||
/// for the given Type.
|
||||
DeclarationName getCXXDestructorName(CanQualType Ty);
|
||||
|
||||
/// Returns the name of a C++ deduction guide for the given template.
|
||||
DeclarationName getCXXDeductionGuideName(TemplateDecl *TD);
|
||||
|
||||
/// getCXXConversionFunctionName - Returns the name of a C++
|
||||
/// conversion function for the given Type.
|
||||
DeclarationName getCXXConversionFunctionName(CanQualType Ty);
|
||||
|
@ -115,6 +115,7 @@ class Expr : public Stmt {
|
||||
ExprBits.InstantiationDependent = ID;
|
||||
ExprBits.ValueKind = VK;
|
||||
ExprBits.ObjectKind = OK;
|
||||
assert(ExprBits.ObjectKind == OK && "truncated kind");
|
||||
ExprBits.ContainsUnexpandedParameterPack = ContainsUnexpandedParameterPack;
|
||||
setType(T);
|
||||
}
|
||||
@ -907,6 +908,10 @@ class OpaqueValueExpr : public Expr {
|
||||
return child_range(child_iterator(), child_iterator());
|
||||
}
|
||||
|
||||
const_child_range children() const {
|
||||
return const_child_range(const_child_iterator(), const_child_iterator());
|
||||
}
|
||||
|
||||
/// The source expression of an opaque value expression is the
|
||||
/// expression which originally generated the value. This is
|
||||
/// provided as a convenience for analyses that don't wish to
|
||||
@ -1167,6 +1172,10 @@ class DeclRefExpr final
|
||||
return child_range(child_iterator(), child_iterator());
|
||||
}
|
||||
|
||||
const_child_range children() const {
|
||||
return const_child_range(const_child_iterator(), const_child_iterator());
|
||||
}
|
||||
|
||||
friend TrailingObjects;
|
||||
friend class ASTStmtReader;
|
||||
friend class ASTStmtWriter;
|
||||
@ -1222,6 +1231,9 @@ class PredefinedExpr : public Expr {
|
||||
|
||||
// Iterators
|
||||
child_range children() { return child_range(&FnName, &FnName + 1); }
|
||||
const_child_range children() const {
|
||||
return const_child_range(&FnName, &FnName + 1);
|
||||
}
|
||||
|
||||
friend class ASTStmtReader;
|
||||
};
|
||||
@ -1315,6 +1327,9 @@ class IntegerLiteral : public Expr, public APIntStorage {
|
||||
child_range children() {
|
||||
return child_range(child_iterator(), child_iterator());
|
||||
}
|
||||
const_child_range children() const {
|
||||
return const_child_range(const_child_iterator(), const_child_iterator());
|
||||
}
|
||||
};
|
||||
|
||||
class CharacterLiteral : public Expr {
|
||||
@ -1365,6 +1380,9 @@ class CharacterLiteral : public Expr {
|
||||
child_range children() {
|
||||
return child_range(child_iterator(), child_iterator());
|
||||
}
|
||||
const_child_range children() const {
|
||||
return const_child_range(const_child_iterator(), const_child_iterator());
|
||||
}
|
||||
};
|
||||
|
||||
class FloatingLiteral : public Expr, private APFloatStorage {
|
||||
@ -1429,6 +1447,9 @@ class FloatingLiteral : public Expr, private APFloatStorage {
|
||||
child_range children() {
|
||||
return child_range(child_iterator(), child_iterator());
|
||||
}
|
||||
const_child_range children() const {
|
||||
return const_child_range(const_child_iterator(), const_child_iterator());
|
||||
}
|
||||
};
|
||||
|
||||
/// ImaginaryLiteral - We support imaginary integer and floating point literals,
|
||||
@ -1461,6 +1482,9 @@ class ImaginaryLiteral : public Expr {
|
||||
|
||||
// Iterators
|
||||
child_range children() { return child_range(&Val, &Val+1); }
|
||||
const_child_range children() const {
|
||||
return const_child_range(&Val, &Val + 1);
|
||||
}
|
||||
};
|
||||
|
||||
/// StringLiteral - This represents a string literal expression, e.g. "foo"
|
||||
@ -1628,6 +1652,9 @@ class StringLiteral : public Expr {
|
||||
child_range children() {
|
||||
return child_range(child_iterator(), child_iterator());
|
||||
}
|
||||
const_child_range children() const {
|
||||
return const_child_range(const_child_iterator(), const_child_iterator());
|
||||
}
|
||||
};
|
||||
|
||||
/// ParenExpr - This represents a parethesized expression, e.g. "(1)". This
|
||||
@ -1669,6 +1696,9 @@ class ParenExpr : public Expr {
|
||||
|
||||
// Iterators
|
||||
child_range children() { return child_range(&Val, &Val+1); }
|
||||
const_child_range children() const {
|
||||
return const_child_range(&Val, &Val + 1);
|
||||
}
|
||||
};
|
||||
|
||||
/// UnaryOperator - This represents the unary-expression's (except sizeof and
|
||||
@ -1778,6 +1808,9 @@ class UnaryOperator : public Expr {
|
||||
|
||||
// Iterators
|
||||
child_range children() { return child_range(&Val, &Val+1); }
|
||||
const_child_range children() const {
|
||||
return const_child_range(&Val, &Val + 1);
|
||||
}
|
||||
};
|
||||
|
||||
/// Helper class for OffsetOfExpr.
|
||||
@ -1981,6 +2014,11 @@ class OffsetOfExpr final
|
||||
Stmt **begin = reinterpret_cast<Stmt **>(getTrailingObjects<Expr *>());
|
||||
return child_range(begin, begin + NumExprs);
|
||||
}
|
||||
const_child_range children() const {
|
||||
Stmt *const *begin =
|
||||
reinterpret_cast<Stmt *const *>(getTrailingObjects<Expr *>());
|
||||
return const_child_range(begin, begin + NumExprs);
|
||||
}
|
||||
friend TrailingObjects;
|
||||
};
|
||||
|
||||
@ -2069,6 +2107,7 @@ class UnaryExprOrTypeTraitExpr : public Expr {
|
||||
|
||||
// Iterators
|
||||
child_range children();
|
||||
const_child_range children() const;
|
||||
};
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
@ -2153,6 +2192,9 @@ class ArraySubscriptExpr : public Expr {
|
||||
child_range children() {
|
||||
return child_range(&SubExprs[0], &SubExprs[0]+END_EXPR);
|
||||
}
|
||||
const_child_range children() const {
|
||||
return const_child_range(&SubExprs[0], &SubExprs[0] + END_EXPR);
|
||||
}
|
||||
};
|
||||
|
||||
/// CallExpr - Represents a function call (C99 6.5.2.2, C++ [expr.call]).
|
||||
@ -2313,6 +2355,11 @@ class CallExpr : public Expr {
|
||||
return child_range(&SubExprs[0],
|
||||
&SubExprs[0]+NumArgs+getNumPreArgs()+PREARGS_START);
|
||||
}
|
||||
|
||||
const_child_range children() const {
|
||||
return const_child_range(&SubExprs[0], &SubExprs[0] + NumArgs +
|
||||
getNumPreArgs() + PREARGS_START);
|
||||
}
|
||||
};
|
||||
|
||||
/// Extra data stored in some MemberExpr objects.
|
||||
@ -2567,6 +2614,9 @@ class MemberExpr final
|
||||
|
||||
// Iterators
|
||||
child_range children() { return child_range(&Base, &Base+1); }
|
||||
const_child_range children() const {
|
||||
return const_child_range(&Base, &Base + 1);
|
||||
}
|
||||
|
||||
friend TrailingObjects;
|
||||
friend class ASTReader;
|
||||
@ -2639,6 +2689,9 @@ class CompoundLiteralExpr : public Expr {
|
||||
|
||||
// Iterators
|
||||
child_range children() { return child_range(&Init, &Init+1); }
|
||||
const_child_range children() const {
|
||||
return const_child_range(&Init, &Init + 1);
|
||||
}
|
||||
};
|
||||
|
||||
/// CastExpr - Base class for type casts, including both implicit
|
||||
@ -2725,6 +2778,7 @@ class CastExpr : public Expr {
|
||||
|
||||
// Iterators
|
||||
child_range children() { return child_range(&Op, &Op+1); }
|
||||
const_child_range children() const { return const_child_range(&Op, &Op + 1); }
|
||||
};
|
||||
|
||||
/// ImplicitCastExpr - Allows us to explicitly represent implicit type
|
||||
@ -2917,11 +2971,9 @@ class BinaryOperator : public Expr {
|
||||
private:
|
||||
unsigned Opc : 6;
|
||||
|
||||
// Records the FP_CONTRACT pragma status at the point that this binary
|
||||
// operator was parsed. This bit is only meaningful for operations on
|
||||
// floating point types. For all other types it should default to
|
||||
// false.
|
||||
unsigned FPContractable : 1;
|
||||
// This is only meaningful for operations on floating point types and 0
|
||||
// otherwise.
|
||||
unsigned FPFeatures : 2;
|
||||
SourceLocation OpLoc;
|
||||
|
||||
enum { LHS, RHS, END_EXPR };
|
||||
@ -2930,7 +2982,7 @@ class BinaryOperator : public Expr {
|
||||
|
||||
BinaryOperator(Expr *lhs, Expr *rhs, Opcode opc, QualType ResTy,
|
||||
ExprValueKind VK, ExprObjectKind OK,
|
||||
SourceLocation opLoc, bool fpContractable)
|
||||
SourceLocation opLoc, FPOptions FPFeatures)
|
||||
: Expr(BinaryOperatorClass, ResTy, VK, OK,
|
||||
lhs->isTypeDependent() || rhs->isTypeDependent(),
|
||||
lhs->isValueDependent() || rhs->isValueDependent(),
|
||||
@ -2938,7 +2990,7 @@ class BinaryOperator : public Expr {
|
||||
rhs->isInstantiationDependent()),
|
||||
(lhs->containsUnexpandedParameterPack() ||
|
||||
rhs->containsUnexpandedParameterPack())),
|
||||
Opc(opc), FPContractable(fpContractable), OpLoc(opLoc) {
|
||||
Opc(opc), FPFeatures(FPFeatures.getInt()), OpLoc(opLoc) {
|
||||
SubExprs[LHS] = lhs;
|
||||
SubExprs[RHS] = rhs;
|
||||
assert(!isCompoundAssignmentOp() &&
|
||||
@ -3070,19 +3122,26 @@ class BinaryOperator : public Expr {
|
||||
child_range children() {
|
||||
return child_range(&SubExprs[0], &SubExprs[0]+END_EXPR);
|
||||
}
|
||||
const_child_range children() const {
|
||||
return const_child_range(&SubExprs[0], &SubExprs[0] + END_EXPR);
|
||||
}
|
||||
|
||||
// Set the FP contractability status of this operator. Only meaningful for
|
||||
// operations on floating point types.
|
||||
void setFPContractable(bool FPC) { FPContractable = FPC; }
|
||||
void setFPFeatures(FPOptions F) { FPFeatures = F.getInt(); }
|
||||
|
||||
FPOptions getFPFeatures() const { return FPOptions(FPFeatures); }
|
||||
|
||||
// Get the FP contractability status of this operator. Only meaningful for
|
||||
// operations on floating point types.
|
||||
bool isFPContractable() const { return FPContractable; }
|
||||
bool isFPContractableWithinStatement() const {
|
||||
return FPOptions(FPFeatures).allowFPContractWithinStatement();
|
||||
}
|
||||
|
||||
protected:
|
||||
BinaryOperator(Expr *lhs, Expr *rhs, Opcode opc, QualType ResTy,
|
||||
ExprValueKind VK, ExprObjectKind OK,
|
||||
SourceLocation opLoc, bool fpContractable, bool dead2)
|
||||
SourceLocation opLoc, FPOptions FPFeatures, bool dead2)
|
||||
: Expr(CompoundAssignOperatorClass, ResTy, VK, OK,
|
||||
lhs->isTypeDependent() || rhs->isTypeDependent(),
|
||||
lhs->isValueDependent() || rhs->isValueDependent(),
|
||||
@ -3090,7 +3149,7 @@ class BinaryOperator : public Expr {
|
||||
rhs->isInstantiationDependent()),
|
||||
(lhs->containsUnexpandedParameterPack() ||
|
||||
rhs->containsUnexpandedParameterPack())),
|
||||
Opc(opc), FPContractable(fpContractable), OpLoc(opLoc) {
|
||||
Opc(opc), FPFeatures(FPFeatures.getInt()), OpLoc(opLoc) {
|
||||
SubExprs[LHS] = lhs;
|
||||
SubExprs[RHS] = rhs;
|
||||
}
|
||||
@ -3112,8 +3171,8 @@ class CompoundAssignOperator : public BinaryOperator {
|
||||
CompoundAssignOperator(Expr *lhs, Expr *rhs, Opcode opc, QualType ResType,
|
||||
ExprValueKind VK, ExprObjectKind OK,
|
||||
QualType CompLHSType, QualType CompResultType,
|
||||
SourceLocation OpLoc, bool fpContractable)
|
||||
: BinaryOperator(lhs, rhs, opc, ResType, VK, OK, OpLoc, fpContractable,
|
||||
SourceLocation OpLoc, FPOptions FPFeatures)
|
||||
: BinaryOperator(lhs, rhs, opc, ResType, VK, OK, OpLoc, FPFeatures,
|
||||
true),
|
||||
ComputationLHSType(CompLHSType),
|
||||
ComputationResultType(CompResultType) {
|
||||
@ -3246,6 +3305,9 @@ class ConditionalOperator : public AbstractConditionalOperator {
|
||||
child_range children() {
|
||||
return child_range(&SubExprs[0], &SubExprs[0]+END_EXPR);
|
||||
}
|
||||
const_child_range children() const {
|
||||
return const_child_range(&SubExprs[0], &SubExprs[0] + END_EXPR);
|
||||
}
|
||||
};
|
||||
|
||||
/// BinaryConditionalOperator - The GNU extension to the conditional
|
||||
@ -3331,6 +3393,9 @@ class BinaryConditionalOperator : public AbstractConditionalOperator {
|
||||
child_range children() {
|
||||
return child_range(SubExprs, SubExprs + NUM_SUBEXPRS);
|
||||
}
|
||||
const_child_range children() const {
|
||||
return const_child_range(SubExprs, SubExprs + NUM_SUBEXPRS);
|
||||
}
|
||||
};
|
||||
|
||||
inline Expr *AbstractConditionalOperator::getCond() const {
|
||||
@ -3385,6 +3450,9 @@ class AddrLabelExpr : public Expr {
|
||||
child_range children() {
|
||||
return child_range(child_iterator(), child_iterator());
|
||||
}
|
||||
const_child_range children() const {
|
||||
return const_child_range(const_child_iterator(), const_child_iterator());
|
||||
}
|
||||
};
|
||||
|
||||
/// StmtExpr - This is the GNU Statement Expression extension: ({int X=4; X;}).
|
||||
@ -3427,6 +3495,9 @@ class StmtExpr : public Expr {
|
||||
|
||||
// Iterators
|
||||
child_range children() { return child_range(&SubStmt, &SubStmt+1); }
|
||||
const_child_range children() const {
|
||||
return const_child_range(&SubStmt, &SubStmt + 1);
|
||||
}
|
||||
};
|
||||
|
||||
/// ShuffleVectorExpr - clang-specific builtin-in function
|
||||
@ -3495,6 +3566,9 @@ class ShuffleVectorExpr : public Expr {
|
||||
child_range children() {
|
||||
return child_range(&SubExprs[0], &SubExprs[0]+NumExprs);
|
||||
}
|
||||
const_child_range children() const {
|
||||
return const_child_range(&SubExprs[0], &SubExprs[0] + NumExprs);
|
||||
}
|
||||
};
|
||||
|
||||
/// ConvertVectorExpr - Clang builtin function __builtin_convertvector
|
||||
@ -3549,6 +3623,9 @@ class ConvertVectorExpr : public Expr {
|
||||
|
||||
// Iterators
|
||||
child_range children() { return child_range(&SrcExpr, &SrcExpr+1); }
|
||||
const_child_range children() const {
|
||||
return const_child_range(&SrcExpr, &SrcExpr + 1);
|
||||
}
|
||||
};
|
||||
|
||||
/// ChooseExpr - GNU builtin-in function __builtin_choose_expr.
|
||||
@ -3629,6 +3706,9 @@ class ChooseExpr : public Expr {
|
||||
child_range children() {
|
||||
return child_range(&SubExprs[0], &SubExprs[0]+END_EXPR);
|
||||
}
|
||||
const_child_range children() const {
|
||||
return const_child_range(&SubExprs[0], &SubExprs[0] + END_EXPR);
|
||||
}
|
||||
};
|
||||
|
||||
/// GNUNullExpr - Implements the GNU __null extension, which is a name
|
||||
@ -3665,6 +3745,9 @@ class GNUNullExpr : public Expr {
|
||||
child_range children() {
|
||||
return child_range(child_iterator(), child_iterator());
|
||||
}
|
||||
const_child_range children() const {
|
||||
return const_child_range(const_child_iterator(), const_child_iterator());
|
||||
}
|
||||
};
|
||||
|
||||
/// Represents a call to the builtin function \c __builtin_va_arg.
|
||||
@ -3712,6 +3795,9 @@ class VAArgExpr : public Expr {
|
||||
|
||||
// Iterators
|
||||
child_range children() { return child_range(&Val, &Val+1); }
|
||||
const_child_range children() const {
|
||||
return const_child_range(&Val, &Val + 1);
|
||||
}
|
||||
};
|
||||
|
||||
/// @brief Describes an C or C++ initializer list.
|
||||
@ -3936,10 +4022,16 @@ class InitListExpr : public Expr {
|
||||
|
||||
// Iterators
|
||||
child_range children() {
|
||||
const_child_range CCR = const_cast<const InitListExpr *>(this)->children();
|
||||
return child_range(cast_away_const(CCR.begin()),
|
||||
cast_away_const(CCR.end()));
|
||||
}
|
||||
|
||||
const_child_range children() const {
|
||||
// FIXME: This does not include the array filler expression.
|
||||
if (InitExprs.empty())
|
||||
return child_range(child_iterator(), child_iterator());
|
||||
return child_range(&InitExprs[0], &InitExprs[0] + InitExprs.size());
|
||||
return const_child_range(const_child_iterator(), const_child_iterator());
|
||||
return const_child_range(&InitExprs[0], &InitExprs[0] + InitExprs.size());
|
||||
}
|
||||
|
||||
typedef InitExprsTy::iterator iterator;
|
||||
@ -4254,6 +4346,10 @@ class DesignatedInitExpr final
|
||||
Stmt **begin = getTrailingObjects<Stmt *>();
|
||||
return child_range(begin, begin + NumSubExprs);
|
||||
}
|
||||
const_child_range children() const {
|
||||
Stmt * const *begin = getTrailingObjects<Stmt *>();
|
||||
return const_child_range(begin, begin + NumSubExprs);
|
||||
}
|
||||
|
||||
friend TrailingObjects;
|
||||
};
|
||||
@ -4287,6 +4383,9 @@ class NoInitExpr : public Expr {
|
||||
child_range children() {
|
||||
return child_range(child_iterator(), child_iterator());
|
||||
}
|
||||
const_child_range children() const {
|
||||
return const_child_range(const_child_iterator(), const_child_iterator());
|
||||
}
|
||||
};
|
||||
|
||||
// In cases like:
|
||||
@ -4332,6 +4431,10 @@ class DesignatedInitUpdateExpr : public Expr {
|
||||
child_range children() {
|
||||
return child_range(&BaseAndUpdaterExprs[0], &BaseAndUpdaterExprs[0] + 2);
|
||||
}
|
||||
const_child_range children() const {
|
||||
return const_child_range(&BaseAndUpdaterExprs[0],
|
||||
&BaseAndUpdaterExprs[0] + 2);
|
||||
}
|
||||
};
|
||||
|
||||
/// \brief Represents a loop initializing the elements of an array.
|
||||
@ -4393,6 +4496,9 @@ class ArrayInitLoopExpr : public Expr {
|
||||
child_range children() {
|
||||
return child_range(SubExprs, SubExprs + 2);
|
||||
}
|
||||
const_child_range children() const {
|
||||
return const_child_range(SubExprs, SubExprs + 2);
|
||||
}
|
||||
|
||||
friend class ASTReader;
|
||||
friend class ASTStmtReader;
|
||||
@ -4421,6 +4527,9 @@ class ArrayInitIndexExpr : public Expr {
|
||||
child_range children() {
|
||||
return child_range(child_iterator(), child_iterator());
|
||||
}
|
||||
const_child_range children() const {
|
||||
return const_child_range(const_child_iterator(), const_child_iterator());
|
||||
}
|
||||
|
||||
friend class ASTReader;
|
||||
friend class ASTStmtReader;
|
||||
@ -4455,6 +4564,9 @@ class ImplicitValueInitExpr : public Expr {
|
||||
child_range children() {
|
||||
return child_range(child_iterator(), child_iterator());
|
||||
}
|
||||
const_child_range children() const {
|
||||
return const_child_range(const_child_iterator(), const_child_iterator());
|
||||
}
|
||||
};
|
||||
|
||||
class ParenListExpr : public Expr {
|
||||
@ -4501,6 +4613,9 @@ class ParenListExpr : public Expr {
|
||||
child_range children() {
|
||||
return child_range(&Exprs[0], &Exprs[0]+NumExprs);
|
||||
}
|
||||
const_child_range children() const {
|
||||
return const_child_range(&Exprs[0], &Exprs[0] + NumExprs);
|
||||
}
|
||||
|
||||
friend class ASTStmtReader;
|
||||
friend class ASTStmtWriter;
|
||||
@ -4621,7 +4736,9 @@ class GenericSelectionExpr : public Expr {
|
||||
child_range children() {
|
||||
return child_range(SubExprs, SubExprs+END_EXPR+NumAssocs);
|
||||
}
|
||||
|
||||
const_child_range children() const {
|
||||
return const_child_range(SubExprs, SubExprs + END_EXPR + NumAssocs);
|
||||
}
|
||||
friend class ASTStmtReader;
|
||||
};
|
||||
|
||||
@ -4690,6 +4807,9 @@ class ExtVectorElementExpr : public Expr {
|
||||
|
||||
// Iterators
|
||||
child_range children() { return child_range(&Base, &Base+1); }
|
||||
const_child_range children() const {
|
||||
return const_child_range(&Base, &Base + 1);
|
||||
}
|
||||
};
|
||||
|
||||
/// BlockExpr - Adaptor class for mixing a BlockDecl with expressions.
|
||||
@ -4731,6 +4851,9 @@ class BlockExpr : public Expr {
|
||||
child_range children() {
|
||||
return child_range(child_iterator(), child_iterator());
|
||||
}
|
||||
const_child_range children() const {
|
||||
return const_child_range(const_child_iterator(), const_child_iterator());
|
||||
}
|
||||
};
|
||||
|
||||
/// AsTypeExpr - Clang builtin function __builtin_astype [OpenCL 6.2.4.2]
|
||||
@ -4776,6 +4899,9 @@ class AsTypeExpr : public Expr {
|
||||
|
||||
// Iterators
|
||||
child_range children() { return child_range(&SrcExpr, &SrcExpr+1); }
|
||||
const_child_range children() const {
|
||||
return const_child_range(&SrcExpr, &SrcExpr + 1);
|
||||
}
|
||||
};
|
||||
|
||||
/// PseudoObjectExpr - An expression which accesses a pseudo-object
|
||||
@ -4914,8 +5040,15 @@ class PseudoObjectExpr final
|
||||
}
|
||||
|
||||
child_range children() {
|
||||
Stmt **cs = reinterpret_cast<Stmt**>(getSubExprsBuffer());
|
||||
return child_range(cs, cs + getNumSubExprs());
|
||||
const_child_range CCR =
|
||||
const_cast<const PseudoObjectExpr *>(this)->children();
|
||||
return child_range(cast_away_const(CCR.begin()),
|
||||
cast_away_const(CCR.end()));
|
||||
}
|
||||
const_child_range children() const {
|
||||
Stmt *const *cs = const_cast<Stmt *const *>(
|
||||
reinterpret_cast<const Stmt *const *>(getSubExprsBuffer()));
|
||||
return const_child_range(cs, cs + getNumSubExprs());
|
||||
}
|
||||
|
||||
static bool classof(const Stmt *T) {
|
||||
@ -5021,6 +5154,9 @@ class AtomicExpr : public Expr {
|
||||
child_range children() {
|
||||
return child_range(SubExprs, SubExprs+NumSubExprs);
|
||||
}
|
||||
const_child_range children() const {
|
||||
return const_child_range(SubExprs, SubExprs + NumSubExprs);
|
||||
}
|
||||
};
|
||||
|
||||
/// TypoExpr - Internal placeholder for expressions where typo correction
|
||||
@ -5039,6 +5175,10 @@ class TypoExpr : public Expr {
|
||||
child_range children() {
|
||||
return child_range(child_iterator(), child_iterator());
|
||||
}
|
||||
const_child_range children() const {
|
||||
return const_child_range(const_child_iterator(), const_child_iterator());
|
||||
}
|
||||
|
||||
SourceLocation getLocStart() const LLVM_READONLY { return SourceLocation(); }
|
||||
SourceLocation getLocEnd() const LLVM_READONLY { return SourceLocation(); }
|
||||
|
||||
|
@ -54,18 +54,16 @@ class CXXOperatorCallExpr : public CallExpr {
|
||||
OverloadedOperatorKind Operator;
|
||||
SourceRange Range;
|
||||
|
||||
// Record the FP_CONTRACT state that applies to this operator call. Only
|
||||
// meaningful for floating point types. For other types this value can be
|
||||
// set to false.
|
||||
unsigned FPContractable : 1;
|
||||
// Only meaningful for floating point types.
|
||||
FPOptions FPFeatures;
|
||||
|
||||
SourceRange getSourceRangeImpl() const LLVM_READONLY;
|
||||
public:
|
||||
CXXOperatorCallExpr(ASTContext& C, OverloadedOperatorKind Op, Expr *fn,
|
||||
ArrayRef<Expr*> args, QualType t, ExprValueKind VK,
|
||||
SourceLocation operatorloc, bool fpContractable)
|
||||
SourceLocation operatorloc, FPOptions FPFeatures)
|
||||
: CallExpr(C, CXXOperatorCallExprClass, fn, args, t, VK, operatorloc),
|
||||
Operator(Op), FPContractable(fpContractable) {
|
||||
Operator(Op), FPFeatures(FPFeatures) {
|
||||
Range = getSourceRangeImpl();
|
||||
}
|
||||
explicit CXXOperatorCallExpr(ASTContext& C, EmptyShell Empty) :
|
||||
@ -113,11 +111,15 @@ class CXXOperatorCallExpr : public CallExpr {
|
||||
|
||||
// Set the FP contractability status of this operator. Only meaningful for
|
||||
// operations on floating point types.
|
||||
void setFPContractable(bool FPC) { FPContractable = FPC; }
|
||||
void setFPFeatures(FPOptions F) { FPFeatures = F; }
|
||||
|
||||
FPOptions getFPFeatures() const { return FPFeatures; }
|
||||
|
||||
// Get the FP contractability status of this operator. Only meaningful for
|
||||
// operations on floating point types.
|
||||
bool isFPContractable() const { return FPContractable; }
|
||||
bool isFPContractableWithinStatement() const {
|
||||
return FPFeatures.allowFPContractWithinStatement();
|
||||
}
|
||||
|
||||
friend class ASTStmtReader;
|
||||
friend class ASTStmtWriter;
|
||||
@ -1470,7 +1472,8 @@ class CXXTemporaryObjectExpr : public CXXConstructExpr {
|
||||
public:
|
||||
CXXTemporaryObjectExpr(const ASTContext &C,
|
||||
CXXConstructorDecl *Cons,
|
||||
TypeSourceInfo *Type,
|
||||
QualType Type,
|
||||
TypeSourceInfo *TSI,
|
||||
ArrayRef<Expr *> Args,
|
||||
SourceRange ParenOrBraceRange,
|
||||
bool HadMultipleCandidates,
|
||||
@ -4122,16 +4125,18 @@ class CoroutineSuspendExpr : public Expr {
|
||||
|
||||
enum SubExpr { Common, Ready, Suspend, Resume, Count };
|
||||
Stmt *SubExprs[SubExpr::Count];
|
||||
OpaqueValueExpr *OpaqueValue = nullptr;
|
||||
|
||||
friend class ASTStmtReader;
|
||||
public:
|
||||
CoroutineSuspendExpr(StmtClass SC, SourceLocation KeywordLoc, Expr *Common,
|
||||
Expr *Ready, Expr *Suspend, Expr *Resume)
|
||||
Expr *Ready, Expr *Suspend, Expr *Resume,
|
||||
OpaqueValueExpr *OpaqueValue)
|
||||
: Expr(SC, Resume->getType(), Resume->getValueKind(),
|
||||
Resume->getObjectKind(), Resume->isTypeDependent(),
|
||||
Resume->isValueDependent(), Common->isInstantiationDependent(),
|
||||
Common->containsUnexpandedParameterPack()),
|
||||
KeywordLoc(KeywordLoc) {
|
||||
KeywordLoc(KeywordLoc), OpaqueValue(OpaqueValue) {
|
||||
SubExprs[SubExpr::Common] = Common;
|
||||
SubExprs[SubExpr::Ready] = Ready;
|
||||
SubExprs[SubExpr::Suspend] = Suspend;
|
||||
@ -4160,6 +4165,8 @@ class CoroutineSuspendExpr : public Expr {
|
||||
Expr *getCommonExpr() const {
|
||||
return static_cast<Expr*>(SubExprs[SubExpr::Common]);
|
||||
}
|
||||
/// \brief getOpaqueValue - Return the opaque value placeholder.
|
||||
OpaqueValueExpr *getOpaqueValue() const { return OpaqueValue; }
|
||||
|
||||
Expr *getReadyExpr() const {
|
||||
return static_cast<Expr*>(SubExprs[SubExpr::Ready]);
|
||||
@ -4193,11 +4200,17 @@ class CoawaitExpr : public CoroutineSuspendExpr {
|
||||
friend class ASTStmtReader;
|
||||
public:
|
||||
CoawaitExpr(SourceLocation CoawaitLoc, Expr *Operand, Expr *Ready,
|
||||
Expr *Suspend, Expr *Resume)
|
||||
Expr *Suspend, Expr *Resume, OpaqueValueExpr *OpaqueValue,
|
||||
bool IsImplicit = false)
|
||||
: CoroutineSuspendExpr(CoawaitExprClass, CoawaitLoc, Operand, Ready,
|
||||
Suspend, Resume) {}
|
||||
CoawaitExpr(SourceLocation CoawaitLoc, QualType Ty, Expr *Operand)
|
||||
: CoroutineSuspendExpr(CoawaitExprClass, CoawaitLoc, Ty, Operand) {}
|
||||
Suspend, Resume, OpaqueValue) {
|
||||
CoawaitBits.IsImplicit = IsImplicit;
|
||||
}
|
||||
CoawaitExpr(SourceLocation CoawaitLoc, QualType Ty, Expr *Operand,
|
||||
bool IsImplicit = false)
|
||||
: CoroutineSuspendExpr(CoawaitExprClass, CoawaitLoc, Ty, Operand) {
|
||||
CoawaitBits.IsImplicit = IsImplicit;
|
||||
}
|
||||
CoawaitExpr(EmptyShell Empty)
|
||||
: CoroutineSuspendExpr(CoawaitExprClass, Empty) {}
|
||||
|
||||
@ -4206,19 +4219,67 @@ class CoawaitExpr : public CoroutineSuspendExpr {
|
||||
return getCommonExpr();
|
||||
}
|
||||
|
||||
bool isImplicit() const { return CoawaitBits.IsImplicit; }
|
||||
void setIsImplicit(bool value = true) { CoawaitBits.IsImplicit = value; }
|
||||
|
||||
static bool classof(const Stmt *T) {
|
||||
return T->getStmtClass() == CoawaitExprClass;
|
||||
}
|
||||
};
|
||||
|
||||
/// \brief Represents a 'co_await' expression while the type of the promise
|
||||
/// is dependent.
|
||||
class DependentCoawaitExpr : public Expr {
|
||||
SourceLocation KeywordLoc;
|
||||
Stmt *SubExprs[2];
|
||||
|
||||
friend class ASTStmtReader;
|
||||
|
||||
public:
|
||||
DependentCoawaitExpr(SourceLocation KeywordLoc, QualType Ty, Expr *Op,
|
||||
UnresolvedLookupExpr *OpCoawait)
|
||||
: Expr(DependentCoawaitExprClass, Ty, VK_RValue, OK_Ordinary,
|
||||
/*TypeDependent*/ true, /*ValueDependent*/ true,
|
||||
/*InstantiationDependent*/ true,
|
||||
Op->containsUnexpandedParameterPack()),
|
||||
KeywordLoc(KeywordLoc) {
|
||||
// NOTE: A co_await expression is dependent on the coroutines promise
|
||||
// type and may be dependent even when the `Op` expression is not.
|
||||
assert(Ty->isDependentType() &&
|
||||
"wrong constructor for non-dependent co_await/co_yield expression");
|
||||
SubExprs[0] = Op;
|
||||
SubExprs[1] = OpCoawait;
|
||||
}
|
||||
|
||||
DependentCoawaitExpr(EmptyShell Empty)
|
||||
: Expr(DependentCoawaitExprClass, Empty) {}
|
||||
|
||||
Expr *getOperand() const { return cast<Expr>(SubExprs[0]); }
|
||||
UnresolvedLookupExpr *getOperatorCoawaitLookup() const {
|
||||
return cast<UnresolvedLookupExpr>(SubExprs[1]);
|
||||
}
|
||||
SourceLocation getKeywordLoc() const { return KeywordLoc; }
|
||||
|
||||
SourceLocation getLocStart() const LLVM_READONLY { return KeywordLoc; }
|
||||
SourceLocation getLocEnd() const LLVM_READONLY {
|
||||
return getOperand()->getLocEnd();
|
||||
}
|
||||
|
||||
child_range children() { return child_range(SubExprs, SubExprs + 2); }
|
||||
|
||||
static bool classof(const Stmt *T) {
|
||||
return T->getStmtClass() == DependentCoawaitExprClass;
|
||||
}
|
||||
};
|
||||
|
||||
/// \brief Represents a 'co_yield' expression.
|
||||
class CoyieldExpr : public CoroutineSuspendExpr {
|
||||
friend class ASTStmtReader;
|
||||
public:
|
||||
CoyieldExpr(SourceLocation CoyieldLoc, Expr *Operand, Expr *Ready,
|
||||
Expr *Suspend, Expr *Resume)
|
||||
Expr *Suspend, Expr *Resume, OpaqueValueExpr *OpaqueValue)
|
||||
: CoroutineSuspendExpr(CoyieldExprClass, CoyieldLoc, Operand, Ready,
|
||||
Suspend, Resume) {}
|
||||
Suspend, Resume, OpaqueValue) {}
|
||||
CoyieldExpr(SourceLocation CoyieldLoc, QualType Ty, Expr *Operand)
|
||||
: CoroutineSuspendExpr(CoyieldExprClass, CoyieldLoc, Ty, Operand) {}
|
||||
CoyieldExpr(EmptyShell Empty)
|
||||
|
51
include/clang/AST/ExternalASTMerger.h
Normal file
51
include/clang/AST/ExternalASTMerger.h
Normal file
@ -0,0 +1,51 @@
|
||||
//===--- ExternalASTMerger.h - Merging External AST Interface ---*- C++ -*-===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// This file declares the ExternalASTMerger, which vends a combination of ASTs
|
||||
// from several different ASTContext/FileManager pairs
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
#ifndef LLVM_CLANG_AST_EXTERNALASTMERGER_H
|
||||
#define LLVM_CLANG_AST_EXTERNALASTMERGER_H
|
||||
|
||||
#include "clang/AST/ASTImporter.h"
|
||||
#include "clang/AST/ExternalASTSource.h"
|
||||
|
||||
namespace clang {
|
||||
|
||||
class ExternalASTMerger : public ExternalASTSource {
|
||||
public:
|
||||
struct ImporterPair {
|
||||
std::unique_ptr<ASTImporter> Forward;
|
||||
std::unique_ptr<ASTImporter> Reverse;
|
||||
};
|
||||
|
||||
private:
|
||||
std::vector<ImporterPair> Importers;
|
||||
|
||||
public:
|
||||
struct ImporterEndpoint {
|
||||
ASTContext &AST;
|
||||
FileManager &FM;
|
||||
};
|
||||
ExternalASTMerger(const ImporterEndpoint &Target,
|
||||
llvm::ArrayRef<ImporterEndpoint> Sources);
|
||||
|
||||
bool FindExternalVisibleDeclsByName(const DeclContext *DC,
|
||||
DeclarationName Name) override;
|
||||
|
||||
void
|
||||
FindExternalLexicalDecls(const DeclContext *DC,
|
||||
llvm::function_ref<bool(Decl::Kind)> IsKindWeWant,
|
||||
SmallVectorImpl<Decl *> &Result) override;
|
||||
};
|
||||
|
||||
} // end namespace clang
|
||||
|
||||
#endif
|
@ -16,6 +16,7 @@
|
||||
|
||||
#include "clang/AST/CharUnits.h"
|
||||
#include "clang/AST/DeclBase.h"
|
||||
#include "clang/Basic/Module.h"
|
||||
#include "llvm/ADT/DenseMap.h"
|
||||
|
||||
namespace clang {
|
||||
@ -149,26 +150,30 @@ class ExternalASTSource : public RefCountedBase<ExternalASTSource> {
|
||||
StringRef PCHModuleName;
|
||||
StringRef Path;
|
||||
StringRef ASTFile;
|
||||
uint64_t Signature = 0;
|
||||
ASTFileSignature Signature;
|
||||
const Module *ClangModule = nullptr;
|
||||
|
||||
public:
|
||||
ASTSourceDescriptor(){};
|
||||
ASTSourceDescriptor(StringRef Name, StringRef Path, StringRef ASTFile,
|
||||
uint64_t Signature)
|
||||
ASTFileSignature Signature)
|
||||
: PCHModuleName(std::move(Name)), Path(std::move(Path)),
|
||||
ASTFile(std::move(ASTFile)), Signature(Signature){};
|
||||
ASTSourceDescriptor(const Module &M);
|
||||
std::string getModuleName() const;
|
||||
StringRef getPath() const { return Path; }
|
||||
StringRef getASTFile() const { return ASTFile; }
|
||||
uint64_t getSignature() const { return Signature; }
|
||||
ASTFileSignature getSignature() const { return Signature; }
|
||||
const Module *getModuleOrNull() const { return ClangModule; }
|
||||
};
|
||||
|
||||
/// Return a descriptor for the corresponding module, if one exists.
|
||||
virtual llvm::Optional<ASTSourceDescriptor> getSourceDescriptor(unsigned ID);
|
||||
|
||||
enum ExtKind { EK_Always, EK_Never, EK_ReplyHazy };
|
||||
|
||||
virtual ExtKind hasExternalDefinitions(const Decl *D);
|
||||
|
||||
/// \brief Finds all declarations lexically contained within the given
|
||||
/// DeclContext, after applying an optional filter predicate.
|
||||
///
|
||||
|
84
include/clang/AST/ODRHash.h
Normal file
84
include/clang/AST/ODRHash.h
Normal file
@ -0,0 +1,84 @@
|
||||
//===-- ODRHash.h - Hashing to diagnose ODR failures ------------*- C++ -*-===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
///
|
||||
/// \file
|
||||
/// This file contains the declaration of the ODRHash class, which calculates
|
||||
/// a hash based on AST nodes, which is stable across different runs.
|
||||
///
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "clang/AST/DeclarationName.h"
|
||||
#include "clang/AST/Type.h"
|
||||
#include "clang/AST/TemplateBase.h"
|
||||
#include "llvm/ADT/DenseMap.h"
|
||||
#include "llvm/ADT/FoldingSet.h"
|
||||
#include "llvm/ADT/PointerUnion.h"
|
||||
#include "llvm/ADT/SmallVector.h"
|
||||
|
||||
namespace clang {
|
||||
|
||||
class Decl;
|
||||
class IdentifierInfo;
|
||||
class NestedNameSpecifer;
|
||||
class Stmt;
|
||||
class TemplateParameterList;
|
||||
|
||||
// ODRHash is used to calculate a hash based on AST node contents that
|
||||
// does not rely on pointer addresses. This allows the hash to not vary
|
||||
// between runs and is usable to detect ODR problems in modules. To use,
|
||||
// construct an ODRHash object, then call Add* methods over the nodes that
|
||||
// need to be hashed. Then call CalculateHash to get the hash value.
|
||||
// Typically, only one Add* call is needed. clear can be called to reuse the
|
||||
// object.
|
||||
class ODRHash {
|
||||
// Use DenseMaps to convert between Decl and Type pointers and an index value.
|
||||
llvm::DenseMap<const Decl*, unsigned> DeclMap;
|
||||
llvm::DenseMap<const Type*, unsigned> TypeMap;
|
||||
|
||||
// Save space by processing bools at the end.
|
||||
llvm::SmallVector<bool, 128> Bools;
|
||||
|
||||
llvm::FoldingSetNodeID ID;
|
||||
|
||||
public:
|
||||
ODRHash() {}
|
||||
|
||||
// Use this for ODR checking classes between modules. This method compares
|
||||
// more information than the AddDecl class.
|
||||
void AddCXXRecordDecl(const CXXRecordDecl *Record);
|
||||
|
||||
// Process SubDecls of the main Decl. This method calls the DeclVisitor
|
||||
// while AddDecl does not.
|
||||
void AddSubDecl(const Decl *D);
|
||||
|
||||
// Reset the object for reuse.
|
||||
void clear();
|
||||
|
||||
// Add booleans to ID and uses it to calculate the hash.
|
||||
unsigned CalculateHash();
|
||||
|
||||
// Add AST nodes that need to be processed.
|
||||
void AddDecl(const Decl *D);
|
||||
void AddType(const Type *T);
|
||||
void AddQualType(QualType T);
|
||||
void AddStmt(const Stmt *S);
|
||||
void AddIdentifierInfo(const IdentifierInfo *II);
|
||||
void AddNestedNameSpecifier(const NestedNameSpecifier *NNS);
|
||||
void AddTemplateName(TemplateName Name);
|
||||
void AddDeclarationName(DeclarationName Name);
|
||||
void AddTemplateArgument(TemplateArgument TA);
|
||||
void AddTemplateParameterList(const TemplateParameterList *TPL);
|
||||
|
||||
// Save booleans until the end to lower the size of data to process.
|
||||
void AddBoolean(bool value);
|
||||
|
||||
static bool isWhitelistedDecl(const Decl* D, const CXXRecordDecl *Record);
|
||||
};
|
||||
|
||||
} // end namespace clang
|
@ -76,10 +76,17 @@ class OMPClauseWithPreInit {
|
||||
friend class OMPClauseReader;
|
||||
/// Pre-initialization statement for the clause.
|
||||
Stmt *PreInit;
|
||||
/// Region that captures the associated stmt.
|
||||
OpenMPDirectiveKind CaptureRegion;
|
||||
|
||||
protected:
|
||||
/// Set pre-initialization statement for the clause.
|
||||
void setPreInitStmt(Stmt *S) { PreInit = S; }
|
||||
OMPClauseWithPreInit(const OMPClause *This) : PreInit(nullptr) {
|
||||
void setPreInitStmt(Stmt *S, OpenMPDirectiveKind ThisRegion = OMPD_unknown) {
|
||||
PreInit = S;
|
||||
CaptureRegion = ThisRegion;
|
||||
}
|
||||
OMPClauseWithPreInit(const OMPClause *This)
|
||||
: PreInit(nullptr), CaptureRegion(OMPD_unknown) {
|
||||
assert(get(This) && "get is not tuned for pre-init.");
|
||||
}
|
||||
|
||||
@ -88,6 +95,8 @@ class OMPClauseWithPreInit {
|
||||
const Stmt *getPreInitStmt() const { return PreInit; }
|
||||
/// Get pre-initialization statement for the clause.
|
||||
Stmt *getPreInitStmt() { return PreInit; }
|
||||
/// Get capture region for the stmt in the clause.
|
||||
OpenMPDirectiveKind getCaptureRegion() { return CaptureRegion; }
|
||||
static OMPClauseWithPreInit *get(OMPClause *C);
|
||||
static const OMPClauseWithPreInit *get(const OMPClause *C);
|
||||
};
|
||||
@ -194,7 +203,7 @@ template <class T> class OMPVarListClause : public OMPClause {
|
||||
/// In this example directive '#pragma omp parallel' has simple 'if' clause with
|
||||
/// condition 'a > 5' and directive name modifier 'parallel'.
|
||||
///
|
||||
class OMPIfClause : public OMPClause {
|
||||
class OMPIfClause : public OMPClause, public OMPClauseWithPreInit {
|
||||
friend class OMPClauseReader;
|
||||
/// \brief Location of '('.
|
||||
SourceLocation LParenLoc;
|
||||
@ -225,26 +234,31 @@ class OMPIfClause : public OMPClause {
|
||||
///
|
||||
/// \param NameModifier [OpenMP 4.1] Directive name modifier of clause.
|
||||
/// \param Cond Condition of the clause.
|
||||
/// \param HelperCond Helper condition for the clause.
|
||||
/// \param CaptureRegion Innermost OpenMP region where expressions in this
|
||||
/// clause must be captured.
|
||||
/// \param StartLoc Starting location of the clause.
|
||||
/// \param LParenLoc Location of '('.
|
||||
/// \param NameModifierLoc Location of directive name modifier.
|
||||
/// \param ColonLoc [OpenMP 4.1] Location of ':'.
|
||||
/// \param EndLoc Ending location of the clause.
|
||||
///
|
||||
OMPIfClause(OpenMPDirectiveKind NameModifier, Expr *Cond,
|
||||
SourceLocation StartLoc, SourceLocation LParenLoc,
|
||||
SourceLocation NameModifierLoc, SourceLocation ColonLoc,
|
||||
SourceLocation EndLoc)
|
||||
: OMPClause(OMPC_if, StartLoc, EndLoc), LParenLoc(LParenLoc),
|
||||
Condition(Cond), ColonLoc(ColonLoc), NameModifier(NameModifier),
|
||||
NameModifierLoc(NameModifierLoc) {}
|
||||
OMPIfClause(OpenMPDirectiveKind NameModifier, Expr *Cond, Stmt *HelperCond,
|
||||
OpenMPDirectiveKind CaptureRegion, SourceLocation StartLoc,
|
||||
SourceLocation LParenLoc, SourceLocation NameModifierLoc,
|
||||
SourceLocation ColonLoc, SourceLocation EndLoc)
|
||||
: OMPClause(OMPC_if, StartLoc, EndLoc), OMPClauseWithPreInit(this),
|
||||
LParenLoc(LParenLoc), Condition(Cond), ColonLoc(ColonLoc),
|
||||
NameModifier(NameModifier), NameModifierLoc(NameModifierLoc) {
|
||||
setPreInitStmt(HelperCond, CaptureRegion);
|
||||
}
|
||||
|
||||
/// \brief Build an empty clause.
|
||||
///
|
||||
OMPIfClause()
|
||||
: OMPClause(OMPC_if, SourceLocation(), SourceLocation()), LParenLoc(),
|
||||
Condition(nullptr), ColonLoc(), NameModifier(OMPD_unknown),
|
||||
NameModifierLoc() {}
|
||||
: OMPClause(OMPC_if, SourceLocation(), SourceLocation()),
|
||||
OMPClauseWithPreInit(this), LParenLoc(), Condition(nullptr), ColonLoc(),
|
||||
NameModifier(OMPD_unknown), NameModifierLoc() {}
|
||||
|
||||
/// \brief Sets the location of '('.
|
||||
void setLParenLoc(SourceLocation Loc) { LParenLoc = Loc; }
|
||||
@ -331,7 +345,7 @@ class OMPFinalClause : public OMPClause {
|
||||
/// In this example directive '#pragma omp parallel' has simple 'num_threads'
|
||||
/// clause with number of threads '6'.
|
||||
///
|
||||
class OMPNumThreadsClause : public OMPClause {
|
||||
class OMPNumThreadsClause : public OMPClause, public OMPClauseWithPreInit {
|
||||
friend class OMPClauseReader;
|
||||
/// \brief Location of '('.
|
||||
SourceLocation LParenLoc;
|
||||
@ -346,20 +360,29 @@ class OMPNumThreadsClause : public OMPClause {
|
||||
/// \brief Build 'num_threads' clause with condition \a NumThreads.
|
||||
///
|
||||
/// \param NumThreads Number of threads for the construct.
|
||||
/// \param HelperNumThreads Helper Number of threads for the construct.
|
||||
/// \param CaptureRegion Innermost OpenMP region where expressions in this
|
||||
/// clause must be captured.
|
||||
/// \param StartLoc Starting location of the clause.
|
||||
/// \param LParenLoc Location of '('.
|
||||
/// \param EndLoc Ending location of the clause.
|
||||
///
|
||||
OMPNumThreadsClause(Expr *NumThreads, SourceLocation StartLoc,
|
||||
SourceLocation LParenLoc, SourceLocation EndLoc)
|
||||
: OMPClause(OMPC_num_threads, StartLoc, EndLoc), LParenLoc(LParenLoc),
|
||||
NumThreads(NumThreads) {}
|
||||
OMPNumThreadsClause(Expr *NumThreads, Stmt *HelperNumThreads,
|
||||
OpenMPDirectiveKind CaptureRegion,
|
||||
SourceLocation StartLoc, SourceLocation LParenLoc,
|
||||
SourceLocation EndLoc)
|
||||
: OMPClause(OMPC_num_threads, StartLoc, EndLoc),
|
||||
OMPClauseWithPreInit(this), LParenLoc(LParenLoc),
|
||||
NumThreads(NumThreads) {
|
||||
setPreInitStmt(HelperNumThreads, CaptureRegion);
|
||||
}
|
||||
|
||||
/// \brief Build an empty clause.
|
||||
///
|
||||
OMPNumThreadsClause()
|
||||
: OMPClause(OMPC_num_threads, SourceLocation(), SourceLocation()),
|
||||
LParenLoc(SourceLocation()), NumThreads(nullptr) {}
|
||||
OMPClauseWithPreInit(this), LParenLoc(SourceLocation()),
|
||||
NumThreads(nullptr) {}
|
||||
|
||||
/// \brief Sets the location of '('.
|
||||
void setLParenLoc(SourceLocation Loc) { LParenLoc = Loc; }
|
||||
@ -3456,7 +3479,7 @@ class OMPMapClause final : public OMPMappableExprListClause<OMPMapClause>,
|
||||
/// In this example directive '#pragma omp teams' has clause 'num_teams'
|
||||
/// with single expression 'n'.
|
||||
///
|
||||
class OMPNumTeamsClause : public OMPClause {
|
||||
class OMPNumTeamsClause : public OMPClause, public OMPClauseWithPreInit {
|
||||
friend class OMPClauseReader;
|
||||
/// \brief Location of '('.
|
||||
SourceLocation LParenLoc;
|
||||
@ -3472,20 +3495,27 @@ class OMPNumTeamsClause : public OMPClause {
|
||||
/// \brief Build 'num_teams' clause.
|
||||
///
|
||||
/// \param E Expression associated with this clause.
|
||||
/// \param HelperE Helper Expression associated with this clause.
|
||||
/// \param CaptureRegion Innermost OpenMP region where expressions in this
|
||||
/// clause must be captured.
|
||||
/// \param StartLoc Starting location of the clause.
|
||||
/// \param LParenLoc Location of '('.
|
||||
/// \param EndLoc Ending location of the clause.
|
||||
///
|
||||
OMPNumTeamsClause(Expr *E, SourceLocation StartLoc, SourceLocation LParenLoc,
|
||||
OMPNumTeamsClause(Expr *E, Stmt *HelperE, OpenMPDirectiveKind CaptureRegion,
|
||||
SourceLocation StartLoc, SourceLocation LParenLoc,
|
||||
SourceLocation EndLoc)
|
||||
: OMPClause(OMPC_num_teams, StartLoc, EndLoc), LParenLoc(LParenLoc),
|
||||
NumTeams(E) {}
|
||||
: OMPClause(OMPC_num_teams, StartLoc, EndLoc), OMPClauseWithPreInit(this),
|
||||
LParenLoc(LParenLoc), NumTeams(E) {
|
||||
setPreInitStmt(HelperE, CaptureRegion);
|
||||
}
|
||||
|
||||
/// \brief Build an empty clause.
|
||||
///
|
||||
OMPNumTeamsClause()
|
||||
: OMPClause(OMPC_num_teams, SourceLocation(), SourceLocation()),
|
||||
LParenLoc(SourceLocation()), NumTeams(nullptr) {}
|
||||
: OMPClause(OMPC_num_teams, SourceLocation(), SourceLocation()),
|
||||
OMPClauseWithPreInit(this), LParenLoc(SourceLocation()),
|
||||
NumTeams(nullptr) {}
|
||||
/// \brief Sets the location of '('.
|
||||
void setLParenLoc(SourceLocation Loc) { LParenLoc = Loc; }
|
||||
/// \brief Returns the location of '('.
|
||||
@ -3511,7 +3541,7 @@ class OMPNumTeamsClause : public OMPClause {
|
||||
/// In this example directive '#pragma omp teams' has clause 'thread_limit'
|
||||
/// with single expression 'n'.
|
||||
///
|
||||
class OMPThreadLimitClause : public OMPClause {
|
||||
class OMPThreadLimitClause : public OMPClause, public OMPClauseWithPreInit {
|
||||
friend class OMPClauseReader;
|
||||
/// \brief Location of '('.
|
||||
SourceLocation LParenLoc;
|
||||
@ -3527,20 +3557,28 @@ class OMPThreadLimitClause : public OMPClause {
|
||||
/// \brief Build 'thread_limit' clause.
|
||||
///
|
||||
/// \param E Expression associated with this clause.
|
||||
/// \param HelperE Helper Expression associated with this clause.
|
||||
/// \param CaptureRegion Innermost OpenMP region where expressions in this
|
||||
/// clause must be captured.
|
||||
/// \param StartLoc Starting location of the clause.
|
||||
/// \param LParenLoc Location of '('.
|
||||
/// \param EndLoc Ending location of the clause.
|
||||
///
|
||||
OMPThreadLimitClause(Expr *E, SourceLocation StartLoc,
|
||||
SourceLocation LParenLoc, SourceLocation EndLoc)
|
||||
: OMPClause(OMPC_thread_limit, StartLoc, EndLoc), LParenLoc(LParenLoc),
|
||||
ThreadLimit(E) {}
|
||||
OMPThreadLimitClause(Expr *E, Stmt *HelperE,
|
||||
OpenMPDirectiveKind CaptureRegion,
|
||||
SourceLocation StartLoc, SourceLocation LParenLoc,
|
||||
SourceLocation EndLoc)
|
||||
: OMPClause(OMPC_thread_limit, StartLoc, EndLoc),
|
||||
OMPClauseWithPreInit(this), LParenLoc(LParenLoc), ThreadLimit(E) {
|
||||
setPreInitStmt(HelperE, CaptureRegion);
|
||||
}
|
||||
|
||||
/// \brief Build an empty clause.
|
||||
///
|
||||
OMPThreadLimitClause()
|
||||
: OMPClause(OMPC_thread_limit, SourceLocation(), SourceLocation()),
|
||||
LParenLoc(SourceLocation()), ThreadLimit(nullptr) {}
|
||||
OMPClauseWithPreInit(this), LParenLoc(SourceLocation()),
|
||||
ThreadLimit(nullptr) {}
|
||||
/// \brief Sets the location of '('.
|
||||
void setLParenLoc(SourceLocation Loc) { LParenLoc = Loc; }
|
||||
/// \brief Returns the location of '('.
|
||||
|
@ -774,6 +774,11 @@ bool RecursiveASTVisitor<Derived>::TraverseDeclarationNameInfo(
|
||||
TRY_TO(TraverseTypeLoc(TSInfo->getTypeLoc()));
|
||||
break;
|
||||
|
||||
case DeclarationName::CXXDeductionGuideName:
|
||||
TRY_TO(TraverseTemplateName(
|
||||
TemplateName(NameInfo.getName().getCXXDeductionGuideTemplate())));
|
||||
break;
|
||||
|
||||
case DeclarationName::Identifier:
|
||||
case DeclarationName::ObjCZeroArgSelector:
|
||||
case DeclarationName::ObjCOneArgSelector:
|
||||
@ -1008,6 +1013,10 @@ DEF_TRAVERSE_TYPE(UnaryTransformType, {
|
||||
})
|
||||
|
||||
DEF_TRAVERSE_TYPE(AutoType, { TRY_TO(TraverseType(T->getDeducedType())); })
|
||||
DEF_TRAVERSE_TYPE(DeducedTemplateSpecializationType, {
|
||||
TRY_TO(TraverseTemplateName(T->getTemplateName()));
|
||||
TRY_TO(TraverseType(T->getDeducedType()));
|
||||
})
|
||||
|
||||
DEF_TRAVERSE_TYPE(RecordType, {})
|
||||
DEF_TRAVERSE_TYPE(EnumType, {})
|
||||
@ -1232,6 +1241,11 @@ DEF_TRAVERSE_TYPELOC(AutoType, {
|
||||
TRY_TO(TraverseType(TL.getTypePtr()->getDeducedType()));
|
||||
})
|
||||
|
||||
DEF_TRAVERSE_TYPELOC(DeducedTemplateSpecializationType, {
|
||||
TRY_TO(TraverseTemplateName(TL.getTypePtr()->getTemplateName()));
|
||||
TRY_TO(TraverseType(TL.getTypePtr()->getDeducedType()));
|
||||
})
|
||||
|
||||
DEF_TRAVERSE_TYPELOC(RecordType, {})
|
||||
DEF_TRAVERSE_TYPELOC(EnumType, {})
|
||||
DEF_TRAVERSE_TYPELOC(TemplateTypeParmType, {})
|
||||
@ -1932,6 +1946,13 @@ DEF_TRAVERSE_DECL(FunctionDecl, {
|
||||
ReturnValue = TraverseFunctionHelper(D);
|
||||
})
|
||||
|
||||
DEF_TRAVERSE_DECL(CXXDeductionGuideDecl, {
|
||||
// We skip decls_begin/decls_end, which are already covered by
|
||||
// TraverseFunctionHelper().
|
||||
ShouldVisitChildren = false;
|
||||
ReturnValue = TraverseFunctionHelper(D);
|
||||
})
|
||||
|
||||
DEF_TRAVERSE_DECL(CXXMethodDecl, {
|
||||
// We skip decls_begin/decls_end, which are already covered by
|
||||
// TraverseFunctionHelper().
|
||||
@ -2495,6 +2516,12 @@ DEF_TRAVERSE_STMT(CoawaitExpr, {
|
||||
ShouldVisitChildren = false;
|
||||
}
|
||||
})
|
||||
DEF_TRAVERSE_STMT(DependentCoawaitExpr, {
|
||||
if (!getDerived().shouldVisitImplicitCode()) {
|
||||
TRY_TO_TRAVERSE_OR_ENQUEUE_STMT(S->getOperand());
|
||||
ShouldVisitChildren = false;
|
||||
}
|
||||
})
|
||||
DEF_TRAVERSE_STMT(CoyieldExpr, {
|
||||
if (!getDerived().shouldVisitImplicitCode()) {
|
||||
TRY_TO_TRAVERSE_OR_ENQUEUE_STMT(S->getOperand());
|
||||
@ -2711,6 +2738,7 @@ bool RecursiveASTVisitor<Derived>::VisitOMPClauseWithPostUpdate(
|
||||
|
||||
template <typename Derived>
|
||||
bool RecursiveASTVisitor<Derived>::VisitOMPIfClause(OMPIfClause *C) {
|
||||
TRY_TO(VisitOMPClauseWithPreInit(C));
|
||||
TRY_TO(TraverseStmt(C->getCondition()));
|
||||
return true;
|
||||
}
|
||||
@ -2724,6 +2752,7 @@ bool RecursiveASTVisitor<Derived>::VisitOMPFinalClause(OMPFinalClause *C) {
|
||||
template <typename Derived>
|
||||
bool
|
||||
RecursiveASTVisitor<Derived>::VisitOMPNumThreadsClause(OMPNumThreadsClause *C) {
|
||||
TRY_TO(VisitOMPClauseWithPreInit(C));
|
||||
TRY_TO(TraverseStmt(C->getNumThreads()));
|
||||
return true;
|
||||
}
|
||||
@ -2993,6 +3022,7 @@ bool RecursiveASTVisitor<Derived>::VisitOMPMapClause(OMPMapClause *C) {
|
||||
template <typename Derived>
|
||||
bool RecursiveASTVisitor<Derived>::VisitOMPNumTeamsClause(
|
||||
OMPNumTeamsClause *C) {
|
||||
TRY_TO(VisitOMPClauseWithPreInit(C));
|
||||
TRY_TO(TraverseStmt(C->getNumTeams()));
|
||||
return true;
|
||||
}
|
||||
@ -3000,6 +3030,7 @@ bool RecursiveASTVisitor<Derived>::VisitOMPNumTeamsClause(
|
||||
template <typename Derived>
|
||||
bool RecursiveASTVisitor<Derived>::VisitOMPThreadLimitClause(
|
||||
OMPThreadLimitClause *C) {
|
||||
TRY_TO(VisitOMPClauseWithPreInit(C));
|
||||
TRY_TO(TraverseStmt(C->getThreadLimit()));
|
||||
return true;
|
||||
}
|
||||
|
@ -39,6 +39,7 @@ namespace clang {
|
||||
class Expr;
|
||||
class IdentifierInfo;
|
||||
class LabelDecl;
|
||||
class ODRHash;
|
||||
class ParmVarDecl;
|
||||
class PrinterHelper;
|
||||
struct PrintingPolicy;
|
||||
@ -126,13 +127,13 @@ class alignas(void *) Stmt {
|
||||
unsigned : NumStmtBits;
|
||||
|
||||
unsigned ValueKind : 2;
|
||||
unsigned ObjectKind : 2;
|
||||
unsigned ObjectKind : 3;
|
||||
unsigned TypeDependent : 1;
|
||||
unsigned ValueDependent : 1;
|
||||
unsigned InstantiationDependent : 1;
|
||||
unsigned ContainsUnexpandedParameterPack : 1;
|
||||
};
|
||||
enum { NumExprBits = 16 };
|
||||
enum { NumExprBits = 17 };
|
||||
|
||||
class CharacterLiteralBitfields {
|
||||
friend class CharacterLiteral;
|
||||
@ -252,6 +253,14 @@ class alignas(void *) Stmt {
|
||||
unsigned NumArgs : 32 - 8 - 1 - NumExprBits;
|
||||
};
|
||||
|
||||
class CoawaitExprBitfields {
|
||||
friend class CoawaitExpr;
|
||||
|
||||
unsigned : NumExprBits;
|
||||
|
||||
unsigned IsImplicit : 1;
|
||||
};
|
||||
|
||||
union {
|
||||
StmtBitfields StmtBits;
|
||||
CompoundStmtBitfields CompoundStmtBits;
|
||||
@ -268,6 +277,7 @@ class alignas(void *) Stmt {
|
||||
ObjCIndirectCopyRestoreExprBitfields ObjCIndirectCopyRestoreExprBits;
|
||||
InitListExprBitfields InitListExprBits;
|
||||
TypeTraitExprBitfields TypeTraitExprBits;
|
||||
CoawaitExprBitfields CoawaitBits;
|
||||
};
|
||||
|
||||
friend class ASTStmtReader;
|
||||
@ -340,6 +350,8 @@ class alignas(void *) Stmt {
|
||||
|
||||
public:
|
||||
Stmt(StmtClass SC) {
|
||||
static_assert(sizeof(*this) == sizeof(void *),
|
||||
"changing bitfields changed sizeof(Stmt)");
|
||||
static_assert(sizeof(*this) % alignof(void *) == 0,
|
||||
"Insufficient alignment!");
|
||||
StmtBits.sClass = SC;
|
||||
@ -436,6 +448,15 @@ class alignas(void *) Stmt {
|
||||
/// written in the source.
|
||||
void Profile(llvm::FoldingSetNodeID &ID, const ASTContext &Context,
|
||||
bool Canonical) const;
|
||||
|
||||
/// \brief Calculate a unique representation for a statement that is
|
||||
/// stable across compiler invocations.
|
||||
///
|
||||
/// \param ID profile information will be stored in ID.
|
||||
///
|
||||
/// \param Hash an ODRHash object which will be called where pointers would
|
||||
/// have been used in the Profile function.
|
||||
void ProcessODRHash(llvm::FoldingSetNodeID &ID, ODRHash& Hash) const;
|
||||
};
|
||||
|
||||
/// DeclStmt - Adaptor class for mixing declarations with statements and
|
||||
|
@ -296,7 +296,9 @@ class MSDependentExistsStmt : public Stmt {
|
||||
/// \brief Represents the body of a coroutine. This wraps the normal function
|
||||
/// body and holds the additional semantic context required to set up and tear
|
||||
/// down the coroutine frame.
|
||||
class CoroutineBodyStmt : public Stmt {
|
||||
class CoroutineBodyStmt final
|
||||
: public Stmt,
|
||||
private llvm::TrailingObjects<CoroutineBodyStmt, Stmt *> {
|
||||
enum SubStmt {
|
||||
Body, ///< The body of the coroutine.
|
||||
Promise, ///< The promise statement.
|
||||
@ -307,65 +309,100 @@ class CoroutineBodyStmt : public Stmt {
|
||||
Allocate, ///< Coroutine frame memory allocation.
|
||||
Deallocate, ///< Coroutine frame memory deallocation.
|
||||
ReturnValue, ///< Return value for thunk function.
|
||||
ReturnStmtOnAllocFailure, ///< Return statement if allocation failed.
|
||||
FirstParamMove ///< First offset for move construction of parameter copies.
|
||||
};
|
||||
Stmt *SubStmts[SubStmt::FirstParamMove];
|
||||
unsigned NumParams;
|
||||
|
||||
friend class ASTStmtReader;
|
||||
friend TrailingObjects;
|
||||
|
||||
Stmt **getStoredStmts() { return getTrailingObjects<Stmt *>(); }
|
||||
|
||||
Stmt *const *getStoredStmts() const { return getTrailingObjects<Stmt *>(); }
|
||||
|
||||
public:
|
||||
CoroutineBodyStmt(Stmt *Body, Stmt *Promise, Stmt *InitSuspend,
|
||||
Stmt *FinalSuspend, Stmt *OnException, Stmt *OnFallthrough,
|
||||
Expr *Allocate, Stmt *Deallocate,
|
||||
Expr *ReturnValue, ArrayRef<Expr *> ParamMoves)
|
||||
: Stmt(CoroutineBodyStmtClass) {
|
||||
SubStmts[CoroutineBodyStmt::Body] = Body;
|
||||
SubStmts[CoroutineBodyStmt::Promise] = Promise;
|
||||
SubStmts[CoroutineBodyStmt::InitSuspend] = InitSuspend;
|
||||
SubStmts[CoroutineBodyStmt::FinalSuspend] = FinalSuspend;
|
||||
SubStmts[CoroutineBodyStmt::OnException] = OnException;
|
||||
SubStmts[CoroutineBodyStmt::OnFallthrough] = OnFallthrough;
|
||||
SubStmts[CoroutineBodyStmt::Allocate] = Allocate;
|
||||
SubStmts[CoroutineBodyStmt::Deallocate] = Deallocate;
|
||||
SubStmts[CoroutineBodyStmt::ReturnValue] = ReturnValue;
|
||||
// FIXME: Tail-allocate space for parameter move expressions and store them.
|
||||
assert(ParamMoves.empty() && "not implemented yet");
|
||||
|
||||
struct CtorArgs {
|
||||
Stmt *Body = nullptr;
|
||||
Stmt *Promise = nullptr;
|
||||
Expr *InitialSuspend = nullptr;
|
||||
Expr *FinalSuspend = nullptr;
|
||||
Stmt *OnException = nullptr;
|
||||
Stmt *OnFallthrough = nullptr;
|
||||
Expr *Allocate = nullptr;
|
||||
Expr *Deallocate = nullptr;
|
||||
Stmt *ReturnValue = nullptr;
|
||||
Stmt *ReturnStmtOnAllocFailure = nullptr;
|
||||
ArrayRef<Stmt *> ParamMoves;
|
||||
};
|
||||
|
||||
private:
|
||||
|
||||
CoroutineBodyStmt(CtorArgs const& Args);
|
||||
|
||||
public:
|
||||
static CoroutineBodyStmt *Create(const ASTContext &C, CtorArgs const &Args);
|
||||
|
||||
bool hasDependentPromiseType() const {
|
||||
return getPromiseDecl()->getType()->isDependentType();
|
||||
}
|
||||
|
||||
/// \brief Retrieve the body of the coroutine as written. This will be either
|
||||
/// a CompoundStmt or a TryStmt.
|
||||
Stmt *getBody() const {
|
||||
return SubStmts[SubStmt::Body];
|
||||
return getStoredStmts()[SubStmt::Body];
|
||||
}
|
||||
|
||||
Stmt *getPromiseDeclStmt() const { return SubStmts[SubStmt::Promise]; }
|
||||
Stmt *getPromiseDeclStmt() const {
|
||||
return getStoredStmts()[SubStmt::Promise];
|
||||
}
|
||||
VarDecl *getPromiseDecl() const {
|
||||
return cast<VarDecl>(cast<DeclStmt>(getPromiseDeclStmt())->getSingleDecl());
|
||||
}
|
||||
|
||||
Stmt *getInitSuspendStmt() const { return SubStmts[SubStmt::InitSuspend]; }
|
||||
Stmt *getFinalSuspendStmt() const { return SubStmts[SubStmt::FinalSuspend]; }
|
||||
|
||||
Stmt *getExceptionHandler() const { return SubStmts[SubStmt::OnException]; }
|
||||
Stmt *getFallthroughHandler() const {
|
||||
return SubStmts[SubStmt::OnFallthrough];
|
||||
Stmt *getInitSuspendStmt() const {
|
||||
return getStoredStmts()[SubStmt::InitSuspend];
|
||||
}
|
||||
Stmt *getFinalSuspendStmt() const {
|
||||
return getStoredStmts()[SubStmt::FinalSuspend];
|
||||
}
|
||||
|
||||
Expr *getAllocate() const { return cast<Expr>(SubStmts[SubStmt::Allocate]); }
|
||||
Stmt *getDeallocate() const { return SubStmts[SubStmt::Deallocate]; }
|
||||
Stmt *getExceptionHandler() const {
|
||||
return getStoredStmts()[SubStmt::OnException];
|
||||
}
|
||||
Stmt *getFallthroughHandler() const {
|
||||
return getStoredStmts()[SubStmt::OnFallthrough];
|
||||
}
|
||||
|
||||
Expr *getAllocate() const {
|
||||
return cast_or_null<Expr>(getStoredStmts()[SubStmt::Allocate]);
|
||||
}
|
||||
Expr *getDeallocate() const {
|
||||
return cast_or_null<Expr>(getStoredStmts()[SubStmt::Deallocate]);
|
||||
}
|
||||
|
||||
Expr *getReturnValueInit() const {
|
||||
return cast<Expr>(SubStmts[SubStmt::ReturnValue]);
|
||||
return cast_or_null<Expr>(getStoredStmts()[SubStmt::ReturnValue]);
|
||||
}
|
||||
Stmt *getReturnStmtOnAllocFailure() const {
|
||||
return getStoredStmts()[SubStmt::ReturnStmtOnAllocFailure];
|
||||
}
|
||||
ArrayRef<Stmt const *> getParamMoves() const {
|
||||
return {getStoredStmts() + SubStmt::FirstParamMove, NumParams};
|
||||
}
|
||||
|
||||
SourceLocation getLocStart() const LLVM_READONLY {
|
||||
return getBody()->getLocStart();
|
||||
return getBody() ? getBody()->getLocStart()
|
||||
: getPromiseDecl()->getLocStart();
|
||||
}
|
||||
SourceLocation getLocEnd() const LLVM_READONLY {
|
||||
return getBody()->getLocEnd();
|
||||
return getBody() ? getBody()->getLocEnd() : getPromiseDecl()->getLocEnd();
|
||||
}
|
||||
|
||||
child_range children() {
|
||||
return child_range(SubStmts, SubStmts + SubStmt::FirstParamMove);
|
||||
return child_range(getStoredStmts(),
|
||||
getStoredStmts() + SubStmt::FirstParamMove + NumParams);
|
||||
}
|
||||
|
||||
static bool classof(const Stmt *T) {
|
||||
@ -390,10 +427,14 @@ class CoreturnStmt : public Stmt {
|
||||
enum SubStmt { Operand, PromiseCall, Count };
|
||||
Stmt *SubStmts[SubStmt::Count];
|
||||
|
||||
bool IsImplicit : 1;
|
||||
|
||||
friend class ASTStmtReader;
|
||||
public:
|
||||
CoreturnStmt(SourceLocation CoreturnLoc, Stmt *Operand, Stmt *PromiseCall)
|
||||
: Stmt(CoreturnStmtClass), CoreturnLoc(CoreturnLoc) {
|
||||
CoreturnStmt(SourceLocation CoreturnLoc, Stmt *Operand, Stmt *PromiseCall,
|
||||
bool IsImplicit = false)
|
||||
: Stmt(CoreturnStmtClass), CoreturnLoc(CoreturnLoc),
|
||||
IsImplicit(IsImplicit) {
|
||||
SubStmts[SubStmt::Operand] = Operand;
|
||||
SubStmts[SubStmt::PromiseCall] = PromiseCall;
|
||||
}
|
||||
@ -411,6 +452,9 @@ class CoreturnStmt : public Stmt {
|
||||
return static_cast<Expr*>(SubStmts[PromiseCall]);
|
||||
}
|
||||
|
||||
bool isImplicit() const { return IsImplicit; }
|
||||
void setIsImplicit(bool value = true) { IsImplicit = value; }
|
||||
|
||||
SourceLocation getLocStart() const LLVM_READONLY { return CoreturnLoc; }
|
||||
SourceLocation getLocEnd() const LLVM_READONLY {
|
||||
return getOperand() ? getOperand()->getLocEnd() : getLocStart();
|
||||
|
@ -118,6 +118,8 @@ class StmtIteratorImpl : public StmtIteratorBase,
|
||||
REFERENCE operator->() const { return operator*(); }
|
||||
};
|
||||
|
||||
struct ConstStmtIterator;
|
||||
|
||||
struct StmtIterator : public StmtIteratorImpl<StmtIterator,Stmt*&> {
|
||||
explicit StmtIterator() : StmtIteratorImpl<StmtIterator,Stmt*&>() {}
|
||||
|
||||
@ -128,6 +130,13 @@ struct StmtIterator : public StmtIteratorImpl<StmtIterator,Stmt*&> {
|
||||
|
||||
StmtIterator(const VariableArrayType *t)
|
||||
: StmtIteratorImpl<StmtIterator,Stmt*&>(t) {}
|
||||
|
||||
private:
|
||||
StmtIterator(const StmtIteratorBase &RHS)
|
||||
: StmtIteratorImpl<StmtIterator, Stmt *&>(RHS) {}
|
||||
|
||||
inline friend StmtIterator
|
||||
cast_away_const(const ConstStmtIterator &RHS);
|
||||
};
|
||||
|
||||
struct ConstStmtIterator : public StmtIteratorImpl<ConstStmtIterator,
|
||||
@ -137,8 +146,15 @@ struct ConstStmtIterator : public StmtIteratorImpl<ConstStmtIterator,
|
||||
|
||||
ConstStmtIterator(const StmtIterator& RHS) :
|
||||
StmtIteratorImpl<ConstStmtIterator,const Stmt*>(RHS) {}
|
||||
|
||||
ConstStmtIterator(Stmt * const *S)
|
||||
: StmtIteratorImpl<ConstStmtIterator, const Stmt *>(
|
||||
const_cast<Stmt **>(S)) {}
|
||||
};
|
||||
|
||||
inline StmtIterator cast_away_const(const ConstStmtIterator &RHS) {
|
||||
return RHS;
|
||||
}
|
||||
} // end namespace clang
|
||||
|
||||
#endif
|
||||
|
@ -198,6 +198,26 @@ class OMPExecutableDirective : public Stmt {
|
||||
return const_cast<Stmt *>(*child_begin());
|
||||
}
|
||||
|
||||
/// \brief Returns the captured statement associated with the
|
||||
/// component region within the (combined) directive.
|
||||
//
|
||||
// \param RegionKind Component region kind.
|
||||
CapturedStmt *getCapturedStmt(OpenMPDirectiveKind RegionKind) const {
|
||||
SmallVector<OpenMPDirectiveKind, 4> CaptureRegions;
|
||||
getOpenMPCaptureRegions(CaptureRegions, getDirectiveKind());
|
||||
assert(std::any_of(
|
||||
CaptureRegions.begin(), CaptureRegions.end(),
|
||||
[=](const OpenMPDirectiveKind K) { return K == RegionKind; }) &&
|
||||
"RegionKind not found in OpenMP CaptureRegions.");
|
||||
auto *CS = cast<CapturedStmt>(getAssociatedStmt());
|
||||
for (auto ThisCaptureRegion : CaptureRegions) {
|
||||
if (ThisCaptureRegion == RegionKind)
|
||||
return CS;
|
||||
CS = cast<CapturedStmt>(CS->getCapturedStmt());
|
||||
}
|
||||
llvm_unreachable("Incorrect RegionKind specified for directive.");
|
||||
}
|
||||
|
||||
OpenMPDirectiveKind getDirectiveKind() const { return Kind; }
|
||||
|
||||
static bool classof(const Stmt *S) {
|
||||
@ -304,6 +324,11 @@ class OMPLoopDirective : public OMPExecutableDirective {
|
||||
/// allocated: loop counters, their updates and final values.
|
||||
/// PrevLowerBound and PrevUpperBound are used to communicate blocking
|
||||
/// information in composite constructs which require loop blocking
|
||||
/// DistInc is used to generate the increment expression for the distribute
|
||||
/// loop when combined with a further nested loop
|
||||
/// PrevEnsureUpperBound is used as the EnsureUpperBound expression for the
|
||||
/// for loop when combined with a previous distribute loop in the same pragma
|
||||
/// (e.g. 'distribute parallel for')
|
||||
///
|
||||
enum {
|
||||
AssociatedStmtOffset = 0,
|
||||
@ -319,7 +344,7 @@ class OMPLoopDirective : public OMPExecutableDirective {
|
||||
// specify the offset to the end (and start of the following counters/
|
||||
// updates/finals arrays).
|
||||
DefaultEnd = 9,
|
||||
// The following 7 exprs are used by worksharing loops only.
|
||||
// The following 12 exprs are used by worksharing and distribute loops only.
|
||||
IsLastIterVariableOffset = 9,
|
||||
LowerBoundVariableOffset = 10,
|
||||
UpperBoundVariableOffset = 11,
|
||||
@ -330,9 +355,11 @@ class OMPLoopDirective : public OMPExecutableDirective {
|
||||
NumIterationsOffset = 16,
|
||||
PrevLowerBoundVariableOffset = 17,
|
||||
PrevUpperBoundVariableOffset = 18,
|
||||
DistIncOffset = 19,
|
||||
PrevEnsureUpperBoundOffset = 20,
|
||||
// Offset to the end (and start of the following counters/updates/finals
|
||||
// arrays) for worksharing loop directives.
|
||||
WorksharingEnd = 19,
|
||||
WorksharingEnd = 21,
|
||||
};
|
||||
|
||||
/// \brief Get the counters storage.
|
||||
@ -501,6 +528,20 @@ class OMPLoopDirective : public OMPExecutableDirective {
|
||||
"expected worksharing loop directive");
|
||||
*std::next(child_begin(), PrevUpperBoundVariableOffset) = PrevUB;
|
||||
}
|
||||
void setDistInc(Expr *DistInc) {
|
||||
assert((isOpenMPWorksharingDirective(getDirectiveKind()) ||
|
||||
isOpenMPTaskLoopDirective(getDirectiveKind()) ||
|
||||
isOpenMPDistributeDirective(getDirectiveKind())) &&
|
||||
"expected worksharing loop directive");
|
||||
*std::next(child_begin(), DistIncOffset) = DistInc;
|
||||
}
|
||||
void setPrevEnsureUpperBound(Expr *PrevEUB) {
|
||||
assert((isOpenMPWorksharingDirective(getDirectiveKind()) ||
|
||||
isOpenMPTaskLoopDirective(getDirectiveKind()) ||
|
||||
isOpenMPDistributeDirective(getDirectiveKind())) &&
|
||||
"expected worksharing loop directive");
|
||||
*std::next(child_begin(), PrevEnsureUpperBoundOffset) = PrevEUB;
|
||||
}
|
||||
void setCounters(ArrayRef<Expr *> A);
|
||||
void setPrivateCounters(ArrayRef<Expr *> A);
|
||||
void setInits(ArrayRef<Expr *> A);
|
||||
@ -535,7 +576,7 @@ class OMPLoopDirective : public OMPExecutableDirective {
|
||||
Expr *UB;
|
||||
/// \brief Stride - local variable passed to runtime.
|
||||
Expr *ST;
|
||||
/// \brief EnsureUpperBound -- expression LB = min(LB, NumIterations).
|
||||
/// \brief EnsureUpperBound -- expression UB = min(UB, NumIterations).
|
||||
Expr *EUB;
|
||||
/// \brief Update of LowerBound for statically sheduled 'omp for' loops.
|
||||
Expr *NLB;
|
||||
@ -547,6 +588,16 @@ class OMPLoopDirective : public OMPExecutableDirective {
|
||||
/// \brief PreviousUpperBound - local variable passed to runtime in the
|
||||
/// enclosing schedule or null if that does not apply.
|
||||
Expr *PrevUB;
|
||||
/// \brief DistInc - increment expression for distribute loop when found
|
||||
/// combined with a further loop level (e.g. in 'distribute parallel for')
|
||||
/// expression IV = IV + ST
|
||||
Expr *DistInc;
|
||||
/// \brief PrevEUB - expression similar to EUB but to be used when loop
|
||||
/// scheduling uses PrevLB and PrevUB (e.g. in 'distribute parallel for'
|
||||
/// when ensuring that the UB is either the calculated UB by the runtime or
|
||||
/// the end of the assigned distribute chunk)
|
||||
/// expression UB = min (UB, PrevUB)
|
||||
Expr *PrevEUB;
|
||||
/// \brief Counters Loop counters.
|
||||
SmallVector<Expr *, 4> Counters;
|
||||
/// \brief PrivateCounters Loop counters.
|
||||
@ -588,6 +639,8 @@ class OMPLoopDirective : public OMPExecutableDirective {
|
||||
NumIterations = nullptr;
|
||||
PrevLB = nullptr;
|
||||
PrevUB = nullptr;
|
||||
DistInc = nullptr;
|
||||
PrevEUB = nullptr;
|
||||
Counters.resize(Size);
|
||||
PrivateCounters.resize(Size);
|
||||
Inits.resize(Size);
|
||||
@ -719,6 +772,22 @@ class OMPLoopDirective : public OMPExecutableDirective {
|
||||
return const_cast<Expr *>(reinterpret_cast<const Expr *>(
|
||||
*std::next(child_begin(), PrevUpperBoundVariableOffset)));
|
||||
}
|
||||
Expr *getDistInc() const {
|
||||
assert((isOpenMPWorksharingDirective(getDirectiveKind()) ||
|
||||
isOpenMPTaskLoopDirective(getDirectiveKind()) ||
|
||||
isOpenMPDistributeDirective(getDirectiveKind())) &&
|
||||
"expected worksharing loop directive");
|
||||
return const_cast<Expr *>(reinterpret_cast<const Expr *>(
|
||||
*std::next(child_begin(), DistIncOffset)));
|
||||
}
|
||||
Expr *getPrevEnsureUpperBound() const {
|
||||
assert((isOpenMPWorksharingDirective(getDirectiveKind()) ||
|
||||
isOpenMPTaskLoopDirective(getDirectiveKind()) ||
|
||||
isOpenMPDistributeDirective(getDirectiveKind())) &&
|
||||
"expected worksharing loop directive");
|
||||
return const_cast<Expr *>(reinterpret_cast<const Expr *>(
|
||||
*std::next(child_begin(), PrevEnsureUpperBoundOffset)));
|
||||
}
|
||||
const Stmt *getBody() const {
|
||||
// This relies on the loop form is already checked by Sema.
|
||||
Stmt *Body = getAssociatedStmt()->IgnoreContainers(true);
|
||||
|
@ -119,10 +119,7 @@ class TemplateArgument {
|
||||
|
||||
public:
|
||||
/// \brief Construct an empty, invalid template argument.
|
||||
TemplateArgument() {
|
||||
TypeOrValue.Kind = Null;
|
||||
TypeOrValue.V = 0;
|
||||
}
|
||||
constexpr TemplateArgument() : TypeOrValue({Null, 0}) {}
|
||||
|
||||
/// \brief Construct a template type argument.
|
||||
TemplateArgument(QualType T, bool isNullPtr = false) {
|
||||
@ -388,8 +385,8 @@ struct TemplateArgumentLocInfo {
|
||||
};
|
||||
|
||||
public:
|
||||
TemplateArgumentLocInfo();
|
||||
|
||||
constexpr TemplateArgumentLocInfo() : Template({nullptr, nullptr, 0, 0}) {}
|
||||
|
||||
TemplateArgumentLocInfo(TypeSourceInfo *TInfo) : Declarator(TInfo) {}
|
||||
|
||||
TemplateArgumentLocInfo(Expr *E) : Expression(E) {}
|
||||
@ -433,7 +430,7 @@ class TemplateArgumentLoc {
|
||||
TemplateArgumentLocInfo LocInfo;
|
||||
|
||||
public:
|
||||
TemplateArgumentLoc() {}
|
||||
constexpr TemplateArgumentLoc() {}
|
||||
|
||||
TemplateArgumentLoc(const TemplateArgument &Argument,
|
||||
TemplateArgumentLocInfo Opaque)
|
||||
@ -578,6 +575,7 @@ struct ASTTemplateArgumentListInfo final
|
||||
TemplateArgumentLoc> {
|
||||
private:
|
||||
friend TrailingObjects;
|
||||
friend class ASTNodeImporter;
|
||||
|
||||
ASTTemplateArgumentListInfo(const TemplateArgumentListInfo &List);
|
||||
|
||||
|
@ -333,6 +333,20 @@ class Qualifiers {
|
||||
|
||||
bool hasAddressSpace() const { return Mask & AddressSpaceMask; }
|
||||
unsigned getAddressSpace() const { return Mask >> AddressSpaceShift; }
|
||||
/// Get the address space attribute value to be printed by diagnostics.
|
||||
unsigned getAddressSpaceAttributePrintValue() const {
|
||||
auto Addr = getAddressSpace();
|
||||
// This function is not supposed to be used with language specific
|
||||
// address spaces. If that happens, the diagnostic message should consider
|
||||
// printing the QualType instead of the address space value.
|
||||
assert(Addr == 0 || Addr >= LangAS::Count);
|
||||
if (Addr)
|
||||
return Addr - LangAS::Count;
|
||||
// TODO: The diagnostic messages where Addr may be 0 should be fixed
|
||||
// since it cannot differentiate the situation where 0 denotes the default
|
||||
// address space or user specified __attribute__((address_space(0))).
|
||||
return 0;
|
||||
}
|
||||
void setAddressSpace(unsigned space) {
|
||||
assert(space <= MaxAddressSpace);
|
||||
Mask = (Mask & ~AddressSpaceMask)
|
||||
@ -1020,6 +1034,9 @@ class QualType {
|
||||
return getQualifiers().hasStrongOrWeakObjCLifetime();
|
||||
}
|
||||
|
||||
// true when Type is objc's weak and weak is enabled but ARC isn't.
|
||||
bool isNonWeakInMRRWithObjCWeak(const ASTContext &Context) const;
|
||||
|
||||
enum DestructionKind {
|
||||
DK_none,
|
||||
DK_cxx_destructor,
|
||||
@ -1744,7 +1761,6 @@ class Type : public ExtQualsTypeCommonBase {
|
||||
bool isEventT() const; // OpenCL event_t
|
||||
bool isClkEventT() const; // OpenCL clk_event_t
|
||||
bool isQueueT() const; // OpenCL queue_t
|
||||
bool isNDRangeT() const; // OpenCL ndrange_t
|
||||
bool isReserveIDT() const; // OpenCL reserve_id_t
|
||||
|
||||
bool isPipeType() const; // OpenCL pipe type
|
||||
@ -1785,7 +1801,8 @@ class Type : public ExtQualsTypeCommonBase {
|
||||
}
|
||||
|
||||
/// \brief Determine whether this type is an undeduced type, meaning that
|
||||
/// it somehow involves a C++11 'auto' type which has not yet been deduced.
|
||||
/// it somehow involves a C++11 'auto' type or similar which has not yet been
|
||||
/// deduced.
|
||||
bool isUndeducedType() const;
|
||||
|
||||
/// \brief Whether this type is a variably-modified type (C99 6.7.5).
|
||||
@ -1862,10 +1879,22 @@ class Type : public ExtQualsTypeCommonBase {
|
||||
/// not refer to a CXXRecordDecl, returns NULL.
|
||||
const CXXRecordDecl *getPointeeCXXRecordDecl() const;
|
||||
|
||||
/// Get the DeducedType whose type will be deduced for a variable with
|
||||
/// an initializer of this type. This looks through declarators like pointer
|
||||
/// types, but not through decltype or typedefs.
|
||||
DeducedType *getContainedDeducedType() const;
|
||||
|
||||
/// Get the AutoType whose type will be deduced for a variable with
|
||||
/// an initializer of this type. This looks through declarators like pointer
|
||||
/// types, but not through decltype or typedefs.
|
||||
AutoType *getContainedAutoType() const;
|
||||
AutoType *getContainedAutoType() const {
|
||||
return dyn_cast_or_null<AutoType>(getContainedDeducedType());
|
||||
}
|
||||
|
||||
/// Determine whether this type was written with a leading 'auto'
|
||||
/// corresponding to a trailing return type (possibly for a nested
|
||||
/// function type within a pointer to function type or similar).
|
||||
bool hasAutoForTrailingReturnType() const;
|
||||
|
||||
/// Member-template getAs<specific type>'. Look through sugar for
|
||||
/// an instance of \<specific type>. This scheme will eventually
|
||||
@ -1875,6 +1904,13 @@ class Type : public ExtQualsTypeCommonBase {
|
||||
/// immediately following this class.
|
||||
template <typename T> const T *getAs() const;
|
||||
|
||||
/// Member-template getAsAdjusted<specific type>. Look through specific kinds
|
||||
/// of sugar (parens, attributes, etc) for an instance of \<specific type>.
|
||||
/// This is used when you need to walk over sugar nodes that represent some
|
||||
/// kind of type adjustment from a type that was written as a \<specific type>
|
||||
/// to another type that is still canonically a \<specific type>.
|
||||
template <typename T> const T *getAsAdjusted() const;
|
||||
|
||||
/// A variant of getAs<> for array types which silently discards
|
||||
/// qualifiers from the outermost type.
|
||||
const ArrayType *getAsArrayTypeUnsafe() const;
|
||||
@ -2057,7 +2093,7 @@ class BuiltinType : public Type {
|
||||
: Type(Builtin, QualType(), /*Dependent=*/(K == Dependent),
|
||||
/*InstantiationDependent=*/(K == Dependent),
|
||||
/*VariablyModified=*/false,
|
||||
/*Unexpanded paramter pack=*/false) {
|
||||
/*Unexpanded parameter pack=*/false) {
|
||||
BuiltinTypeBits.Kind = K;
|
||||
}
|
||||
|
||||
@ -3097,9 +3133,11 @@ class FunctionProtoType : public FunctionType, public llvm::FoldingSetNode {
|
||||
class ExtParameterInfo {
|
||||
enum {
|
||||
ABIMask = 0x0F,
|
||||
IsConsumed = 0x10
|
||||
IsConsumed = 0x10,
|
||||
HasPassObjSize = 0x20,
|
||||
};
|
||||
unsigned char Data;
|
||||
|
||||
public:
|
||||
ExtParameterInfo() : Data(0) {}
|
||||
|
||||
@ -3128,6 +3166,15 @@ class FunctionProtoType : public FunctionType, public llvm::FoldingSetNode {
|
||||
return copy;
|
||||
}
|
||||
|
||||
bool hasPassObjectSize() const {
|
||||
return Data & HasPassObjSize;
|
||||
}
|
||||
ExtParameterInfo withHasPassObjectSize() const {
|
||||
ExtParameterInfo Copy = *this;
|
||||
Copy.Data |= HasPassObjSize;
|
||||
return Copy;
|
||||
}
|
||||
|
||||
unsigned char getOpaqueValue() const { return Data; }
|
||||
static ExtParameterInfo getFromOpaqueValue(unsigned char data) {
|
||||
ExtParameterInfo result;
|
||||
@ -4089,25 +4136,60 @@ class SubstTemplateTypeParmPackType : public Type, public llvm::FoldingSetNode {
|
||||
}
|
||||
};
|
||||
|
||||
/// \brief Represents a C++11 auto or C++14 decltype(auto) type.
|
||||
/// \brief Common base class for placeholders for types that get replaced by
|
||||
/// placeholder type deduction: C++11 auto, C++14 decltype(auto), C++17 deduced
|
||||
/// class template types, and (eventually) constrained type names from the C++
|
||||
/// Concepts TS.
|
||||
///
|
||||
/// These types are usually a placeholder for a deduced type. However, before
|
||||
/// the initializer is attached, or (usually) if the initializer is
|
||||
/// type-dependent, there is no deduced type and an auto type is canonical. In
|
||||
/// type-dependent, there is no deduced type and the type is canonical. In
|
||||
/// the latter case, it is also a dependent type.
|
||||
class AutoType : public Type, public llvm::FoldingSetNode {
|
||||
AutoType(QualType DeducedType, AutoTypeKeyword Keyword, bool IsDependent)
|
||||
: Type(Auto, DeducedType.isNull() ? QualType(this, 0) : DeducedType,
|
||||
/*Dependent=*/IsDependent, /*InstantiationDependent=*/IsDependent,
|
||||
/*VariablyModified=*/false, /*ContainsParameterPack=*/false) {
|
||||
if (!DeducedType.isNull()) {
|
||||
if (DeducedType->isDependentType())
|
||||
class DeducedType : public Type {
|
||||
protected:
|
||||
DeducedType(TypeClass TC, QualType DeducedAsType, bool IsDependent,
|
||||
bool IsInstantiationDependent, bool ContainsParameterPack)
|
||||
: Type(TC,
|
||||
// FIXME: Retain the sugared deduced type?
|
||||
DeducedAsType.isNull() ? QualType(this, 0)
|
||||
: DeducedAsType.getCanonicalType(),
|
||||
IsDependent, IsInstantiationDependent,
|
||||
/*VariablyModified=*/false, ContainsParameterPack) {
|
||||
if (!DeducedAsType.isNull()) {
|
||||
if (DeducedAsType->isDependentType())
|
||||
setDependent();
|
||||
if (DeducedType->isInstantiationDependentType())
|
||||
if (DeducedAsType->isInstantiationDependentType())
|
||||
setInstantiationDependent();
|
||||
if (DeducedType->containsUnexpandedParameterPack())
|
||||
if (DeducedAsType->containsUnexpandedParameterPack())
|
||||
setContainsUnexpandedParameterPack();
|
||||
}
|
||||
}
|
||||
|
||||
public:
|
||||
bool isSugared() const { return !isCanonicalUnqualified(); }
|
||||
QualType desugar() const { return getCanonicalTypeInternal(); }
|
||||
|
||||
/// \brief Get the type deduced for this placeholder type, or null if it's
|
||||
/// either not been deduced or was deduced to a dependent type.
|
||||
QualType getDeducedType() const {
|
||||
return !isCanonicalUnqualified() ? getCanonicalTypeInternal() : QualType();
|
||||
}
|
||||
bool isDeduced() const {
|
||||
return !isCanonicalUnqualified() || isDependentType();
|
||||
}
|
||||
|
||||
static bool classof(const Type *T) {
|
||||
return T->getTypeClass() == Auto ||
|
||||
T->getTypeClass() == DeducedTemplateSpecialization;
|
||||
}
|
||||
};
|
||||
|
||||
/// \brief Represents a C++11 auto or C++14 decltype(auto) type.
|
||||
class AutoType : public DeducedType, public llvm::FoldingSetNode {
|
||||
AutoType(QualType DeducedAsType, AutoTypeKeyword Keyword,
|
||||
bool IsDeducedAsDependent)
|
||||
: DeducedType(Auto, DeducedAsType, IsDeducedAsDependent,
|
||||
IsDeducedAsDependent, /*ContainsPack=*/false) {
|
||||
AutoTypeBits.Keyword = (unsigned)Keyword;
|
||||
}
|
||||
|
||||
@ -4121,18 +4203,6 @@ class AutoType : public Type, public llvm::FoldingSetNode {
|
||||
return (AutoTypeKeyword)AutoTypeBits.Keyword;
|
||||
}
|
||||
|
||||
bool isSugared() const { return !isCanonicalUnqualified(); }
|
||||
QualType desugar() const { return getCanonicalTypeInternal(); }
|
||||
|
||||
/// \brief Get the type deduced for this auto type, or null if it's either
|
||||
/// not been deduced or was deduced to a dependent type.
|
||||
QualType getDeducedType() const {
|
||||
return !isCanonicalUnqualified() ? getCanonicalTypeInternal() : QualType();
|
||||
}
|
||||
bool isDeduced() const {
|
||||
return !isCanonicalUnqualified() || isDependentType();
|
||||
}
|
||||
|
||||
void Profile(llvm::FoldingSetNodeID &ID) {
|
||||
Profile(ID, getDeducedType(), getKeyword(), isDependentType());
|
||||
}
|
||||
@ -4149,6 +4219,43 @@ class AutoType : public Type, public llvm::FoldingSetNode {
|
||||
}
|
||||
};
|
||||
|
||||
/// \brief Represents a C++17 deduced template specialization type.
|
||||
class DeducedTemplateSpecializationType : public DeducedType,
|
||||
public llvm::FoldingSetNode {
|
||||
/// The name of the template whose arguments will be deduced.
|
||||
TemplateName Template;
|
||||
|
||||
DeducedTemplateSpecializationType(TemplateName Template,
|
||||
QualType DeducedAsType,
|
||||
bool IsDeducedAsDependent)
|
||||
: DeducedType(DeducedTemplateSpecialization, DeducedAsType,
|
||||
IsDeducedAsDependent || Template.isDependent(),
|
||||
IsDeducedAsDependent || Template.isInstantiationDependent(),
|
||||
Template.containsUnexpandedParameterPack()),
|
||||
Template(Template) {}
|
||||
|
||||
friend class ASTContext; // ASTContext creates these
|
||||
|
||||
public:
|
||||
/// Retrieve the name of the template that we are deducing.
|
||||
TemplateName getTemplateName() const { return Template;}
|
||||
|
||||
void Profile(llvm::FoldingSetNodeID &ID) {
|
||||
Profile(ID, getTemplateName(), getDeducedType(), isDependentType());
|
||||
}
|
||||
|
||||
static void Profile(llvm::FoldingSetNodeID &ID, TemplateName Template,
|
||||
QualType Deduced, bool IsDependent) {
|
||||
Template.Profile(ID);
|
||||
ID.AddPointer(Deduced.getAsOpaquePtr());
|
||||
ID.AddBoolean(IsDependent);
|
||||
}
|
||||
|
||||
static bool classof(const Type *T) {
|
||||
return T->getTypeClass() == DeducedTemplateSpecialization;
|
||||
}
|
||||
};
|
||||
|
||||
/// \brief Represents a type template specialization; the template
|
||||
/// must be a class template, a type alias template, or a template
|
||||
/// template parameter. A template which cannot be resolved to one of
|
||||
@ -4345,6 +4452,9 @@ class InjectedClassNameType : public Type {
|
||||
const TemplateSpecializationType *getInjectedTST() const {
|
||||
return cast<TemplateSpecializationType>(InjectedType.getTypePtr());
|
||||
}
|
||||
TemplateName getTemplateName() const {
|
||||
return getInjectedTST()->getTemplateName();
|
||||
}
|
||||
|
||||
CXXRecordDecl *getDecl() const;
|
||||
|
||||
@ -5718,10 +5828,6 @@ inline bool Type::isQueueT() const {
|
||||
return isSpecificBuiltinType(BuiltinType::OCLQueue);
|
||||
}
|
||||
|
||||
inline bool Type::isNDRangeT() const {
|
||||
return isSpecificBuiltinType(BuiltinType::OCLNDRange);
|
||||
}
|
||||
|
||||
inline bool Type::isReserveIDT() const {
|
||||
return isSpecificBuiltinType(BuiltinType::OCLReserveID);
|
||||
}
|
||||
@ -5739,7 +5845,7 @@ inline bool Type::isPipeType() const {
|
||||
|
||||
inline bool Type::isOpenCLSpecificType() const {
|
||||
return isSamplerT() || isEventT() || isImageType() || isClkEventT() ||
|
||||
isQueueT() || isNDRangeT() || isReserveIDT() || isPipeType();
|
||||
isQueueT() || isReserveIDT() || isPipeType();
|
||||
}
|
||||
|
||||
inline bool Type::isTemplateTypeParmType() const {
|
||||
@ -5849,8 +5955,8 @@ inline bool Type::isBooleanType() const {
|
||||
}
|
||||
|
||||
inline bool Type::isUndeducedType() const {
|
||||
const AutoType *AT = getContainedAutoType();
|
||||
return AT && !AT->isDeduced();
|
||||
auto *DT = getContainedDeducedType();
|
||||
return DT && !DT->isDeduced();
|
||||
}
|
||||
|
||||
/// \brief Determines whether this is a type for which one can define
|
||||
@ -5932,6 +6038,38 @@ template <typename T> const T *Type::getAs() const {
|
||||
return cast<T>(getUnqualifiedDesugaredType());
|
||||
}
|
||||
|
||||
template <typename T> const T *Type::getAsAdjusted() const {
|
||||
static_assert(!TypeIsArrayType<T>::value, "ArrayType cannot be used with getAsAdjusted!");
|
||||
|
||||
// If this is directly a T type, return it.
|
||||
if (const T *Ty = dyn_cast<T>(this))
|
||||
return Ty;
|
||||
|
||||
// If the canonical form of this type isn't the right kind, reject it.
|
||||
if (!isa<T>(CanonicalType))
|
||||
return nullptr;
|
||||
|
||||
// Strip off type adjustments that do not modify the underlying nature of the
|
||||
// type.
|
||||
const Type *Ty = this;
|
||||
while (Ty) {
|
||||
if (const auto *A = dyn_cast<AttributedType>(Ty))
|
||||
Ty = A->getModifiedType().getTypePtr();
|
||||
else if (const auto *E = dyn_cast<ElaboratedType>(Ty))
|
||||
Ty = E->desugar().getTypePtr();
|
||||
else if (const auto *P = dyn_cast<ParenType>(Ty))
|
||||
Ty = P->desugar().getTypePtr();
|
||||
else if (const auto *A = dyn_cast<AdjustedType>(Ty))
|
||||
Ty = A->desugar().getTypePtr();
|
||||
else
|
||||
break;
|
||||
}
|
||||
|
||||
// Just because the canonical type is correct does not mean we can use cast<>,
|
||||
// since we may not have stripped off all the sugar down to the base type.
|
||||
return dyn_cast<T>(Ty);
|
||||
}
|
||||
|
||||
inline const ArrayType *Type::getAsArrayTypeUnsafe() const {
|
||||
// If this is directly an array type, return it.
|
||||
if (const ArrayType *arr = dyn_cast<ArrayType>(this))
|
||||
|
@ -70,6 +70,13 @@ class TypeLoc {
|
||||
return t;
|
||||
}
|
||||
|
||||
/// \brief Convert to the specified TypeLoc type, returning a null TypeLoc if
|
||||
/// this TypeLock is not of the desired type. It will consider type
|
||||
/// adjustments from a type that wad written as a T to another type that is
|
||||
/// still canonically a T (ignores parens, attributes, elaborated types, etc).
|
||||
template <typename T>
|
||||
T getAsAdjusted() const;
|
||||
|
||||
/// The kinds of TypeLocs. Equivalent to the Type::TypeClass enum,
|
||||
/// except it also defines a Qualified enum that corresponds to the
|
||||
/// QualifiedLoc class.
|
||||
@ -1827,9 +1834,25 @@ class UnaryTransformTypeLoc : public ConcreteTypeLoc<UnqualTypeLoc,
|
||||
}
|
||||
};
|
||||
|
||||
class AutoTypeLoc : public InheritingConcreteTypeLoc<TypeSpecTypeLoc,
|
||||
AutoTypeLoc,
|
||||
AutoType> {
|
||||
class DeducedTypeLoc
|
||||
: public InheritingConcreteTypeLoc<TypeSpecTypeLoc, DeducedTypeLoc,
|
||||
DeducedType> {};
|
||||
|
||||
class AutoTypeLoc
|
||||
: public InheritingConcreteTypeLoc<DeducedTypeLoc, AutoTypeLoc, AutoType> {
|
||||
};
|
||||
|
||||
class DeducedTemplateSpecializationTypeLoc
|
||||
: public InheritingConcreteTypeLoc<DeducedTypeLoc,
|
||||
DeducedTemplateSpecializationTypeLoc,
|
||||
DeducedTemplateSpecializationType> {
|
||||
public:
|
||||
SourceLocation getTemplateNameLoc() const {
|
||||
return getNameLoc();
|
||||
}
|
||||
void setTemplateNameLoc(SourceLocation Loc) {
|
||||
setNameLoc(Loc);
|
||||
}
|
||||
};
|
||||
|
||||
struct ElaboratedLocInfo {
|
||||
@ -2172,6 +2195,24 @@ class PipeTypeLoc : public ConcreteTypeLoc<UnqualTypeLoc, PipeTypeLoc, PipeType,
|
||||
|
||||
QualType getInnerType() const { return this->getTypePtr()->getElementType(); }
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
inline T TypeLoc::getAsAdjusted() const {
|
||||
TypeLoc Cur = *this;
|
||||
while (!T::isKind(Cur)) {
|
||||
if (auto PTL = Cur.getAs<ParenTypeLoc>())
|
||||
Cur = PTL.getInnerLoc();
|
||||
else if (auto ATL = Cur.getAs<AttributedTypeLoc>())
|
||||
Cur = ATL.getModifiedLoc();
|
||||
else if (auto ETL = Cur.getAs<ElaboratedTypeLoc>())
|
||||
Cur = ETL.getNamedTypeLoc();
|
||||
else if (auto ATL = Cur.getAs<AdjustedTypeLoc>())
|
||||
Cur = ATL.getOriginalLoc();
|
||||
else
|
||||
break;
|
||||
}
|
||||
return Cur.getAs<T>();
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
@ -96,7 +96,9 @@ DEPENDENT_TYPE(TemplateTypeParm, Type)
|
||||
NON_CANONICAL_TYPE(SubstTemplateTypeParm, Type)
|
||||
DEPENDENT_TYPE(SubstTemplateTypeParmPack, Type)
|
||||
NON_CANONICAL_UNLESS_DEPENDENT_TYPE(TemplateSpecialization, Type)
|
||||
TYPE(Auto, Type)
|
||||
ABSTRACT_TYPE(Deduced, Type)
|
||||
TYPE(Auto, DeducedType)
|
||||
TYPE(DeducedTemplateSpecialization, DeducedType)
|
||||
DEPENDENT_TYPE(InjectedClassName, Type)
|
||||
DEPENDENT_TYPE(DependentName, Type)
|
||||
DEPENDENT_TYPE(DependentTemplateSpecialization, Type)
|
||||
|
@ -26,7 +26,7 @@
|
||||
namespace clang {
|
||||
|
||||
/// \brief Function object that provides a total ordering on QualType values.
|
||||
struct QualTypeOrdering : std::binary_function<QualType, QualType, bool> {
|
||||
struct QualTypeOrdering {
|
||||
bool operator()(QualType T1, QualType T2) const {
|
||||
return std::less<void*>()(T1.getAsOpaquePtr(), T2.getAsOpaquePtr());
|
||||
}
|
||||
|
@ -180,6 +180,16 @@ const internal::VariadicDynCastAllOfMatcher<Decl, TypedefNameDecl>
|
||||
/// matches "using Y = int", but not "typedef int X"
|
||||
const internal::VariadicDynCastAllOfMatcher<Decl, TypeAliasDecl> typeAliasDecl;
|
||||
|
||||
/// \brief Matches type alias template declarations.
|
||||
///
|
||||
/// typeAliasTemplateDecl() matches
|
||||
/// \code
|
||||
/// template <typename T>
|
||||
/// using Y = X<T>;
|
||||
/// \endcode
|
||||
const internal::VariadicDynCastAllOfMatcher<Decl, TypeAliasTemplateDecl>
|
||||
typeAliasTemplateDecl;
|
||||
|
||||
/// \brief Matches AST nodes that were expanded within the main-file.
|
||||
///
|
||||
/// Example matches X but not Y
|
||||
@ -1118,6 +1128,69 @@ const internal::VariadicDynCastAllOfMatcher<
|
||||
Decl,
|
||||
ObjCInterfaceDecl> objcInterfaceDecl;
|
||||
|
||||
/// \brief Matches Objective-C protocol declarations.
|
||||
///
|
||||
/// Example matches FooDelegate
|
||||
/// \code
|
||||
/// @protocol FooDelegate
|
||||
/// @end
|
||||
/// \endcode
|
||||
const internal::VariadicDynCastAllOfMatcher<
|
||||
Decl,
|
||||
ObjCProtocolDecl> objcProtocolDecl;
|
||||
|
||||
/// \brief Matches Objective-C category declarations.
|
||||
///
|
||||
/// Example matches Foo (Additions)
|
||||
/// \code
|
||||
/// @interface Foo (Additions)
|
||||
/// @end
|
||||
/// \endcode
|
||||
const internal::VariadicDynCastAllOfMatcher<
|
||||
Decl,
|
||||
ObjCCategoryDecl> objcCategoryDecl;
|
||||
|
||||
/// \brief Matches Objective-C method declarations.
|
||||
///
|
||||
/// Example matches both declaration and definition of -[Foo method]
|
||||
/// \code
|
||||
/// @interface Foo
|
||||
/// - (void)method;
|
||||
/// @end
|
||||
///
|
||||
/// @implementation Foo
|
||||
/// - (void)method {}
|
||||
/// @end
|
||||
/// \endcode
|
||||
const internal::VariadicDynCastAllOfMatcher<
|
||||
Decl,
|
||||
ObjCMethodDecl> objcMethodDecl;
|
||||
|
||||
/// \brief Matches Objective-C instance variable declarations.
|
||||
///
|
||||
/// Example matches _enabled
|
||||
/// \code
|
||||
/// @implementation Foo {
|
||||
/// BOOL _enabled;
|
||||
/// }
|
||||
/// @end
|
||||
/// \endcode
|
||||
const internal::VariadicDynCastAllOfMatcher<
|
||||
Decl,
|
||||
ObjCIvarDecl> objcIvarDecl;
|
||||
|
||||
/// \brief Matches Objective-C property declarations.
|
||||
///
|
||||
/// Example matches enabled
|
||||
/// \code
|
||||
/// @interface Foo
|
||||
/// @property BOOL enabled;
|
||||
/// @end
|
||||
/// \endcode
|
||||
const internal::VariadicDynCastAllOfMatcher<
|
||||
Decl,
|
||||
ObjCPropertyDecl> objcPropertyDecl;
|
||||
|
||||
/// \brief Matches expressions that introduce cleanups to be run at the end
|
||||
/// of the sub-expression's evaluation.
|
||||
///
|
||||
@ -2522,7 +2595,7 @@ AST_MATCHER_P(CXXMemberCallExpr, on, internal::Matcher<Expr>,
|
||||
/// \brief Matches on the receiver of an ObjectiveC Message expression.
|
||||
///
|
||||
/// Example
|
||||
/// matcher = objCMessageExpr(hasRecieverType(asString("UIWebView *")));
|
||||
/// matcher = objCMessageExpr(hasReceiverType(asString("UIWebView *")));
|
||||
/// matches the [webView ...] message invocation.
|
||||
/// \code
|
||||
/// NSString *webViewJavaScript = ...
|
||||
@ -5507,7 +5580,7 @@ AST_MATCHER_FUNCTION(internal::Matcher<Expr>, nullPointerConstant) {
|
||||
integerLiteral(equals(0), hasParent(expr(hasType(pointerType())))));
|
||||
}
|
||||
|
||||
/// \brief Matches declaration of the function the statemenet belongs to
|
||||
/// \brief Matches declaration of the function the statement belongs to
|
||||
///
|
||||
/// Given:
|
||||
/// \code
|
||||
|
@ -56,7 +56,7 @@ class ArgKind {
|
||||
/// \param To the requested destination type.
|
||||
///
|
||||
/// \param Specificity value corresponding to the "specificity" of the
|
||||
/// convertion.
|
||||
/// conversion.
|
||||
bool isConvertibleTo(ArgKind To, unsigned *Specificity) const;
|
||||
|
||||
bool operator<(const ArgKind &Other) const {
|
||||
@ -182,7 +182,7 @@ class VariantMatcher {
|
||||
/// \param Kind the requested destination type.
|
||||
///
|
||||
/// \param Specificity value corresponding to the "specificity" of the
|
||||
/// convertion.
|
||||
/// conversion.
|
||||
bool isConvertibleTo(ast_type_traits::ASTNodeKind Kind,
|
||||
unsigned *Specificity) const {
|
||||
if (Value)
|
||||
@ -281,7 +281,7 @@ class VariantValue {
|
||||
/// \param Kind the requested destination type.
|
||||
///
|
||||
/// \param Specificity value corresponding to the "specificity" of the
|
||||
/// convertion.
|
||||
/// conversion.
|
||||
bool isConvertibleTo(ArgKind Kind, unsigned* Specificity) const;
|
||||
|
||||
/// \brief Determines if the contained value can be converted to any kind
|
||||
@ -290,7 +290,7 @@ class VariantValue {
|
||||
/// \param Kinds the requested destination types.
|
||||
///
|
||||
/// \param Specificity value corresponding to the "specificity" of the
|
||||
/// convertion. It is the maximum specificity of all the possible
|
||||
/// conversion. It is the maximum specificity of all the possible
|
||||
/// conversions.
|
||||
bool isConvertibleTo(ArrayRef<ArgKind> Kinds, unsigned *Specificity) const;
|
||||
|
||||
|
@ -98,7 +98,7 @@ class CallGraph : public RecursiveASTVisitor<CallGraph> {
|
||||
bool VisitFunctionDecl(FunctionDecl *FD) {
|
||||
// We skip function template definitions, as their semantics is
|
||||
// only determined when they are instantiated.
|
||||
if (includeInGraph(FD)) {
|
||||
if (includeInGraph(FD) && FD->isThisDeclarationADefinition()) {
|
||||
// Add all blocks declared inside this function to the graph.
|
||||
addNodesForBlocks(FD);
|
||||
// If this function has external linkage, anything could call it.
|
||||
|
@ -16,9 +16,7 @@
|
||||
#define LLVM_CLANG_AST_CLONEDETECTION_H
|
||||
|
||||
#include "clang/Basic/SourceLocation.h"
|
||||
#include "llvm/ADT/Hashing.h"
|
||||
#include "llvm/ADT/StringMap.h"
|
||||
|
||||
#include "llvm/ADT/SmallVector.h"
|
||||
#include <vector>
|
||||
|
||||
namespace clang {
|
||||
@ -29,7 +27,7 @@ class VarDecl;
|
||||
class ASTContext;
|
||||
class CompoundStmt;
|
||||
|
||||
/// \brief Identifies a list of statements.
|
||||
/// Identifies a list of statements.
|
||||
///
|
||||
/// Can either identify a single arbitrary Stmt object, a continuous sequence of
|
||||
/// child statements inside a CompoundStmt or no statements at all.
|
||||
@ -39,8 +37,8 @@ class StmtSequence {
|
||||
/// Stmt, then S is a pointer to this Stmt.
|
||||
const Stmt *S;
|
||||
|
||||
/// The related ASTContext for S.
|
||||
ASTContext *Context;
|
||||
/// The declaration that contains the statements.
|
||||
const Decl *D;
|
||||
|
||||
/// If EndIndex is non-zero, then S is a CompoundStmt and this StmtSequence
|
||||
/// instance is representing the CompoundStmt children inside the array
|
||||
@ -49,7 +47,7 @@ class StmtSequence {
|
||||
unsigned EndIndex;
|
||||
|
||||
public:
|
||||
/// \brief Constructs a StmtSequence holding multiple statements.
|
||||
/// Constructs a StmtSequence holding multiple statements.
|
||||
///
|
||||
/// The resulting StmtSequence identifies a continuous sequence of statements
|
||||
/// in the body of the given CompoundStmt. Which statements of the body should
|
||||
@ -57,20 +55,20 @@ class StmtSequence {
|
||||
/// that describe a non-empty sub-array in the body of the given CompoundStmt.
|
||||
///
|
||||
/// \param Stmt A CompoundStmt that contains all statements in its body.
|
||||
/// \param Context The ASTContext for the given CompoundStmt.
|
||||
/// \param D The Decl containing this Stmt.
|
||||
/// \param StartIndex The inclusive start index in the children array of
|
||||
/// \p Stmt
|
||||
/// \param EndIndex The exclusive end index in the children array of \p Stmt.
|
||||
StmtSequence(const CompoundStmt *Stmt, ASTContext &Context,
|
||||
unsigned StartIndex, unsigned EndIndex);
|
||||
StmtSequence(const CompoundStmt *Stmt, const Decl *D, unsigned StartIndex,
|
||||
unsigned EndIndex);
|
||||
|
||||
/// \brief Constructs a StmtSequence holding a single statement.
|
||||
/// Constructs a StmtSequence holding a single statement.
|
||||
///
|
||||
/// \param Stmt An arbitrary Stmt.
|
||||
/// \param Context The ASTContext for the given Stmt.
|
||||
StmtSequence(const Stmt *Stmt, ASTContext &Context);
|
||||
/// \param D The Decl containing this Stmt.
|
||||
StmtSequence(const Stmt *Stmt, const Decl *D);
|
||||
|
||||
/// \brief Constructs an empty StmtSequence.
|
||||
/// Constructs an empty StmtSequence.
|
||||
StmtSequence();
|
||||
|
||||
typedef const Stmt *const *iterator;
|
||||
@ -110,9 +108,12 @@ class StmtSequence {
|
||||
bool empty() const { return size() == 0; }
|
||||
|
||||
/// Returns the related ASTContext for the stored Stmts.
|
||||
ASTContext &getASTContext() const {
|
||||
assert(Context);
|
||||
return *Context;
|
||||
ASTContext &getASTContext() const;
|
||||
|
||||
/// Returns the declaration that contains the stored Stmts.
|
||||
const Decl *getContainingDecl() const {
|
||||
assert(D);
|
||||
return D;
|
||||
}
|
||||
|
||||
/// Returns true if this objects holds a list of statements.
|
||||
@ -150,106 +151,215 @@ class StmtSequence {
|
||||
bool contains(const StmtSequence &Other) const;
|
||||
};
|
||||
|
||||
/// \brief Searches for clones in source code.
|
||||
/// Searches for similar subtrees in the AST.
|
||||
///
|
||||
/// First, this class needs a translation unit which is passed via
|
||||
/// \p analyzeTranslationUnit . It will then generate and store search data
|
||||
/// for all statements inside the given translation unit.
|
||||
/// Afterwards the generated data can be used to find code clones by calling
|
||||
/// \p findClones .
|
||||
/// First, this class needs several declarations with statement bodies which
|
||||
/// can be passed via analyzeCodeBody. Afterwards all statements can be
|
||||
/// searched for clones by calling findClones with a given list of constraints
|
||||
/// that should specify the wanted properties of the clones.
|
||||
///
|
||||
/// The result of findClones can be further constrained with the constrainClones
|
||||
/// method.
|
||||
///
|
||||
/// This class only searches for clones in exectuable source code
|
||||
/// (e.g. function bodies). Other clones (e.g. cloned comments or declarations)
|
||||
/// are not supported.
|
||||
class CloneDetector {
|
||||
|
||||
public:
|
||||
typedef unsigned DataPiece;
|
||||
/// A collection of StmtSequences that share an arbitrary property.
|
||||
typedef llvm::SmallVector<StmtSequence, 8> CloneGroup;
|
||||
|
||||
/// Holds the data about a StmtSequence that is needed during the search for
|
||||
/// code clones.
|
||||
struct CloneSignature {
|
||||
/// \brief The hash code of the StmtSequence.
|
||||
///
|
||||
/// The initial clone groups that are formed during the search for clones
|
||||
/// consist only of Sequences that share the same hash code. This makes this
|
||||
/// value the central part of this heuristic that is needed to find clones
|
||||
/// in a performant way. For this to work, the type of this variable
|
||||
/// always needs to be small and fast to compare.
|
||||
///
|
||||
/// Also, StmtSequences that are clones of each others have to share
|
||||
/// the same hash code. StmtSequences that are not clones of each other
|
||||
/// shouldn't share the same hash code, but if they do, it will only
|
||||
/// degrade the performance of the hash search but doesn't influence
|
||||
/// the correctness of the result.
|
||||
size_t Hash;
|
||||
|
||||
/// \brief The complexity of the StmtSequence.
|
||||
///
|
||||
/// This value gives an approximation on how many direct or indirect child
|
||||
/// statements are contained in the related StmtSequence. In general, the
|
||||
/// greater this value, the greater the amount of statements. However, this
|
||||
/// is only an approximation and the actual amount of statements can be
|
||||
/// higher or lower than this value. Statements that are generated by the
|
||||
/// compiler (e.g. macro expansions) for example barely influence the
|
||||
/// complexity value.
|
||||
///
|
||||
/// The main purpose of this value is to filter clones that are too small
|
||||
/// and therefore probably not interesting enough for the user.
|
||||
unsigned Complexity;
|
||||
|
||||
/// \brief Creates an empty CloneSignature without any data.
|
||||
CloneSignature() : Complexity(1) {}
|
||||
|
||||
CloneSignature(llvm::hash_code Hash, unsigned Complexity)
|
||||
: Hash(Hash), Complexity(Complexity) {}
|
||||
};
|
||||
|
||||
/// Holds group of StmtSequences that are clones of each other and the
|
||||
/// complexity value (see CloneSignature::Complexity) that all stored
|
||||
/// StmtSequences have in common.
|
||||
struct CloneGroup {
|
||||
std::vector<StmtSequence> Sequences;
|
||||
CloneSignature Signature;
|
||||
|
||||
CloneGroup() {}
|
||||
|
||||
CloneGroup(const StmtSequence &Seq, CloneSignature Signature)
|
||||
: Signature(Signature) {
|
||||
Sequences.push_back(Seq);
|
||||
}
|
||||
|
||||
/// \brief Returns false if and only if this group should be skipped when
|
||||
/// searching for clones.
|
||||
bool isValid() const {
|
||||
// A clone group with only one member makes no sense, so we skip them.
|
||||
return Sequences.size() > 1;
|
||||
}
|
||||
};
|
||||
|
||||
/// \brief Generates and stores search data for all statements in the body of
|
||||
/// the given Decl.
|
||||
/// Generates and stores search data for all statements in the body of
|
||||
/// the given Decl.
|
||||
void analyzeCodeBody(const Decl *D);
|
||||
|
||||
/// \brief Stores the CloneSignature to allow future querying.
|
||||
void add(const StmtSequence &S, const CloneSignature &Signature);
|
||||
|
||||
/// \brief Searches the provided statements for clones.
|
||||
/// Constrains the given list of clone groups with the given constraint.
|
||||
///
|
||||
/// \param Result Output parameter that is filled with a list of found
|
||||
/// clone groups. Each group contains multiple StmtSequences
|
||||
/// that were identified to be clones of each other.
|
||||
/// \param MinGroupComplexity Only return clones which have at least this
|
||||
/// complexity value.
|
||||
/// \param CheckPatterns Returns only clone groups in which the referenced
|
||||
/// variables follow the same pattern.
|
||||
void findClones(std::vector<CloneGroup> &Result, unsigned MinGroupComplexity,
|
||||
bool CheckPatterns = true);
|
||||
/// The constraint is expected to have a method with the signature
|
||||
/// `void constrain(std::vector<CloneDetector::CloneGroup> &Sequences)`
|
||||
/// as this is the interface that the CloneDetector uses for applying the
|
||||
/// constraint. The constraint is supposed to directly modify the passed list
|
||||
/// so that all clones in the list fulfill the specific property this
|
||||
/// constraint ensures.
|
||||
template <typename T>
|
||||
static void constrainClones(std::vector<CloneGroup> &CloneGroups, T C) {
|
||||
C.constrain(CloneGroups);
|
||||
}
|
||||
|
||||
/// \brief Describes two clones that reference their variables in a different
|
||||
/// pattern which could indicate a programming error.
|
||||
/// Constrains the given list of clone groups with the given list of
|
||||
/// constraints.
|
||||
///
|
||||
/// The constraints are applied in sequence in the order in which they are
|
||||
/// passed to this function.
|
||||
template <typename T1, typename... Ts>
|
||||
static void constrainClones(std::vector<CloneGroup> &CloneGroups, T1 C,
|
||||
Ts... ConstraintList) {
|
||||
constrainClones(CloneGroups, C);
|
||||
constrainClones(CloneGroups, ConstraintList...);
|
||||
}
|
||||
|
||||
/// Searches for clones in all previously passed statements.
|
||||
/// \param Result Output parameter to which all created clone groups are
|
||||
/// added.
|
||||
/// \param ConstraintList The constraints that should be applied to the
|
||||
// result.
|
||||
template <typename... Ts>
|
||||
void findClones(std::vector<CloneGroup> &Result, Ts... ConstraintList) {
|
||||
// The initial assumption is that there is only one clone group and every
|
||||
// statement is a clone of the others. This clone group will then be
|
||||
// split up with the help of the constraints.
|
||||
CloneGroup AllClones;
|
||||
AllClones.reserve(Sequences.size());
|
||||
for (const auto &C : Sequences) {
|
||||
AllClones.push_back(C);
|
||||
}
|
||||
|
||||
Result.push_back(AllClones);
|
||||
|
||||
constrainClones(Result, ConstraintList...);
|
||||
}
|
||||
|
||||
private:
|
||||
CloneGroup Sequences;
|
||||
};
|
||||
|
||||
/// This class is a utility class that contains utility functions for building
|
||||
/// custom constraints.
|
||||
class CloneConstraint {
|
||||
public:
|
||||
/// Removes all groups by using a filter function.
|
||||
/// \param CloneGroups The list of CloneGroups that is supposed to be
|
||||
/// filtered.
|
||||
/// \param Filter The filter function that should return true for all groups
|
||||
/// that should be removed from the list.
|
||||
static void
|
||||
filterGroups(std::vector<CloneDetector::CloneGroup> &CloneGroups,
|
||||
std::function<bool(const CloneDetector::CloneGroup &)> Filter) {
|
||||
CloneGroups.erase(
|
||||
std::remove_if(CloneGroups.begin(), CloneGroups.end(), Filter),
|
||||
CloneGroups.end());
|
||||
}
|
||||
|
||||
/// Splits the given CloneGroups until the given Compare function returns true
|
||||
/// for all clones in a single group.
|
||||
/// \param CloneGroups A list of CloneGroups that should be modified.
|
||||
/// \param Compare The comparison function that all clones are supposed to
|
||||
/// pass. Should return true if and only if two clones belong
|
||||
/// to the same CloneGroup.
|
||||
static void splitCloneGroups(
|
||||
std::vector<CloneDetector::CloneGroup> &CloneGroups,
|
||||
std::function<bool(const StmtSequence &, const StmtSequence &)> Compare);
|
||||
};
|
||||
|
||||
/// Searches all children of the given clones for type II clones (i.e. they are
|
||||
/// identical in every aspect beside the used variable names).
|
||||
class RecursiveCloneTypeIIConstraint {
|
||||
|
||||
/// Generates and saves a hash code for the given Stmt.
|
||||
/// \param S The given Stmt.
|
||||
/// \param D The Decl containing S.
|
||||
/// \param StmtsByHash Output parameter that will contain the hash codes for
|
||||
/// each StmtSequence in the given Stmt.
|
||||
/// \return The hash code of the given Stmt.
|
||||
///
|
||||
/// If the given Stmt is a CompoundStmt, this method will also generate
|
||||
/// hashes for all possible StmtSequences in the children of this Stmt.
|
||||
size_t saveHash(const Stmt *S, const Decl *D,
|
||||
std::vector<std::pair<size_t, StmtSequence>> &StmtsByHash);
|
||||
|
||||
public:
|
||||
void constrain(std::vector<CloneDetector::CloneGroup> &Sequences);
|
||||
};
|
||||
|
||||
/// Ensures that every clone has at least the given complexity.
|
||||
///
|
||||
/// Complexity is here defined as the total amount of children of a statement.
|
||||
/// This constraint assumes the first statement in the group is representative
|
||||
/// for all other statements in the group in terms of complexity.
|
||||
class MinComplexityConstraint {
|
||||
unsigned MinComplexity;
|
||||
|
||||
public:
|
||||
MinComplexityConstraint(unsigned MinComplexity)
|
||||
: MinComplexity(MinComplexity) {}
|
||||
|
||||
size_t calculateStmtComplexity(const StmtSequence &Seq,
|
||||
const std::string &ParentMacroStack = "");
|
||||
|
||||
void constrain(std::vector<CloneDetector::CloneGroup> &CloneGroups) {
|
||||
CloneConstraint::filterGroups(
|
||||
CloneGroups, [this](const CloneDetector::CloneGroup &A) {
|
||||
if (!A.empty())
|
||||
return calculateStmtComplexity(A.front()) < MinComplexity;
|
||||
else
|
||||
return false;
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
/// Ensures that all clone groups contain at least the given amount of clones.
|
||||
class MinGroupSizeConstraint {
|
||||
unsigned MinGroupSize;
|
||||
|
||||
public:
|
||||
MinGroupSizeConstraint(unsigned MinGroupSize = 2)
|
||||
: MinGroupSize(MinGroupSize) {}
|
||||
|
||||
void constrain(std::vector<CloneDetector::CloneGroup> &CloneGroups) {
|
||||
CloneConstraint::filterGroups(CloneGroups,
|
||||
[this](const CloneDetector::CloneGroup &A) {
|
||||
return A.size() < MinGroupSize;
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
/// Ensures that no clone group fully contains another clone group.
|
||||
struct OnlyLargestCloneConstraint {
|
||||
void constrain(std::vector<CloneDetector::CloneGroup> &Result);
|
||||
};
|
||||
|
||||
/// Analyzes the pattern of the referenced variables in a statement.
|
||||
class VariablePattern {
|
||||
|
||||
/// Describes an occurence of a variable reference in a statement.
|
||||
struct VariableOccurence {
|
||||
/// The index of the associated VarDecl in the Variables vector.
|
||||
size_t KindID;
|
||||
/// The statement in the code where the variable was referenced.
|
||||
const Stmt *Mention;
|
||||
|
||||
VariableOccurence(size_t KindID, const Stmt *Mention)
|
||||
: KindID(KindID), Mention(Mention) {}
|
||||
};
|
||||
|
||||
/// All occurences of referenced variables in the order of appearance.
|
||||
std::vector<VariableOccurence> Occurences;
|
||||
/// List of referenced variables in the order of appearance.
|
||||
/// Every item in this list is unique.
|
||||
std::vector<const VarDecl *> Variables;
|
||||
|
||||
/// Adds a new variable referenced to this pattern.
|
||||
/// \param VarDecl The declaration of the variable that is referenced.
|
||||
/// \param Mention The SourceRange where this variable is referenced.
|
||||
void addVariableOccurence(const VarDecl *VarDecl, const Stmt *Mention);
|
||||
|
||||
/// Adds each referenced variable from the given statement.
|
||||
void addVariables(const Stmt *S);
|
||||
|
||||
public:
|
||||
/// Creates an VariablePattern object with information about the given
|
||||
/// StmtSequence.
|
||||
VariablePattern(const StmtSequence &Sequence) {
|
||||
for (const Stmt *S : Sequence)
|
||||
addVariables(S);
|
||||
}
|
||||
|
||||
/// Describes two clones that reference their variables in a different pattern
|
||||
/// which could indicate a programming error.
|
||||
struct SuspiciousClonePair {
|
||||
/// \brief Utility class holding the relevant information about a single
|
||||
/// clone in this pair.
|
||||
/// Utility class holding the relevant information about a single
|
||||
/// clone in this pair.
|
||||
struct SuspiciousCloneInfo {
|
||||
/// The variable which referencing in this clone was against the pattern.
|
||||
const VarDecl *Variable;
|
||||
@ -270,17 +380,37 @@ class CloneDetector {
|
||||
SuspiciousCloneInfo SecondCloneInfo;
|
||||
};
|
||||
|
||||
/// \brief Searches the provided statements for pairs of clones that don't
|
||||
/// follow the same pattern when referencing variables.
|
||||
/// \param Result Output parameter that will contain the clone pairs.
|
||||
/// \param MinGroupComplexity Only clone pairs in which the clones have at
|
||||
/// least this complexity value.
|
||||
void findSuspiciousClones(std::vector<SuspiciousClonePair> &Result,
|
||||
unsigned MinGroupComplexity);
|
||||
/// Counts the differences between this pattern and the given one.
|
||||
/// \param Other The given VariablePattern to compare with.
|
||||
/// \param FirstMismatch Output parameter that will be filled with information
|
||||
/// about the first difference between the two patterns. This parameter
|
||||
/// can be a nullptr, in which case it will be ignored.
|
||||
/// \return Returns the number of differences between the pattern this object
|
||||
/// is following and the given VariablePattern.
|
||||
///
|
||||
/// For example, the following statements all have the same pattern and this
|
||||
/// function would return zero:
|
||||
///
|
||||
/// if (a < b) return a; return b;
|
||||
/// if (x < y) return x; return y;
|
||||
/// if (u2 < u1) return u2; return u1;
|
||||
///
|
||||
/// But the following statement has a different pattern (note the changed
|
||||
/// variables in the return statements) and would have two differences when
|
||||
/// compared with one of the statements above.
|
||||
///
|
||||
/// if (a < b) return b; return a;
|
||||
///
|
||||
/// This function should only be called if the related statements of the given
|
||||
/// pattern and the statements of this objects are clones of each other.
|
||||
unsigned countPatternDifferences(
|
||||
const VariablePattern &Other,
|
||||
VariablePattern::SuspiciousClonePair *FirstMismatch = nullptr);
|
||||
};
|
||||
|
||||
private:
|
||||
/// Stores all encountered StmtSequences alongside their CloneSignature.
|
||||
std::vector<std::pair<CloneSignature, StmtSequence>> Sequences;
|
||||
/// Ensures that all clones reference variables in the same pattern.
|
||||
struct MatchingVariablePatternConstraint {
|
||||
void constrain(std::vector<CloneDetector::CloneGroup> &CloneGroups);
|
||||
};
|
||||
|
||||
} // end namespace clang
|
||||
|
@ -20,24 +20,32 @@ namespace clang {
|
||||
|
||||
namespace LangAS {
|
||||
|
||||
/// \brief Defines the set of possible language-specific address spaces.
|
||||
/// \brief Defines the address space values used by the address space qualifier
|
||||
/// of QualType.
|
||||
///
|
||||
/// This uses a high starting offset so as not to conflict with any address
|
||||
/// space used by a target.
|
||||
enum ID {
|
||||
Offset = 0x7FFF00,
|
||||
// The default value 0 is the value used in QualType for the the situation
|
||||
// where there is no address space qualifier. For most languages, this also
|
||||
// corresponds to the situation where there is no address space qualifier in
|
||||
// the source code, except for OpenCL, where the address space value 0 in
|
||||
// QualType represents private address space in OpenCL source code.
|
||||
Default = 0,
|
||||
|
||||
opencl_global = Offset,
|
||||
// OpenCL specific address spaces.
|
||||
opencl_global,
|
||||
opencl_local,
|
||||
opencl_constant,
|
||||
opencl_generic,
|
||||
|
||||
// CUDA specific address spaces.
|
||||
cuda_device,
|
||||
cuda_constant,
|
||||
cuda_shared,
|
||||
|
||||
Last,
|
||||
Count = Last-Offset
|
||||
// This denotes the count of language-specific address spaces and also
|
||||
// the offset added to the target-specific address spaces, which are usually
|
||||
// specified by address space attributes __attribute__(address_space(n))).
|
||||
Count
|
||||
};
|
||||
|
||||
/// The type of a lookup table which maps from language-specific address spaces
|
||||
|
@ -258,6 +258,7 @@ class TargetArch<list<string> arches> {
|
||||
list<string> CXXABIs;
|
||||
}
|
||||
def TargetARM : TargetArch<["arm", "thumb", "armeb", "thumbeb"]>;
|
||||
def TargetAVR : TargetArch<["avr"]>;
|
||||
def TargetMips : TargetArch<["mips", "mipsel"]>;
|
||||
def TargetMSP430 : TargetArch<["msp430"]>;
|
||||
def TargetX86 : TargetArch<["x86"]>;
|
||||
@ -301,6 +302,9 @@ class Attr {
|
||||
// Set to true if this attribute can be duplicated on a subject when merging
|
||||
// attributes. By default, attributes are not merged.
|
||||
bit DuplicatesAllowedWhileMerging = 0;
|
||||
// Set to true if this attribute meaningful when applied to or inherited
|
||||
// in a class template definition.
|
||||
bit MeaningfulToClassTemplateDefinition = 0;
|
||||
// Lists language options, one of which is required to be true for the
|
||||
// attribute to be applicable. If empty, no language options are required.
|
||||
list<LangOpt> LangOpts = [];
|
||||
@ -340,7 +344,7 @@ class TargetSpecificAttr<TargetArch target> {
|
||||
// should contain a shared value between the attributes.
|
||||
//
|
||||
// Target-specific attributes which use this feature should ensure that the
|
||||
// spellings match exactly betweeen the attributes, and if the arguments or
|
||||
// spellings match exactly between the attributes, and if the arguments or
|
||||
// subjects differ, should specify HasCustomParsing = 1 and implement their
|
||||
// own parsing and semantic handling requirements as-needed.
|
||||
string ParseKind;
|
||||
@ -372,6 +376,7 @@ def AbiTag : Attr {
|
||||
let Args = [VariadicStringArgument<"Tags">];
|
||||
let Subjects = SubjectList<[Struct, Var, Function, Namespace], ErrorDiag,
|
||||
"ExpectedStructClassVariableFunctionOrInlineNamespace">;
|
||||
let MeaningfulToClassTemplateDefinition = 1;
|
||||
let Documentation = [AbiTagsDocs];
|
||||
}
|
||||
|
||||
@ -449,6 +454,15 @@ def XRayInstrument : InheritableAttr {
|
||||
let Documentation = [XRayDocs];
|
||||
}
|
||||
|
||||
def XRayLogArgs : InheritableAttr {
|
||||
let Spellings = [GNU<"xray_log_args">, CXX11<"clang", "xray_log_args">];
|
||||
let Subjects = SubjectList<
|
||||
[CXXMethod, ObjCMethod, Function], WarnDiag, "ExpectedFunctionOrMethod"
|
||||
>;
|
||||
let Args = [UnsignedArgument<"ArgumentCount">];
|
||||
let Documentation = [XRayDocs];
|
||||
}
|
||||
|
||||
def TLSModel : InheritableAttr {
|
||||
let Spellings = [GCC<"tls_model">];
|
||||
let Subjects = SubjectList<[TLSVar], ErrorDiag, "ExpectedTLSVar">;
|
||||
@ -480,6 +494,19 @@ def ARMInterrupt : InheritableAttr, TargetSpecificAttr<TargetARM> {
|
||||
let Documentation = [ARMInterruptDocs];
|
||||
}
|
||||
|
||||
def AVRInterrupt : InheritableAttr, TargetSpecificAttr<TargetAVR> {
|
||||
let Spellings = [GNU<"interrupt">];
|
||||
let Subjects = SubjectList<[Function]>;
|
||||
let ParseKind = "Interrupt";
|
||||
let Documentation = [AVRInterruptDocs];
|
||||
}
|
||||
|
||||
def AVRSignal : InheritableAttr, TargetSpecificAttr<TargetAVR> {
|
||||
let Spellings = [GNU<"signal">];
|
||||
let Subjects = SubjectList<[Function]>;
|
||||
let Documentation = [AVRSignalDocs];
|
||||
}
|
||||
|
||||
def AsmLabel : InheritableAttr {
|
||||
let Spellings = [Keyword<"asm">, Keyword<"__asm__">];
|
||||
let Args = [StringArgument<"Label">];
|
||||
@ -513,6 +540,17 @@ def Availability : InheritableAttr {
|
||||
let Documentation = [AvailabilityDocs];
|
||||
}
|
||||
|
||||
def ExternalSourceSymbol : InheritableAttr {
|
||||
let Spellings = [GNU<"external_source_symbol">,
|
||||
CXX11<"clang", "external_source_symbol">];
|
||||
let Args = [StringArgument<"language", 1>,
|
||||
StringArgument<"definedIn", 1>,
|
||||
BoolArgument<"generatedDeclaration", 1>];
|
||||
let HasCustomParsing = 1;
|
||||
// let Subjects = SubjectList<[Named]>;
|
||||
let Documentation = [ExternalSourceSymbolDocs];
|
||||
}
|
||||
|
||||
def Blocks : InheritableAttr {
|
||||
let Spellings = [GNU<"blocks">];
|
||||
let Args = [EnumArgument<"Type", "BlockType", ["byref"], ["ByRef"]>];
|
||||
@ -771,6 +809,7 @@ def Deprecated : InheritableAttr {
|
||||
// An optional string argument that enables us to provide a
|
||||
// Fix-It.
|
||||
StringArgument<"Replacement", 1>];
|
||||
let MeaningfulToClassTemplateDefinition = 1;
|
||||
let Documentation = [DeprecatedDocs];
|
||||
}
|
||||
|
||||
@ -847,7 +886,15 @@ def FlagEnum : InheritableAttr {
|
||||
let Spellings = [GNU<"flag_enum">];
|
||||
let Subjects = SubjectList<[Enum]>;
|
||||
let Documentation = [FlagEnumDocs];
|
||||
let LangOpts = [COnly];
|
||||
}
|
||||
|
||||
def EnumExtensibility : InheritableAttr {
|
||||
let Spellings = [GNU<"enum_extensibility">,
|
||||
CXX11<"clang", "enum_extensibility">];
|
||||
let Subjects = SubjectList<[Enum]>;
|
||||
let Args = [EnumArgument<"Extensibility", "Kind",
|
||||
["closed", "open"], ["Closed", "Open"]>];
|
||||
let Documentation = [EnumExtensibilityDocs];
|
||||
}
|
||||
|
||||
def Flatten : InheritableAttr {
|
||||
@ -1115,7 +1162,7 @@ def NoSplitStack : InheritableAttr {
|
||||
let Documentation = [NoSplitStackDocs];
|
||||
}
|
||||
|
||||
def NonNull : InheritableAttr {
|
||||
def NonNull : InheritableParamAttr {
|
||||
let Spellings = [GCC<"nonnull">];
|
||||
let Subjects = SubjectList<[ObjCMethod, HasFunctionProto, ParmVar], WarnDiag,
|
||||
"ExpectedFunctionMethodOrParameter">;
|
||||
@ -1178,6 +1225,14 @@ def AssumeAligned : InheritableAttr {
|
||||
let Documentation = [AssumeAlignedDocs];
|
||||
}
|
||||
|
||||
def AllocAlign : InheritableAttr {
|
||||
let Spellings = [GCC<"alloc_align">];
|
||||
let Subjects = SubjectList<[HasFunctionProto], WarnDiag,
|
||||
"ExpectedFunctionWithProtoType">;
|
||||
let Args = [IntArgument<"ParamIndex">];
|
||||
let Documentation = [AllocAlignDocs];
|
||||
}
|
||||
|
||||
def NoReturn : InheritableAttr {
|
||||
let Spellings = [GCC<"noreturn">, Declspec<"noreturn">];
|
||||
// FIXME: Does GCC allow this on the function instead?
|
||||
@ -1498,6 +1553,12 @@ def SwiftIndirectResult : ParameterABIAttr {
|
||||
let Documentation = [SwiftIndirectResultDocs];
|
||||
}
|
||||
|
||||
def Suppress : StmtAttr {
|
||||
let Spellings = [CXX11<"gsl", "suppress">];
|
||||
let Args = [VariadicStringArgument<"DiagnosticIdentifiers">];
|
||||
let Documentation = [SuppressDocs];
|
||||
}
|
||||
|
||||
def SysVABI : InheritableAttr {
|
||||
let Spellings = [GCC<"sysv_abi">];
|
||||
// let Subjects = [Function, ObjCMethod];
|
||||
@ -1681,6 +1742,7 @@ def Visibility : InheritableAttr {
|
||||
let Args = [EnumArgument<"Visibility", "VisibilityType",
|
||||
["default", "hidden", "internal", "protected"],
|
||||
["Default", "Hidden", "Hidden", "Protected"]>];
|
||||
let MeaningfulToClassTemplateDefinition = 1;
|
||||
let Documentation = [Undocumented];
|
||||
}
|
||||
|
||||
|
@ -244,6 +244,36 @@ An example of how to use ``alloc_size``
|
||||
}];
|
||||
}
|
||||
|
||||
def AllocAlignDocs : Documentation {
|
||||
let Category = DocCatFunction;
|
||||
let Content = [{
|
||||
Use ``__attribute__((alloc_align(<alignment>))`` on a function
|
||||
declaration to specify that the return value of the function (which must be a
|
||||
pointer type) is at least as aligned as the value of the indicated parameter. The
|
||||
parameter is given by its index in the list of formal parameters; the first
|
||||
parameter has index 1 unless the function is a C++ non-static member function,
|
||||
in which case the first parameter has index 2 to account for the implicit ``this``
|
||||
parameter.
|
||||
|
||||
.. code-block:: c++
|
||||
|
||||
// The returned pointer has the alignment specified by the first parameter.
|
||||
void *a(size_t align) __attribute__((alloc_align(1)));
|
||||
|
||||
// The returned pointer has the alignment specified by the second parameter.
|
||||
void *b(void *v, size_t align) __attribute__((alloc_align(2)));
|
||||
|
||||
// The returned pointer has the alignment specified by the second visible
|
||||
// parameter, however it must be adjusted for the implicit 'this' parameter.
|
||||
void *Foo::b(void *v, size_t align) __attribute__((alloc_align(3)));
|
||||
|
||||
Note that this attribute merely informs the compiler that a function always
|
||||
returns a sufficiently aligned pointer. It does not cause the compiler to
|
||||
emit code to enforce that alignment. The behavior is undefined if the returned
|
||||
poitner is not sufficiently aligned.
|
||||
}];
|
||||
}
|
||||
|
||||
def EnableIfDocs : Documentation {
|
||||
let Category = DocCatFunction;
|
||||
let Content = [{
|
||||
@ -960,6 +990,63 @@ When one method overrides another, the overriding method can be more widely avai
|
||||
}];
|
||||
}
|
||||
|
||||
def ExternalSourceSymbolDocs : Documentation {
|
||||
let Category = DocCatFunction;
|
||||
let Content = [{
|
||||
The ``external_source_symbol`` attribute specifies that a declaration originates
|
||||
from an external source and describes the nature of that source.
|
||||
|
||||
The fact that Clang is capable of recognizing declarations that were defined
|
||||
externally can be used to provide better tooling support for mixed-language
|
||||
projects or projects that rely on auto-generated code. For instance, an IDE that
|
||||
uses Clang and that supports mixed-language projects can use this attribute to
|
||||
provide a correct 'jump-to-definition' feature. For a concrete example,
|
||||
consider a protocol that's defined in a Swift file:
|
||||
|
||||
.. code-block:: swift
|
||||
|
||||
@objc public protocol SwiftProtocol {
|
||||
func method()
|
||||
}
|
||||
|
||||
This protocol can be used from Objective-C code by including a header file that
|
||||
was generated by the Swift compiler. The declarations in that header can use
|
||||
the ``external_source_symbol`` attribute to make Clang aware of the fact
|
||||
that ``SwiftProtocol`` actually originates from a Swift module:
|
||||
|
||||
.. code-block:: objc
|
||||
|
||||
__attribute__((external_source_symbol(language="Swift",defined_in="module")))
|
||||
@protocol SwiftProtocol
|
||||
@required
|
||||
- (void) method;
|
||||
@end
|
||||
|
||||
Consequently, when 'jump-to-definition' is performed at a location that
|
||||
references ``SwiftProtocol``, the IDE can jump to the original definition in
|
||||
the Swift source file rather than jumping to the Objective-C declaration in the
|
||||
auto-generated header file.
|
||||
|
||||
The ``external_source_symbol`` attribute is a comma-separated list that includes
|
||||
clauses that describe the origin and the nature of the particular declaration.
|
||||
Those clauses can be:
|
||||
|
||||
language=\ *string-literal*
|
||||
The name of the source language in which this declaration was defined.
|
||||
|
||||
defined_in=\ *string-literal*
|
||||
The name of the source container in which the declaration was defined. The
|
||||
exact definition of source container is language-specific, e.g. Swift's
|
||||
source containers are modules, so ``defined_in`` should specify the Swift
|
||||
module name.
|
||||
|
||||
generated_declaration
|
||||
This declaration was automatically generated by some tool.
|
||||
|
||||
The clauses can be specified in any order. The clauses that are listed above are
|
||||
all optional, but the attribute has to have at least one clause.
|
||||
}];
|
||||
}
|
||||
|
||||
def RequireConstantInitDocs : Documentation {
|
||||
let Category = DocCatVariable;
|
||||
@ -1182,6 +1269,33 @@ The semantics are as follows:
|
||||
}];
|
||||
}
|
||||
|
||||
def AVRInterruptDocs : Documentation {
|
||||
let Category = DocCatFunction;
|
||||
let Content = [{
|
||||
Clang supports the GNU style ``__attribute__((interrupt))`` attribute on
|
||||
AVR targets. This attribute may be attached to a function definition and instructs
|
||||
the backend to generate appropriate function entry/exit code so that it can be used
|
||||
directly as an interrupt service routine.
|
||||
|
||||
On the AVR, the hardware globally disables interrupts when an interrupt is executed.
|
||||
The first instruction of an interrupt handler declared with this attribute is a SEI
|
||||
instruction to re-enable interrupts. See also the signal attribute that
|
||||
does not insert a SEI instruction.
|
||||
}];
|
||||
}
|
||||
|
||||
def AVRSignalDocs : Documentation {
|
||||
let Category = DocCatFunction;
|
||||
let Content = [{
|
||||
Clang supports the GNU style ``__attribute__((signal))`` attribute on
|
||||
AVR targets. This attribute may be attached to a function definition and instructs
|
||||
the backend to generate appropriate function entry/exit code so that it can be used
|
||||
directly as an interrupt service routine.
|
||||
|
||||
Interrupt handler functions defined with the signal attribute do not re-enable interrupts.
|
||||
}];
|
||||
}
|
||||
|
||||
def TargetDocs : Documentation {
|
||||
let Category = DocCatFunction;
|
||||
let Content = [{
|
||||
@ -1879,6 +1993,55 @@ manipulating bits of the enumerator when issuing warnings.
|
||||
}];
|
||||
}
|
||||
|
||||
def EnumExtensibilityDocs : Documentation {
|
||||
let Category = DocCatType;
|
||||
let Content = [{
|
||||
Attribute ``enum_extensibility`` is used to distinguish between enum definitions
|
||||
that are extensible and those that are not. The attribute can take either
|
||||
``closed`` or ``open`` as an argument. ``closed`` indicates a variable of the
|
||||
enum type takes a value that corresponds to one of the enumerators listed in the
|
||||
enum definition or, when the enum is annotated with ``flag_enum``, a value that
|
||||
can be constructed using values corresponding to the enumerators. ``open``
|
||||
indicates a variable of the enum type can take any values allowed by the
|
||||
standard and instructs clang to be more lenient when issuing warnings.
|
||||
|
||||
.. code-block:: c
|
||||
|
||||
enum __attribute__((enum_extensibility(closed))) ClosedEnum {
|
||||
A0, A1
|
||||
};
|
||||
|
||||
enum __attribute__((enum_extensibility(open))) OpenEnum {
|
||||
B0, B1
|
||||
};
|
||||
|
||||
enum __attribute__((enum_extensibility(closed),flag_enum)) ClosedFlagEnum {
|
||||
C0 = 1 << 0, C1 = 1 << 1
|
||||
};
|
||||
|
||||
enum __attribute__((enum_extensibility(open),flag_enum)) OpenFlagEnum {
|
||||
D0 = 1 << 0, D1 = 1 << 1
|
||||
};
|
||||
|
||||
void foo1() {
|
||||
enum ClosedEnum ce;
|
||||
enum OpenEnum oe;
|
||||
enum ClosedFlagEnum cfe;
|
||||
enum OpenFlagEnum ofe;
|
||||
|
||||
ce = A1; // no warnings
|
||||
ce = 100; // warning issued
|
||||
oe = B1; // no warnings
|
||||
oe = 100; // no warnings
|
||||
cfe = C0 | C1; // no warnings
|
||||
cfe = C0 | C1 | 4; // warning issued
|
||||
ofe = D0 | D1; // no warnings
|
||||
ofe = D0 | D1 | 4; // no warnings
|
||||
}
|
||||
|
||||
}];
|
||||
}
|
||||
|
||||
def EmptyBasesDocs : Documentation {
|
||||
let Category = DocCatType;
|
||||
let Content = [{
|
||||
@ -2638,6 +2801,32 @@ optimizations like C++'s named return value optimization (NRVO).
|
||||
}];
|
||||
}
|
||||
|
||||
def SuppressDocs : Documentation {
|
||||
let Category = DocCatStmt;
|
||||
let Content = [{
|
||||
The ``[[gsl::suppress]]`` attribute suppresses specific
|
||||
clang-tidy diagnostics for rules of the `C++ Core Guidelines`_ in a portable
|
||||
way. The attribute can be attached to declarations, statements, and at
|
||||
namespace scope.
|
||||
|
||||
.. code-block:: c++
|
||||
|
||||
[[gsl::suppress("Rh-public")]]
|
||||
void f_() {
|
||||
int *p;
|
||||
[[gsl::suppress("type")]] {
|
||||
p = reinterpret_cast<int*>(7);
|
||||
}
|
||||
}
|
||||
namespace N {
|
||||
[[clang::suppress("type", "bounds")]];
|
||||
...
|
||||
}
|
||||
|
||||
.. _`C++ Core Guidelines`: https://github.com/isocpp/CppCoreGuidelines/blob/master/CppCoreGuidelines.md#inforce-enforcement
|
||||
}];
|
||||
}
|
||||
|
||||
def AbiTagsDocs : Documentation {
|
||||
let Category = DocCatFunction;
|
||||
let Content = [{
|
||||
@ -2777,13 +2966,15 @@ See the RenderScript_ documentation for more information.
|
||||
|
||||
def XRayDocs : Documentation {
|
||||
let Category = DocCatFunction;
|
||||
let Heading = "xray_always_instrument (clang::xray_always_instrument), xray_never_instrument (clang::xray_never_instrument)";
|
||||
let Heading = "xray_always_instrument (clang::xray_always_instrument), xray_never_instrument (clang::xray_never_instrument), xray_log_args (clang::xray_log_args)";
|
||||
let Content = [{
|
||||
``__attribute__((xray_always_instrument))`` or ``[[clang::xray_always_instrument]]`` is used to mark member functions (in C++), methods (in Objective C), and free functions (in C, C++, and Objective C) to be instrumented with XRay. This will cause the function to always have space at the beginning and exit points to allow for runtime patching.
|
||||
|
||||
Conversely, ``__attribute__((xray_never_instrument))`` or ``[[clang::xray_never_instrument]]`` will inhibit the insertion of these instrumentation points.
|
||||
|
||||
If a function has neither of these attributes, they become subject to the XRay heuristics used to determine whether a function should be instrumented or otherwise.
|
||||
|
||||
``__attribute__((xray_log_args(N)))`` or ``[[clang::xray_log_args(N)]]`` is used to preserve N function arguments for the logging function. Currently, only N==1 is supported.
|
||||
}];
|
||||
}
|
||||
|
||||
|
@ -756,11 +756,11 @@ LANGBUILTIN(_InterlockedOr, "LiLiD*Li", "n", ALL_MS_LANGUAGES)
|
||||
LANGBUILTIN(_InterlockedXor8, "ccD*c", "n", ALL_MS_LANGUAGES)
|
||||
LANGBUILTIN(_InterlockedXor16, "ssD*s", "n", ALL_MS_LANGUAGES)
|
||||
LANGBUILTIN(_InterlockedXor, "LiLiD*Li", "n", ALL_MS_LANGUAGES)
|
||||
LANGBUILTIN(_interlockedbittestandset, "UcLiD*Li", "n", ALL_MS_LANGUAGES)
|
||||
LANGBUILTIN(__noop, "i.", "n", ALL_MS_LANGUAGES)
|
||||
LANGBUILTIN(__popcnt16, "UsUs", "nc", ALL_MS_LANGUAGES)
|
||||
LANGBUILTIN(__popcnt, "UiUi", "nc", ALL_MS_LANGUAGES)
|
||||
LANGBUILTIN(__popcnt64, "ULLiULLi", "nc", ALL_MS_LANGUAGES)
|
||||
LANGBUILTIN(__readfsdword, "ULiULi", "n", ALL_MS_LANGUAGES)
|
||||
LANGBUILTIN(_ReturnAddress, "v*", "n", ALL_MS_LANGUAGES)
|
||||
LANGBUILTIN(_rotl8, "UcUcUc", "n", ALL_MS_LANGUAGES)
|
||||
LANGBUILTIN(_rotl16, "UsUsUc", "n", ALL_MS_LANGUAGES)
|
||||
@ -773,6 +773,7 @@ LANGBUILTIN(_rotr, "UiUii", "n", ALL_MS_LANGUAGES)
|
||||
LANGBUILTIN(_lrotr, "ULiULii", "n", ALL_MS_LANGUAGES)
|
||||
LANGBUILTIN(_rotr64, "ULLiULLii", "n", ALL_MS_LANGUAGES)
|
||||
LANGBUILTIN(__va_start, "vc**.", "nt", ALL_MS_LANGUAGES)
|
||||
LANGBUILTIN(__fastfail, "vUi", "nr", ALL_MS_LANGUAGES)
|
||||
|
||||
// Microsoft library builtins.
|
||||
LIBBUILTIN(_setjmpex, "iJ", "fj", "setjmpex.h", ALL_MS_LANGUAGES)
|
||||
@ -1086,9 +1087,11 @@ LIBBUILTIN(ilogb, "id", "fne", "math.h", ALL_LANGUAGES)
|
||||
LIBBUILTIN(ilogbf, "if", "fne", "math.h", ALL_LANGUAGES)
|
||||
LIBBUILTIN(ilogbl, "iLd", "fne", "math.h", ALL_LANGUAGES)
|
||||
|
||||
LIBBUILTIN(lgamma, "dd", "fne", "math.h", ALL_LANGUAGES)
|
||||
LIBBUILTIN(lgammaf, "ff", "fne", "math.h", ALL_LANGUAGES)
|
||||
LIBBUILTIN(lgammal, "LdLd", "fne", "math.h", ALL_LANGUAGES)
|
||||
// POSIX math.h declares a global, signgam, that lgamma writes to, so these
|
||||
// shouldn't have "e" or "c" attributes
|
||||
LIBBUILTIN(lgamma, "dd", "fn", "math.h", ALL_LANGUAGES)
|
||||
LIBBUILTIN(lgammaf, "ff", "fn", "math.h", ALL_LANGUAGES)
|
||||
LIBBUILTIN(lgammal, "LdLd", "fn", "math.h", ALL_LANGUAGES)
|
||||
|
||||
LIBBUILTIN(llrint, "LLid", "fne", "math.h", ALL_LANGUAGES)
|
||||
LIBBUILTIN(llrintf, "LLif", "fne", "math.h", ALL_LANGUAGES)
|
||||
@ -1362,7 +1365,7 @@ BUILTIN(__builtin_coro_free, "v*v*", "n")
|
||||
BUILTIN(__builtin_coro_id, "v*Iiv*v*v*", "n")
|
||||
BUILTIN(__builtin_coro_alloc, "b", "n")
|
||||
BUILTIN(__builtin_coro_begin, "v*v*", "n")
|
||||
BUILTIN(__builtin_coro_end, "vv*Ib", "n")
|
||||
BUILTIN(__builtin_coro_end, "bv*Ib", "n")
|
||||
BUILTIN(__builtin_coro_suspend, "cIb", "n")
|
||||
BUILTIN(__builtin_coro_param, "bv*v*", "n")
|
||||
// OpenCL v2.0 s6.13.16, s9.17.3.5 - Pipe functions.
|
||||
|
@ -35,8 +35,14 @@ BUILTIN(__builtin_amdgcn_workitem_id_z, "Ui", "nc")
|
||||
//===----------------------------------------------------------------------===//
|
||||
// Instruction builtins.
|
||||
//===----------------------------------------------------------------------===//
|
||||
BUILTIN(__builtin_amdgcn_s_getreg, "UiIi", "n")
|
||||
BUILTIN(__builtin_amdgcn_s_waitcnt, "vIi", "n")
|
||||
BUILTIN(__builtin_amdgcn_s_sendmsg, "vIiUi", "n")
|
||||
BUILTIN(__builtin_amdgcn_s_sendmsghalt, "vIiUi", "n")
|
||||
BUILTIN(__builtin_amdgcn_s_barrier, "v", "n")
|
||||
BUILTIN(__builtin_amdgcn_wave_barrier, "v", "n")
|
||||
BUILTIN(__builtin_amdgcn_s_dcache_inv, "v", "n")
|
||||
BUILTIN(__builtin_amdgcn_buffer_wbinvl1, "v", "n")
|
||||
BUILTIN(__builtin_amdgcn_div_scale, "dddbb*", "n")
|
||||
BUILTIN(__builtin_amdgcn_div_scalef, "fffbb*", "n")
|
||||
BUILTIN(__builtin_amdgcn_div_fmas, "ddddb", "nc")
|
||||
@ -80,6 +86,11 @@ BUILTIN(__builtin_amdgcn_sicmpl, "LUiLiLiIi", "nc")
|
||||
BUILTIN(__builtin_amdgcn_fcmp, "LUiddIi", "nc")
|
||||
BUILTIN(__builtin_amdgcn_fcmpf, "LUiffIi", "nc")
|
||||
BUILTIN(__builtin_amdgcn_ds_swizzle, "iiIi", "nc")
|
||||
BUILTIN(__builtin_amdgcn_ds_permute, "iii", "nc")
|
||||
BUILTIN(__builtin_amdgcn_ds_bpermute, "iii", "nc")
|
||||
BUILTIN(__builtin_amdgcn_readfirstlane, "ii", "nc")
|
||||
BUILTIN(__builtin_amdgcn_readlane, "iii", "nc")
|
||||
BUILTIN(__builtin_amdgcn_fmed3f, "ffff", "nc")
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// VI+ only builtins.
|
||||
@ -96,6 +107,13 @@ TARGET_BUILTIN(__builtin_amdgcn_frexp_exph, "sh", "nc", "16-bit-insts")
|
||||
TARGET_BUILTIN(__builtin_amdgcn_fracth, "hh", "nc", "16-bit-insts")
|
||||
TARGET_BUILTIN(__builtin_amdgcn_classh, "bhi", "nc", "16-bit-insts")
|
||||
TARGET_BUILTIN(__builtin_amdgcn_s_memrealtime, "LUi", "n", "s-memrealtime")
|
||||
TARGET_BUILTIN(__builtin_amdgcn_mov_dpp, "iiIiIiIiIb", "nc", "dpp")
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// GFX9+ only builtins.
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
TARGET_BUILTIN(__builtin_amdgcn_fmed3h, "hhhh", "nc", "gfx9-insts")
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// Special builtins.
|
||||
|
@ -64,24 +64,10 @@ BUILTIN(__nvvm_read_ptx_sreg_pm3, "i", "n")
|
||||
|
||||
// MISC
|
||||
|
||||
BUILTIN(__nvvm_clz_i, "ii", "")
|
||||
BUILTIN(__nvvm_clz_ll, "iLLi", "")
|
||||
BUILTIN(__nvvm_popc_i, "ii", "")
|
||||
BUILTIN(__nvvm_popc_ll, "iLLi", "")
|
||||
BUILTIN(__nvvm_prmt, "UiUiUiUi", "")
|
||||
|
||||
// Min Max
|
||||
|
||||
BUILTIN(__nvvm_min_i, "iii", "")
|
||||
BUILTIN(__nvvm_min_ui, "UiUiUi", "")
|
||||
BUILTIN(__nvvm_min_ll, "LLiLLiLLi", "")
|
||||
BUILTIN(__nvvm_min_ull, "ULLiULLiULLi", "")
|
||||
|
||||
BUILTIN(__nvvm_max_i, "iii", "")
|
||||
BUILTIN(__nvvm_max_ui, "UiUiUi", "")
|
||||
BUILTIN(__nvvm_max_ll, "LLiLLiLLi", "")
|
||||
BUILTIN(__nvvm_max_ull, "ULLiULLiULLi", "")
|
||||
|
||||
BUILTIN(__nvvm_fmax_ftz_f, "fff", "")
|
||||
BUILTIN(__nvvm_fmax_f, "fff", "")
|
||||
BUILTIN(__nvvm_fmin_ftz_f, "fff", "")
|
||||
@ -133,11 +119,6 @@ BUILTIN(__nvvm_div_rz_d, "ddd", "")
|
||||
BUILTIN(__nvvm_div_rm_d, "ddd", "")
|
||||
BUILTIN(__nvvm_div_rp_d, "ddd", "")
|
||||
|
||||
// Brev
|
||||
|
||||
BUILTIN(__nvvm_brev32, "UiUi", "")
|
||||
BUILTIN(__nvvm_brev64, "ULLiULLi", "")
|
||||
|
||||
// Sad
|
||||
|
||||
BUILTIN(__nvvm_sad_i, "iiii", "")
|
||||
@ -155,9 +136,6 @@ BUILTIN(__nvvm_ceil_d, "dd", "")
|
||||
|
||||
// Abs
|
||||
|
||||
BUILTIN(__nvvm_abs_i, "ii", "")
|
||||
BUILTIN(__nvvm_abs_ll, "LLiLLi", "")
|
||||
|
||||
BUILTIN(__nvvm_fabs_ftz_f, "ff", "")
|
||||
BUILTIN(__nvvm_fabs_f, "ff", "")
|
||||
BUILTIN(__nvvm_fabs_d, "dd", "")
|
||||
@ -385,8 +363,6 @@ BUILTIN(__nvvm_ull2d_rp, "dULLi", "")
|
||||
BUILTIN(__nvvm_f2h_rn_ftz, "Usf", "")
|
||||
BUILTIN(__nvvm_f2h_rn, "Usf", "")
|
||||
|
||||
BUILTIN(__nvvm_h2f, "fUs", "")
|
||||
|
||||
// Bitcast
|
||||
|
||||
BUILTIN(__nvvm_bitcast_f2i, "if", "")
|
||||
|
@ -16,9 +16,9 @@
|
||||
|
||||
// The format of this database matches clang/Basic/Builtins.def.
|
||||
|
||||
// Note that current_memory is not "c" (readnone) because it must be sequenced with
|
||||
// respect to grow_memory calls.
|
||||
// Note that current_memory is not "c" (readnone) because it must be sequenced
|
||||
// with respect to grow_memory calls.
|
||||
BUILTIN(__builtin_wasm_current_memory, "z", "n")
|
||||
BUILTIN(__builtin_wasm_grow_memory, "vz", "n")
|
||||
BUILTIN(__builtin_wasm_grow_memory, "zz", "n")
|
||||
|
||||
#undef BUILTIN
|
||||
|
@ -391,7 +391,6 @@ TARGET_BUILTIN(__builtin_ia32_roundsd, "V2dV2dV2dIi", "", "sse4.1")
|
||||
TARGET_BUILTIN(__builtin_ia32_roundpd, "V2dV2dIi", "", "sse4.1")
|
||||
TARGET_BUILTIN(__builtin_ia32_dpps, "V4fV4fV4fIc", "", "sse4.1")
|
||||
TARGET_BUILTIN(__builtin_ia32_dppd, "V2dV2dV2dIc", "", "sse4.1")
|
||||
TARGET_BUILTIN(__builtin_ia32_movntdqa, "V2LLiV2LLiC*", "", "sse4.1")
|
||||
TARGET_BUILTIN(__builtin_ia32_ptestz128, "iV2LLiV2LLi", "", "sse4.1")
|
||||
TARGET_BUILTIN(__builtin_ia32_ptestc128, "iV2LLiV2LLi", "", "sse4.1")
|
||||
TARGET_BUILTIN(__builtin_ia32_ptestnzc128, "iV2LLiV2LLi", "", "sse4.1")
|
||||
@ -576,7 +575,6 @@ TARGET_BUILTIN(__builtin_ia32_psrldi256, "V8iV8ii", "", "avx2")
|
||||
TARGET_BUILTIN(__builtin_ia32_psrld256, "V8iV8iV4i", "", "avx2")
|
||||
TARGET_BUILTIN(__builtin_ia32_psrlqi256, "V4LLiV4LLii", "", "avx2")
|
||||
TARGET_BUILTIN(__builtin_ia32_psrlq256, "V4LLiV4LLiV2LLi", "", "avx2")
|
||||
TARGET_BUILTIN(__builtin_ia32_movntdqa256, "V4LLiV4LLiC*", "", "avx2")
|
||||
TARGET_BUILTIN(__builtin_ia32_permvarsi256, "V8iV8iV8i", "", "avx2")
|
||||
TARGET_BUILTIN(__builtin_ia32_permvarsf256, "V8fV8fV8i", "", "avx2")
|
||||
TARGET_BUILTIN(__builtin_ia32_permti256, "V4LLiV4LLiV4LLiIc", "", "avx2")
|
||||
@ -832,8 +830,6 @@ TARGET_BUILTIN(__builtin_ia32_vphaddudq, "V2LLiV4i", "", "xop")
|
||||
TARGET_BUILTIN(__builtin_ia32_vphsubbw, "V8sV16c", "", "xop")
|
||||
TARGET_BUILTIN(__builtin_ia32_vphsubwd, "V4iV8s", "", "xop")
|
||||
TARGET_BUILTIN(__builtin_ia32_vphsubdq, "V2LLiV4i", "", "xop")
|
||||
TARGET_BUILTIN(__builtin_ia32_vpcmov, "V2LLiV2LLiV2LLiV2LLi", "", "xop")
|
||||
TARGET_BUILTIN(__builtin_ia32_vpcmov_256, "V4LLiV4LLiV4LLiV4LLi", "", "xop")
|
||||
TARGET_BUILTIN(__builtin_ia32_vpperm, "V16cV16cV16cV16c", "", "xop")
|
||||
TARGET_BUILTIN(__builtin_ia32_vprotb, "V16cV16cV16c", "", "xop")
|
||||
TARGET_BUILTIN(__builtin_ia32_vprotw, "V8sV8sV8s", "", "xop")
|
||||
@ -997,22 +993,22 @@ TARGET_BUILTIN(__builtin_ia32_vpermt2varq512_mask, "V8LLiV8LLiV8LLiV8LLiUc", "",
|
||||
TARGET_BUILTIN(__builtin_ia32_vpermt2varps512_mask, "V16fV16iV16fV16fUs", "", "avx512f")
|
||||
TARGET_BUILTIN(__builtin_ia32_vpermt2varpd512_mask, "V8dV8LLiV8dV8dUc", "", "avx512f")
|
||||
|
||||
TARGET_BUILTIN(__builtin_ia32_gather3div2df, "V2dV2ddC*V2LLiUci","","avx512vl")
|
||||
TARGET_BUILTIN(__builtin_ia32_gather3div2di, "V2LLiV2LLiLLiC*V2LLiUci","","avx512vl")
|
||||
TARGET_BUILTIN(__builtin_ia32_gather3div4df, "V4dV4ddC*V4LLiUci","","avx512vl")
|
||||
TARGET_BUILTIN(__builtin_ia32_gather3div4di, "V4LLiV4LLiLLiC*V4LLiUci","","avx512vl")
|
||||
TARGET_BUILTIN(__builtin_ia32_gather3div4sf, "V4fV4ffC*V2LLiUci","","avx512vl")
|
||||
TARGET_BUILTIN(__builtin_ia32_gather3div4si, "V4iV4iiC*V2LLiUci","","avx512vl")
|
||||
TARGET_BUILTIN(__builtin_ia32_gather3div8sf, "V4fV4ffC*V4LLiUci","","avx512vl")
|
||||
TARGET_BUILTIN(__builtin_ia32_gather3div8si, "V4iV4iiC*V4LLiUci","","avx512vl")
|
||||
TARGET_BUILTIN(__builtin_ia32_gather3siv2df, "V2dV2ddC*V4iUci","","avx512vl")
|
||||
TARGET_BUILTIN(__builtin_ia32_gather3siv2di, "V2LLiV2LLiLLiC*V4iUci","","avx512vl")
|
||||
TARGET_BUILTIN(__builtin_ia32_gather3siv4df, "V4dV4ddC*V4iUci","","avx512vl")
|
||||
TARGET_BUILTIN(__builtin_ia32_gather3siv4di, "V4LLiV4LLiLLiC*V4iUci","","avx512vl")
|
||||
TARGET_BUILTIN(__builtin_ia32_gather3siv4sf, "V4fV4ffC*V4iUci","","avx512vl")
|
||||
TARGET_BUILTIN(__builtin_ia32_gather3siv4si, "V4iV4iiC*V4iUci","","avx512vl")
|
||||
TARGET_BUILTIN(__builtin_ia32_gather3siv8sf, "V8fV8ffC*V8iUci","","avx512vl")
|
||||
TARGET_BUILTIN(__builtin_ia32_gather3siv8si, "V8iV8iiC*V8iUci","","avx512vl")
|
||||
TARGET_BUILTIN(__builtin_ia32_gather3div2df, "V2dV2ddC*V2LLiUcIi","","avx512vl")
|
||||
TARGET_BUILTIN(__builtin_ia32_gather3div2di, "V2LLiV2LLiLLiC*V2LLiUcIi","","avx512vl")
|
||||
TARGET_BUILTIN(__builtin_ia32_gather3div4df, "V4dV4ddC*V4LLiUcIi","","avx512vl")
|
||||
TARGET_BUILTIN(__builtin_ia32_gather3div4di, "V4LLiV4LLiLLiC*V4LLiUcIi","","avx512vl")
|
||||
TARGET_BUILTIN(__builtin_ia32_gather3div4sf, "V4fV4ffC*V2LLiUcIi","","avx512vl")
|
||||
TARGET_BUILTIN(__builtin_ia32_gather3div4si, "V4iV4iiC*V2LLiUcIi","","avx512vl")
|
||||
TARGET_BUILTIN(__builtin_ia32_gather3div8sf, "V4fV4ffC*V4LLiUcIi","","avx512vl")
|
||||
TARGET_BUILTIN(__builtin_ia32_gather3div8si, "V4iV4iiC*V4LLiUcIi","","avx512vl")
|
||||
TARGET_BUILTIN(__builtin_ia32_gather3siv2df, "V2dV2ddC*V4iUcIi","","avx512vl")
|
||||
TARGET_BUILTIN(__builtin_ia32_gather3siv2di, "V2LLiV2LLiLLiC*V4iUcIi","","avx512vl")
|
||||
TARGET_BUILTIN(__builtin_ia32_gather3siv4df, "V4dV4ddC*V4iUcIi","","avx512vl")
|
||||
TARGET_BUILTIN(__builtin_ia32_gather3siv4di, "V4LLiV4LLiLLiC*V4iUcIi","","avx512vl")
|
||||
TARGET_BUILTIN(__builtin_ia32_gather3siv4sf, "V4fV4ffC*V4iUcIi","","avx512vl")
|
||||
TARGET_BUILTIN(__builtin_ia32_gather3siv4si, "V4iV4iiC*V4iUcIi","","avx512vl")
|
||||
TARGET_BUILTIN(__builtin_ia32_gather3siv8sf, "V8fV8ffC*V8iUcIi","","avx512vl")
|
||||
TARGET_BUILTIN(__builtin_ia32_gather3siv8si, "V8iV8iiC*V8iUcIi","","avx512vl")
|
||||
TARGET_BUILTIN(__builtin_ia32_gathersiv8df, "V8dV8ddC*V8iUcIi", "", "avx512f")
|
||||
TARGET_BUILTIN(__builtin_ia32_gathersiv16sf, "V16fV16ffC*V16fUsIi", "", "avx512f")
|
||||
TARGET_BUILTIN(__builtin_ia32_gatherdiv8df, "V8dV8ddC*V8LLiUcIi", "", "avx512f")
|
||||
@ -1068,10 +1064,10 @@ TARGET_BUILTIN(__builtin_ia32_ucmpw512_mask, "UiV32sV32sIiUi", "", "avx512bw")
|
||||
|
||||
TARGET_BUILTIN(__builtin_ia32_pabsb512_mask, "V64cV64cV64cULLi", "", "avx512bw")
|
||||
TARGET_BUILTIN(__builtin_ia32_pabsw512_mask, "V32sV32sV32sUi", "", "avx512bw")
|
||||
TARGET_BUILTIN(__builtin_ia32_packssdw512_mask, "V32sV16iV16iV32sUi", "", "avx512bw")
|
||||
TARGET_BUILTIN(__builtin_ia32_packsswb512_mask, "V64cV32sV32sV64cULLi", "", "avx512bw")
|
||||
TARGET_BUILTIN(__builtin_ia32_packusdw512_mask, "V32sV16iV16iV32sUi", "", "avx512bw")
|
||||
TARGET_BUILTIN(__builtin_ia32_packuswb512_mask, "V64cV32sV32sV64cULLi", "", "avx512bw")
|
||||
TARGET_BUILTIN(__builtin_ia32_packssdw512, "V32sV16iV16i", "", "avx512bw")
|
||||
TARGET_BUILTIN(__builtin_ia32_packsswb512, "V64cV32sV32s", "", "avx512bw")
|
||||
TARGET_BUILTIN(__builtin_ia32_packusdw512, "V32sV16iV16i", "", "avx512bw")
|
||||
TARGET_BUILTIN(__builtin_ia32_packuswb512, "V64cV32sV32s", "", "avx512bw")
|
||||
TARGET_BUILTIN(__builtin_ia32_paddsb512_mask, "V64cV64cV64cV64cULLi", "", "avx512bw")
|
||||
TARGET_BUILTIN(__builtin_ia32_paddsw512_mask, "V32sV32sV32sV32sUi", "", "avx512bw")
|
||||
TARGET_BUILTIN(__builtin_ia32_paddusb512_mask, "V64cV64cV64cV64cULLi", "", "avx512bw")
|
||||
@ -1590,27 +1586,15 @@ TARGET_BUILTIN(__builtin_ia32_cvtq2mask128, "UcV2LLi","","avx512dq,avx512vl")
|
||||
TARGET_BUILTIN(__builtin_ia32_cvtq2mask256, "UcV4LLi","","avx512dq,avx512vl")
|
||||
TARGET_BUILTIN(__builtin_ia32_broadcastmb512, "V8LLiUc","","avx512cd")
|
||||
TARGET_BUILTIN(__builtin_ia32_broadcastmw512, "V16iUs","","avx512cd")
|
||||
TARGET_BUILTIN(__builtin_ia32_broadcastf32x4_512, "V16fV4fV16fUs","","avx512f")
|
||||
TARGET_BUILTIN(__builtin_ia32_broadcastf64x4_512, "V8dV4dV8dUc","","avx512f")
|
||||
TARGET_BUILTIN(__builtin_ia32_broadcasti32x4_512, "V16iV4iV16iUs","","avx512f")
|
||||
TARGET_BUILTIN(__builtin_ia32_broadcasti64x4_512, "V8LLiV4LLiV8LLiUc","","avx512f")
|
||||
TARGET_BUILTIN(__builtin_ia32_broadcastmb128, "V2LLiUc","","avx512cd,avx512vl")
|
||||
TARGET_BUILTIN(__builtin_ia32_broadcastmb256, "V4LLiUc","","avx512cd,avx512vl")
|
||||
TARGET_BUILTIN(__builtin_ia32_broadcastmw128, "V4iUs","","avx512cd,avx512vl")
|
||||
TARGET_BUILTIN(__builtin_ia32_broadcastmw256, "V8iUs","","avx512cd,avx512vl")
|
||||
TARGET_BUILTIN(__builtin_ia32_broadcastf32x2_512_mask, "V16fV4fV16fUs","","avx512dq")
|
||||
TARGET_BUILTIN(__builtin_ia32_broadcastf32x8_512_mask, "V16fV8fV16fUs","","avx512dq")
|
||||
TARGET_BUILTIN(__builtin_ia32_broadcastf64x2_512_mask, "V8dV2dV8dUc","","avx512dq")
|
||||
TARGET_BUILTIN(__builtin_ia32_broadcasti32x2_512_mask, "V16iV4iV16iUs","","avx512dq")
|
||||
TARGET_BUILTIN(__builtin_ia32_broadcasti32x8_512_mask, "V16iV8iV16iUs","","avx512dq")
|
||||
TARGET_BUILTIN(__builtin_ia32_broadcasti64x2_512_mask, "V8LLiV2LLiV8LLiUc","","avx512dq")
|
||||
TARGET_BUILTIN(__builtin_ia32_broadcastf32x2_256_mask, "V8fV4fV8fUc","","avx512dq,avx512vl")
|
||||
TARGET_BUILTIN(__builtin_ia32_broadcastf64x2_256_mask, "V4dV2dV4dUc","","avx512dq,avx512vl")
|
||||
TARGET_BUILTIN(__builtin_ia32_broadcasti32x2_128_mask, "V4iV4iV4iUc","","avx512dq,avx512vl")
|
||||
TARGET_BUILTIN(__builtin_ia32_broadcasti32x2_256_mask, "V8iV4iV8iUc","","avx512dq,avx512vl")
|
||||
TARGET_BUILTIN(__builtin_ia32_broadcasti64x2_256_mask, "V4LLiV2LLiV4LLiUc","","avx512dq,avx512vl")
|
||||
TARGET_BUILTIN(__builtin_ia32_broadcastf32x4_256_mask, "V8fV4fV8fUc","","avx512vl")
|
||||
TARGET_BUILTIN(__builtin_ia32_broadcasti32x4_256_mask, "V8iV4iV8iUc","","avx512vl")
|
||||
TARGET_BUILTIN(__builtin_ia32_pbroadcastw512_gpr_mask, "V32shV32sUi","","avx512bw")
|
||||
TARGET_BUILTIN(__builtin_ia32_pbroadcastw256_gpr_mask, "V16shV16sUs","","avx512bw,avx512vl")
|
||||
TARGET_BUILTIN(__builtin_ia32_pbroadcastw128_gpr_mask, "V8ssV8sUc","","avx512bw,avx512vl")
|
||||
@ -1761,7 +1745,6 @@ TARGET_BUILTIN(__builtin_ia32_kortestzhi, "iUsUs","","avx512f")
|
||||
TARGET_BUILTIN(__builtin_ia32_kunpckhi, "UsUsUs","","avx512f")
|
||||
TARGET_BUILTIN(__builtin_ia32_kxnorhi, "UsUsUs","","avx512f")
|
||||
TARGET_BUILTIN(__builtin_ia32_kxorhi, "UsUsUs","","avx512f")
|
||||
TARGET_BUILTIN(__builtin_ia32_movntdqa512, "V8LLiV8LLi*","","avx512f")
|
||||
TARGET_BUILTIN(__builtin_ia32_palignr512_mask, "V64cV64cV64cIiV64cULLi","","avx512bw")
|
||||
TARGET_BUILTIN(__builtin_ia32_dbpsadbw128_mask, "V8sV16cV16cIiV8sUc","","avx512bw,avx512vl")
|
||||
TARGET_BUILTIN(__builtin_ia32_dbpsadbw256_mask, "V16sV32cV32cIiV16sUs","","avx512bw,avx512vl")
|
||||
@ -1826,6 +1809,9 @@ TARGET_BUILTIN(__builtin_ia32_selectpd_512, "V8dUcV8dV8d", "", "")
|
||||
TARGET_BUILTIN(__builtin_ia32_monitorx, "vv*UiUi", "", "mwaitx")
|
||||
TARGET_BUILTIN(__builtin_ia32_mwaitx, "vUiUiUi", "", "mwaitx")
|
||||
|
||||
// CLZERO
|
||||
TARGET_BUILTIN(__builtin_ia32_clzero, "vv*", "", "clzero")
|
||||
|
||||
// MSVC
|
||||
TARGET_HEADER_BUILTIN(_BitScanForward, "UcULi*ULi", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
|
||||
TARGET_HEADER_BUILTIN(_BitScanReverse, "UcULi*ULi", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
|
||||
@ -1840,6 +1826,18 @@ TARGET_HEADER_BUILTIN(__emulu, "ULLiUiUi", "nh", "intrin.h", ALL_MS_LANGUAGES, "
|
||||
TARGET_HEADER_BUILTIN(_AddressOfReturnAddress, "v*", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
|
||||
|
||||
TARGET_HEADER_BUILTIN(__stosb, "vUc*Ucz", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
|
||||
TARGET_HEADER_BUILTIN(__int2c, "v", "nr", "intrin.h", ALL_MS_LANGUAGES, "")
|
||||
TARGET_HEADER_BUILTIN(__ud2, "v", "nr", "intrin.h", ALL_MS_LANGUAGES, "")
|
||||
|
||||
TARGET_HEADER_BUILTIN(__readfsbyte, "UcULi", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
|
||||
TARGET_HEADER_BUILTIN(__readfsword, "UsULi", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
|
||||
TARGET_HEADER_BUILTIN(__readfsdword, "ULiULi", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
|
||||
TARGET_HEADER_BUILTIN(__readfsqword, "ULLiULi", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
|
||||
|
||||
TARGET_HEADER_BUILTIN(__readgsbyte, "UcULi", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
|
||||
TARGET_HEADER_BUILTIN(__readgsword, "UsULi", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
|
||||
TARGET_HEADER_BUILTIN(__readgsdword, "ULiULi", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
|
||||
TARGET_HEADER_BUILTIN(__readgsqword, "ULLiULi", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
|
||||
|
||||
#undef BUILTIN
|
||||
#undef TARGET_BUILTIN
|
||||
|
@ -45,6 +45,7 @@ def Named : Decl<1>;
|
||||
def ObjCAtDefsField : DDecl<Field>;
|
||||
def MSProperty : DDecl<Declarator>;
|
||||
def Function : DDecl<Declarator>, DeclContext;
|
||||
def CXXDeductionGuide : DDecl<Function>;
|
||||
def CXXMethod : DDecl<Function>;
|
||||
def CXXConstructor : DDecl<CXXMethod>;
|
||||
def CXXDestructor : DDecl<CXXMethod>;
|
||||
|
@ -29,6 +29,7 @@
|
||||
#include <cassert>
|
||||
#include <cstdint>
|
||||
#include <list>
|
||||
#include <map>
|
||||
#include <memory>
|
||||
#include <string>
|
||||
#include <type_traits>
|
||||
@ -222,6 +223,9 @@ class DiagnosticsEngine : public RefCountedBase<DiagnosticsEngine> {
|
||||
void setMapping(diag::kind Diag, DiagnosticMapping Info) {
|
||||
DiagMap[Diag] = Info;
|
||||
}
|
||||
DiagnosticMapping lookupMapping(diag::kind Diag) const {
|
||||
return DiagMap.lookup(Diag);
|
||||
}
|
||||
|
||||
DiagnosticMapping &getOrAddMapping(diag::kind Diag);
|
||||
|
||||
@ -232,59 +236,97 @@ class DiagnosticsEngine : public RefCountedBase<DiagnosticsEngine> {
|
||||
/// \brief Keeps and automatically disposes all DiagStates that we create.
|
||||
std::list<DiagState> DiagStates;
|
||||
|
||||
/// \brief Represents a point in source where the diagnostic state was
|
||||
/// modified because of a pragma.
|
||||
///
|
||||
/// 'Loc' can be null if the point represents the diagnostic state
|
||||
/// modifications done through the command-line.
|
||||
struct DiagStatePoint {
|
||||
DiagState *State;
|
||||
FullSourceLoc Loc;
|
||||
DiagStatePoint(DiagState *State, FullSourceLoc Loc)
|
||||
: State(State), Loc(Loc) { }
|
||||
|
||||
bool operator<(const DiagStatePoint &RHS) const {
|
||||
// If Loc is invalid it means it came from <command-line>, in which case
|
||||
// we regard it as coming before any valid source location.
|
||||
if (RHS.Loc.isInvalid())
|
||||
return false;
|
||||
if (Loc.isInvalid())
|
||||
return true;
|
||||
return Loc.isBeforeInTranslationUnitThan(RHS.Loc);
|
||||
/// A mapping from files to the diagnostic states for those files. Lazily
|
||||
/// built on demand for files in which the diagnostic state has not changed.
|
||||
class DiagStateMap {
|
||||
public:
|
||||
/// Add an initial diagnostic state.
|
||||
void appendFirst(DiagState *State);
|
||||
/// Add a new latest state point.
|
||||
void append(SourceManager &SrcMgr, SourceLocation Loc, DiagState *State);
|
||||
/// Look up the diagnostic state at a given source location.
|
||||
DiagState *lookup(SourceManager &SrcMgr, SourceLocation Loc) const;
|
||||
/// Determine whether this map is empty.
|
||||
bool empty() const { return Files.empty(); }
|
||||
/// Clear out this map.
|
||||
void clear() {
|
||||
Files.clear();
|
||||
FirstDiagState = CurDiagState = nullptr;
|
||||
CurDiagStateLoc = SourceLocation();
|
||||
}
|
||||
|
||||
/// Grab the most-recently-added state point.
|
||||
DiagState *getCurDiagState() const { return CurDiagState; }
|
||||
/// Get the location at which a diagnostic state was last added.
|
||||
SourceLocation getCurDiagStateLoc() const { return CurDiagStateLoc; }
|
||||
|
||||
private:
|
||||
/// \brief Represents a point in source where the diagnostic state was
|
||||
/// modified because of a pragma.
|
||||
///
|
||||
/// 'Loc' can be null if the point represents the diagnostic state
|
||||
/// modifications done through the command-line.
|
||||
struct DiagStatePoint {
|
||||
DiagState *State;
|
||||
unsigned Offset;
|
||||
DiagStatePoint(DiagState *State, unsigned Offset)
|
||||
: State(State), Offset(Offset) { }
|
||||
};
|
||||
|
||||
/// Description of the diagnostic states and state transitions for a
|
||||
/// particular FileID.
|
||||
struct File {
|
||||
/// The diagnostic state for the parent file. This is strictly redundant,
|
||||
/// as looking up the DecomposedIncludedLoc for the FileID in the Files
|
||||
/// map would give us this, but we cache it here for performance.
|
||||
File *Parent = nullptr;
|
||||
/// The offset of this file within its parent.
|
||||
unsigned ParentOffset = 0;
|
||||
/// Whether this file has any local (not imported from an AST file)
|
||||
/// diagnostic state transitions.
|
||||
bool HasLocalTransitions = false;
|
||||
/// The points within the file where the state changes. There will always
|
||||
/// be at least one of these (the state on entry to the file).
|
||||
llvm::SmallVector<DiagStatePoint, 4> StateTransitions;
|
||||
|
||||
DiagState *lookup(unsigned Offset) const;
|
||||
};
|
||||
|
||||
/// The diagnostic states for each file.
|
||||
mutable std::map<FileID, File> Files;
|
||||
|
||||
/// The initial diagnostic state.
|
||||
DiagState *FirstDiagState;
|
||||
/// The current diagnostic state.
|
||||
DiagState *CurDiagState;
|
||||
/// The location at which the current diagnostic state was established.
|
||||
SourceLocation CurDiagStateLoc;
|
||||
|
||||
/// Get the diagnostic state information for a file.
|
||||
File *getFile(SourceManager &SrcMgr, FileID ID) const;
|
||||
|
||||
friend class ASTReader;
|
||||
friend class ASTWriter;
|
||||
};
|
||||
|
||||
/// \brief A sorted vector of all DiagStatePoints representing changes in
|
||||
/// diagnostic state due to diagnostic pragmas.
|
||||
///
|
||||
/// The vector is always sorted according to the SourceLocation of the
|
||||
/// DiagStatePoint.
|
||||
typedef std::vector<DiagStatePoint> DiagStatePointsTy;
|
||||
mutable DiagStatePointsTy DiagStatePoints;
|
||||
DiagStateMap DiagStatesByLoc;
|
||||
|
||||
/// \brief Keeps the DiagState that was active during each diagnostic 'push'
|
||||
/// so we can get back at it when we 'pop'.
|
||||
std::vector<DiagState *> DiagStateOnPushStack;
|
||||
|
||||
DiagState *GetCurDiagState() const {
|
||||
assert(!DiagStatePoints.empty());
|
||||
return DiagStatePoints.back().State;
|
||||
return DiagStatesByLoc.getCurDiagState();
|
||||
}
|
||||
|
||||
void PushDiagStatePoint(DiagState *State, SourceLocation L) {
|
||||
FullSourceLoc Loc(L, getSourceManager());
|
||||
// Make sure that DiagStatePoints is always sorted according to Loc.
|
||||
assert(Loc.isValid() && "Adding invalid loc point");
|
||||
assert(!DiagStatePoints.empty() &&
|
||||
(DiagStatePoints.back().Loc.isInvalid() ||
|
||||
DiagStatePoints.back().Loc.isBeforeInTranslationUnitThan(Loc)) &&
|
||||
"Previous point loc comes after or is the same as new one");
|
||||
DiagStatePoints.push_back(DiagStatePoint(State, Loc));
|
||||
}
|
||||
void PushDiagStatePoint(DiagState *State, SourceLocation L);
|
||||
|
||||
/// \brief Finds the DiagStatePoint that contains the diagnostic state of
|
||||
/// the given source location.
|
||||
DiagStatePointsTy::iterator GetDiagStatePointForLoc(SourceLocation Loc) const;
|
||||
DiagState *GetDiagStateForLoc(SourceLocation Loc) const {
|
||||
return SourceMgr ? DiagStatesByLoc.lookup(*SourceMgr, Loc)
|
||||
: DiagStatesByLoc.getCurDiagState();
|
||||
}
|
||||
|
||||
/// \brief Sticky flag set to \c true when an error is emitted.
|
||||
bool ErrorOccurred;
|
||||
@ -390,7 +432,11 @@ class DiagnosticsEngine : public RefCountedBase<DiagnosticsEngine> {
|
||||
assert(SourceMgr && "SourceManager not set!");
|
||||
return *SourceMgr;
|
||||
}
|
||||
void setSourceManager(SourceManager *SrcMgr) { SourceMgr = SrcMgr; }
|
||||
void setSourceManager(SourceManager *SrcMgr) {
|
||||
assert(DiagStatesByLoc.empty() &&
|
||||
"Leftover diag state from a different SourceManager.");
|
||||
SourceMgr = SrcMgr;
|
||||
}
|
||||
|
||||
//===--------------------------------------------------------------------===//
|
||||
// DiagnosticsEngine characterization methods, used by a client to customize
|
||||
|
@ -44,7 +44,8 @@ def note_constexpr_non_global : Note<
|
||||
def note_constexpr_uninitialized : Note<
|
||||
"%select{|sub}0object of type %1 is not initialized">;
|
||||
def note_constexpr_array_index : Note<"cannot refer to element %0 of "
|
||||
"%select{array of %2 elements|non-array object}1 in a constant expression">;
|
||||
"%select{array of %2 element%plural{1:|:s}2|non-array object}1 "
|
||||
"in a constant expression">;
|
||||
def note_constexpr_float_arithmetic : Note<
|
||||
"floating point arithmetic produces %select{an infinity|a NaN}0">;
|
||||
def note_constexpr_pointer_subtraction_not_same_array : Note<
|
||||
|
@ -45,7 +45,9 @@ def err_expected_colon_after_setter_name : Error<
|
||||
"must end with ':'">;
|
||||
def err_expected_string_literal : Error<"expected string literal "
|
||||
"%select{in %1|for diagnostic message in static_assert|"
|
||||
"for optional message in 'availability' attribute}0">;
|
||||
"for optional message in 'availability' attribute|"
|
||||
"for %select{language|source container}1 name in "
|
||||
"'external_source_symbol' attribute}0">;
|
||||
def err_invalid_string_udl : Error<
|
||||
"string literal with user-defined suffix cannot be used here">;
|
||||
def err_invalid_character_udl : Error<
|
||||
@ -88,10 +90,10 @@ def err_module_unavailable : Error<
|
||||
"module '%0' %select{is incompatible with|requires}1 feature '%2'">;
|
||||
def err_module_header_missing : Error<
|
||||
"%select{|umbrella }0header '%1' not found">;
|
||||
def err_module_lock_failure : Error<
|
||||
"could not acquire lock file for module '%0': %1">, DefaultFatal;
|
||||
def err_module_lock_timeout : Error<
|
||||
"timed out waiting to acquire lock file for module '%0'">, DefaultFatal;
|
||||
def remark_module_lock_failure : Remark<
|
||||
"could not acquire lock file for module '%0': %1">, InGroup<ModuleBuild>;
|
||||
def remark_module_lock_timeout : Remark<
|
||||
"timed out waiting to acquire lock file for module '%0'">, InGroup<ModuleBuild>;
|
||||
def err_module_cycle : Error<"cyclic dependency in module '%0': %1">,
|
||||
DefaultFatal;
|
||||
def err_module_prebuilt : Error<
|
||||
|
@ -85,6 +85,8 @@ def err_drv_clang_unsupported : Error<
|
||||
"the clang compiler does not support '%0'">;
|
||||
def err_drv_clang_unsupported_opt_cxx_darwin_i386 : Error<
|
||||
"the clang compiler does not support '%0' for C++ on Darwin/i386">;
|
||||
def err_drv_clang_unsupported_opt_faltivec : Error<
|
||||
"the clang compiler does not support '%0', %1">;
|
||||
def err_drv_command_failed : Error<
|
||||
"%0 command failed with exit code %1 (use -v to see invocation)">;
|
||||
def err_drv_compilationdatabase : Error<
|
||||
@ -92,7 +94,7 @@ def err_drv_compilationdatabase : Error<
|
||||
def err_drv_command_signalled : Error<
|
||||
"%0 command failed due to signal (use -v to see invocation)">;
|
||||
def err_drv_force_crash : Error<
|
||||
"failing because environment variable '%0' is set">;
|
||||
"failing because %select{environment variable 'FORCE_CLANG_DIAGNOSTICS_CRASH' is set|'-gen-reproducer' is used}0">;
|
||||
def err_drv_invalid_mfloat_abi : Error<
|
||||
"invalid float ABI '%0'">;
|
||||
def err_drv_invalid_libcxx_deployment : Error<
|
||||
@ -133,6 +135,7 @@ def err_drv_invalid_gcc_output_type : Error<
|
||||
"invalid output type '%0' for use with gcc tool">;
|
||||
def err_drv_cc_print_options_failure : Error<
|
||||
"unable to open CC_PRINT_OPTIONS file: %0">;
|
||||
def err_drv_lto_without_lld : Error<"LTO requires -fuse-ld=lld">;
|
||||
def err_drv_preamble_format : Error<
|
||||
"incorrect format for -preamble-bytes=N,END">;
|
||||
def err_drv_conflicting_deployment_targets : Error<
|
||||
@ -230,6 +233,7 @@ def note_drv_t_option_is_global : Note<
|
||||
"The last /TC or /TP option takes precedence over earlier instances">;
|
||||
def note_drv_address_sanitizer_debug_runtime : Note<
|
||||
"AddressSanitizer doesn't support linking with debug runtime libraries yet">;
|
||||
def note_drv_use_standard : Note<"use '%0' for '%1' standard">;
|
||||
|
||||
def err_analyzer_config_no_value : Error<
|
||||
"analyzer-config option '%0' has a key but no value">;
|
||||
@ -247,6 +251,10 @@ def err_test_module_file_extension_format : Error<
|
||||
def warn_drv_invoking_fallback : Warning<"falling back to %0">,
|
||||
InGroup<Fallback>;
|
||||
|
||||
def warn_slash_u_filename : Warning<"'/U%0' treated as the '/U' option">,
|
||||
InGroup<DiagGroup<"slash-u-filename">>;
|
||||
def note_use_dashdash : Note<"Use '--' to treat subsequent arguments as filenames">;
|
||||
|
||||
def err_drv_ropi_rwpi_incompatible_with_pic : Error<
|
||||
"embedded and GOT-based position independence are incompatible">;
|
||||
def err_drv_ropi_incompatible_with_cxx : Error<
|
||||
@ -277,4 +285,8 @@ def warn_drv_ps4_sdk_dir : Warning<
|
||||
def err_drv_unsupported_linker : Error<"unsupported value '%0' for -linker option">;
|
||||
def err_drv_defsym_invalid_format : Error<"defsym must be of the form: sym=value: %0">;
|
||||
def err_drv_defsym_invalid_symval : Error<"Value is not an integer: %0">;
|
||||
def warn_drv_msvc_not_found : Warning<
|
||||
"unable to find a Visual Studio installation; "
|
||||
"try running Clang from a developer command prompt">,
|
||||
InGroup<DiagGroup<"msvc-not-found">>;
|
||||
}
|
||||
|
@ -34,7 +34,9 @@ def CXX14BinaryLiteral : DiagGroup<"c++14-binary-literal">;
|
||||
def GNUBinaryLiteral : DiagGroup<"gnu-binary-literal">;
|
||||
def GNUCompoundLiteralInitializer : DiagGroup<"gnu-compound-literal-initializer">;
|
||||
def BitFieldConstantConversion : DiagGroup<"bitfield-constant-conversion">;
|
||||
def BitFieldEnumConversion : DiagGroup<"bitfield-enum-conversion">;
|
||||
def BitFieldWidth : DiagGroup<"bitfield-width">;
|
||||
def Coroutine : DiagGroup<"coroutine">;
|
||||
def ConstantConversion :
|
||||
DiagGroup<"constant-conversion", [ BitFieldConstantConversion ] >;
|
||||
def LiteralConversion : DiagGroup<"literal-conversion">;
|
||||
@ -175,6 +177,8 @@ def CXX98CompatPedantic : DiagGroup<"c++98-compat-pedantic",
|
||||
|
||||
def CXX11Narrowing : DiagGroup<"c++11-narrowing">;
|
||||
|
||||
def CXX11WarnOverrideDestructor :
|
||||
DiagGroup<"inconsistent-missing-destructor-override">;
|
||||
def CXX11WarnOverrideMethod : DiagGroup<"inconsistent-missing-override">;
|
||||
|
||||
// Original name of this warning in Clang
|
||||
@ -355,6 +359,7 @@ def SemiBeforeMethodBody : DiagGroup<"semicolon-before-method-body">;
|
||||
def Sentinel : DiagGroup<"sentinel">;
|
||||
def MissingMethodReturnType : DiagGroup<"missing-method-return-type">;
|
||||
|
||||
def ShadowField : DiagGroup<"shadow-field">;
|
||||
def ShadowFieldInConstructorModified : DiagGroup<"shadow-field-in-constructor-modified">;
|
||||
def ShadowFieldInConstructor : DiagGroup<"shadow-field-in-constructor",
|
||||
[ShadowFieldInConstructorModified]>;
|
||||
@ -366,7 +371,7 @@ def ShadowUncapturedLocal : DiagGroup<"shadow-uncaptured-local">;
|
||||
def Shadow : DiagGroup<"shadow", [ShadowFieldInConstructorModified,
|
||||
ShadowIvar]>;
|
||||
def ShadowAll : DiagGroup<"shadow-all", [Shadow, ShadowFieldInConstructor,
|
||||
ShadowUncapturedLocal]>;
|
||||
ShadowUncapturedLocal, ShadowField]>;
|
||||
|
||||
def Shorten64To32 : DiagGroup<"shorten-64-to-32">;
|
||||
def : DiagGroup<"sign-promo">;
|
||||
@ -480,6 +485,7 @@ def UnusedFunction : DiagGroup<"unused-function", [UnneededInternalDecl]>;
|
||||
def UnusedMemberFunction : DiagGroup<"unused-member-function",
|
||||
[UnneededMemberFunction]>;
|
||||
def UnusedLabel : DiagGroup<"unused-label">;
|
||||
def UnusedLambdaCapture : DiagGroup<"unused-lambda-capture">;
|
||||
def UnusedParameter : DiagGroup<"unused-parameter">;
|
||||
def UnusedResult : DiagGroup<"unused-result">;
|
||||
def PotentiallyEvaluatedExpression : DiagGroup<"potentially-evaluated-expression">;
|
||||
@ -602,6 +608,7 @@ def Conversion : DiagGroup<"conversion",
|
||||
[BoolConversion,
|
||||
ConstantConversion,
|
||||
EnumConversion,
|
||||
BitFieldEnumConversion,
|
||||
FloatConversion,
|
||||
Shorten64To32,
|
||||
IntConversion,
|
||||
@ -617,8 +624,9 @@ def Unused : DiagGroup<"unused",
|
||||
[UnusedArgument, UnusedFunction, UnusedLabel,
|
||||
// UnusedParameter, (matches GCC's behavior)
|
||||
// UnusedMemberFunction, (clean-up llvm before enabling)
|
||||
UnusedPrivateField, UnusedLocalTypedef,
|
||||
UnusedValue, UnusedVariable, UnusedPropertyIvar]>,
|
||||
UnusedPrivateField, UnusedLambdaCapture,
|
||||
UnusedLocalTypedef, UnusedValue, UnusedVariable,
|
||||
UnusedPropertyIvar]>,
|
||||
DiagCategory<"Unused Entity Issue">;
|
||||
|
||||
// Format settings.
|
||||
@ -881,7 +889,7 @@ def BackendOptimizationFailure : DiagGroup<"pass-failed">;
|
||||
def ProfileInstrOutOfDate : DiagGroup<"profile-instr-out-of-date">;
|
||||
def ProfileInstrUnprofiled : DiagGroup<"profile-instr-unprofiled">;
|
||||
|
||||
// AddressSanitizer frontent instrumentation remarks.
|
||||
// AddressSanitizer frontend instrumentation remarks.
|
||||
def SanitizeAddressRemarks : DiagGroup<"sanitize-address">;
|
||||
|
||||
// Issues with serialized diagnostics.
|
||||
|
@ -84,6 +84,7 @@ class DiagnosticMapping {
|
||||
unsigned IsPragma : 1;
|
||||
unsigned HasNoWarningAsError : 1;
|
||||
unsigned HasNoErrorAsFatal : 1;
|
||||
unsigned WasUpgradedFromWarning : 1;
|
||||
|
||||
public:
|
||||
static DiagnosticMapping Make(diag::Severity Severity, bool IsUser,
|
||||
@ -94,6 +95,7 @@ class DiagnosticMapping {
|
||||
Result.IsPragma = IsPragma;
|
||||
Result.HasNoWarningAsError = 0;
|
||||
Result.HasNoErrorAsFatal = 0;
|
||||
Result.WasUpgradedFromWarning = 0;
|
||||
return Result;
|
||||
}
|
||||
|
||||
@ -103,11 +105,33 @@ class DiagnosticMapping {
|
||||
bool isUser() const { return IsUser; }
|
||||
bool isPragma() const { return IsPragma; }
|
||||
|
||||
bool isErrorOrFatal() const {
|
||||
return getSeverity() == diag::Severity::Error ||
|
||||
getSeverity() == diag::Severity::Fatal;
|
||||
}
|
||||
|
||||
bool hasNoWarningAsError() const { return HasNoWarningAsError; }
|
||||
void setNoWarningAsError(bool Value) { HasNoWarningAsError = Value; }
|
||||
|
||||
bool hasNoErrorAsFatal() const { return HasNoErrorAsFatal; }
|
||||
void setNoErrorAsFatal(bool Value) { HasNoErrorAsFatal = Value; }
|
||||
|
||||
/// Whether this mapping attempted to map the diagnostic to a warning, but
|
||||
/// was overruled because the diagnostic was already mapped to an error or
|
||||
/// fatal error.
|
||||
bool wasUpgradedFromWarning() const { return WasUpgradedFromWarning; }
|
||||
void setUpgradedFromWarning(bool Value) { WasUpgradedFromWarning = Value; }
|
||||
|
||||
/// Serialize the bits that aren't based on context.
|
||||
unsigned serializeBits() const {
|
||||
return (WasUpgradedFromWarning << 3) | Severity;
|
||||
}
|
||||
static diag::Severity deserializeSeverity(unsigned Bits) {
|
||||
return (diag::Severity)(Bits & 0x7);
|
||||
}
|
||||
static bool deserializeUpgradedFromWarning(unsigned Bits) {
|
||||
return Bits >> 3;
|
||||
}
|
||||
};
|
||||
|
||||
/// \brief Used for handling and querying diagnostic IDs.
|
||||
|
@ -176,6 +176,9 @@ def warn_gcc_attribute_location : Warning<
|
||||
def warn_attribute_no_decl : Warning<
|
||||
"attribute %0 ignored, because it is not attached to a declaration">,
|
||||
InGroup<IgnoredAttributes>;
|
||||
def err_ms_attributes_not_enabled : Error<
|
||||
"'__declspec' attributes are not enabled; use '-fdeclspec' or "
|
||||
"'-fms-extensions' to enable support for __declspec attributes">;
|
||||
def err_expected_method_body : Error<"expected method body">;
|
||||
def err_declspec_after_virtspec : Error<
|
||||
"'%0' qualifier may not appear after the virtual specifier '%1'">;
|
||||
@ -361,8 +364,6 @@ def ext_decomp_decl_empty : ExtWarn<
|
||||
/// Objective-C parser diagnostics
|
||||
def err_expected_minus_or_plus : Error<
|
||||
"method type specifier must start with '-' or '+'">;
|
||||
def err_objc_no_attributes_on_category : Error<
|
||||
"attributes may not be specified on a category">;
|
||||
def err_objc_missing_end : Error<"missing '@end'">;
|
||||
def note_objc_container_start : Note<
|
||||
"%select{class|protocol|category|class extension|implementation"
|
||||
@ -435,6 +436,13 @@ def err_declaration_does_not_declare_param : Error<
|
||||
"declaration does not declare a parameter">;
|
||||
def err_no_matching_param : Error<"parameter named %0 is missing">;
|
||||
|
||||
/// Objective-C++ parser diagnostics
|
||||
def err_expected_token_instead_of_objcxx_keyword : Error<
|
||||
"expected %0; %1 is a keyword in Objective-C++">;
|
||||
def err_expected_member_name_or_semi_objcxx_keyword : Error<
|
||||
"expected member name or ';' after declaration specifiers; "
|
||||
"%0 is a keyword in Objective-C++">;
|
||||
|
||||
/// C++ parser diagnostics
|
||||
def err_invalid_operator_on_type : Error<
|
||||
"cannot use %select{dot|arrow}0 operator on a type">;
|
||||
@ -669,9 +677,6 @@ def warn_static_inline_explicit_inst_ignored : Warning<
|
||||
// Constructor template diagnostics.
|
||||
def err_out_of_line_constructor_template_id : Error<
|
||||
"out-of-line constructor for %0 cannot have template arguments">;
|
||||
def err_out_of_line_template_id_type_names_constructor : Error<
|
||||
"qualified reference to %0 is a constructor name rather than a "
|
||||
"%select{template name|type}1 wherever a constructor can be declared">;
|
||||
|
||||
def err_expected_qualified_after_typename : Error<
|
||||
"expected a qualified name after 'typename'">;
|
||||
@ -859,6 +864,12 @@ def err_availability_query_repeated_platform: Error<
|
||||
def err_availability_query_repeated_star : Error<
|
||||
"'*' query has already been specified">;
|
||||
|
||||
// External source symbol attribute
|
||||
def err_external_source_symbol_expected_keyword : Error<
|
||||
"expected 'language', 'defined_in', or 'generated_declaration'">;
|
||||
def err_external_source_symbol_duplicate_clause : Error<
|
||||
"duplicate %0 clause in an 'external_source_symbol' attribute">;
|
||||
|
||||
// Type safety attributes
|
||||
def err_type_safety_unknown_flag : Error<
|
||||
"invalid comparison flag %0; use 'layout_compatible' or 'must_be_null'">;
|
||||
@ -1036,6 +1047,16 @@ def err_pragma_loop_missing_argument : Error<
|
||||
def err_pragma_loop_invalid_option : Error<
|
||||
"%select{invalid|missing}0 option%select{ %1|}0; expected vectorize, "
|
||||
"vectorize_width, interleave, interleave_count, unroll, unroll_count, or distribute">;
|
||||
|
||||
def err_pragma_fp_invalid_option : Error<
|
||||
"%select{invalid|missing}0 option%select{ %1|}0; expected contract">;
|
||||
def err_pragma_fp_invalid_argument : Error<
|
||||
"unexpected argument '%0' to '#pragma clang fp %1'; "
|
||||
"expected 'on', 'fast' or 'off'">;
|
||||
def err_pragma_fp_scope : Error<
|
||||
"'#pragma clang fp' can only appear at file scope or at the start of a "
|
||||
"compound statement">;
|
||||
|
||||
def err_pragma_invalid_keyword : Error<
|
||||
"invalid argument; expected 'enable'%select{|, 'full'}0%select{|, 'assume_safety'}1 or 'disable'">;
|
||||
|
||||
|
@ -259,6 +259,9 @@ def err_anyx86_interrupt_attribute : Error<
|
||||
"a pointer as the first parameter|a %2 type as the second parameter}1">;
|
||||
def err_anyx86_interrupt_called : Error<
|
||||
"interrupt service routine cannot be called directly">;
|
||||
def warn_arm_interrupt_calling_convention : Warning<
|
||||
"call to function without interrupt attribute could clobber interruptee's VFP registers">,
|
||||
InGroup<Extra>;
|
||||
def warn_mips_interrupt_attribute : Warning<
|
||||
"MIPS 'interrupt' attribute only applies to functions that have "
|
||||
"%select{no parameters|a 'void' return type}0">,
|
||||
@ -316,6 +319,9 @@ def warn_unneeded_member_function : Warning<
|
||||
InGroup<UnneededMemberFunction>, DefaultIgnore;
|
||||
def warn_unused_private_field: Warning<"private field %0 is not used">,
|
||||
InGroup<UnusedPrivateField>, DefaultIgnore;
|
||||
def warn_unused_lambda_capture: Warning<"lambda capture %0 is not "
|
||||
"%select{used|required to be captured for this use}1">,
|
||||
InGroup<UnusedLambdaCapture>, DefaultIgnore;
|
||||
|
||||
def warn_parameter_size: Warning<
|
||||
"%0 is a large (%1 bytes) pass-by-value argument; "
|
||||
@ -363,7 +369,9 @@ def warn_decl_shadow :
|
||||
"local variable|"
|
||||
"variable in %2|"
|
||||
"static data member of %2|"
|
||||
"field of %2}1">,
|
||||
"field of %2|"
|
||||
"typedef in %2|"
|
||||
"type alias in %2}1">,
|
||||
InGroup<Shadow>, DefaultIgnore;
|
||||
def warn_decl_shadow_uncaptured_local :
|
||||
Warning<warn_decl_shadow.Text>,
|
||||
@ -1201,8 +1209,9 @@ def warn_cxx98_compat_unelaborated_friend_type : Warning<
|
||||
def err_qualified_friend_not_found : Error<
|
||||
"no function named %0 with type %1 was found in the specified scope">;
|
||||
def err_introducing_special_friend : Error<
|
||||
"must use a qualified name when declaring a %select{constructor|"
|
||||
"destructor|conversion operator}0 as a friend">;
|
||||
"%plural{[0,2]:must use a qualified name when declaring|3:cannot declare}0"
|
||||
" a %select{constructor|destructor|conversion operator|deduction guide}0 "
|
||||
"as a friend">;
|
||||
def err_tagless_friend_type_template : Error<
|
||||
"friend type templates must use an elaborated type">;
|
||||
def err_no_matching_local_friend : Error<
|
||||
@ -1447,6 +1456,15 @@ def err_nested_name_spec_is_not_class : Error<
|
||||
def ext_nested_name_spec_is_enum : ExtWarn<
|
||||
"use of enumeration in a nested name specifier is a C++11 extension">,
|
||||
InGroup<CXX11>;
|
||||
def err_out_of_line_qualified_id_type_names_constructor : Error<
|
||||
"qualified reference to %0 is a constructor name rather than a "
|
||||
"%select{template name|type}1 in this context">;
|
||||
def ext_out_of_line_qualified_id_type_names_constructor : ExtWarn<
|
||||
"ISO C++ specifies that "
|
||||
"qualified reference to %0 is a constructor name rather than a "
|
||||
"%select{template name|type}1 in this context, despite preceding "
|
||||
"%select{'typename'|'template'}2 keyword">, SFINAEFailure,
|
||||
InGroup<DiagGroup<"injected-class-name">>;
|
||||
|
||||
// C++ class members
|
||||
def err_storageclass_invalid_for_member : Error<
|
||||
@ -1608,7 +1626,14 @@ def err_covariant_return_type_class_type_more_qualified : Error<
|
||||
"return type of virtual function %0 is not covariant with the return type of "
|
||||
"the function it overrides (class type %1 is more qualified than class "
|
||||
"type %2">;
|
||||
|
||||
|
||||
// C++ implicit special member functions
|
||||
def note_in_declaration_of_implicit_special_member : Note<
|
||||
"while declaring the implicit "
|
||||
"%select{default constructor|copy constructor|move constructor|"
|
||||
"copy assignment operator|move assignment operator|destructor}1"
|
||||
" for %0">;
|
||||
|
||||
// C++ constructors
|
||||
def err_constructor_cannot_be : Error<"constructor cannot be declared '%0'">;
|
||||
def err_invalid_qualified_constructor : Error<
|
||||
@ -1664,8 +1689,8 @@ def err_init_conversion_failed : Error<
|
||||
"cannot initialize %select{a variable|a parameter|return object|an "
|
||||
"exception object|a member subobject|an array element|a new value|a value|a "
|
||||
"base class|a constructor delegation|a vector element|a block element|a "
|
||||
"complex element|a lambda capture|a compound literal initializer|a "
|
||||
"related result|a parameter of CF audited function}0 "
|
||||
"block element|a complex element|a lambda capture|a compound literal "
|
||||
"initializer|a related result|a parameter of CF audited function}0 "
|
||||
"%diff{of type $ with an %select{rvalue|lvalue}2 of type $|"
|
||||
"with an %select{rvalue|lvalue}2 of incompatible type}1,3"
|
||||
"%select{|: different classes%diff{ ($ vs $)|}5,6"
|
||||
@ -1791,8 +1816,9 @@ def note_uninit_fixit_remove_cond : Note<
|
||||
"remove the %select{'%1' if its condition|condition if it}0 "
|
||||
"is always %select{false|true}2">;
|
||||
def err_init_incomplete_type : Error<"initialization of incomplete type %0">;
|
||||
def err_list_init_in_parens : Error<"list-initializer for non-class type %0 "
|
||||
"must not be parenthesized">;
|
||||
def err_list_init_in_parens : Error<
|
||||
"cannot initialize %select{non-class|reference}0 type %1 with a "
|
||||
"parenthesized initializer list">;
|
||||
|
||||
def warn_unsequenced_mod_mod : Warning<
|
||||
"multiple unsequenced modifications to %0">, InGroup<Unsequenced>;
|
||||
@ -1833,8 +1859,8 @@ def warn_cxx98_compat_temp_copy : Warning<
|
||||
InGroup<CXX98CompatBindToTemporaryCopy>, DefaultIgnore;
|
||||
def err_selected_explicit_constructor : Error<
|
||||
"chosen constructor is explicit in copy-initialization">;
|
||||
def note_constructor_declared_here : Note<
|
||||
"constructor declared here">;
|
||||
def note_explicit_ctor_deduction_guide_here : Note<
|
||||
"explicit %select{constructor|deduction guide}0 declared here">;
|
||||
|
||||
// C++11 decltype
|
||||
def err_decltype_in_declarator : Error<
|
||||
@ -1845,8 +1871,8 @@ def warn_cxx98_compat_auto_type_specifier : Warning<
|
||||
"'auto' type specifier is incompatible with C++98">,
|
||||
InGroup<CXX98Compat>, DefaultIgnore;
|
||||
def err_auto_variable_cannot_appear_in_own_initializer : Error<
|
||||
"variable %0 declared with %select{'auto'|'decltype(auto)'|'__auto_type'}1 "
|
||||
"type cannot appear in its own initializer">;
|
||||
"variable %0 declared with deduced type %1 "
|
||||
"cannot appear in its own initializer">;
|
||||
def err_binding_cannot_appear_in_own_initializer : Error<
|
||||
"binding %0 cannot appear in the initializer of its own "
|
||||
"decomposition declaration">;
|
||||
@ -1855,20 +1881,29 @@ def err_illegal_decl_array_of_auto : Error<
|
||||
def err_new_array_of_auto : Error<
|
||||
"cannot allocate array of 'auto'">;
|
||||
def err_auto_not_allowed : Error<
|
||||
"%select{'auto'|'decltype(auto)'|'__auto_type'}0 not allowed "
|
||||
"%select{'auto'|'decltype(auto)'|'__auto_type'|"
|
||||
"use of "
|
||||
"%select{class template|function template|variable template|alias template|"
|
||||
"template template parameter|template}2 %3 requires template arguments; "
|
||||
"argument deduction}0 not allowed "
|
||||
"%select{in function prototype"
|
||||
"|in non-static struct member|in struct member"
|
||||
"|in non-static union member|in union member"
|
||||
"|in non-static class member|in interface member"
|
||||
"|in exception declaration|in template parameter|in block literal"
|
||||
"|in exception declaration|in template parameter until C++1z|in block literal"
|
||||
"|in template argument|in typedef|in type alias|in function return type"
|
||||
"|in conversion function type|here|in lambda parameter"
|
||||
"|in type allocated by 'new'|in K&R-style function parameter}1"
|
||||
"%select{|||||||| until C++1z||||||||||}1">;
|
||||
"|in type allocated by 'new'|in K&R-style function parameter"
|
||||
"|in template parameter|in friend declaration}1">;
|
||||
def err_dependent_deduced_tst : Error<
|
||||
"typename specifier refers to "
|
||||
"%select{class template|function template|variable template|alias template|"
|
||||
"template template parameter|template}0 member in %1; "
|
||||
"argument deduction not allowed here">;
|
||||
def err_auto_not_allowed_var_inst : Error<
|
||||
"'auto' variable template instantiation is not allowed">;
|
||||
def err_auto_var_requires_init : Error<
|
||||
"declaration of variable %0 with type %1 requires an initializer">;
|
||||
"declaration of variable %0 with deduced type %1 requires an initializer">;
|
||||
def err_auto_new_requires_ctor_arg : Error<
|
||||
"new expression for type %0 requires a constructor argument">;
|
||||
def err_auto_new_list_init : Error<
|
||||
@ -1898,8 +1933,13 @@ def err_auto_var_deduction_failure_from_init_list : Error<
|
||||
def err_auto_new_deduction_failure : Error<
|
||||
"new expression for type %0 has incompatible constructor argument of type %1">;
|
||||
def err_auto_different_deductions : Error<
|
||||
"'%select{auto|decltype(auto)|__auto_type}0' deduced as %1 in declaration "
|
||||
"of %2 and deduced as %3 in declaration of %4">;
|
||||
"%select{'auto'|'decltype(auto)'|'__auto_type'|template arguments}0 "
|
||||
"deduced as %1 in declaration of %2 and "
|
||||
"deduced as %3 in declaration of %4">;
|
||||
def err_auto_non_deduced_not_alone : Error<
|
||||
"%select{function with deduced return type|"
|
||||
"declaration with trailing return type}0 "
|
||||
"must be the only declaration in its group">;
|
||||
def err_implied_std_initializer_list_not_found : Error<
|
||||
"cannot deduce type of initializer list because std::initializer_list was "
|
||||
"not found; include <initializer_list>">;
|
||||
@ -1915,6 +1955,8 @@ def err_auto_bitfield : Error<
|
||||
"cannot pass bit-field as __auto_type initializer in C">;
|
||||
|
||||
// C++1y decltype(auto) type
|
||||
def err_decltype_auto_invalid : Error<
|
||||
"'decltype(auto)' not allowed here">;
|
||||
def err_decltype_auto_cannot_be_combined : Error<
|
||||
"'decltype(auto)' cannot be combined with other type specifiers">;
|
||||
def err_decltype_auto_function_declarator_not_declaration : Error<
|
||||
@ -1925,6 +1967,56 @@ def err_decltype_auto_compound_type : Error<
|
||||
def err_decltype_auto_initializer_list : Error<
|
||||
"cannot deduce 'decltype(auto)' from initializer list">;
|
||||
|
||||
// C++1z deduced class template specialization types
|
||||
def err_deduced_class_template_compound_type : Error<
|
||||
"cannot %select{form pointer to|form reference to|form array of|"
|
||||
"form function returning|use parentheses when declaring variable with}0 "
|
||||
"deduced class template specialization type">;
|
||||
def err_deduced_non_class_template_specialization_type : Error<
|
||||
"%select{<error>|function template|variable template|alias template|"
|
||||
"template template parameter|template}0 %1 requires template arguments; "
|
||||
"argument deduction only allowed for class templates">;
|
||||
def err_deduced_class_template_ctor_ambiguous : Error<
|
||||
"ambiguous deduction for template arguments of %0">;
|
||||
def err_deduced_class_template_ctor_no_viable : Error<
|
||||
"no viable constructor or deduction guide for deduction of "
|
||||
"template arguments of %0">;
|
||||
def err_deduced_class_template_incomplete : Error<
|
||||
"template %0 has no definition and no %select{|viable }1deduction guides "
|
||||
"for deduction of template arguments">;
|
||||
def err_deduced_class_template_deleted : Error<
|
||||
"class template argument deduction for %0 selected a deleted constructor">;
|
||||
def err_deduced_class_template_explicit : Error<
|
||||
"class template argument deduction for %0 selected an explicit "
|
||||
"%select{constructor|deduction guide}1 for copy-list-initialization">;
|
||||
def err_deduction_guide_no_trailing_return_type : Error<
|
||||
"deduction guide declaration without trailing return type">;
|
||||
def err_deduction_guide_bad_trailing_return_type : Error<
|
||||
"deduced type %1 of deduction guide is not %select{|written as }2"
|
||||
"a specialization of template %0">;
|
||||
def err_deduction_guide_with_complex_decl : Error<
|
||||
"cannot specify any part of a return type in the "
|
||||
"declaration of a deduction guide">;
|
||||
def err_deduction_guide_invalid_specifier : Error<
|
||||
"deduction guide cannot be declared '%0'">;
|
||||
def err_deduction_guide_name_not_class_template : Error<
|
||||
"cannot specify deduction guide for "
|
||||
"%select{<error>|function template|variable template|alias template|"
|
||||
"template template parameter|dependent template name}0 %1">;
|
||||
def err_deduction_guide_wrong_scope : Error<
|
||||
"deduction guide must be declared in the same scope as template %q0">;
|
||||
def err_deduction_guide_defines_function : Error<
|
||||
"deduction guide cannot have a function definition">;
|
||||
def err_deduction_guide_explicit_mismatch : Error<
|
||||
"deduction guide is %select{not |}0declared 'explicit' but "
|
||||
"previous declaration was%select{ not|}0">;
|
||||
def err_deduction_guide_specialized : Error<"deduction guide cannot be "
|
||||
"%select{explicitly instantiated|explicitly specialized}0">;
|
||||
def err_deduction_guide_template_not_deducible : Error<
|
||||
"deduction guide template contains "
|
||||
"%select{a template parameter|template parameters}0 that cannot be "
|
||||
"deduced">;
|
||||
|
||||
// C++1y deduced return types
|
||||
def err_auto_fn_deduction_failure : Error<
|
||||
"cannot deduce return type %0 from returned value of type %1">;
|
||||
@ -1950,6 +2042,9 @@ def override_keyword_hides_virtual_member_function : Error<
|
||||
"%select{function|functions}1">;
|
||||
def err_function_marked_override_not_overriding : Error<
|
||||
"%0 marked 'override' but does not override any member functions">;
|
||||
def warn_destructor_marked_not_override_overriding : Warning <
|
||||
"%0 overrides a destructor but is not marked 'override'">,
|
||||
InGroup<CXX11WarnOverrideDestructor>, DefaultIgnore;
|
||||
def warn_function_marked_not_override_overriding : Warning <
|
||||
"%0 overrides a member function but is not marked 'override'">,
|
||||
InGroup<CXX11WarnOverrideMethod>;
|
||||
@ -2215,6 +2310,9 @@ def err_concept_specialized : Error<
|
||||
"%select{function|variable}0 concept cannot be "
|
||||
"%select{explicitly instantiated|explicitly specialized|partially specialized}1">;
|
||||
|
||||
def err_template_different_associated_constraints : Error<
|
||||
"associated constraints differ in template redeclaration">;
|
||||
|
||||
// C++11 char16_t/char32_t
|
||||
def warn_cxx98_compat_unicode_type : Warning<
|
||||
"'%0' type specifier is incompatible with C++98">,
|
||||
@ -2261,7 +2359,7 @@ def warn_unsupported_target_attribute
|
||||
InGroup<IgnoredAttributes>;
|
||||
def err_attribute_unsupported
|
||||
: Error<"%0 attribute is not supported for this target">;
|
||||
// The err_*_attribute_argument_not_int are seperate because they're used by
|
||||
// The err_*_attribute_argument_not_int are separate because they're used by
|
||||
// VerifyIntegerConstantExpression.
|
||||
def err_aligned_attribute_argument_not_int : Error<
|
||||
"'aligned' attribute requires integer constant">;
|
||||
@ -2659,7 +2757,8 @@ def warn_attribute_wrong_decl_type : Warning<
|
||||
"|functions, methods, enums, and classes"
|
||||
"|structs, classes, variables, functions, and inline namespaces"
|
||||
"|variables, functions, methods, types, enumerations, enumerators, labels, and non-static data members"
|
||||
"|classes and enumerations}1">,
|
||||
"|classes and enumerations"
|
||||
"|named declarations}1">,
|
||||
InGroup<IgnoredAttributes>;
|
||||
def err_attribute_wrong_decl_type : Error<warn_attribute_wrong_decl_type.Text>;
|
||||
def warn_type_attribute_wrong_type : Warning<
|
||||
@ -3132,7 +3231,8 @@ def err_attribute_regparm_invalid_number : Error<
|
||||
"'regparm' parameter must be between 0 and %0 inclusive">;
|
||||
def err_attribute_not_supported_in_lang : Error<
|
||||
"%0 attribute is not supported in %select{C|C++|Objective-C}1">;
|
||||
|
||||
def err_attribute_not_supported_on_arch
|
||||
: Error<"%0 attribute is not supported on '%1'">;
|
||||
|
||||
// Clang-Specific Attributes
|
||||
def warn_attribute_iboutlet : Warning<
|
||||
@ -3380,7 +3480,7 @@ def note_ovl_candidate_disabled_by_function_cond_attr : Note<
|
||||
def note_ovl_candidate_disabled_by_extension : Note<
|
||||
"candidate disabled due to OpenCL extension">;
|
||||
def err_addrof_function_disabled_by_enable_if_attr : Error<
|
||||
"cannot take address of function %0 becuase it has one or more "
|
||||
"cannot take address of function %0 because it has one or more "
|
||||
"non-tautological enable_if conditions">;
|
||||
def note_addrof_ovl_candidate_disabled_by_enable_if_attr : Note<
|
||||
"candidate function made ineligible by enable_if">;
|
||||
@ -3789,11 +3889,13 @@ def err_template_decl_ref : Error<
|
||||
|
||||
// C++ Template Argument Lists
|
||||
def err_template_missing_args : Error<
|
||||
"use of class template %0 requires template arguments">;
|
||||
"use of "
|
||||
"%select{class template|function template|variable template|alias template|"
|
||||
"template template parameter|template}0 %1 requires template arguments">;
|
||||
def err_template_arg_list_different_arity : Error<
|
||||
"%select{too few|too many}0 template arguments for "
|
||||
"%select{class template|function template|template template parameter"
|
||||
"|template}1 %2">;
|
||||
"%select{class template|function template|variable template|alias template|"
|
||||
"template template parameter|template}1 %2">;
|
||||
def note_template_decl_here : Note<"template is declared here">;
|
||||
def err_template_arg_must_be_type : Error<
|
||||
"template argument for template type parameter must be a type">;
|
||||
@ -4063,7 +4165,7 @@ def ext_partial_specs_not_deducible : ExtWarn<
|
||||
"%select{a template parameter|template parameters}1 that cannot be "
|
||||
"deduced; this partial specialization will never be used">,
|
||||
DefaultError, InGroup<DiagGroup<"unusable-partial-specialization">>;
|
||||
def note_partial_spec_unused_parameter : Note<
|
||||
def note_non_deducible_parameter : Note<
|
||||
"non-deducible template parameter %0">;
|
||||
def err_partial_spec_ordering_ambiguous : Error<
|
||||
"ambiguous partial specializations of %0">;
|
||||
@ -4286,6 +4388,8 @@ def note_typename_refers_here : Note<
|
||||
"referenced member %0 is declared here">;
|
||||
def err_typename_missing : Error<
|
||||
"missing 'typename' prior to dependent type name '%0%1'">;
|
||||
def err_typename_missing_template : Error<
|
||||
"missing 'typename' prior to dependent type template name '%0%1'">;
|
||||
def ext_typename_missing : ExtWarn<
|
||||
"missing 'typename' prior to dependent type name '%0%1'">,
|
||||
InGroup<DiagGroup<"typename-missing">>;
|
||||
@ -4304,7 +4408,7 @@ def err_template_kw_refers_to_non_template : Error<
|
||||
"%0 following the 'template' keyword does not refer to a template">;
|
||||
def err_template_kw_refers_to_class_template : Error<
|
||||
"'%0%1' instantiated to a class template, not a function template">;
|
||||
def note_referenced_class_template : Error<
|
||||
def note_referenced_class_template : Note<
|
||||
"class template declared here">;
|
||||
def err_template_kw_missing : Error<
|
||||
"missing 'template' keyword prior to dependent template name '%0%1'">;
|
||||
@ -4808,6 +4912,21 @@ def warn_bitfield_width_exceeds_type_width: Warning<
|
||||
def warn_anon_bitfield_width_exceeds_type_width : Warning<
|
||||
"width of anonymous bit-field (%0 bits) exceeds width of its type; value "
|
||||
"will be truncated to %1 bit%s1">, InGroup<BitFieldWidth>;
|
||||
def warn_bitfield_too_small_for_enum : Warning<
|
||||
"bit-field %0 is not wide enough to store all enumerators of %1">,
|
||||
InGroup<BitFieldEnumConversion>, DefaultIgnore;
|
||||
def note_widen_bitfield : Note<
|
||||
"widen this field to %0 bits to store all values of %1">;
|
||||
def warn_unsigned_bitfield_assigned_signed_enum : Warning<
|
||||
"assigning value of signed enum type %1 to unsigned bit-field %0; "
|
||||
"negative enumerators of enum %1 will be converted to positive values">,
|
||||
InGroup<BitFieldEnumConversion>, DefaultIgnore;
|
||||
def warn_signed_bitfield_enum_conversion : Warning<
|
||||
"signed bit-field %0 needs an extra bit to represent the largest positive "
|
||||
"enumerators of %1">,
|
||||
InGroup<BitFieldEnumConversion>, DefaultIgnore;
|
||||
def note_change_bitfield_sign : Note<
|
||||
"consider making the bitfield type %select{unsigned|signed}0">;
|
||||
|
||||
def warn_missing_braces : Warning<
|
||||
"suggest braces around initialization of subobject">,
|
||||
@ -5164,7 +5283,7 @@ def err_arc_inconsistent_property_ownership : Error<
|
||||
def warn_block_capture_autoreleasing : Warning<
|
||||
"block captures an autoreleasing out-parameter, which may result in "
|
||||
"use-after-free bugs">,
|
||||
InGroup<BlockCaptureAutoReleasing>, DefaultIgnore;
|
||||
InGroup<BlockCaptureAutoReleasing>;
|
||||
def note_declare_parameter_autoreleasing : Note<
|
||||
"declare the parameter __autoreleasing explicitly to suppress this warning">;
|
||||
def note_declare_parameter_strong : Note<
|
||||
@ -5725,8 +5844,8 @@ def err_this_static_member_func : Error<
|
||||
def err_invalid_member_use_in_static_method : Error<
|
||||
"invalid use of member %0 in static member function">;
|
||||
def err_invalid_qualified_function_type : Error<
|
||||
"%select{static |non-}0member function %select{of type %2 |}1"
|
||||
"cannot have '%3' qualifier">;
|
||||
"%select{non-member function|static member function|deduction guide}0 "
|
||||
"%select{of type %2 |}1cannot have '%3' qualifier">;
|
||||
def err_compound_qualified_function_type : Error<
|
||||
"%select{block pointer|pointer|reference}0 to function type %select{%2 |}1"
|
||||
"cannot have '%3' qualifier">;
|
||||
@ -5750,8 +5869,8 @@ def err_builtin_func_cast_more_than_one_arg : Error<
|
||||
"function-style cast to a builtin type can only take one argument">;
|
||||
def err_value_init_for_array_type : Error<
|
||||
"array types cannot be value-initialized">;
|
||||
def err_value_init_for_function_type : Error<
|
||||
"function types cannot be value-initialized">;
|
||||
def err_init_for_function_type : Error<
|
||||
"cannot create object of function type %0">;
|
||||
def warn_format_nonliteral_noargs : Warning<
|
||||
"format string is not a string literal (potentially insecure)">,
|
||||
InGroup<FormatSecurity>;
|
||||
@ -5916,6 +6035,12 @@ def warn_objc_circular_container : Warning<
|
||||
"adding '%0' to '%1' might cause circular dependency in container">,
|
||||
InGroup<DiagGroup<"objc-circular-container">>;
|
||||
def note_objc_circular_container_declared_here : Note<"'%0' declared here">;
|
||||
def warn_objc_unsafe_perform_selector : Warning<
|
||||
"%0 is incompatible with selectors that return a "
|
||||
"%select{struct|union|vector}1 type">,
|
||||
InGroup<DiagGroup<"objc-unsafe-perform-selector">>;
|
||||
def note_objc_unsafe_perform_selector_method_declared_here : Note<
|
||||
"method %0 that returns %1 declared here">;
|
||||
|
||||
def warn_setter_getter_impl_required : Warning<
|
||||
"property %0 requires method %1 to be defined - "
|
||||
@ -7001,7 +7126,7 @@ def err_incomplete_type_used_in_type_trait_expr : Error<
|
||||
def err_require_constant_init_failed : Error<
|
||||
"variable does not have a constant initializer">;
|
||||
def note_declared_required_constant_init_here : Note<
|
||||
"required by 'require_constant_initializer' attribute here">;
|
||||
"required by 'require_constant_initialization' attribute here">;
|
||||
|
||||
def err_dimension_expr_not_constant_integer : Error<
|
||||
"dimension expression does not evaluate to a constant unsigned int">;
|
||||
@ -7899,6 +8024,8 @@ def err_x86_builtin_32_bit_tgt : Error<
|
||||
"this builtin is only available on x86-64 targets">;
|
||||
def err_x86_builtin_invalid_rounding : Error<
|
||||
"invalid rounding argument">;
|
||||
def err_x86_builtin_invalid_scale : Error<
|
||||
"scale argument must be 1, 2, 4, or 8">;
|
||||
|
||||
def err_builtin_longjmp_unsupported : Error<
|
||||
"__builtin_longjmp is not supported for the current target">;
|
||||
@ -8113,6 +8240,8 @@ def err_opencl_ptrptr_kernel_param : Error<
|
||||
def err_kernel_arg_address_space : Error<
|
||||
"pointer arguments to kernel functions must reside in '__global', "
|
||||
"'__constant' or '__local' address space">;
|
||||
def err_opencl_ext_vector_component_invalid_length : Error<
|
||||
"vector component access has invalid length %0. Supported: 1,2,3,4,8,16.">;
|
||||
def err_opencl_function_variable : Error<
|
||||
"%select{non-kernel function|function scope}0 variable cannot be declared in %1 address space">;
|
||||
def err_static_function_scope : Error<
|
||||
@ -8158,9 +8287,9 @@ def err_opencl_return_value_with_address_space : Error<
|
||||
"return value cannot be qualified with address space">;
|
||||
def err_opencl_constant_no_init : Error<
|
||||
"variable in constant address space must be initialized">;
|
||||
def err_atomic_init_constant : Error<
|
||||
"atomic variable can only be assigned to a compile time constant"
|
||||
" in the declaration statement in the program scope">;
|
||||
def err_opencl_atomic_init: Error<
|
||||
"atomic variable can be %select{assigned|initialized}0 to a variable only "
|
||||
"in global address space">;
|
||||
def err_opencl_implicit_vector_conversion : Error<
|
||||
"implicit conversions between vector types (%0 and %1) are not permitted">;
|
||||
def err_opencl_invalid_type_array : Error<
|
||||
@ -8210,6 +8339,8 @@ def err_opencl_invalid_block_declaration : Error<
|
||||
"invalid block variable declaration - must be %select{const qualified|initialized}0">;
|
||||
def err_opencl_extern_block_declaration : Error<
|
||||
"invalid block variable declaration - using 'extern' storage class is disallowed">;
|
||||
def err_opencl_block_ref_block : Error<
|
||||
"cannot refer to a block inside block">;
|
||||
|
||||
// OpenCL v2.0 s6.13.9 - Address space qualifier functions.
|
||||
def err_opencl_builtin_to_addr_arg_num : Error<
|
||||
@ -8227,9 +8358,9 @@ def err_opencl_enqueue_kernel_local_size_args : Error<
|
||||
def err_opencl_enqueue_kernel_invalid_local_size_type : Error<
|
||||
"illegal call to enqueue_kernel, parameter needs to be specified as integer type">;
|
||||
def err_opencl_enqueue_kernel_blocks_non_local_void_args : Error<
|
||||
"blocks used in device side enqueue are expected to have parameters of type 'local void*'">;
|
||||
"blocks used in enqueue_kernel call are expected to have parameters of type 'local void*'">;
|
||||
def err_opencl_enqueue_kernel_blocks_no_args : Error<
|
||||
"blocks in this form of device side enqueue call are expected to have have no parameters">;
|
||||
"blocks with parameters are not accepted in this prototype of enqueue_kernel call">;
|
||||
|
||||
// OpenCL v2.2 s2.1.2.3 - Vector Component Access
|
||||
def ext_opencl_ext_vector_type_rgba_selector: ExtWarn<
|
||||
@ -8708,8 +8839,7 @@ let CategoryName = "Coroutines Issue" in {
|
||||
def err_return_in_coroutine : Error<
|
||||
"return statement not allowed in coroutine; did you mean 'co_return'?">;
|
||||
def note_declared_coroutine_here : Note<
|
||||
"function is a coroutine due to use of "
|
||||
"'%select{co_await|co_yield|co_return}0' here">;
|
||||
"function is a coroutine due to use of '%0' here">;
|
||||
def err_coroutine_objc_method : Error<
|
||||
"Objective-C methods as coroutines are not yet supported">;
|
||||
def err_coroutine_unevaluated_context : Error<
|
||||
@ -8721,24 +8851,38 @@ def err_coroutine_invalid_func_context : Error<
|
||||
"|a copy assignment operator|a move assignment operator|the 'main' function"
|
||||
"|a constexpr function|a function with a deduced return type"
|
||||
"|a varargs function}0">;
|
||||
def err_implied_std_coroutine_traits_not_found : Error<
|
||||
"you need to include <experimental/coroutine> before defining a coroutine">;
|
||||
def err_implied_coroutine_type_not_found : Error<
|
||||
"%0 type was not found; include <experimental/coroutine> before defining "
|
||||
"a coroutine">;
|
||||
def err_malformed_std_coroutine_handle : Error<
|
||||
"std::experimental::coroutine_handle must be a class template">;
|
||||
def err_coroutine_handle_missing_member : Error<
|
||||
"std::experimental::coroutine_handle missing a member named '%0'">;
|
||||
def err_malformed_std_coroutine_traits : Error<
|
||||
"'std::experimental::coroutine_traits' must be a class template">;
|
||||
def err_implied_std_coroutine_traits_promise_type_not_found : Error<
|
||||
"this function cannot be a coroutine: %q0 has no member named 'promise_type'">;
|
||||
def err_implied_std_coroutine_traits_promise_type_not_class : Error<
|
||||
"this function cannot be a coroutine: %0 is not a class">;
|
||||
def err_coroutine_traits_missing_specialization : Error<
|
||||
def err_coroutine_promise_type_incomplete : Error<
|
||||
"this function cannot be a coroutine: %0 is an incomplete type">;
|
||||
def err_coroutine_type_missing_specialization : Error<
|
||||
"this function cannot be a coroutine: missing definition of "
|
||||
"specialization %q0">;
|
||||
def err_implied_std_current_exception_not_found : Error<
|
||||
"you need to include <exception> before defining a coroutine that implicitly "
|
||||
"uses 'set_exception'">;
|
||||
def err_malformed_std_current_exception : Error<
|
||||
"'std::current_exception' must be a function">;
|
||||
def err_coroutine_promise_return_ill_formed : Error<
|
||||
"%0 declares both 'return_value' and 'return_void'">;
|
||||
def note_coroutine_promise_implicit_await_transform_required_here : Note<
|
||||
"call to 'await_transform' implicitly required by 'co_await' here">;
|
||||
def note_coroutine_promise_call_implicitly_required : Note<
|
||||
"call to '%select{initial_suspend|final_suspend}0' implicitly "
|
||||
"required by the %select{initial suspend point|final suspend point}0">;
|
||||
def err_coroutine_promise_unhandled_exception_required : Error<
|
||||
"%0 is required to declare the member 'unhandled_exception()'">;
|
||||
def warn_coroutine_promise_unhandled_exception_required_with_exceptions : Warning<
|
||||
"%0 is required to declare the member 'unhandled_exception()' when exceptions are enabled">,
|
||||
InGroup<Coroutine>;
|
||||
def err_coroutine_promise_get_return_object_on_allocation_failure : Error<
|
||||
"%0: 'get_return_object_on_allocation_failure()' must be a static member function">;
|
||||
}
|
||||
|
||||
let CategoryName = "Documentation Issue" in {
|
||||
@ -8905,4 +9049,9 @@ def ext_warn_gnu_final : ExtWarn<
|
||||
"__final is a GNU extension, consider using C++11 final">,
|
||||
InGroup<GccCompat>;
|
||||
|
||||
def warn_shadow_field :
|
||||
Warning<"non-static data member '%0' of '%1' shadows member inherited from type '%2'">,
|
||||
InGroup<ShadowField>, DefaultIgnore;
|
||||
def note_shadow_field : Note<"declared here">;
|
||||
|
||||
} // end of sema component.
|
||||
|
@ -117,6 +117,57 @@ def note_module_odr_violation_different_definitions : Note<
|
||||
def err_module_odr_violation_different_instantiations : Error<
|
||||
"instantiation of %q0 is different in different modules">;
|
||||
|
||||
def err_module_odr_violation_mismatch_decl : Error<
|
||||
"%q0 has different definitions in different modules; first difference is "
|
||||
"%select{definition in module '%2'|defined here}1 found "
|
||||
"%select{end of class|public access specifier|private access specifier|"
|
||||
"protected access specifier|static assert|field|method}3">;
|
||||
def note_module_odr_violation_mismatch_decl : Note<"but in '%0' found "
|
||||
"%select{end of class|public access specifier|private access specifier|"
|
||||
"protected access specifier|static assert|field|method}1">;
|
||||
|
||||
def err_module_odr_violation_mismatch_decl_diff : Error<
|
||||
"%q0 has different definitions in different modules; first difference is "
|
||||
"%select{definition in module '%2'|defined here}1 found "
|
||||
"%select{"
|
||||
"static assert with condition|"
|
||||
"static assert with message|"
|
||||
"static assert with %select{|no }4message|"
|
||||
"field %4|"
|
||||
"field %4 with type %5|"
|
||||
"%select{non-|}5bitfield %4|"
|
||||
"bitfield %4 with one width expression|"
|
||||
"%select{non-|}5mutable field %4|"
|
||||
"field %4 with %select{no|an}5 initalizer|"
|
||||
"field %4 with an initializer|"
|
||||
"method %4|"
|
||||
"method %4 is %select{not deleted|deleted}5|"
|
||||
"method %4 is %select{|pure }5%select{not virtual|virtual}6|"
|
||||
"method %4 is %select{not static|static}5|"
|
||||
"method %4 is %select{not volatile|volatile}5|"
|
||||
"method %4 is %select{not const|const}5|"
|
||||
"method %4 is %select{not inline|inline}5}3">;
|
||||
|
||||
def note_module_odr_violation_mismatch_decl_diff : Note<"but in '%0' found "
|
||||
"%select{"
|
||||
"static assert with different condition|"
|
||||
"static assert with different message|"
|
||||
"static assert with %select{|no }2message|"
|
||||
"field %2|"
|
||||
"field %2 with type %3|"
|
||||
"%select{non-|}3bitfield %2|"
|
||||
"bitfield %2 with different width expression|"
|
||||
"%select{non-|}3mutable field %2|"
|
||||
"field %2 with %select{no|an}3 initializer|"
|
||||
"field %2 with a different initializer|"
|
||||
"method %2|"
|
||||
"method %2 is %select{not deleted|deleted}3|"
|
||||
"method %2 is %select{|pure }3%select{not virtual|virtual}4|"
|
||||
"method %2 is %select{not static|static}3|"
|
||||
"method %2 is %select{not volatile|volatile}3|"
|
||||
"method %2 is %select{not const|const}3|"
|
||||
"method %2 is %select{not inline|inline}3}1">;
|
||||
|
||||
def warn_module_uses_date_time : Warning<
|
||||
"%select{precompiled header|module}0 uses __DATE__ or __TIME__">,
|
||||
InGroup<DiagGroup<"pch-date-time">>;
|
||||
@ -125,6 +176,11 @@ def warn_duplicate_module_file_extension : Warning<
|
||||
"duplicate module file extension block name '%0'">,
|
||||
InGroup<ModuleFileExtension>;
|
||||
|
||||
def warn_module_system_bit_conflict : Warning<
|
||||
"module file '%0' was validated as a system module and is now being imported "
|
||||
"as a non-system module; any difference in diagnostic options will be ignored">,
|
||||
InGroup<ModuleConflict>;
|
||||
|
||||
} // let CategoryName
|
||||
} // let Component
|
||||
|
||||
|
@ -280,7 +280,11 @@ class IdentifierInfo {
|
||||
bool isCPlusPlusOperatorKeyword() const { return IsCPPOperatorKeyword; }
|
||||
|
||||
/// \brief Return true if this token is a keyword in the specified language.
|
||||
bool isKeyword(const LangOptions &LangOpts);
|
||||
bool isKeyword(const LangOptions &LangOpts) const;
|
||||
|
||||
/// \brief Return true if this token is a C++ keyword in the specified
|
||||
/// language.
|
||||
bool isCPlusPlusKeyword(const LangOptions &LangOpts) const;
|
||||
|
||||
/// getFETokenInfo/setFETokenInfo - The language front-end is allowed to
|
||||
/// associate arbitrary metadata with this token.
|
||||
@ -818,6 +822,7 @@ class DeclarationNameExtra {
|
||||
#define OVERLOADED_OPERATOR(Name,Spelling,Token,Unary,Binary,MemberOnly) \
|
||||
CXXOperator##Name,
|
||||
#include "clang/Basic/OperatorKinds.def"
|
||||
CXXDeductionGuide,
|
||||
CXXLiteralOperator,
|
||||
CXXUsingDirective,
|
||||
NUM_EXTRA_KINDS
|
||||
|
@ -107,7 +107,7 @@ LANGOPT(WChar , 1, CPlusPlus, "wchar_t keyword")
|
||||
LANGOPT(DeclSpecKeyword , 1, 0, "__declspec keyword")
|
||||
BENIGN_LANGOPT(DollarIdents , 1, 1, "'$' in identifiers")
|
||||
BENIGN_LANGOPT(AsmPreprocessor, 1, 0, "preprocessor in asm mode")
|
||||
BENIGN_LANGOPT(GNUMode , 1, 1, "GNU extensions")
|
||||
LANGOPT(GNUMode , 1, 1, "GNU extensions")
|
||||
LANGOPT(GNUKeywords , 1, 1, "GNU keywords")
|
||||
BENIGN_LANGOPT(ImplicitInt, 1, !C99 && !CPlusPlus, "C89 implicit 'int'")
|
||||
LANGOPT(Digraphs , 1, 0, "digraphs")
|
||||
@ -201,6 +201,8 @@ LANGOPT(SizedDeallocation , 1, 0, "sized deallocation")
|
||||
LANGOPT(AlignedAllocation , 1, 0, "aligned allocation")
|
||||
LANGOPT(NewAlignOverride , 32, 0, "maximum alignment guaranteed by '::operator new(size_t)'")
|
||||
LANGOPT(ConceptsTS , 1, 0, "enable C++ Extensions for Concepts")
|
||||
BENIGN_LANGOPT(ModulesCodegen , 1, 0, "Modules code generation")
|
||||
BENIGN_LANGOPT(ModulesDebugInfo , 1, 0, "Modules debug info")
|
||||
BENIGN_LANGOPT(ElideConstructors , 1, 1, "C++ copy constructor elision")
|
||||
BENIGN_LANGOPT(DumpRecordLayouts , 1, 0, "dumping the layout of IRgen'd records")
|
||||
BENIGN_LANGOPT(DumpRecordLayoutsSimple , 1, 0, "dumping the layout of IRgen'd records in a simple form")
|
||||
@ -215,7 +217,8 @@ BENIGN_LANGOPT(DebuggerObjCLiteral , 1, 0, "debugger Objective-C literals and su
|
||||
BENIGN_LANGOPT(SpellChecking , 1, 1, "spell-checking")
|
||||
LANGOPT(SinglePrecisionConstants , 1, 0, "treating double-precision floating point constants as single precision constants")
|
||||
LANGOPT(FastRelaxedMath , 1, 0, "OpenCL fast relaxed math")
|
||||
LANGOPT(DefaultFPContract , 1, 0, "FP_CONTRACT")
|
||||
/// \brief FP_CONTRACT mode (on/off/fast).
|
||||
ENUM_LANGOPT(DefaultFPContractMode, FPContractModeKind, 2, FPC_Off, "FP contraction type")
|
||||
LANGOPT(NoBitFieldTypeAlign , 1, 0, "bit-field type alignment")
|
||||
LANGOPT(HexagonQdsp6Compat , 1, 0, "hexagon-qdsp6 backward compatibility")
|
||||
LANGOPT(ObjCAutoRefCount , 1, 0, "Objective-C automated reference counting")
|
||||
@ -261,6 +264,8 @@ LANGOPT(SanitizeAddressFieldPadding, 2, 0, "controls how aggressive is ASan "
|
||||
"field padding (0: none, 1:least "
|
||||
"aggressive, 2: more aggressive)")
|
||||
|
||||
LANGOPT(XRayInstrument, 1, 0, "controls whether to do XRay instrumentation")
|
||||
|
||||
#undef LANGOPT
|
||||
#undef COMPATIBLE_LANGOPT
|
||||
#undef BENIGN_LANGOPT
|
||||
|
@ -88,6 +88,12 @@ class LangOptions : public LangOptionsBase {
|
||||
MSVC2015 = 19
|
||||
};
|
||||
|
||||
enum FPContractModeKind {
|
||||
FPC_Off, // Form fused FP ops only where result will not be affected.
|
||||
FPC_On, // Form fused FP ops according to FP_CONTRACT rules.
|
||||
FPC_Fast // Aggressively fuse FP ops (E.g. FMA).
|
||||
};
|
||||
|
||||
public:
|
||||
/// \brief Set of enabled sanitizers.
|
||||
SanitizerSet Sanitize;
|
||||
@ -96,6 +102,16 @@ class LangOptions : public LangOptionsBase {
|
||||
/// (files, functions, variables) should not be instrumented.
|
||||
std::vector<std::string> SanitizerBlacklistFiles;
|
||||
|
||||
/// \brief Paths to the XRay "always instrument" files specifying which
|
||||
/// objects (files, functions, variables) should be imbued with the XRay
|
||||
/// "always instrument" attribute.
|
||||
std::vector<std::string> XRayAlwaysInstrumentFiles;
|
||||
|
||||
/// \brief Paths to the XRay "never instrument" files specifying which
|
||||
/// objects (files, functions, variables) should be imbued with the XRay
|
||||
/// "never instrument" attribute.
|
||||
std::vector<std::string> XRayNeverInstrumentFiles;
|
||||
|
||||
clang::ObjCRuntime ObjCRuntime;
|
||||
|
||||
std::string ObjCConstantStringClass;
|
||||
@ -170,17 +186,45 @@ class LangOptions : public LangOptionsBase {
|
||||
/// \brief Is this a libc/libm function that is no longer recognized as a
|
||||
/// builtin because a -fno-builtin-* option has been specified?
|
||||
bool isNoBuiltinFunc(StringRef Name) const;
|
||||
|
||||
/// \brief True if any ObjC types may have non-trivial lifetime qualifiers.
|
||||
bool allowsNonTrivialObjCLifetimeQualifiers() const {
|
||||
return ObjCAutoRefCount || ObjCWeak;
|
||||
}
|
||||
};
|
||||
|
||||
/// \brief Floating point control options
|
||||
class FPOptions {
|
||||
public:
|
||||
unsigned fp_contract : 1;
|
||||
FPOptions() : fp_contract(LangOptions::FPC_Off) {}
|
||||
|
||||
FPOptions() : fp_contract(0) {}
|
||||
// Used for serializing.
|
||||
explicit FPOptions(unsigned I)
|
||||
: fp_contract(static_cast<LangOptions::FPContractModeKind>(I)) {}
|
||||
|
||||
FPOptions(const LangOptions &LangOpts) :
|
||||
fp_contract(LangOpts.DefaultFPContract) {}
|
||||
explicit FPOptions(const LangOptions &LangOpts)
|
||||
: fp_contract(LangOpts.getDefaultFPContractMode()) {}
|
||||
|
||||
bool allowFPContractWithinStatement() const {
|
||||
return fp_contract == LangOptions::FPC_On;
|
||||
}
|
||||
bool allowFPContractAcrossStatement() const {
|
||||
return fp_contract == LangOptions::FPC_Fast;
|
||||
}
|
||||
void setAllowFPContractWithinStatement() {
|
||||
fp_contract = LangOptions::FPC_On;
|
||||
}
|
||||
void setAllowFPContractAcrossStatement() {
|
||||
fp_contract = LangOptions::FPC_Fast;
|
||||
}
|
||||
void setDisallowFPContract() { fp_contract = LangOptions::FPC_Off; }
|
||||
|
||||
/// Used to serialize this.
|
||||
unsigned getInt() const { return fp_contract; }
|
||||
|
||||
private:
|
||||
/// Adjust BinaryOperator::FPFeatures to match the bit-field size of this.
|
||||
unsigned fp_contract : 2;
|
||||
};
|
||||
|
||||
/// \brief Describes the kind of translation unit being processed.
|
||||
|
80
include/clang/Basic/MemoryBufferCache.h
Normal file
80
include/clang/Basic/MemoryBufferCache.h
Normal file
@ -0,0 +1,80 @@
|
||||
//===- MemoryBufferCache.h - Cache for loaded memory buffers ----*- C++ -*-===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef LLVM_CLANG_BASIC_MEMORYBUFFERCACHE_H
|
||||
#define LLVM_CLANG_BASIC_MEMORYBUFFERCACHE_H
|
||||
|
||||
#include "llvm/ADT/IntrusiveRefCntPtr.h"
|
||||
#include "llvm/ADT/StringMap.h"
|
||||
#include <memory>
|
||||
|
||||
namespace llvm {
|
||||
class MemoryBuffer;
|
||||
} // end namespace llvm
|
||||
|
||||
namespace clang {
|
||||
|
||||
/// Manage memory buffers across multiple users.
|
||||
///
|
||||
/// Ensures that multiple users have a consistent view of each buffer. This is
|
||||
/// used by \a CompilerInstance when building PCMs to ensure that each \a
|
||||
/// ModuleManager sees the same files.
|
||||
///
|
||||
/// \a finalizeCurrentBuffers() should be called before creating a new user.
|
||||
/// This locks in the current buffers, ensuring that no buffer that has already
|
||||
/// been accessed can be purged, preventing use-after-frees.
|
||||
class MemoryBufferCache : public llvm::RefCountedBase<MemoryBufferCache> {
|
||||
struct BufferEntry {
|
||||
std::unique_ptr<llvm::MemoryBuffer> Buffer;
|
||||
|
||||
/// Track the timeline of when this was added to the cache.
|
||||
unsigned Index;
|
||||
};
|
||||
|
||||
/// Cache of buffers.
|
||||
llvm::StringMap<BufferEntry> Buffers;
|
||||
|
||||
/// Monotonically increasing index.
|
||||
unsigned NextIndex = 0;
|
||||
|
||||
/// Bumped to prevent "older" buffers from being removed.
|
||||
unsigned FirstRemovableIndex = 0;
|
||||
|
||||
public:
|
||||
/// Store the Buffer under the Filename.
|
||||
///
|
||||
/// \pre There is not already buffer is not already in the cache.
|
||||
/// \return a reference to the buffer as a convenience.
|
||||
llvm::MemoryBuffer &addBuffer(llvm::StringRef Filename,
|
||||
std::unique_ptr<llvm::MemoryBuffer> Buffer);
|
||||
|
||||
/// Try to remove a buffer from the cache.
|
||||
///
|
||||
/// \return false on success, iff \c !isBufferFinal().
|
||||
bool tryToRemoveBuffer(llvm::StringRef Filename);
|
||||
|
||||
/// Get a pointer to the buffer if it exists; else nullptr.
|
||||
llvm::MemoryBuffer *lookupBuffer(llvm::StringRef Filename);
|
||||
|
||||
/// Check whether the buffer is final.
|
||||
///
|
||||
/// \return true iff \a finalizeCurrentBuffers() has been called since the
|
||||
/// buffer was added. This prevents buffers from being removed.
|
||||
bool isBufferFinal(llvm::StringRef Filename);
|
||||
|
||||
/// Finalize the current buffers in the cache.
|
||||
///
|
||||
/// Should be called when creating a new user to ensure previous uses aren't
|
||||
/// invalidated.
|
||||
void finalizeCurrentBuffers();
|
||||
};
|
||||
|
||||
} // end namespace clang
|
||||
|
||||
#endif // LLVM_CLANG_BASIC_MEMORYBUFFERCACHE_H
|
@ -42,7 +42,17 @@ class IdentifierInfo;
|
||||
|
||||
/// \brief Describes the name of a module.
|
||||
typedef SmallVector<std::pair<std::string, SourceLocation>, 2> ModuleId;
|
||||
|
||||
|
||||
/// The signature of a module, which is a hash of the AST content.
|
||||
struct ASTFileSignature : std::array<uint32_t, 5> {
|
||||
ASTFileSignature(std::array<uint32_t, 5> S = {{0}})
|
||||
: std::array<uint32_t, 5>(std::move(S)) {}
|
||||
|
||||
explicit operator bool() const {
|
||||
return *this != std::array<uint32_t, 5>({{0}});
|
||||
}
|
||||
};
|
||||
|
||||
/// \brief Describes a module or submodule.
|
||||
class Module {
|
||||
public:
|
||||
@ -65,7 +75,7 @@ class Module {
|
||||
llvm::PointerUnion<const DirectoryEntry *, const FileEntry *> Umbrella;
|
||||
|
||||
/// \brief The module signature.
|
||||
uint64_t Signature;
|
||||
ASTFileSignature Signature;
|
||||
|
||||
/// \brief The name of the umbrella entry, as written in the module map.
|
||||
std::string UmbrellaAsWritten;
|
||||
|
@ -326,6 +326,20 @@ class ObjCRuntime {
|
||||
}
|
||||
}
|
||||
|
||||
/// Are the empty collection symbols available?
|
||||
bool hasEmptyCollections() const {
|
||||
switch (getKind()) {
|
||||
default:
|
||||
return false;
|
||||
case MacOSX:
|
||||
return getVersion() >= VersionTuple(10, 11);
|
||||
case iOS:
|
||||
return getVersion() >= VersionTuple(9);
|
||||
case WatchOS:
|
||||
return getVersion() >= VersionTuple(2);
|
||||
}
|
||||
}
|
||||
|
||||
/// \brief Try to parse an Objective-C runtime specification from the given
|
||||
/// string.
|
||||
///
|
||||
|
@ -66,7 +66,7 @@ IMAGE_WRITE_TYPE(image2d_msaa, OCLImage2dMSAA, "cl_khr_gl_msaa_sharing")
|
||||
IMAGE_WRITE_TYPE(image2d_array_msaa, OCLImage2dArrayMSAA, "cl_khr_gl_msaa_sharing")
|
||||
IMAGE_WRITE_TYPE(image2d_msaa_depth, OCLImage2dMSAADepth, "cl_khr_gl_msaa_sharing")
|
||||
IMAGE_WRITE_TYPE(image2d_array_msaa_depth, OCLImage2dArrayMSAADepth, "cl_khr_gl_msaa_sharing")
|
||||
IMAGE_WRITE_TYPE(image3d, OCLImage3d, "")
|
||||
IMAGE_WRITE_TYPE(image3d, OCLImage3d, "cl_khr_3d_image_writes")
|
||||
|
||||
IMAGE_READ_WRITE_TYPE(image1d, OCLImage1d, "")
|
||||
IMAGE_READ_WRITE_TYPE(image1d_array, OCLImage1dArray, "")
|
||||
|
@ -234,6 +234,11 @@ bool isOpenMPTaskingDirective(OpenMPDirectiveKind Kind);
|
||||
/// directives that need loop bound sharing across loops outlined in nested
|
||||
/// functions
|
||||
bool isOpenMPLoopBoundSharingDirective(OpenMPDirectiveKind Kind);
|
||||
|
||||
/// Return the captured regions of an OpenMP directive.
|
||||
void getOpenMPCaptureRegions(
|
||||
llvm::SmallVectorImpl<OpenMPDirectiveKind> &CaptureRegions,
|
||||
OpenMPDirectiveKind DKind);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
@ -64,6 +64,11 @@ SANITIZER("function", Function)
|
||||
SANITIZER("integer-divide-by-zero", IntegerDivideByZero)
|
||||
SANITIZER("nonnull-attribute", NonnullAttribute)
|
||||
SANITIZER("null", Null)
|
||||
SANITIZER("nullability-arg", NullabilityArg)
|
||||
SANITIZER("nullability-assign", NullabilityAssign)
|
||||
SANITIZER("nullability-return", NullabilityReturn)
|
||||
SANITIZER_GROUP("nullability", Nullability,
|
||||
NullabilityArg | NullabilityAssign | NullabilityReturn)
|
||||
SANITIZER("object-size", ObjectSize)
|
||||
SANITIZER("return", Return)
|
||||
SANITIZER("returns-nonnull-attribute", ReturnsNonnullAttribute)
|
||||
|
@ -321,8 +321,7 @@ class FullSourceLoc : public SourceLocation {
|
||||
}
|
||||
|
||||
/// \brief Comparison function class, useful for sorting FullSourceLocs.
|
||||
struct BeforeThanCompare : public std::binary_function<FullSourceLoc,
|
||||
FullSourceLoc, bool> {
|
||||
struct BeforeThanCompare {
|
||||
bool operator()(const FullSourceLoc& lhs, const FullSourceLoc& rhs) const {
|
||||
return lhs.isBeforeInTranslationUnitThan(rhs);
|
||||
}
|
||||
|
@ -82,11 +82,12 @@ namespace clang {
|
||||
/// \brief Structure that packs information about the type specifiers that
|
||||
/// were written in a particular type specifier sequence.
|
||||
struct WrittenBuiltinSpecs {
|
||||
/*DeclSpec::TST*/ unsigned Type : 5;
|
||||
static_assert(TST_error < 1 << 6, "Type bitfield not wide enough for TST");
|
||||
/*DeclSpec::TST*/ unsigned Type : 6;
|
||||
/*DeclSpec::TSS*/ unsigned Sign : 2;
|
||||
/*DeclSpec::TSW*/ unsigned Width : 2;
|
||||
unsigned ModeAttr : 1;
|
||||
};
|
||||
};
|
||||
|
||||
/// \brief A C++ access specifier (public, private, protected), plus the
|
||||
/// special value "none" which means different things in different contexts.
|
||||
|
@ -43,7 +43,7 @@ def ObjCAtSynchronizedStmt : Stmt;
|
||||
def ObjCForCollectionStmt : Stmt;
|
||||
def ObjCAutoreleasePoolStmt : Stmt;
|
||||
|
||||
// C++ statments
|
||||
// C++ statements
|
||||
def CXXCatchStmt : Stmt;
|
||||
def CXXTryStmt : Stmt;
|
||||
def CXXForRangeStmt : Stmt;
|
||||
@ -150,6 +150,7 @@ def CXXFoldExpr : DStmt<Expr>;
|
||||
// C++ Coroutines TS expressions
|
||||
def CoroutineSuspendExpr : DStmt<Expr, 1>;
|
||||
def CoawaitExpr : DStmt<CoroutineSuspendExpr>;
|
||||
def DependentCoawaitExpr : DStmt<Expr>;
|
||||
def CoyieldExpr : DStmt<CoroutineSuspendExpr>;
|
||||
|
||||
// Obj-C Expressions.
|
||||
|
@ -154,7 +154,7 @@ class TargetInfo : public RefCountedBase<TargetInfo> {
|
||||
/// typedef void* __builtin_va_list;
|
||||
VoidPtrBuiltinVaList,
|
||||
|
||||
/// __builtin_va_list as defind by the AArch64 ABI
|
||||
/// __builtin_va_list as defined by the AArch64 ABI
|
||||
/// http://infocenter.arm.com/help/topic/com.arm.doc.ihi0055a/IHI0055A_aapcs64.pdf
|
||||
AArch64ABIBuiltinVaList,
|
||||
|
||||
@ -168,7 +168,7 @@ class TargetInfo : public RefCountedBase<TargetInfo> {
|
||||
PowerABIBuiltinVaList,
|
||||
|
||||
/// __builtin_va_list as defined by the x86-64 ABI:
|
||||
/// http://www.x86-64.org/documentation/abi.pdf
|
||||
/// http://refspecs.linuxbase.org/elf/x86_64-abi-0.21.pdf
|
||||
X86_64ABIBuiltinVaList,
|
||||
|
||||
/// __builtin_va_list as defined by ARM AAPCS ABI
|
||||
@ -823,8 +823,9 @@ class TargetInfo : public RefCountedBase<TargetInfo> {
|
||||
/// \brief Set forced language options.
|
||||
///
|
||||
/// Apply changes to the target information with respect to certain
|
||||
/// language options which change the target configuration.
|
||||
virtual void adjust(const LangOptions &Opts);
|
||||
/// language options which change the target configuration and adjust
|
||||
/// the language based on the target options where applicable.
|
||||
virtual void adjust(LangOptions &Opts);
|
||||
|
||||
/// \brief Adjust target options based on codegen options.
|
||||
virtual void adjustTargetOptions(const CodeGenOptions &CGOpts,
|
||||
@ -1032,6 +1033,21 @@ class TargetInfo : public RefCountedBase<TargetInfo> {
|
||||
return LangAS::opencl_global;
|
||||
}
|
||||
|
||||
/// \returns Target specific vtbl ptr address space.
|
||||
virtual unsigned getVtblPtrAddressSpace() const {
|
||||
return 0;
|
||||
}
|
||||
|
||||
/// \returns If a target requires an address within a target specific address
|
||||
/// space \p AddressSpace to be converted in order to be used, then return the
|
||||
/// corresponding target specific DWARF address space.
|
||||
///
|
||||
/// \returns Otherwise return None and no conversion will be emitted in the
|
||||
/// DWARF.
|
||||
virtual Optional<unsigned> getDWARFAddressSpace(unsigned AddressSpace) const {
|
||||
return None;
|
||||
}
|
||||
|
||||
/// \brief Check the target is valid after it is fully initialized.
|
||||
virtual bool validateTarget(DiagnosticsEngine &Diags) const {
|
||||
return true;
|
||||
|
@ -432,6 +432,7 @@ TYPE_TRAIT_1(__has_trivial_move_constructor, HasTrivialMoveConstructor, KEYCXX)
|
||||
TYPE_TRAIT_1(__has_trivial_destructor, HasTrivialDestructor, KEYCXX)
|
||||
TYPE_TRAIT_1(__has_virtual_destructor, HasVirtualDestructor, KEYCXX)
|
||||
TYPE_TRAIT_1(__is_abstract, IsAbstract, KEYCXX)
|
||||
TYPE_TRAIT_1(__is_aggregate, IsAggregate, KEYCXX)
|
||||
TYPE_TRAIT_2(__is_base_of, IsBaseOf, KEYCXX)
|
||||
TYPE_TRAIT_1(__is_class, IsClass, KEYCXX)
|
||||
TYPE_TRAIT_2(__is_convertible_to, IsConvertibleTo, KEYCXX)
|
||||
@ -787,6 +788,8 @@ ANNOTATION(pragma_openmp_end)
|
||||
// handles #pragma loop ... directives.
|
||||
ANNOTATION(pragma_loop_hint)
|
||||
|
||||
ANNOTATION(pragma_fp)
|
||||
|
||||
// Annotations for module import translated from #include etc.
|
||||
ANNOTATION(module_include)
|
||||
ANNOTATION(module_begin)
|
||||
|
@ -31,6 +31,7 @@ namespace clang {
|
||||
UTT_HasTrivialDestructor,
|
||||
UTT_HasVirtualDestructor,
|
||||
UTT_IsAbstract,
|
||||
UTT_IsAggregate,
|
||||
UTT_IsArithmetic,
|
||||
UTT_IsArray,
|
||||
UTT_IsClass,
|
||||
|
@ -161,7 +161,7 @@ class directory_iterator {
|
||||
directory_iterator &increment(std::error_code &EC) {
|
||||
assert(Impl && "attempting to increment past end");
|
||||
EC = Impl->increment();
|
||||
if (EC || !Impl->CurrentEntry.isStatusKnown())
|
||||
if (!Impl->CurrentEntry.isStatusKnown())
|
||||
Impl.reset(); // Normalize the end iterator to Impl == nullptr.
|
||||
return *this;
|
||||
}
|
||||
|
54
include/clang/Basic/XRayLists.h
Normal file
54
include/clang/Basic/XRayLists.h
Normal file
@ -0,0 +1,54 @@
|
||||
//===--- XRayLists.h - XRay automatic attribution ---------------*- C++ -*-===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// User-provided filters for always/never XRay instrumenting certain functions.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
#ifndef LLVM_CLANG_BASIC_XRAYLISTS_H
|
||||
#define LLVM_CLANG_BASIC_XRAYLISTS_H
|
||||
|
||||
#include "clang/Basic/LLVM.h"
|
||||
#include "clang/Basic/SourceLocation.h"
|
||||
#include "clang/Basic/SourceManager.h"
|
||||
#include "llvm/ADT/ArrayRef.h"
|
||||
#include "llvm/ADT/StringRef.h"
|
||||
#include "llvm/Support/SpecialCaseList.h"
|
||||
#include <memory>
|
||||
|
||||
namespace clang {
|
||||
|
||||
class XRayFunctionFilter {
|
||||
std::unique_ptr<llvm::SpecialCaseList> AlwaysInstrument;
|
||||
std::unique_ptr<llvm::SpecialCaseList> NeverInstrument;
|
||||
SourceManager &SM;
|
||||
|
||||
public:
|
||||
XRayFunctionFilter(ArrayRef<std::string> AlwaysInstrumentPaths,
|
||||
ArrayRef<std::string> NeverInstrumentPaths,
|
||||
SourceManager &SM);
|
||||
|
||||
enum class ImbueAttribute {
|
||||
NONE,
|
||||
ALWAYS,
|
||||
NEVER,
|
||||
};
|
||||
|
||||
ImbueAttribute shouldImbueFunction(StringRef FunctionName) const;
|
||||
|
||||
ImbueAttribute
|
||||
shouldImbueFunctionsInFile(StringRef Filename,
|
||||
StringRef Category = StringRef()) const;
|
||||
|
||||
ImbueAttribute shouldImbueLocation(SourceLocation Loc,
|
||||
StringRef Category = StringRef()) const;
|
||||
};
|
||||
|
||||
} // namespace clang
|
||||
|
||||
#endif
|
@ -1362,7 +1362,7 @@ def SCALAR_SHL: SInst<"vshl", "sss", "SlSUl">;
|
||||
def SCALAR_QSHL: SInst<"vqshl", "sss", "ScSsSiSlSUcSUsSUiSUl">;
|
||||
// Scalar Saturating Rounding Shift Left
|
||||
def SCALAR_QRSHL: SInst<"vqrshl", "sss", "ScSsSiSlSUcSUsSUiSUl">;
|
||||
// Scalar Shift Rouding Left
|
||||
// Scalar Shift Rounding Left
|
||||
def SCALAR_RSHL: SInst<"vrshl", "sss", "SlSUl">;
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
@ -15,6 +15,8 @@
|
||||
#include <memory>
|
||||
|
||||
namespace llvm {
|
||||
class BitcodeModule;
|
||||
template <typename T> class Expected;
|
||||
class Module;
|
||||
class MemoryBufferRef;
|
||||
}
|
||||
@ -44,6 +46,9 @@ namespace clang {
|
||||
|
||||
void EmbedBitcode(llvm::Module *M, const CodeGenOptions &CGOpts,
|
||||
llvm::MemoryBufferRef Buf);
|
||||
|
||||
llvm::Expected<llvm::BitcodeModule>
|
||||
FindThinLTOModule(llvm::MemoryBufferRef MBRef);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
@ -16,7 +16,7 @@
|
||||
//
|
||||
// It allows other clients, like LLDB, to determine the LLVM types that are
|
||||
// actually used in function calls, which makes it possible to then determine
|
||||
// the acutal ABI locations (e.g. registers, stack locations, etc.) that
|
||||
// the actual ABI locations (e.g. registers, stack locations, etc.) that
|
||||
// these parameters are stored in.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
@ -23,14 +23,36 @@ class BackendConsumer;
|
||||
|
||||
class CodeGenAction : public ASTFrontendAction {
|
||||
private:
|
||||
// Let BackendConsumer access LinkModule.
|
||||
friend class BackendConsumer;
|
||||
|
||||
/// Info about module to link into a module we're generating.
|
||||
struct LinkModule {
|
||||
/// The module to link in.
|
||||
std::unique_ptr<llvm::Module> Module;
|
||||
|
||||
/// If true, we set attributes on Module's functions according to our
|
||||
/// CodeGenOptions and LangOptions, as though we were generating the
|
||||
/// function ourselves.
|
||||
bool PropagateAttrs;
|
||||
|
||||
/// If true, we use LLVM module internalizer.
|
||||
bool Internalize;
|
||||
|
||||
/// Bitwise combination of llvm::LinkerFlags used when we link the module.
|
||||
unsigned LinkFlags;
|
||||
};
|
||||
|
||||
unsigned Act;
|
||||
std::unique_ptr<llvm::Module> TheModule;
|
||||
// Vector of {Linker::Flags, Module*} pairs to specify bitcode
|
||||
// modules to link in using corresponding linker flags.
|
||||
SmallVector<std::pair<unsigned, llvm::Module *>, 4> LinkModules;
|
||||
|
||||
/// Bitcode modules to link in to our module.
|
||||
SmallVector<LinkModule, 4> LinkModules;
|
||||
llvm::LLVMContext *VMContext;
|
||||
bool OwnsVMContext;
|
||||
|
||||
std::unique_ptr<llvm::Module> loadModule(llvm::MemoryBufferRef MBRef);
|
||||
|
||||
protected:
|
||||
/// Create a new code generation action. If the optional \p _VMContext
|
||||
/// parameter is supplied, the action uses it without taking ownership,
|
||||
@ -49,13 +71,6 @@ class CodeGenAction : public ASTFrontendAction {
|
||||
public:
|
||||
~CodeGenAction() override;
|
||||
|
||||
/// setLinkModule - Set the link module to be used by this action. If a link
|
||||
/// module is not provided, and CodeGenOptions::LinkBitcodeFile is non-empty,
|
||||
/// the action will load it from the specified file.
|
||||
void addLinkModule(llvm::Module *Mod, unsigned LinkFlags) {
|
||||
LinkModules.push_back(std::make_pair(LinkFlags, Mod));
|
||||
}
|
||||
|
||||
/// Take the generated LLVM module, for use after the action has been run.
|
||||
/// The result may be null on failure.
|
||||
std::unique_ptr<llvm::Module> takeModule();
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user